@fusengine/harness 0.1.45 → 0.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -116,6 +116,8 @@ Ten portable guards + the APEX gate chain, all evaluated before a tool runs:
116
116
  | APEX freshness | `explore-codebase` + `research-expert` not run within the window |
117
117
  | APEX doc-consulted | no doc source (Context7 / Exa / fuse-browser / WebSearch / WebFetch) consulted this session |
118
118
  | APEX solid-read | required SOLID refs (auto-discovered, or `FUSE_HARNESS_REFS`) not read |
119
+ | framework sub-skill | framework / shadcn / Tailwind code whose required skill (`skills/<name>/`) wasn't read this session |
120
+ | Gemini MCP (opt-in) | hand-written Tailwind UI without a `mcp__gemini-design__*` call — only when `FUSE_ENFORCE_GEMINI_MCP` is set |
119
121
  | brainstorm | creating a new file without brainstorming (when flagged) |
120
122
  | MCP verbosity / cache | caps exa `numResults`; serves a fresh cached MCP/WebFetch result |
121
123
 
@@ -131,6 +133,8 @@ through per window without the full APEX gates.
131
133
  | `FUSE_HARNESS_MARKETPLACES` | Comma-list of marketplace names whose `solid-*` skill refs are auto-discovered when `FUSE_HARNESS_REFS` is unset (default `fusengine-plugins`; an absent marketplace contributes nothing). Standalone `.claude`/`.codex`/`.cursor`/`.agents` skills are always scanned. |
132
134
  | `FUSE_ENFORCE_TTL_SEC` | APEX freshness window in seconds. |
133
135
  | `FUSE_LESSONS_THROTTLE_MIN` | Lessons-injection throttle (memory module). |
136
+ | `FUSE_ENFORCE_GEMINI_MCP` | **Opt-in (default off).** `1`/`true` blocks hand-written Tailwind UI (`.tsx/.jsx/.vue/.svelte`, ≥3 utility classes) until a `mcp__gemini-design__*` call is made this session. Read fresh per call. |
137
+ | `RALPH_MODE` | **Opt-in (default off).** `1`/`true` enables autonomous "Ralph" mode: exempts the safe git commands (`add`/`commit`/`checkout -b`/`status`/`diff`/`log`) from the confirmation ASK and auto-approves project installs. Destructive git (force-push, `reset --hard`) and system installs still gate. |
134
138
 
135
139
  ## Library usage
136
140
 
@@ -1,2 +1,2 @@
1
- import { a as guard, c as toClaudeResponse, i as fileSizeGuard, n as contextResponse, o as readClaudeInput, r as denyResponse, s as systemMessage, t as blockResponse } from "../../claude-DLh0fHWM.mjs";
1
+ import { a as guard, c as toClaudeResponse, i as fileSizeGuard, n as contextResponse, o as readClaudeInput, r as denyResponse, s as systemMessage, t as blockResponse } from "../../claude-U1KTaRG4.mjs";
2
2
  export { blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, readClaudeInput, systemMessage, toClaudeResponse };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-d7Pp8XJH.mjs";
1
+ import { t as evaluate } from "../../evaluate-qYC5xClb.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 guard, n as contextResponse, o as readClaudeInput, r as denyResponse } from "../../claude-DLh0fHWM.mjs";
1
+ import { a as guard, n as contextResponse, o as readClaudeInput, r as denyResponse } from "../../claude-U1KTaRG4.mjs";
2
2
  export { contextResponse, denyResponse, guard, readClaudeInput as readCodexInput };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-d7Pp8XJH.mjs";
1
+ import { t as evaluate } from "../../evaluate-qYC5xClb.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-d7Pp8XJH.mjs";
1
+ import { t as evaluate } from "../../evaluate-qYC5xClb.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-d7Pp8XJH.mjs";
1
+ import { t as evaluate } from "./evaluate-qYC5xClb.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,9 +2,9 @@
2
2
  import { r as loadDotenv, s as resolveTtlSec } from "../dotenv-B9nM4cuQ.mjs";
3
3
  import { t as detectHarness } from "../harness-C8Nxxyn_.mjs";
4
4
  import { t as claudeHome } from "../home-state-mKZxP4oZ.mjs";
5
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-DLXtA5DH.mjs";
5
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-CaqeQFYp.mjs";
6
6
  import { n as writeInitFile, t as initFor } from "../run-Do2JltgU.mjs";
7
- import { Mt as todayUtc, t as handleHook } from "../handle-DJaaD2BT.mjs";
7
+ import { Mt as todayUtc, t as handleHook } from "../handle-DUlUbhyF.mjs";
8
8
  import { delimiter, dirname, 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-DLXtA5DH.mjs";
1
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-CaqeQFYp.mjs";
2
2
  export { checkStaged, stagedContent, stagedFiles };
@@ -147,6 +147,27 @@ const PROJECT_INSTALL = [
147
147
  function matchPatterns(cmd, patterns) {
148
148
  return patterns.some((re) => re.test(cmd));
149
149
  }
150
+ /** Git commands exempt from confirmation when Ralph mode is on (parity git-guard.py RALPH_SAFE). */
151
+ const RALPH_SAFE = [
152
+ "git add",
153
+ "git commit",
154
+ "git checkout -b",
155
+ "git branch --show-current",
156
+ "git status",
157
+ "git diff",
158
+ "git log"
159
+ ];
160
+ /**
161
+ * OPT-IN autonomous "Ralph" mode: OFF unless `RALPH_MODE` is `1`/`true`, read
162
+ * fresh on each call. Only the env var activates it — the Python source also
163
+ * auto-enabled on a `.claude/ralph/prd.json` file or a `feature/*` branch, but
164
+ * those silent activations are dropped here: a mode that removes git/install
165
+ * confirmations must never turn on implicitly (owner: default OFF, env opt-in).
166
+ */
167
+ function isRalphMode() {
168
+ const v = process.env.RALPH_MODE;
169
+ return v === "1" || v === "true";
170
+ }
150
171
  //#endregion
151
172
  //#region src/policy/file-size-scope.ts
152
173
  /**
@@ -302,23 +323,32 @@ function stripHeredoc(cmd) {
302
323
  }
303
324
  return out;
304
325
  }
305
- /** Guards against dangerous Bash commands (critical → block, sensitive → ask). */
326
+ /**
327
+ * Guards against dangerous Bash commands. Parity `security_rules.validate_command`
328
+ * + `security-guard.py`: ACCUMULATE every matched violation, then deny when any
329
+ * critical matched else ask, joining all violation labels in the reason. The
330
+ * generic `rm` ask is exempt when the command targets a trash location (parity
331
+ * `not re.search('trash', cmd)`).
332
+ */
306
333
  function securityGuard(ctx) {
307
334
  if (ctx.tool !== "Bash" || !ctx.command) return null;
308
335
  const cmd = stripHeredoc(ctx.command);
309
- for (const { re, label } of CRITICAL_PATTERNS) if (re.test(cmd)) return {
336
+ const hasTrash = /trash/i.test(cmd);
337
+ const critical = CRITICAL_PATTERNS.filter(({ re }) => re.test(cmd)).map((p) => p.label);
338
+ const ask = ASK_PATTERNS.filter(({ re, label }) => re.test(cmd) && !(hasTrash && label.startsWith("DELETE: 'rm'"))).map((p) => p.label);
339
+ if (critical.length === 0 && ask.length === 0) return null;
340
+ if (critical.length > 0) return {
310
341
  kind: "block",
311
342
  title: "Dangerous command",
312
- reason: `${label}.`,
343
+ reason: `${[...critical, ...ask].join(", ")}.`,
313
344
  actions: ["Remove the destructive command", "Scope the operation to a specific safe path"]
314
345
  };
315
- for (const { re, label } of ASK_PATTERNS) if (re.test(cmd)) return {
346
+ return {
316
347
  kind: "ask",
317
348
  title: "Dangerous command",
318
- reason: `${label}.`,
349
+ reason: `${ask.join(", ")}.`,
319
350
  actions: ["Confirm this command is intended", "Run with least privilege"]
320
351
  };
321
- return null;
322
352
  }
323
353
  //#endregion
324
354
  //#region src/policy/guards/protected-path.ts
@@ -611,7 +641,7 @@ function bashWriteGuard(ctx) {
611
641
  /** TS/JS component files: top-level `interface`/`type Foo`. */
612
642
  const TS_DECL_RE = /^\s*(export\s+)?(interface|type)\s+[A-Z]/m;
613
643
  /** Python view models: class subclassing a schema/protocol base. */
614
- const PY_MODEL_RE = /^\s*class\s+\w+\((BaseModel|TypedDict|Protocol)\)/m;
644
+ const PY_MODEL_RE = /^\s*class\s+\w+\s*\([^)]*\b(?:BaseModel|TypedDict|Protocol)\b/m;
615
645
  /**
616
646
  * PHP controllers: top-level `interface`, `abstract class`, or a concrete
617
647
  * `class …Interface/DTO/Request`. Union of the TS-only `abstract class` rule
@@ -662,16 +692,23 @@ function interfaceSeparationGuard(ctx) {
662
692
  }
663
693
  //#endregion
664
694
  //#region src/policy/guards/install.ts
665
- /** Asks for confirmation before a dependency or system package install. */
695
+ /**
696
+ * Asks for confirmation before a dependency or system package install. In Ralph
697
+ * mode (opt-in `RALPH_MODE`) a PROJECT install is auto-approved for autonomous
698
+ * runs (parity install-guard.py:52), but a SYSTEM install always asks.
699
+ */
666
700
  function installGuard(ctx) {
667
701
  if (ctx.tool !== "Bash" || !ctx.command) return null;
668
- if (matchPatterns(ctx.command, PROJECT_INSTALL) || matchPatterns(ctx.command, SYSTEM_INSTALL)) return {
702
+ const isSystem = matchPatterns(ctx.command, SYSTEM_INSTALL);
703
+ const isProject = matchPatterns(ctx.command, PROJECT_INSTALL);
704
+ if (!isSystem && !isProject) return null;
705
+ if (!isSystem && isProject && isRalphMode()) return null;
706
+ return {
669
707
  kind: "ask",
670
708
  title: "Dependency install",
671
709
  reason: `This command installs packages: ${ctx.command.trim()}`,
672
710
  actions: ["Confirm this install is intended"]
673
711
  };
674
- return null;
675
712
  }
676
713
  //#endregion
677
714
  //#region src/policy/guards/index.ts
@@ -730,7 +767,9 @@ function evaluate(ctx) {
730
767
  message: guard.reason,
731
768
  prompt: guard
732
769
  };
733
- if (ctx.command && matchPatterns(ctx.command, GIT_BLOCKED)) {
770
+ const cmd = ctx.command;
771
+ const ralphSafe = !!cmd && isRalphMode() && RALPH_SAFE.some((s) => cmd.startsWith(s));
772
+ if (!ralphSafe && ctx.command && matchPatterns(ctx.command, GIT_BLOCKED)) {
734
773
  const reason = `Destructive git command: ${ctx.command}`;
735
774
  return {
736
775
  decision: "deny",
@@ -743,7 +782,7 @@ function evaluate(ctx) {
743
782
  }
744
783
  };
745
784
  }
746
- if (ctx.command && matchPatterns(ctx.command, GIT_ASK)) return {
785
+ if (!ralphSafe && ctx.command && matchPatterns(ctx.command, GIT_ASK)) return {
747
786
  decision: "deny",
748
787
  message: `Git operation requires confirmation: ${ctx.command}`,
749
788
  prompt: {
@@ -781,4 +820,4 @@ function evaluate(ctx) {
781
820
  };
782
821
  }
783
822
  //#endregion
784
- export { PROJECT_INSTALL as A, PROTECTED_GIT_RE as C, securityGuard as D, CRITICAL_PATTERNS as E, countFrameworkCodeLines as F, countLines as I, evaluateFileSize as L, matchPatterns as M, PLUGINS_DIR as N, GIT_ASK as O, SOLID_REF as P, PROTECTED_FRAGMENTS as S, ASK_PATTERNS as T, CODE_MUTATORS as _, registerGuard as a, SAFE_PREFIXES as b, GO_DECL_RE as c, PY_MODEL_RE as d, SWIFT_PROTO_RE as f, ASK_WRITERS as g, bashWriteGuard as h, clearUserGuards as i, SYSTEM_INSTALL as j, GIT_BLOCKED as k, JAVA_DECL_RE as l, interfaceSeparationGuard as m, FAIL_CLOSED as n, runGuards as o, TS_DECL_RE as p, GUARDS as r, installGuard as s, evaluate as t, PHP_DECL_RE as u, CODE_REDIRECT as v, protectedPathGuard as w, SESSION_STATE_FRAGMENT as x, FILE_REDIRECT as y };
823
+ export { PROJECT_INSTALL as A, PROTECTED_GIT_RE as C, securityGuard as D, CRITICAL_PATTERNS as E, PLUGINS_DIR as F, SOLID_REF as I, countFrameworkCodeLines as L, SYSTEM_INSTALL as M, isRalphMode as N, GIT_ASK as O, matchPatterns as P, countLines as R, PROTECTED_FRAGMENTS as S, ASK_PATTERNS as T, CODE_MUTATORS as _, registerGuard as a, SAFE_PREFIXES as b, GO_DECL_RE as c, PY_MODEL_RE as d, SWIFT_PROTO_RE as f, ASK_WRITERS as g, bashWriteGuard as h, clearUserGuards as i, RALPH_SAFE as j, GIT_BLOCKED as k, JAVA_DECL_RE as l, interfaceSeparationGuard as m, FAIL_CLOSED as n, runGuards as o, TS_DECL_RE as p, GUARDS as r, installGuard as s, evaluate as t, PHP_DECL_RE as u, CODE_REDIRECT as v, protectedPathGuard as w, SESSION_STATE_FRAGMENT as x, FILE_REDIRECT as y, evaluateFileSize as z };
@@ -1,8 +1,8 @@
1
1
  import { a as parseEnvInt, i as splitTarget, r as resolveMaxLines } from "./limits-CHn8AIL1.mjs";
2
2
  import { r as projectLayout } from "./layout-C0jaaCQC.mjs";
3
3
  import { i as walkUpFor, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-3kk7gCOp.mjs";
4
- import { A as detectCreationIntent, B as detectProjectType$1, C as findMarketplacePlugins, E as frameworkSolidGate, H as requiredArchSkill, L as detectFramework, N as docConsultedGate, P as evaluateApex, _ 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 readPluginMeta, x as skillTriggerGate, y as parseField, z as detectModularArchitecture } from "./validate-DcQaKzau.mjs";
5
- import { F as countFrameworkCodeLines, I as countLines, N as PLUGINS_DIR, n as FAIL_CLOSED, t as evaluate } from "./evaluate-d7Pp8XJH.mjs";
4
+ import { B as detectFramework, C as resolveSkillPath, D as frameworkSolidGate, G as requiredArchSkill, H as detectModularArchitecture, I as docConsultedGate, L as evaluateApex, M as capVerbosity, N as detectCreationIntent, O as isExcludedJsPath, S as usesTailwindUtilities, T as readPluginMeta, U as detectProjectType$1, _ as scanPlugin, c as EXCLUDE_DIRS$1, d as buildApexTaskInjection, h as buildClaudeMdContext, k as isExcludedSwiftPath, l as PROJECT_INDICATORS, n as missingSeoElements, o as parseEnrichment, r as descFromText, s as parseEntry, t as isHtmlLike, w as findMarketplacePlugins, x as skillTriggerGate, y as parseField } from "./validate-DVV4nRfr.mjs";
5
+ import { F as PLUGINS_DIR, L as countFrameworkCodeLines, R as countLines, n as FAIL_CLOSED, t as evaluate } from "./evaluate-qYC5xClb.mjs";
6
6
  import { a as writeJsonFile, i as readJsonFile, r as hashText, t as atomicWrite } from "./json-io-DisYd2fb.mjs";
7
7
  import { a as sanitizeSessionId, c as sessionsDir, i as loadSessionState, n as fuseHarnessHome, o as saveSessionState, r as fusengineCache, t as claudeHome } from "./home-state-mKZxP4oZ.mjs";
8
8
  import { r as isDocConsulted } from "./doc-helpers-CWZegVdR.mjs";
@@ -11,7 +11,7 @@ import { a as nowStamp, l as throttleMs, n as readRoots, o as readState, s as se
11
11
  import { d as loadIndex, i as cacheLookupMeta, n as webfetchCacheWrite, o as cacheLookupSubstringMeta, t as mcpCacheWrite, u as extractText } from "./mcp-store-BkBDmuxN.mjs";
12
12
  import { t as loadRefs } from "./loader-AGz4nK7d.mjs";
13
13
  import { c as recordDoc, d as trivialCount, i as agentsFresh, l as recordRefRead, n as saveTrack, o as recordAgent, r as verifyTrack, s as recordBrainstormRequired, t as loadTrack, u as recordTrivialEdit } from "./store-CNjFenWe.mjs";
14
- import { d as readText, f as sleep, l as collectFiles, m as writeText, n as contextResponse, p as spawnCapture, r as denyResponse, s as systemMessage, t as blockResponse, u as pathExists } from "./claude-DLh0fHWM.mjs";
14
+ import { d as readText, f as sleep, l as collectFiles, m as writeText, n as contextResponse, p as spawnCapture, r as denyResponse, s as systemMessage, t as blockResponse, u as pathExists } from "./claude-U1KTaRG4.mjs";
15
15
  import { basename, dirname, extname, join, relative, resolve, sep } from "node:path";
16
16
  import { appendFileSync, copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
17
17
  import { homedir } from "node:os";
@@ -3537,7 +3537,7 @@ const EXEMPT_PATTERNS = [
3537
3537
  /\.claude-plugin\//,
3538
3538
  /CHANGELOG\.md$/,
3539
3539
  /marketplace\.json$/,
3540
- /\/\.claude\/(apex|memory|logs)\//,
3540
+ /\/\.claude\/(apex|memory|logs|fusengine-cache)\//,
3541
3541
  /\/\.fuse-harness\//
3542
3542
  ];
3543
3543
  /**
@@ -3849,11 +3849,12 @@ function nextModular(filePath, content, cwd) {
3849
3849
  }
3850
3850
  /** Laravel FuseCore architecture: `app/` domain ban + module.json + cross-module `use` rules. */
3851
3851
  function fusecore(filePath, content, cwd) {
3852
- for (const b of PHP_BLOCKED_IN_APP) if (filePath.includes(b)) return block$1(`BLOCKED: FuseCore domain code in '${b}' must move to FuseCore/{Module}/App/.`);
3852
+ for (const b of PHP_BLOCKED_IN_APP) if (filePath.includes(b)) return block$1(`BLOCKED: FuseCore project. Code in '${b.replace(/^\/|\/$/g, "")}' FORBIDDEN. Move to '${b.replaceAll("/app/", "/FuseCore/{Module}/App/").replace(/^\/|\/$/g, "")}'.`);
3853
3853
  const mod = filePath.match(/\/FuseCore\/([A-Za-z]+)\//);
3854
3854
  if (!mod) return null;
3855
3855
  const name = mod[1] ?? "";
3856
- if (!existsSync(join(cwd, "FuseCore", name, "module.json"))) return block$1(`BLOCKED: FuseCore module '${name}' is missing module.json — create it first.`);
3856
+ const mj = join(cwd, "FuseCore", name, "module.json");
3857
+ if (!existsSync(mj)) return block$1(`BLOCKED: Module '${name}' missing module.json. Create ${mj} first.`);
3857
3858
  for (const m of content.matchAll(/use\s+FuseCore\\(\w+)\\/g)) {
3858
3859
  const imported = m[1] ?? "";
3859
3860
  if (name === "Core") {
@@ -3873,6 +3874,19 @@ function modularGate(tool, filePath, content, cwd) {
3873
3874
  }
3874
3875
  //#endregion
3875
3876
  //#region src/runtime/framework-skill-gate.ts
3877
+ /** PHP paths the Laravel skill check skips — broader than the SOLID vendor-only exclude (parity check-laravel-skill.py `/(vendor|storage|bootstrap/cache)/`). */
3878
+ const PHP_SKILL_EXCLUDE_RE = /\/(vendor|storage|bootstrap\/cache)\//;
3879
+ /**
3880
+ * Whether the sub-skill gate should skip this path — parity with the early return
3881
+ * in check-*-skill.py (build/vendor artifacts never require a sub-skill).
3882
+ * @param framework - the detected framework ("laravel" | "swift" | JS otherwise).
3883
+ * @param filePath - the file being written.
3884
+ */
3885
+ function skillGateExcluded(framework, filePath) {
3886
+ if (framework === "laravel") return PHP_SKILL_EXCLUDE_RE.test(filePath);
3887
+ if (framework === "swift") return isExcludedSwiftPath(filePath);
3888
+ return isExcludedJsPath(filePath);
3889
+ }
3876
3890
  /**
3877
3891
  * Effective line count for the SOLID size check. On an Edit, `content` is only
3878
3892
  * the `new_string` snippet, so for Next.js — mirroring the base file-size guard
@@ -3912,6 +3926,7 @@ function frameworkSkillGate(input, refsRead, existingCodeLines) {
3912
3926
  const content = input.content ?? "";
3913
3927
  const solid = frameworkSolidGate(input.filePath, content, effectiveLines(input.tool, input.framework, content, existingCodeLines));
3914
3928
  if (solid) return solid;
3929
+ if (skillGateExcluded(input.framework, input.filePath)) return null;
3915
3930
  const forced = input.cwd ? requiredArchSkill(input.cwd) : null;
3916
3931
  return skillTriggerGate(input.framework, content, refsRead, forced, input.cwd, input.filePath);
3917
3932
  }
@@ -3979,6 +3994,122 @@ function shadcnSkillGate(tool, filePath, content, ev) {
3979
3994
  });
3980
3995
  }
3981
3996
  //#endregion
3997
+ //#region src/policy/tailwind-skill-gate.ts
3998
+ /** Vendored/build paths exempt (parity check-tailwind-skill.py `/(node_modules|dist|build)/`). */
3999
+ const TW_EXCLUDE_RE = /(^|\/)(node_modules|dist|build)\//;
4000
+ /** A read reference proving a base Tailwind skill was consulted (Phase 1). */
4001
+ const TW_BASE_SKILL_RE = /skills\/(tailwindcss-v4|tailwindcss-utilities)\//;
4002
+ /**
4003
+ * True when this Write/Edit is a `.tsx`/`.jsx` file carrying Tailwind utility
4004
+ * classes, outside vendored dirs — the trigger condition of Phase 1.
4005
+ * @param tool - the tool name.
4006
+ * @param filePath - the file being written.
4007
+ * @param content - the written content.
4008
+ */
4009
+ function isTailwindWrite(tool, filePath, content) {
4010
+ if (tool !== "Write" && tool !== "Edit") return false;
4011
+ if (TW_EXCLUDE_RE.test(filePath)) return false;
4012
+ return usesTailwindUtilities(filePath, content);
4013
+ }
4014
+ /** True when `tailwindcss-v4` or `tailwindcss-utilities` was read this session (Phase 1 base skill). */
4015
+ function tailwindBaseSkillRead(refsRead) {
4016
+ return refsRead.some((p) => TW_BASE_SKILL_RE.test(p));
4017
+ }
4018
+ /**
4019
+ * Gate a Tailwind-scoped write: block until a base Tailwind skill is read
4020
+ * (parity check-tailwind-skill.py Phase 1). Returns `null` when out of scope
4021
+ * or already satisfied.
4022
+ * @param tool - the tool name.
4023
+ * @param filePath - the file being written.
4024
+ * @param content - the written content.
4025
+ * @param refsRead - in-session read reference paths.
4026
+ */
4027
+ function tailwindSkillGate(tool, filePath, content, refsRead) {
4028
+ if (!isTailwindWrite(tool, filePath, content)) return null;
4029
+ if (tailwindBaseSkillRead(refsRead)) return null;
4030
+ return {
4031
+ kind: "block",
4032
+ title: "Tailwind CSS skill",
4033
+ reason: "BLOCKED: Tailwind skill not consulted. Read tailwindcss-v4/SKILL.md or tailwindcss-utilities/SKILL.md, or use mcp__context7__query-docs (topic: tailwindcss), then retry.",
4034
+ actions: [`Read ${resolveSkillPath("tailwindcss-v4")} or ${resolveSkillPath("tailwindcss-utilities")}`]
4035
+ };
4036
+ }
4037
+ //#endregion
4038
+ //#region src/policy/gemini-mcp-gate.ts
4039
+ /** UI file extensions the gate polices (parity enforce-gemini-mcp.py UI_EXT). */
4040
+ const UI_EXT_RE = /\.(tsx|jsx|vue|svelte)$/;
4041
+ /** Paths exempt from the gate (parity EXEMPT_DIRS). */
4042
+ const GEMINI_EXEMPT_RE = /(node_modules|dist|build|\.next|\.claude)\//;
4043
+ /** A live `mcp__gemini-design__*` call recorded this session proves consultation. */
4044
+ const GEMINI_MCP_SOURCE_RE = /gemini-mcp/i;
4045
+ /** Tailwind utility patterns (parity TAILWIND_PATTERNS). */
4046
+ const TW_PATTERNS = [
4047
+ /\bflex\b/,
4048
+ /\bgrid\b/,
4049
+ /\bp-\d/,
4050
+ /\bpx-\d/,
4051
+ /\bpy-\d/,
4052
+ /\bm-\d/,
4053
+ /\bmx-\d/,
4054
+ /\bmy-\d/,
4055
+ /\bmt-\d/,
4056
+ /\bmb-\d/,
4057
+ /\bbg-\w+/,
4058
+ /\btext-\w+/,
4059
+ /\brounded/,
4060
+ /\bshadow/,
4061
+ /\bborder\b/,
4062
+ /\bgap-\d/,
4063
+ /\bw-\w+/,
4064
+ /\bh-\w+/,
4065
+ /\bjustify-\w+/,
4066
+ /\bitems-\w+/,
4067
+ /\bspace-\w+-\d/
4068
+ ];
4069
+ /** Min distinct Tailwind patterns before the gate fires (parity MIN_TAILWIND_CLASSES). */
4070
+ const MIN_TW = 3;
4071
+ /** Min newlines an Edit's new_string must have to be gated (parity MIN_LINES_FOR_EDIT). */
4072
+ const MIN_LINES_EDIT = 2;
4073
+ /** OPT-IN: off unless `FUSE_ENFORCE_GEMINI_MCP` is `1`/`true`. Read fresh each call (dynamic). */
4074
+ function geminiMcpEnforced() {
4075
+ const v = process.env.FUSE_ENFORCE_GEMINI_MCP;
4076
+ return v === "1" || v === "true";
4077
+ }
4078
+ /** Count distinct Tailwind utility patterns present in `content` (parity count_tailwind_classes). */
4079
+ function countTailwindClasses(content) {
4080
+ return TW_PATTERNS.reduce((n, re) => re.test(content) ? n + 1 : n, 0);
4081
+ }
4082
+ /** True when a `mcp__gemini-design__*` call was recorded this session (parity gemini_was_called). */
4083
+ function geminiMcpConsulted(authorizations, sessionId) {
4084
+ if (!authorizations) return false;
4085
+ return Object.values(authorizations).some((a) => a.doc_sessions?.includes(sessionId) && (a.sources ?? (a.source ? [a.source] : [])).some((s) => GEMINI_MCP_SOURCE_RE.test(s)));
4086
+ }
4087
+ /**
4088
+ * Gate a UI write when `FUSE_ENFORCE_GEMINI_MCP` is on: block hand-written
4089
+ * Tailwind (>= 3 classes) in a `.tsx/.jsx/.vue/.svelte` file unless a Gemini
4090
+ * Design MCP call was made this session. Returns `null` when disabled (default),
4091
+ * out of scope, or already satisfied.
4092
+ * @param tool - the tool name.
4093
+ * @param filePath - the file being written.
4094
+ * @param content - the written content (new_string on Edit).
4095
+ * @param ev - session evidence (authorizations + sessionId).
4096
+ */
4097
+ function geminiMcpGate(tool, filePath, content, ev) {
4098
+ if (!geminiMcpEnforced()) return null;
4099
+ if (tool !== "Write" && tool !== "Edit") return null;
4100
+ if (!filePath || !UI_EXT_RE.test(filePath) || GEMINI_EXEMPT_RE.test(filePath)) return null;
4101
+ if (!content) return null;
4102
+ if (tool === "Edit" && (content.match(/\n/g)?.length ?? 0) < MIN_LINES_EDIT) return null;
4103
+ if (countTailwindClasses(content) < MIN_TW) return null;
4104
+ if (geminiMcpConsulted(ev.authorizations, ev.sessionId)) return null;
4105
+ return {
4106
+ kind: "block",
4107
+ title: "Gemini Design MCP",
4108
+ reason: "BLOCKED: UI code with Tailwind detected but Gemini Design MCP not used. Use mcp__gemini-design__create_frontend, modify_frontend, or snippet_frontend BEFORE writing UI code manually.",
4109
+ actions: ["Call mcp__gemini-design__create_frontend / modify_frontend / snippet_frontend, then retry"]
4110
+ };
4111
+ }
4112
+ //#endregion
3982
4113
  //#region src/freshness/explore-tools.ts
3983
4114
  /** Native exploration tools (parity `apex_constants.EXPLORE_TOOLS`). */
3984
4115
  const EXPLORE_TOOLS = /* @__PURE__ */ new Set(["Glob", "Grep"]);
@@ -4160,7 +4291,7 @@ async function apexScopedGate(input, track, window) {
4160
4291
  agentsFresh: freshnessFor([...REQUIRED_AGENTS]),
4161
4292
  missingAgents: REQUIRED_AGENTS.filter((name) => !freshnessFor([name])),
4162
4293
  windowMs: window,
4163
- brainstormRequired: input.tool === "Edit" ? false : track.brainstormRequired,
4294
+ brainstormRequired: input.tool === "Edit" || input.agentId ? false : track.brainstormRequired,
4164
4295
  brainstormFresh: freshnessFor(["brainstorming"], Number.MAX_SAFE_INTEGER)
4165
4296
  };
4166
4297
  try {
@@ -4221,6 +4352,15 @@ async function gate(input) {
4221
4352
  });
4222
4353
  if (shadcnBlock) return shadcnBlock;
4223
4354
  }
4355
+ if (isTailwindWrite(input.tool, filePath, input.content ?? "")) {
4356
+ const twBlock = tailwindSkillGate(input.tool, filePath, input.content ?? "", track.refsRead);
4357
+ if (twBlock) return twBlock;
4358
+ }
4359
+ const geminiBlock = geminiMcpGate(input.tool, filePath, input.content ?? "", {
4360
+ authorizations: track.authorizations,
4361
+ sessionId: input.sessionId
4362
+ });
4363
+ if (geminiBlock) return geminiBlock;
4224
4364
  if (isApexScoped(input.filePath)) {
4225
4365
  const apex = await apexScopedGate(input, track, window);
4226
4366
  if (apex) return apex;
@@ -4646,25 +4786,6 @@ function htmlCssOnlyGate(filePath) {
4646
4786
  function stateFileGate(filePath) {
4647
4787
  return filePath.includes(".design-state-") ? deny("BLOCKED: .design-state files are READ-ONLY for you. Hooks update them automatically as you progress. Do NOT try to modify them — it will not unblock you. Follow the pipeline: Phase 0→1→2→3→4→5→6 in order.") : null;
4648
4788
  }
4649
- /**
4650
- * Ports browser_helpers.is_exempt: design-system.md is NOT exempt (it must meet
4651
- * the quota); other `.md` files and vendored dirs ARE exempt from the check.
4652
- */
4653
- function screenshotExempt(filePath) {
4654
- if (filePath.endsWith("design-system.md")) return false;
4655
- return filePath.endsWith(".md") || EXEMPT_DIRS.some((d) => filePath.includes(d));
4656
- }
4657
- /**
4658
- * Block ANY non-exempt write (html/css/design-system.md) until the per-mode
4659
- * screenshot quota is met. Ports check-browser-browsing.py's "Browse N sites
4660
- * BEFORE writing" deny for the active design agent.
4661
- */
4662
- function preScreenshotWriteGate(filePath, state) {
4663
- if (screenshotExempt(filePath)) return null;
4664
- const needed = MIN_SCREENSHOTS[state.mode];
4665
- if (state.screenshotsCount < needed) return deny(`BLOCKED: ${state.screenshotsCount}/${needed} fuse-browser screenshots for mode '${state.mode}'. Browse ${needed - state.screenshotsCount} more site(s) BEFORE writing. Read design-inspiration.md, then browser_open + browser_navigate + browser_screenshot.`);
4666
- return null;
4667
- }
4668
4789
  /** Return the requirements missing from a design-system.md (empty = valid). */
4669
4790
  function validateDesignSystem(content) {
4670
4791
  const missing = [];
@@ -4759,7 +4880,7 @@ function designGate(payload, event, cacheDir, cwd) {
4759
4880
  }
4760
4881
  if (event.tool === "Write" || event.tool === "Edit") {
4761
4882
  const fp = event.filePath ?? "";
4762
- const base = stateFileGate(fp) ?? htmlCssOnlyGate(fp) ?? preScreenshotWriteGate(fp, state) ?? designSystemWriteGate(fp, state);
4883
+ const base = stateFileGate(fp) ?? htmlCssOnlyGate(fp) ?? designSystemWriteGate(fp, state);
4763
4884
  if (base) return base;
4764
4885
  if (geminiEnabled() && state.geminiCalls === 0 && /\.(html|css)$/.test(fp)) return {
4765
4886
  kind: "block",
@@ -4775,7 +4896,14 @@ function designGate(payload, event, cacheDir, cwd) {
4775
4896
  if (!geminiEnabled()) return null;
4776
4897
  const block = geminiCreateGate(state);
4777
4898
  if (block) return block;
4778
- const missing = validateDesignSystem(findDesignSystem(cwd));
4899
+ const ds = findDesignSystem(cwd);
4900
+ if (ds === "") return {
4901
+ kind: "block",
4902
+ title: "Design pipeline",
4903
+ reason: "BLOCKED: design-system.md not found. RECOVERY: 1) Read the identity templates 2) Read design-inspiration.md 3) Browse 4 reference sites 4) Write design-system.md, then retry create_frontend.",
4904
+ actions: ["Create design-system.md via the pipeline, then retry create_frontend"]
4905
+ };
4906
+ const missing = validateDesignSystem(ds);
4779
4907
  if (missing.length) return {
4780
4908
  kind: "block",
4781
4909
  title: "Design pipeline",
@@ -4844,6 +4972,7 @@ async function handlePre(ctx) {
4844
4972
  refs: opts.refsDir ? await loadRefs(opts.refsDir) : void 0,
4845
4973
  isReplaceAll: event.input.replace_all === true,
4846
4974
  agentType: event.agentType,
4975
+ agentId: typeof payload.agent_id === "string" ? payload.agent_id : void 0,
4847
4976
  windowMs: opts.windowMs,
4848
4977
  now: opts.now,
4849
4978
  trackFile: file,
@@ -4900,6 +5029,7 @@ function docSourceOf(tool) {
4900
5029
  if (tool === "WebSearch") return "websearch";
4901
5030
  if (tool === "WebFetch") return "webfetch";
4902
5031
  if (/^mcp__shadcn__/i.test(tool)) return "shadcn-mcp";
5032
+ if (/^mcp__gemini-design__/i.test(tool)) return "gemini-mcp";
4903
5033
  }
4904
5034
  /**
4905
5035
  * Map a live tool-use to the activity to record, or null when nothing is
@@ -113,6 +113,16 @@ declare const SYSTEM_INSTALL: ReadonlyArray<RegExp>;
113
113
  declare const PROJECT_INSTALL: ReadonlyArray<RegExp>;
114
114
  /** True when `cmd` matches any pattern in `patterns`. */
115
115
  declare function matchPatterns(cmd: string, patterns: ReadonlyArray<RegExp>): boolean;
116
+ /** Git commands exempt from confirmation when Ralph mode is on (parity git-guard.py RALPH_SAFE). */
117
+ declare const RALPH_SAFE: ReadonlyArray<string>;
118
+ /**
119
+ * OPT-IN autonomous "Ralph" mode: OFF unless `RALPH_MODE` is `1`/`true`, read
120
+ * fresh on each call. Only the env var activates it — the Python source also
121
+ * auto-enabled on a `.claude/ralph/prd.json` file or a `feature/*` branch, but
122
+ * those silent activations are dropped here: a mode that removes git/install
123
+ * confirmations must never turn on implicitly (owner: default OFF, env opt-in).
124
+ */
125
+ declare function isRalphMode(): boolean;
116
126
  //#endregion
117
127
  //#region src/policy/interfaces/types.d.ts
118
128
  /** Harness-agnostic input to {@link evaluate}. */
@@ -214,7 +224,13 @@ interface LabeledPattern {
214
224
  declare const CRITICAL_PATTERNS: LabeledPattern[];
215
225
  /** Patterns that warrant explicit confirmation before running — parity `security_rules.py`'s ask-level violation names. */
216
226
  declare const ASK_PATTERNS: LabeledPattern[];
217
- /** Guards against dangerous Bash commands (critical → block, sensitive → ask). */
227
+ /**
228
+ * Guards against dangerous Bash commands. Parity `security_rules.validate_command`
229
+ * + `security-guard.py`: ACCUMULATE every matched violation, then deny when any
230
+ * critical matched else ask, joining all violation labels in the reason. The
231
+ * generic `rm` ask is exempt when the command targets a trash location (parity
232
+ * `not re.search('trash', cmd)`).
233
+ */
218
234
  declare function securityGuard(ctx: GuardContext): Prompt | null;
219
235
  //#endregion
220
236
  //#region src/policy/guards/protected-path.d.ts
@@ -323,7 +339,11 @@ declare const JAVA_DECL_RE: RegExp;
323
339
  declare function interfaceSeparationGuard(ctx: GuardContext): Prompt | null;
324
340
  //#endregion
325
341
  //#region src/policy/guards/install.d.ts
326
- /** Asks for confirmation before a dependency or system package install. */
342
+ /**
343
+ * Asks for confirmation before a dependency or system package install. In Ralph
344
+ * mode (opt-in `RALPH_MODE`) a PROJECT install is auto-approved for autonomous
345
+ * runs (parity install-guard.py:52), but a SYSTEM install always asks.
346
+ */
327
347
  declare function installGuard(ctx: GuardContext): Prompt | null;
328
348
  //#endregion
329
349
  //#region src/policy/guards/index.d.ts
@@ -571,4 +591,4 @@ declare function isHtmlLike(path: string): boolean;
571
591
  */
572
592
  declare function missingSeoElements(html: string): string[];
573
593
  //#endregion
574
- export { ASK_PATTERNS as $, FAIL_CLOSED as A, ProjectType as At, SWIFT_PROTO_RE as B, usesTailwindUtilities as C, SOLID_REF as Ct, MAX_TOKENS as D, detectFramework as Dt, MAX_EXA_RESULTS as E, evaluateFileSize as Et, installGuard as F, CODE_MUTATORS as G, interfaceSeparationGuard as H, GO_DECL_RE as I, SAFE_PREFIXES as J, CODE_REDIRECT as K, JAVA_DECL_RE as L, clearUserGuards as M, detectProjectType as Mt, registerGuard as N, isApexCommand as Nt, capVerbosity as O, DEV_KEYWORDS as Ot, runGuards as P, requiredArchSkill as Pt, protectedPathGuard as Q, PHP_DECL_RE as R, skillTriggerGate as S, PLUGINS_DIR as St, frameworkSolidGate as T, countLines as Tt, bashWriteGuard as U, TS_DECL_RE as V, ASK_WRITERS as W, PROTECTED_FRAGMENTS as X, SESSION_STATE_FRAGMENT as Y, PROTECTED_GIT_RE as Z, DEV_VERBS as _, GIT_BLOCKED as _t, firstHeading as a, APEX_GATES as at, detectClaudeMdProjectType as b, matchPatterns as bt, parseEntry as c, brainstormGate as ct, EXCLUDE_DIRS as d, freshnessGate as dt, CRITICAL_PATTERNS as et, PROJECT_INDICATORS as f, solidReadGate as ft, loadApexTaskState as g, GIT_ASK as gt, buildApexTaskInjection as h, PolicyResult as ht, firstComment as i, GuardContext as it, GUARDS as j, detectModularArchitecture as jt, detectCreationIntent as k, ModularArchitecture as kt, parseBodyDesc as l, docConsultedGate as lt, buildApexTaskContext as m, PolicyContext as mt, missingSeoElements as n, securityGuard as nt, TreeEntry as o, ApexContext as ot, ApexTaskState as p, evaluate as pt, FILE_REDIRECT as q, descFromText as r, Guard as rt, parseEnrichment as s, ApexGate as st, isHtmlLike as t, LabeledPattern as tt, parseField as u, evaluateApex as ut, buildApexInstruction as v, PROJECT_INSTALL as vt, SKILL_TRIGGERS as w, countFrameworkCodeLines as wt, detectRequiredSkills as x, FileSizeVerdict as xt, buildClaudeMdContext as y, SYSTEM_INSTALL as yt, PY_MODEL_RE as z };
594
+ export { ASK_PATTERNS as $, FAIL_CLOSED as A, DEV_KEYWORDS as At, SWIFT_PROTO_RE as B, usesTailwindUtilities as C, FileSizeVerdict as Ct, MAX_TOKENS as D, countLines as Dt, MAX_EXA_RESULTS as E, countFrameworkCodeLines as Et, installGuard as F, isApexCommand as Ft, CODE_MUTATORS as G, interfaceSeparationGuard as H, GO_DECL_RE as I, requiredArchSkill as It, SAFE_PREFIXES as J, CODE_REDIRECT as K, JAVA_DECL_RE as L, clearUserGuards as M, ProjectType as Mt, registerGuard as N, detectModularArchitecture as Nt, capVerbosity as O, evaluateFileSize as Ot, runGuards as P, detectProjectType as Pt, protectedPathGuard as Q, PHP_DECL_RE as R, skillTriggerGate as S, matchPatterns as St, frameworkSolidGate as T, SOLID_REF as Tt, bashWriteGuard as U, TS_DECL_RE as V, ASK_WRITERS as W, PROTECTED_FRAGMENTS as X, SESSION_STATE_FRAGMENT as Y, PROTECTED_GIT_RE as Z, DEV_VERBS as _, GIT_BLOCKED as _t, firstHeading as a, APEX_GATES as at, detectClaudeMdProjectType as b, SYSTEM_INSTALL as bt, parseEntry as c, brainstormGate as ct, EXCLUDE_DIRS as d, freshnessGate as dt, CRITICAL_PATTERNS as et, PROJECT_INDICATORS as f, solidReadGate as ft, loadApexTaskState as g, GIT_ASK as gt, buildApexTaskInjection as h, PolicyResult as ht, firstComment as i, GuardContext as it, GUARDS as j, ModularArchitecture as jt, detectCreationIntent as k, detectFramework as kt, parseBodyDesc as l, docConsultedGate as lt, buildApexTaskContext as m, PolicyContext as mt, missingSeoElements as n, securityGuard as nt, TreeEntry as o, ApexContext as ot, ApexTaskState as p, evaluate as pt, FILE_REDIRECT as q, descFromText as r, Guard as rt, parseEnrichment as s, ApexGate as st, isHtmlLike as t, LabeledPattern as tt, parseField as u, evaluateApex as ut, buildApexInstruction as v, PROJECT_INSTALL as vt, SKILL_TRIGGERS as w, PLUGINS_DIR as wt, detectRequiredSkills as x, isRalphMode as xt, buildClaudeMdContext as y, RALPH_SAFE as yt, PY_MODEL_RE as z };
package/dist/index.d.mts CHANGED
@@ -5,10 +5,9 @@ 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-BNfYWvYv.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, At as ProjectType, B as SWIFT_PROTO_RE, C as usesTailwindUtilities, Ct as SOLID_REF, D as MAX_TOKENS, Dt as detectFramework, E as MAX_EXA_RESULTS, Et as evaluateFileSize, 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, Mt as detectProjectType, N as registerGuard, Nt as isApexCommand, O as capVerbosity, Ot as DEV_KEYWORDS, P as runGuards, Pt as requiredArchSkill, Q as protectedPathGuard, R as PHP_DECL_RE, S as skillTriggerGate, St as PLUGINS_DIR, T as frameworkSolidGate, Tt as countLines, 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 GIT_BLOCKED, a as firstHeading, at as APEX_GATES, b as detectClaudeMdProjectType, bt as matchPatterns, c as parseEntry, ct as brainstormGate, d as EXCLUDE_DIRS, dt as freshnessGate, et as CRITICAL_PATTERNS, f as PROJECT_INDICATORS, ft as solidReadGate, g as loadApexTaskState, gt as GIT_ASK, h as buildApexTaskInjection, ht as PolicyResult, i as firstComment, it as GuardContext, j as GUARDS, jt as detectModularArchitecture, k as detectCreationIntent, kt as ModularArchitecture, l as parseBodyDesc, lt as docConsultedGate, m as buildApexTaskContext, mt as PolicyContext, n as missingSeoElements, nt as securityGuard, o as TreeEntry, ot as ApexContext, p as ApexTaskState, pt as evaluate, q as FILE_REDIRECT, r as descFromText, rt as Guard, s as parseEnrichment, st as ApexGate, t as isHtmlLike, tt as LabeledPattern, u as parseField, ut as evaluateApex, v as buildApexInstruction, vt as PROJECT_INSTALL, w as SKILL_TRIGGERS, wt as countFrameworkCodeLines, x as detectRequiredSkills, xt as FileSizeVerdict, y as buildClaudeMdContext, yt as SYSTEM_INSTALL, z as PY_MODEL_RE } from "./index-CVhw7eA0.mjs";
8
+ import { $ as ASK_PATTERNS, A as FAIL_CLOSED, At as DEV_KEYWORDS, B as SWIFT_PROTO_RE, C as usesTailwindUtilities, Ct as FileSizeVerdict, D as MAX_TOKENS, Dt as countLines, E as MAX_EXA_RESULTS, Et as countFrameworkCodeLines, F as installGuard, Ft as isApexCommand, G as CODE_MUTATORS, H as interfaceSeparationGuard, I as GO_DECL_RE, It as requiredArchSkill, J as SAFE_PREFIXES, K as CODE_REDIRECT, L as JAVA_DECL_RE, M as clearUserGuards, Mt as ProjectType, N as registerGuard, Nt as detectModularArchitecture, O as capVerbosity, Ot as evaluateFileSize, P as runGuards, Pt as detectProjectType, Q as protectedPathGuard, R as PHP_DECL_RE, S as skillTriggerGate, St as matchPatterns, T as frameworkSolidGate, Tt as SOLID_REF, 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 GIT_BLOCKED, a as firstHeading, at as APEX_GATES, b as detectClaudeMdProjectType, bt as SYSTEM_INSTALL, c as parseEntry, ct as brainstormGate, d as EXCLUDE_DIRS, dt as freshnessGate, et as CRITICAL_PATTERNS, f as PROJECT_INDICATORS, ft as solidReadGate, g as loadApexTaskState, gt as GIT_ASK, h as buildApexTaskInjection, ht as PolicyResult, i as firstComment, it as GuardContext, j as GUARDS, jt as ModularArchitecture, k as detectCreationIntent, kt as detectFramework, l as parseBodyDesc, lt as docConsultedGate, m as buildApexTaskContext, mt as PolicyContext, n as missingSeoElements, nt as securityGuard, o as TreeEntry, ot as ApexContext, p as ApexTaskState, pt as evaluate, q as FILE_REDIRECT, r as descFromText, rt as Guard, s as parseEnrichment, st as ApexGate, t as isHtmlLike, tt as LabeledPattern, u as parseField, ut as evaluateApex, v as buildApexInstruction, vt as PROJECT_INSTALL, w as SKILL_TRIGGERS, wt as PLUGINS_DIR, x as detectRequiredSkills, xt as isRalphMode, y as buildClaudeMdContext, yt as RALPH_SAFE, z as PY_MODEL_RE } from "./index-l9Xvxrx7.mjs";
9
9
  import { n as RouteResult, r as ScoredRef, t as RefMeta } from "./types-CY5qT2X1.mjs";
10
10
  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";
11
11
  import { a as globToRe, i as scoreReferences, n as toRefMeta, o as parseFrontmatter, r as routeReferences, t as loadRefs } from "./index-mmRF3KNp.mjs";
12
- import { a as taskStart, c as ensureStateDir, d as stateFilePath, f as acquireLock, i as taskCreate, l as loadState, n as ApexTaskFile, o as ApexState, r as taskComplete, s as apexStateDir, t as ApexTask, u as saveState } from "./index-BA-SqNR7.mjs";
13
12
  import { _ as TIME_INTERVALS, a as formatCost, c as formatTokens, d as colors, f as progressiveColor, g as PROGRESS_CHARS, h as PROGRESS_BAR_DEFAULTS, i as formatBasename, l as ColorFn, m as GRADIENT_BLOCKS, n as generateGradientBar, o as formatPath, p as COLOR_THRESHOLDS, r as generateProgressBar, s as formatTimeLeft, t as ProgressBarOptions, u as Palette } from "./index-BWK8slRi.mjs";
14
- export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, ApexContext, ApexGate, ApexState, ApexTask, ApexTaskFile, ApexTaskState, AuthEntry, CODE_MUTATORS, CODE_REDIRECT, COLOR_THRESHOLDS, CRITICAL_PATTERNS, CacheHit, ColorFn, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, DEV_VERBS, DocSatisfactionStatus, EXCLUDE_DIRS, FAIL_CLOSED, FILE_REDIRECT, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GRADIENT_BLOCKS, GUARDS, Guard, GuardContext, HOME_DIR, type HarnessId, type HarnessInfo, type HarnessMode, type HarnessVia, IndexSummary, JAVA_DECL_RE, LabeledPattern, MAX_EXA_RESULTS, MAX_LINES_ENV_KEY, MAX_TOKENS, ModularArchitecture, PHP_DECL_RE, PLUGINS_DIR, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, Palette, type PolicyContext, type PolicyResult, ProgressBarOptions, ProjectLayout, ProjectType, Prompt, PromptKind, RefMeta, ReminderState, RouteResult, SAFE_PREFIXES, SESSION_STATE_FRAGMENT, SKILL_TRIGGERS, SOLID_REF, STATE_GITIGNORE, STATE_ROOT, SWIFT_PROTO_RE, SYSTEM_INSTALL, ScoredRef, TIME_INTERVALS, TS_DECL_RE, TTL_ENV_KEY, TreeEntry, acquireLock, addRoot, apexStateDir, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, cacheLookup, cacheLookupMeta, cacheLookupSubstring, cacheLookupSubstringMeta, cachePath, cacheStore, capVerbosity, clearUserGuards, colors, compactJson, compactMarkdown, countFrameworkCodeLines, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectHarness, detectMode, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, ensureMemoryGitignore, ensureStateDir, envCandidates, evaluate, evaluateApex, evaluateFileSize, extractText, firstComment, firstHeading, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, frameworkSolidGate, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, installGuard, interfaceSeparationGuard, isApexCommand, isCodeFile, isDocConsulted, isHtmlLike, jaccardSimilar, lessonsFileFor, loadApexTaskState, loadDotenv, loadIndex, loadRefs, loadState, matchPatterns, mcpCacheKey, mcpCacheWrite, missingSeoElements, modeFor, nowStamp, parseBodyDesc, parseEnrichment, parseEntry, parseEnvFile, parseEnvInt, parseField, parseFrontmatter, progressiveColor, projectLayout, projectRoot, projectRootOrNull, protectedPathGuard, queryHash, readRoots, readState, registerGuard, registryFile, requiredArchSkill, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, runGuards, saveState, scoreReferences, securityGuard, setStateField, skillTriggerGate, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, toRefMeta, ttlLabel, usesTailwindUtilities, walkUpFor, webfetchCacheWrite };
13
+ export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, ApexContext, ApexGate, ApexTaskState, AuthEntry, CODE_MUTATORS, CODE_REDIRECT, COLOR_THRESHOLDS, CRITICAL_PATTERNS, CacheHit, ColorFn, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, DEV_VERBS, DocSatisfactionStatus, EXCLUDE_DIRS, FAIL_CLOSED, FILE_REDIRECT, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GRADIENT_BLOCKS, GUARDS, Guard, GuardContext, HOME_DIR, type HarnessId, type HarnessInfo, type HarnessMode, type HarnessVia, IndexSummary, JAVA_DECL_RE, LabeledPattern, MAX_EXA_RESULTS, MAX_LINES_ENV_KEY, MAX_TOKENS, ModularArchitecture, PHP_DECL_RE, PLUGINS_DIR, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, Palette, type PolicyContext, type PolicyResult, ProgressBarOptions, ProjectLayout, ProjectType, Prompt, PromptKind, RALPH_SAFE, RefMeta, ReminderState, RouteResult, SAFE_PREFIXES, SESSION_STATE_FRAGMENT, SKILL_TRIGGERS, SOLID_REF, STATE_GITIGNORE, STATE_ROOT, SWIFT_PROTO_RE, SYSTEM_INSTALL, ScoredRef, TIME_INTERVALS, TS_DECL_RE, TTL_ENV_KEY, TreeEntry, addRoot, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, cacheLookup, cacheLookupMeta, cacheLookupSubstring, cacheLookupSubstringMeta, cachePath, cacheStore, capVerbosity, clearUserGuards, colors, compactJson, compactMarkdown, countFrameworkCodeLines, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectHarness, detectMode, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, ensureMemoryGitignore, envCandidates, evaluate, evaluateApex, evaluateFileSize, extractText, firstComment, firstHeading, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, frameworkSolidGate, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, installGuard, interfaceSeparationGuard, isApexCommand, isCodeFile, isDocConsulted, isHtmlLike, isRalphMode, jaccardSimilar, lessonsFileFor, loadApexTaskState, loadDotenv, loadIndex, loadRefs, matchPatterns, mcpCacheKey, mcpCacheWrite, missingSeoElements, modeFor, nowStamp, parseBodyDesc, parseEnrichment, parseEntry, parseEnvFile, parseEnvInt, parseField, parseFrontmatter, progressiveColor, projectLayout, projectRoot, projectRootOrNull, protectedPathGuard, queryHash, readRoots, readState, registerGuard, registryFile, requiredArchSkill, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, runGuards, scoreReferences, securityGuard, setStateField, skillTriggerGate, solidReadGate, splitTarget, stateFileFor, summarizeIndex, throttleMs, toRefMeta, ttlLabel, usesTailwindUtilities, walkUpFor, webfetchCacheWrite };
package/dist/index.mjs CHANGED
@@ -4,8 +4,8 @@ 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-C8Nxxyn_.mjs";
7
- import { A as detectCreationIntent, B as detectProjectType, D as MAX_EXA_RESULTS, E as frameworkSolidGate, F as freshnessGate, H as requiredArchSkill, I as solidReadGate, L as detectFramework, M as brainstormGate, N as docConsultedGate, O as MAX_TOKENS, P as evaluateApex, R as DEV_KEYWORDS, S as usesTailwindUtilities, T as SKILL_TRIGGERS, V as isApexCommand, 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, x as skillTriggerGate, y as parseField, z as detectModularArchitecture } from "./validate-DcQaKzau.mjs";
8
- import { A as PROJECT_INSTALL, C as PROTECTED_GIT_RE, D as securityGuard, E as CRITICAL_PATTERNS, F as countFrameworkCodeLines, I as countLines, L as evaluateFileSize, M as matchPatterns, N as PLUGINS_DIR, O as GIT_ASK, P as SOLID_REF, 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 SYSTEM_INSTALL, 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-d7Pp8XJH.mjs";
7
+ import { A as MAX_EXA_RESULTS, B as detectFramework, D as frameworkSolidGate, E as SKILL_TRIGGERS, F as brainstormGate, G as requiredArchSkill, H as detectModularArchitecture, I as docConsultedGate, L as evaluateApex, M as capVerbosity, N as detectCreationIntent, P as APEX_GATES, R as freshnessGate, S as usesTailwindUtilities, U as detectProjectType, V as DEV_KEYWORDS, W as isApexCommand, 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 MAX_TOKENS, 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, x as skillTriggerGate, y as parseField, z as solidReadGate } from "./validate-DVV4nRfr.mjs";
8
+ import { A as PROJECT_INSTALL, C as PROTECTED_GIT_RE, D as securityGuard, E as CRITICAL_PATTERNS, F as PLUGINS_DIR, I as SOLID_REF, L as countFrameworkCodeLines, M as SYSTEM_INSTALL, N as isRalphMode, O as GIT_ASK, P as matchPatterns, R as countLines, 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, z as evaluateFileSize } from "./evaluate-qYC5xClb.mjs";
9
9
  import { i as resolveSessions, n as formatDocSatisfactionStatus, r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-CWZegVdR.mjs";
10
10
  import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./router-PKVNBHge.mjs";
11
11
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
@@ -13,6 +13,5 @@ import { a as nowStamp, c as stateFileFor, i as lessonsFileFor, l as throttleMs,
13
13
  import { a as cacheLookupSubstring, c as cacheStore, d as loadIndex, f as summarizeIndex, h as queryHash, i as cacheLookupMeta, l as mcpCacheKey, m as jaccardSimilar, n as webfetchCacheWrite, o as cacheLookupSubstringMeta, p as compactMarkdown, r as cacheLookup, s as cachePath, t as mcpCacheWrite, u as extractText } from "./mcp-store-BkBDmuxN.mjs";
14
14
  import { t as incrementTrivialEditCounter } from "./freshness-BV3PQkDB.mjs";
15
15
  import { n as toRefMeta, t as loadRefs } from "./loader-AGz4nK7d.mjs";
16
- 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-9lWvvWk8.mjs";
17
16
  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";
18
- export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, COLOR_THRESHOLDS, CRITICAL_PATTERNS, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, FILE_REDIRECT, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GRADIENT_BLOCKS, GUARDS, HOME_DIR, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_LINES_ENV_KEY, MAX_TOKENS, PHP_DECL_RE, PLUGINS_DIR, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, SAFE_PREFIXES, SESSION_STATE_FRAGMENT, SKILL_TRIGGERS, SOLID_REF, STATE_GITIGNORE, STATE_ROOT, SWIFT_PROTO_RE, SYSTEM_INSTALL, TIME_INTERVALS, TS_DECL_RE, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, cacheLookup, cacheLookupMeta, cacheLookupSubstring, cacheLookupSubstringMeta, cachePath, cacheStore, capVerbosity, clearUserGuards, colors, compactJson, compactMarkdown, countFrameworkCodeLines, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectHarness, detectMode, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, ensureMemoryGitignore, ensureStateDir, envCandidates, evaluate, evaluateApex, evaluateFileSize, extractText, firstComment, firstHeading, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, frameworkSolidGate, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, installGuard, interfaceSeparationGuard, isApexCommand, isCodeFile, isDocConsulted, isHtmlLike, jaccardSimilar, lessonsFileFor, loadApexTaskState, loadDotenv, loadIndex, loadRefs, loadState, matchPatterns, mcpCacheKey, mcpCacheWrite, missingSeoElements, modeFor, nowStamp, parseBodyDesc, parseEnrichment, parseEntry, parseEnvFile, parseEnvInt, parseField, parseFrontmatter, progressiveColor, projectLayout, projectRoot, projectRootOrNull, protectedPathGuard, queryHash, readRoots, readState, registerGuard, registryFile, requiredArchSkill, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, runGuards, saveState, scoreReferences, securityGuard, setStateField, skillTriggerGate, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, toRefMeta, ttlLabel, usesTailwindUtilities, walkUpFor, webfetchCacheWrite };
17
+ export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, COLOR_THRESHOLDS, CRITICAL_PATTERNS, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, FILE_REDIRECT, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GRADIENT_BLOCKS, GUARDS, HOME_DIR, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_LINES_ENV_KEY, MAX_TOKENS, PHP_DECL_RE, PLUGINS_DIR, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, RALPH_SAFE, SAFE_PREFIXES, SESSION_STATE_FRAGMENT, SKILL_TRIGGERS, SOLID_REF, STATE_GITIGNORE, STATE_ROOT, SWIFT_PROTO_RE, SYSTEM_INSTALL, TIME_INTERVALS, TS_DECL_RE, TTL_ENV_KEY, addRoot, bashWriteGuard, brainstormGate, buildApexInstruction, buildApexTaskContext, buildApexTaskInjection, buildClaudeMdContext, cacheLookup, cacheLookupMeta, cacheLookupSubstring, cacheLookupSubstringMeta, cachePath, cacheStore, capVerbosity, clearUserGuards, colors, compactJson, compactMarkdown, countFrameworkCodeLines, countLines, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectHarness, detectMode, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, ensureMemoryGitignore, envCandidates, evaluate, evaluateApex, evaluateFileSize, extractText, firstComment, firstHeading, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, frameworkSolidGate, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, installGuard, interfaceSeparationGuard, isApexCommand, isCodeFile, isDocConsulted, isHtmlLike, isRalphMode, jaccardSimilar, lessonsFileFor, loadApexTaskState, loadDotenv, loadIndex, loadRefs, matchPatterns, mcpCacheKey, mcpCacheWrite, missingSeoElements, modeFor, nowStamp, parseBodyDesc, parseEnrichment, parseEntry, parseEnvFile, parseEnvInt, parseField, parseFrontmatter, progressiveColor, projectLayout, projectRoot, projectRootOrNull, protectedPathGuard, queryHash, readRoots, readState, registerGuard, registryFile, requiredArchSkill, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, runGuards, scoreReferences, securityGuard, setStateField, skillTriggerGate, solidReadGate, splitTarget, stateFileFor, summarizeIndex, throttleMs, toRefMeta, ttlLabel, usesTailwindUtilities, walkUpFor, webfetchCacheWrite };
@@ -1,2 +1,2 @@
1
- import { $ as ASK_PATTERNS, A as FAIL_CLOSED, At as ProjectType, B as SWIFT_PROTO_RE, C as usesTailwindUtilities, Ct as SOLID_REF, D as MAX_TOKENS, Dt as detectFramework, E as MAX_EXA_RESULTS, Et as evaluateFileSize, 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, Mt as detectProjectType, N as registerGuard, Nt as isApexCommand, O as capVerbosity, Ot as DEV_KEYWORDS, P as runGuards, Pt as requiredArchSkill, Q as protectedPathGuard, R as PHP_DECL_RE, S as skillTriggerGate, St as PLUGINS_DIR, T as frameworkSolidGate, Tt as countLines, 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 GIT_BLOCKED, a as firstHeading, at as APEX_GATES, b as detectClaudeMdProjectType, bt as matchPatterns, c as parseEntry, ct as brainstormGate, d as EXCLUDE_DIRS, dt as freshnessGate, et as CRITICAL_PATTERNS, f as PROJECT_INDICATORS, ft as solidReadGate, g as loadApexTaskState, gt as GIT_ASK, h as buildApexTaskInjection, ht as PolicyResult, i as firstComment, it as GuardContext, j as GUARDS, jt as detectModularArchitecture, k as detectCreationIntent, kt as ModularArchitecture, l as parseBodyDesc, lt as docConsultedGate, m as buildApexTaskContext, mt as PolicyContext, n as missingSeoElements, nt as securityGuard, o as TreeEntry, ot as ApexContext, p as ApexTaskState, pt as evaluate, q as FILE_REDIRECT, r as descFromText, rt as Guard, s as parseEnrichment, st as ApexGate, t as isHtmlLike, tt as LabeledPattern, u as parseField, ut as evaluateApex, v as buildApexInstruction, vt as PROJECT_INSTALL, w as SKILL_TRIGGERS, wt as countFrameworkCodeLines, x as detectRequiredSkills, xt as FileSizeVerdict, y as buildClaudeMdContext, yt as SYSTEM_INSTALL, z as PY_MODEL_RE } from "../index-CVhw7eA0.mjs";
2
- 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, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, type PolicyContext, type PolicyResult, ProjectType, 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, loadApexTaskState, matchPatterns, missingSeoElements, parseBodyDesc, parseEnrichment, parseEntry, parseField, protectedPathGuard, registerGuard, requiredArchSkill, runGuards, securityGuard, skillTriggerGate, solidReadGate, usesTailwindUtilities };
1
+ import { $ as ASK_PATTERNS, A as FAIL_CLOSED, At as DEV_KEYWORDS, B as SWIFT_PROTO_RE, C as usesTailwindUtilities, Ct as FileSizeVerdict, D as MAX_TOKENS, Dt as countLines, E as MAX_EXA_RESULTS, Et as countFrameworkCodeLines, F as installGuard, Ft as isApexCommand, G as CODE_MUTATORS, H as interfaceSeparationGuard, I as GO_DECL_RE, It as requiredArchSkill, J as SAFE_PREFIXES, K as CODE_REDIRECT, L as JAVA_DECL_RE, M as clearUserGuards, Mt as ProjectType, N as registerGuard, Nt as detectModularArchitecture, O as capVerbosity, Ot as evaluateFileSize, P as runGuards, Pt as detectProjectType, Q as protectedPathGuard, R as PHP_DECL_RE, S as skillTriggerGate, St as matchPatterns, T as frameworkSolidGate, Tt as SOLID_REF, 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 GIT_BLOCKED, a as firstHeading, at as APEX_GATES, b as detectClaudeMdProjectType, bt as SYSTEM_INSTALL, c as parseEntry, ct as brainstormGate, d as EXCLUDE_DIRS, dt as freshnessGate, et as CRITICAL_PATTERNS, f as PROJECT_INDICATORS, ft as solidReadGate, g as loadApexTaskState, gt as GIT_ASK, h as buildApexTaskInjection, ht as PolicyResult, i as firstComment, it as GuardContext, j as GUARDS, jt as ModularArchitecture, k as detectCreationIntent, kt as detectFramework, l as parseBodyDesc, lt as docConsultedGate, m as buildApexTaskContext, mt as PolicyContext, n as missingSeoElements, nt as securityGuard, o as TreeEntry, ot as ApexContext, p as ApexTaskState, pt as evaluate, q as FILE_REDIRECT, r as descFromText, rt as Guard, s as parseEnrichment, st as ApexGate, t as isHtmlLike, tt as LabeledPattern, u as parseField, ut as evaluateApex, v as buildApexInstruction, vt as PROJECT_INSTALL, w as SKILL_TRIGGERS, wt as PLUGINS_DIR, x as detectRequiredSkills, xt as isRalphMode, y as buildClaudeMdContext, yt as RALPH_SAFE, z as PY_MODEL_RE } from "../index-l9Xvxrx7.mjs";
2
+ 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, 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,4 +1,4 @@
1
- import { A as detectCreationIntent, B as detectProjectType, D as MAX_EXA_RESULTS, E as frameworkSolidGate, F as freshnessGate, H as requiredArchSkill, I as solidReadGate, L as detectFramework, M as brainstormGate, N as docConsultedGate, O as MAX_TOKENS, P as evaluateApex, R as DEV_KEYWORDS, S as usesTailwindUtilities, T as SKILL_TRIGGERS, V as isApexCommand, 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, x as skillTriggerGate, y as parseField, z as detectModularArchitecture } from "../validate-DcQaKzau.mjs";
2
- import { A as PROJECT_INSTALL, C as PROTECTED_GIT_RE, D as securityGuard, E as CRITICAL_PATTERNS, F as countFrameworkCodeLines, I as countLines, L as evaluateFileSize, M as matchPatterns, N as PLUGINS_DIR, O as GIT_ASK, P as SOLID_REF, 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 SYSTEM_INSTALL, 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-d7Pp8XJH.mjs";
1
+ import { A as MAX_EXA_RESULTS, B as detectFramework, D as frameworkSolidGate, E as SKILL_TRIGGERS, F as brainstormGate, G as requiredArchSkill, H as detectModularArchitecture, I as docConsultedGate, L as evaluateApex, M as capVerbosity, N as detectCreationIntent, P as APEX_GATES, R as freshnessGate, S as usesTailwindUtilities, U as detectProjectType, V as DEV_KEYWORDS, W as isApexCommand, 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 MAX_TOKENS, 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, x as skillTriggerGate, y as parseField, z as solidReadGate } from "../validate-DVV4nRfr.mjs";
2
+ import { A as PROJECT_INSTALL, C as PROTECTED_GIT_RE, D as securityGuard, E as CRITICAL_PATTERNS, F as PLUGINS_DIR, I as SOLID_REF, L as countFrameworkCodeLines, M as SYSTEM_INSTALL, N as isRalphMode, O as GIT_ASK, P as matchPatterns, R as countLines, 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, z as evaluateFileSize } from "../evaluate-qYC5xClb.mjs";
3
3
  import "../policy-la_KkjCS.mjs";
4
- 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, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, 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, loadApexTaskState, matchPatterns, missingSeoElements, parseBodyDesc, parseEnrichment, parseEntry, parseField, protectedPathGuard, registerGuard, requiredArchSkill, runGuards, securityGuard, skillTriggerGate, solidReadGate, usesTailwindUtilities };
4
+ 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, 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-d7Pp8XJH.mjs";
2
+ import { t as evaluate } from "./evaluate-qYC5xClb.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
@@ -96,6 +96,8 @@ interface GateInput {
96
96
  windowMs?: number;
97
97
  isReplaceAll?: boolean;
98
98
  agentType?: string;
99
+ /** Claude `agent_id` when the tool-use comes from a subagent (parity require-apex-agents.py:41 — subagents inherit the lead's brainstorm decision). */
100
+ agentId?: string;
99
101
  /** Absolute path to the session transcript (Claude `transcript_path`) for evidence-based freshness. */
100
102
  transcriptPath?: string;
101
103
  }
@@ -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-mKZxP4oZ.mjs";
3
- import { $ as saveApexState, A as trackSkillRead, At as securityStateDir, B as writePluginMap, C as seoPostToolUse, Ct as defaultStateDir, D as postTrackingSideEffects, Dt as isoUtc, E as securityAdvisory, Et as normalizeEvent, F as dispatchLessons, G as mergeLines, H as isProject, I as lessonsFileFor, J as listChildren, K as countFiles, L as lessonsStateFileFor, M as dispatchLifecycle, Mt as todayUtc, N as aipilotPostToolUse, O as trackWatchResearch, Ot as loadSecurityState, P as dispatchAipilot, Q as cleanupSession, R as cartoSessionStart, S as postEditContext, St as taskContext, T as dispatchMemory, Tt as trackFile, U as writeTree, V as generateProjectMap, W as loadEnriched, X as trackSessionChanges, Y as postEditTypescript, Z as validateRulesLoaded, _ as preCommitGate, _t as trimLogFile, a as recordActivity, at as validateSolidGate, b as extractSymbols, bt as projectContext, c as MCP_TTL_MS, ct as detectSolidProfile, d as isMcpTool, dt as readRules, et as logToolFailure, f as queryOf, ft as runSessionStartCleanups, g as gate, gt as removeOldFiles, h as TRIVIAL_BUDGET, ht as purgeTtlTree, i as respond, it as validateTailwind, j as trackEnrichment, jt as securityStatePath, k as trackMcpResearch, kt as saveSecurityState, l as WEBFETCH_TTL_MS, lt as solidDetectStart, m as REQUIRED_AGENTS, mt as pruneEmptyDirs, n as activityFor, nt as trackAgentMemory, o as mcpPostStore, ot as checkFileSize, p as DEFAULT_WINDOW_MS, pt as sessionStartCore, q as getFileDesc, r as handlePre, rt as subagentCacheContext, s as mcpPreIntercept, st as countLoc, t as handleHook, tt as validateTeammateOutput, u as cacheQueryOf, ut as injectRules, v as detectDuplication, vt as devContext, w as seoPostToolUseResponse, wt as projectHash, x as lifecycleStdout, xt as promptSubmitContext, y as dryGate, yt as gitContext, z as generateEcosystemMap } from "../handle-DJaaD2BT.mjs";
3
+ import { $ as saveApexState, A as trackSkillRead, At as securityStateDir, B as writePluginMap, C as seoPostToolUse, Ct as defaultStateDir, D as postTrackingSideEffects, Dt as isoUtc, E as securityAdvisory, Et as normalizeEvent, F as dispatchLessons, G as mergeLines, H as isProject, I as lessonsFileFor, J as listChildren, K as countFiles, L as lessonsStateFileFor, M as dispatchLifecycle, Mt as todayUtc, N as aipilotPostToolUse, O as trackWatchResearch, Ot as loadSecurityState, P as dispatchAipilot, Q as cleanupSession, R as cartoSessionStart, S as postEditContext, St as taskContext, T as dispatchMemory, Tt as trackFile, U as writeTree, V as generateProjectMap, W as loadEnriched, X as trackSessionChanges, Y as postEditTypescript, Z as validateRulesLoaded, _ as preCommitGate, _t as trimLogFile, a as recordActivity, at as validateSolidGate, b as extractSymbols, bt as projectContext, c as MCP_TTL_MS, ct as detectSolidProfile, d as isMcpTool, dt as readRules, et as logToolFailure, f as queryOf, ft as runSessionStartCleanups, g as gate, gt as removeOldFiles, h as TRIVIAL_BUDGET, ht as purgeTtlTree, i as respond, it as validateTailwind, j as trackEnrichment, jt as securityStatePath, k as trackMcpResearch, kt as saveSecurityState, l as WEBFETCH_TTL_MS, lt as solidDetectStart, m as REQUIRED_AGENTS, mt as pruneEmptyDirs, n as activityFor, nt as trackAgentMemory, o as mcpPostStore, ot as checkFileSize, p as DEFAULT_WINDOW_MS, pt as sessionStartCore, q as getFileDesc, r as handlePre, rt as subagentCacheContext, s as mcpPreIntercept, st as countLoc, t as handleHook, tt as validateTeammateOutput, u as cacheQueryOf, ut as injectRules, v as detectDuplication, vt as devContext, w as seoPostToolUseResponse, wt as projectHash, x as lifecycleStdout, xt as promptSubmitContext, y as dryGate, yt as gitContext, z as generateEcosystemMap } from "../handle-DUlUbhyF.mjs";
4
4
  //#region src/runtime/storage.ts
5
5
  /**
6
6
  * The project's single state dir (`<root>/.harness`) — neutral + harness-agnostic,
@@ -1,7 +1,7 @@
1
1
  import { r as resolveMaxLines } from "./limits-CHn8AIL1.mjs";
2
2
  import { c as ttlLabel, t as HOME_DIR } from "./dotenv-B9nM4cuQ.mjs";
3
3
  import { t as detectHarness } from "./harness-C8Nxxyn_.mjs";
4
- import { F as countFrameworkCodeLines, N as PLUGINS_DIR, P as SOLID_REF } from "./evaluate-d7Pp8XJH.mjs";
4
+ import { F as PLUGINS_DIR, I as SOLID_REF, L as countFrameworkCodeLines } from "./evaluate-qYC5xClb.mjs";
5
5
  import { r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-CWZegVdR.mjs";
6
6
  import { t as routeReferences } from "./router-PKVNBHge.mjs";
7
7
  import { extname, join } from "node:path";
@@ -95,7 +95,7 @@ function detectProjectType(dir) {
95
95
  */
96
96
  function detectFramework(filePath, content) {
97
97
  if (/\.(tsx?|jsx?|vue|svelte)$/.test(filePath) || /from ['"]react|useState|className=/.test(content)) {
98
- if (/(page|layout|loading|error|route)\.(ts|tsx)$/.test(filePath) || /use client|use server/.test(content)) return "nextjs";
98
+ if (/(page|layout|loading|error|route|middleware)\.(ts|tsx)$/.test(filePath) || /use client|use server|NextRequest|NextResponse|from ['"]next|getServerSideProps|getStaticProps/.test(content)) return "nextjs";
99
99
  return "react";
100
100
  }
101
101
  if (/\.swift$/.test(filePath)) return "swift";
@@ -124,7 +124,7 @@ const solidReadGate = (ctx) => {
124
124
  };
125
125
  }
126
126
  const read = new Set(ctx.refsRead ?? []);
127
- const missing = routed.required.map((r) => r.meta.filePath).filter((p) => !read.has(p));
127
+ const missing = !!routed.skillPath && read.has(routed.skillPath) ? [] : routed.required.map((r) => r.meta.filePath).filter((p) => !read.has(p));
128
128
  if (missing.length === 0) return null;
129
129
  const optional = routed.optional.map((r) => r.meta.filePath);
130
130
  const reason = [
@@ -232,8 +232,8 @@ function capVerbosity(tool, input) {
232
232
  }
233
233
  //#endregion
234
234
  //#region src/policy/framework-solid-exclude.ts
235
- /** Build-output / dependency paths excluded from React/Next.js SOLID gating. */
236
- const JS_EXCLUDE_RE = /(node_modules|dist|build|\.next)/;
235
+ /** Build/dep paths excluded from React/Next.js SOLID gating — segment-anchored (parity `r"/(node_modules|dist|build|\.next)/"`), NOT a bare substring, so `distance.ts`/`rebuild/` stay gated. */
236
+ const JS_EXCLUDE_RE = /(^|\/)(node_modules|dist|build|\.next)(\/|$)/;
237
237
  /** Vendored dependency paths excluded from Laravel/PHP SOLID gating. */
238
238
  const PHP_EXCLUDE_RE = /\/vendor\//;
239
239
  /** Derived/build artifact paths excluded from Swift SOLID gating. */
@@ -945,6 +945,12 @@ function usesTailwindUtilities(filePath, content) {
945
945
  * @returns a `block` Prompt naming the missing sub-skills, or `null` when satisfied.
946
946
  */
947
947
  function skillTriggerGate(framework, content, refsRead, forcedSkill, cwd, filePath) {
948
+ if (forcedSkill === "fusecore" && !refsRead.some((r) => r.includes("skills/fusecore/"))) return {
949
+ kind: "block",
950
+ title: "FuseCore skill not consulted",
951
+ reason: "BLOCKED: FuseCore project detected. Read the FuseCore skill before writing code in FuseCore modules.",
952
+ actions: [`Read ${resolveSkillPath("fusecore")}`]
953
+ };
948
954
  let required = detectRequiredSkills(framework, content);
949
955
  if (framework !== "tailwind" && filePath && usesTailwindUtilities(filePath, content)) required = [...required, ...detectRequiredSkills("tailwind", content)];
950
956
  if (forcedSkill && !required.includes(forcedSkill)) required.push(forcedSkill);
@@ -1243,7 +1249,7 @@ function buildClaudeMdContext(prompt, cwd) {
1243
1249
  } catch {
1244
1250
  return null;
1245
1251
  }
1246
- if (!DEV_VERBS.test(prompt)) return `# CLAUDE.md\n${claudeContent}`;
1252
+ if (!DEV_VERBS.test(prompt) && !DEV_KEYWORDS.test(prompt)) return `# CLAUDE.md\n${claudeContent}`;
1247
1253
  return `${buildApexInstruction(detectClaudeMdProjectType(cwd), resolveMaxLines())}\n\n# CLAUDE.md\n${claudeContent}`;
1248
1254
  }
1249
1255
  //#endregion
@@ -1539,4 +1545,4 @@ function missingSeoElements(html) {
1539
1545
  return missing;
1540
1546
  }
1541
1547
  //#endregion
1542
- export { detectCreationIntent as A, detectProjectType as B, findMarketplacePlugins as C, MAX_EXA_RESULTS as D, frameworkSolidGate as E, freshnessGate as F, requiredArchSkill as H, solidReadGate as I, detectFramework as L, brainstormGate as M, docConsultedGate as N, MAX_TOKENS as O, evaluateApex as P, DEV_KEYWORDS as R, usesTailwindUtilities as S, SKILL_TRIGGERS as T, isApexCommand as V, scanPlugin as _, firstHeading as a, detectRequiredSkills as b, EXCLUDE_DIRS as c, buildApexTaskInjection as d, loadApexTaskState as f, detectClaudeMdProjectType as g, buildClaudeMdContext as h, firstComment as i, APEX_GATES as j, capVerbosity as k, PROJECT_INDICATORS as l, buildApexInstruction as m, missingSeoElements as n, parseEnrichment as o, DEV_VERBS as p, descFromText as r, parseEntry as s, isHtmlLike as t, buildApexTaskContext as u, parseBodyDesc as v, readPluginMeta as w, skillTriggerGate as x, parseField as y, detectModularArchitecture as z };
1548
+ export { MAX_EXA_RESULTS as A, detectFramework as B, resolveSkillPath as C, frameworkSolidGate as D, SKILL_TRIGGERS as E, brainstormGate as F, requiredArchSkill as G, detectModularArchitecture as H, docConsultedGate as I, evaluateApex as L, capVerbosity as M, detectCreationIntent as N, isExcludedJsPath as O, APEX_GATES as P, freshnessGate as R, usesTailwindUtilities as S, readPluginMeta as T, detectProjectType as U, DEV_KEYWORDS as V, isApexCommand as W, scanPlugin as _, firstHeading as a, detectRequiredSkills as b, EXCLUDE_DIRS as c, buildApexTaskInjection as d, loadApexTaskState as f, detectClaudeMdProjectType as g, buildClaudeMdContext as h, firstComment as i, MAX_TOKENS as j, isExcludedSwiftPath as k, PROJECT_INDICATORS as l, buildApexInstruction as m, missingSeoElements as n, parseEnrichment as o, DEV_VERBS as p, descFromText as r, parseEntry as s, isHtmlLike as t, buildApexTaskContext as u, parseBodyDesc as v, findMarketplacePlugins as w, skillTriggerGate as x, parseField as y, solidReadGate as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/harness",
3
- "version": "0.1.45",
3
+ "version": "0.1.47",
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",
@@ -59,11 +59,6 @@
59
59
  "types": "./dist/refs/index.d.mts",
60
60
  "import": "./dist/refs/index.mjs"
61
61
  },
62
- "./state": {
63
- "bun": "./src/state/index.ts",
64
- "types": "./dist/state/index.d.mts",
65
- "import": "./dist/state/index.mjs"
66
- },
67
62
  "./statusline": {
68
63
  "bun": "./src/statusline/index.ts",
69
64
  "types": "./dist/statusline/index.d.mts",
@@ -132,7 +127,7 @@
132
127
  "test": "bun test",
133
128
  "typecheck": "tsc --noEmit",
134
129
  "docs:api": "typedoc",
135
- "build": "tsdown src/index.ts src/config/index.ts src/util/index.ts src/detect/index.ts src/policy/index.ts src/prompt/index.ts src/memory/index.ts src/cache/index.ts src/freshness/index.ts src/refs/index.ts src/state/index.ts src/statusline/index.ts src/cli/index.ts src/cli/bin.ts src/init/index.ts src/tracking/index.ts src/runtime/index.ts src/adapters/claude/index.ts src/adapters/codex/index.ts src/adapters/cursor/index.ts src/adapters/cline/index.ts src/adapters/gemini/index.ts --dts --format esm --clean --out-dir dist",
130
+ "build": "tsdown src/index.ts src/config/index.ts src/util/index.ts src/detect/index.ts src/policy/index.ts src/prompt/index.ts src/memory/index.ts src/cache/index.ts src/freshness/index.ts src/refs/index.ts src/statusline/index.ts src/cli/index.ts src/cli/bin.ts src/init/index.ts src/tracking/index.ts src/runtime/index.ts src/adapters/claude/index.ts src/adapters/codex/index.ts src/adapters/cursor/index.ts src/adapters/cline/index.ts src/adapters/gemini/index.ts --dts --format esm --clean --out-dir dist",
136
131
  "prepublishOnly": "bun test && tsc --noEmit && bun run build"
137
132
  },
138
133
  "publishConfig": {
@@ -1,59 +0,0 @@
1
- import { t as AuthEntry } from "./doc-helpers-BNfYWvYv.mjs";
2
-
3
- //#region src/state/lock.d.ts
4
- /**
5
- * Acquire a directory-based lock (atomic `mkdir`, EEXIST = already held) with a timeout.
6
- * @returns a release function, or null if the lock could not be acquired in time.
7
- */
8
- declare function acquireLock(lockDir: string, timeoutMs?: number): Promise<(() => Promise<void>) | null>;
9
- //#endregion
10
- //#region src/state/apex-state.d.ts
11
- declare const DEFAULT_STATE: {
12
- $schema: string;
13
- description: string;
14
- target: Record<string, string>;
15
- authorizations: Record<string, AuthEntry & {
16
- doc_consulted?: string;
17
- }>;
18
- };
19
- /** APEX state shape. */
20
- type ApexState = typeof DEFAULT_STATE;
21
- /** APEX state directory under a home dir. */
22
- declare function apexStateDir(home?: string): string;
23
- /** Daily state file path: `<home>/.claude/logs/00-apex/<YYYY-MM-DD>-state.json`. */
24
- declare function stateFilePath(home?: string, today?: string): string;
25
- /** Ensure the state directory exists and return its path. */
26
- declare function ensureStateDir(home?: string): Promise<string>;
27
- /** Load APEX state, or a fresh default. */
28
- declare function loadState(path: string): Promise<ApexState>;
29
- /** Save APEX state. */
30
- declare function saveState(path: string, state: ApexState): Promise<void>;
31
- //#endregion
32
- //#region src/state/task-helpers.d.ts
33
- /** A task entry in task.json. */
34
- interface ApexTask {
35
- subject: string;
36
- description: string;
37
- status: string;
38
- phase: string;
39
- started_at?: string;
40
- completed_at?: string;
41
- created_at?: string;
42
- doc_consulted: Record<string, unknown>;
43
- files_modified: string[];
44
- blockedBy?: string[];
45
- }
46
- /** Structure of `.claude/apex/task.json`. */
47
- interface ApexTaskFile {
48
- current_task: string;
49
- created_at: string;
50
- tasks: Record<string, ApexTask>;
51
- }
52
- /** Add a new pending task. */
53
- declare function taskCreate(file: string, id: string, subject: string, desc: string): Promise<void>;
54
- /** Mark a task in_progress (creating a stub if absent). */
55
- declare function taskStart(file: string, id: string, subject?: string, desc?: string, blocked?: string): Promise<void>;
56
- /** Mark a task completed. */
57
- declare function taskComplete(file: string, id: string): Promise<void>;
58
- //#endregion
59
- export { taskStart as a, ensureStateDir as c, stateFilePath as d, acquireLock as f, taskCreate as i, loadState as l, ApexTaskFile as n, ApexState as o, taskComplete as r, apexStateDir as s, ApexTask as t, saveState as u };
@@ -1,2 +0,0 @@
1
- import { a as taskStart, c as ensureStateDir, d as stateFilePath, f as acquireLock, i as taskCreate, l as loadState, n as ApexTaskFile, o as ApexState, r as taskComplete, s as apexStateDir, t as ApexTask, u as saveState } from "../index-BA-SqNR7.mjs";
2
- export { ApexState, ApexTask, ApexTaskFile, acquireLock, apexStateDir, ensureStateDir, loadState, saveState, stateFilePath, taskComplete, taskCreate, taskStart };
@@ -1,2 +0,0 @@
1
- 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-9lWvvWk8.mjs";
2
- export { acquireLock, apexStateDir, ensureStateDir, loadState, saveState, stateFilePath, taskComplete, taskCreate, taskStart };
@@ -1,104 +0,0 @@
1
- import { a as writeJsonFile, i as readJsonFile, n as ensureDir } from "./json-io-DisYd2fb.mjs";
2
- import { mkdir, rmdir } from "node:fs/promises";
3
- //#region src/state/lock.ts
4
- const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
5
- /**
6
- * Acquire a directory-based lock (atomic `mkdir`, EEXIST = already held) with a timeout.
7
- * @returns a release function, or null if the lock could not be acquired in time.
8
- */
9
- async function acquireLock(lockDir, timeoutMs = 5e3) {
10
- const start = Date.now();
11
- while (Date.now() - start < timeoutMs) try {
12
- await mkdir(lockDir, { recursive: false });
13
- return async () => {
14
- try {
15
- await rmdir(lockDir);
16
- } catch {}
17
- };
18
- } catch {
19
- await sleep(100);
20
- }
21
- return null;
22
- }
23
- //#endregion
24
- //#region src/state/apex-state.ts
25
- const DEFAULT_STATE = {
26
- $schema: "apex-state-v1",
27
- description: "APEX/SOLID state - sessions[] + 2min expiry",
28
- target: {},
29
- authorizations: {}
30
- };
31
- /** APEX state directory under a home dir. */
32
- function apexStateDir(home = process.env.HOME ?? "") {
33
- return `${home}/.claude/logs/00-apex`;
34
- }
35
- /** Daily state file path: `<home>/.claude/logs/00-apex/<YYYY-MM-DD>-state.json`. */
36
- function stateFilePath(home = process.env.HOME ?? "", today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)) {
37
- return `${apexStateDir(home)}/${today}-state.json`;
38
- }
39
- /** Ensure the state directory exists and return its path. */
40
- async function ensureStateDir(home) {
41
- const dir = apexStateDir(home);
42
- await ensureDir(dir);
43
- return dir;
44
- }
45
- /** Load APEX state, or a fresh default. */
46
- async function loadState(path) {
47
- return await readJsonFile(path) ?? { ...DEFAULT_STATE };
48
- }
49
- /** Save APEX state. */
50
- async function saveState(path, state) {
51
- await writeJsonFile(path, state);
52
- }
53
- //#endregion
54
- //#region src/state/task-helpers.ts
55
- /** Add a new pending task. */
56
- async function taskCreate(file, id, subject, desc) {
57
- const data = await readJsonFile(file);
58
- if (!data) return;
59
- data.tasks[id] = {
60
- subject,
61
- description: desc,
62
- status: "pending",
63
- phase: "pending",
64
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
65
- doc_consulted: {},
66
- files_modified: [],
67
- blockedBy: []
68
- };
69
- await writeJsonFile(file, data);
70
- }
71
- /** Mark a task in_progress (creating a stub if absent). */
72
- async function taskStart(file, id, subject, desc, blocked) {
73
- const data = await readJsonFile(file);
74
- if (!data) return;
75
- const task = data.tasks[id] ?? {
76
- subject: "",
77
- description: "",
78
- status: "in_progress",
79
- phase: "analyze",
80
- doc_consulted: {},
81
- files_modified: []
82
- };
83
- data.tasks[id] = task;
84
- data.current_task = id;
85
- task.status = "in_progress";
86
- task.phase = "analyze";
87
- task.started_at = (/* @__PURE__ */ new Date()).toISOString();
88
- if (subject) task.subject = subject;
89
- if (desc) task.description = desc;
90
- if (blocked) task.blockedBy = blocked.split(",");
91
- await writeJsonFile(file, data);
92
- }
93
- /** Mark a task completed. */
94
- async function taskComplete(file, id) {
95
- const data = await readJsonFile(file);
96
- const task = data?.tasks[id];
97
- if (!data || !task) return;
98
- task.status = "completed";
99
- task.phase = "completed";
100
- task.completed_at = (/* @__PURE__ */ new Date()).toISOString();
101
- await writeJsonFile(file, data);
102
- }
103
- //#endregion
104
- export { ensureStateDir as a, stateFilePath as c, apexStateDir as i, acquireLock as l, taskCreate as n, loadState as o, taskStart as r, saveState as s, taskComplete as t };