@fusengine/harness 0.1.84 → 0.1.86

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- import { a as fileSizeGuard, c as readClaudeInput, i as denyResponse, l as systemMessage, n as blockResponse, o as guard, r as contextResponse, s as informResponse, t as attachSystemMessage, u as toClaudeResponse } from "../../claude-D93HY8dq.mjs";
1
+ import { a as fileSizeGuard, c as readClaudeInput, i as denyResponse, l as systemMessage, n as blockResponse, o as guard, r as contextResponse, s as informResponse, t as attachSystemMessage, u as toClaudeResponse } from "../../claude-CEWX-8m9.mjs";
2
2
  export { attachSystemMessage, blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, informResponse, readClaudeInput, systemMessage, toClaudeResponse };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-B4-MhOy_.mjs";
1
+ import { t as evaluate } from "../../evaluate-9bUzRquQ.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/cline/index.ts
4
4
  /**
@@ -1,8 +1,8 @@
1
- import { t as evaluate } from "../../evaluate-B4-MhOy_.mjs";
1
+ import { t as evaluate } from "../../evaluate-9bUzRquQ.mjs";
2
2
  import { f as countLines } from "../../home-state-oUGFB4ds.mjs";
3
3
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
4
4
  import { n as parseApplyPatch, t as isBypassPermissions } from "../../permission-mode-BN3MNgbm.mjs";
5
- import { _ as commandToString, c as readClaudeInput, i as denyResponse, r as contextResponse, s as informResponse } from "../../claude-D93HY8dq.mjs";
5
+ import { _ as commandToString, c as readClaudeInput, i as denyResponse, r as contextResponse, s as informResponse } from "../../claude-CEWX-8m9.mjs";
6
6
  //#region src/adapters/codex/index.ts
7
7
  /**
8
8
  * OpenAI Codex CLI adapter (hook-mode). Codex's `PreToolUse` hook (since 2026)
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-B4-MhOy_.mjs";
1
+ import { t as evaluate } from "../../evaluate-9bUzRquQ.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-B4-MhOy_.mjs";
1
+ import { t as evaluate } from "../../evaluate-9bUzRquQ.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/gemini/index.ts
4
4
  /**
@@ -1,2 +1,2 @@
1
- import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-1PUEoY8q.mjs";
1
+ import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-H6qePmBC.mjs";
2
2
  export { guard, readHermesInput, toHermesResponse };
@@ -1,2 +1,2 @@
1
- import { i as toKimiResponse, n as kimiDenyResponse, r as readKimiInput, t as guard } from "../../kimi-ChbcU2uI.mjs";
1
+ import { i as toKimiResponse, n as kimiDenyResponse, r as readKimiInput, t as guard } from "../../kimi-CqLkpg1A.mjs";
2
2
  export { guard, kimiDenyResponse, readKimiInput, toKimiResponse };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "./evaluate-B4-MhOy_.mjs";
1
+ import { t as evaluate } from "./evaluate-9bUzRquQ.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
@@ -3,9 +3,9 @@ import { o as resolveStdinMaxBytes } from "../limits-DG5pl-5s.mjs";
3
3
  import { r as loadDotenv, s as resolveTtlSec } from "../dotenv-DoqNlALG.mjs";
4
4
  import { t as detectHarness } from "../harness-BMuLJ9lm.mjs";
5
5
  import { t as claudeHome } from "../home-state-oUGFB4ds.mjs";
6
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-D_WchZ3R.mjs";
6
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-B4kqWMA3.mjs";
7
7
  import { n as writeInitFile, t as initFor } from "../run-TAXNRSpD.mjs";
8
- import { $ as runningVersion, Q as runDoctor, Z as notify, et as versionBanner, i as respond, t as handleHook, zt as todayUtc } from "../handle-DsP67KZ4.mjs";
8
+ import { $ as runningVersion, Q as runDoctor, Z as notify, et as versionBanner, i as respond, t as handleHook, zt as todayUtc } from "../handle-Dzf4JbrL.mjs";
9
9
  import { delimiter, join } from "node:path";
10
10
  import { existsSync, mkdirSync, readFileSync, readSync, readdirSync, writeFileSync } from "node:fs";
11
11
  import { homedir } from "node:os";
@@ -1,2 +1,2 @@
1
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-D_WchZ3R.mjs";
1
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-B4kqWMA3.mjs";
2
2
  export { checkStaged, stagedContent, stagedFiles };
@@ -261,6 +261,17 @@ const NEXT_CONTENT = /use client|use server|NextRequest|NextResponse|from ['"]ne
261
261
  const NEXT_ROUTE = /(page|layout|loading|error|route|middleware)\.(ts|tsx|js|jsx)$/;
262
262
  /** TanStack Start markers (file routes, server fns, start/router imports). */
263
263
  const TANSTACK_CONTENT = /createFileRoute|createServerFn|from ['"]@tanstack\/react-(start|router)/;
264
+ /**
265
+ * C7: Tailwind CSS-file signals, verified against official docs (v3 + v4) —
266
+ * `@tailwind` (v3 layer directive, removed in v4), `@apply` (both versions),
267
+ * `@config` (v3 native / v4 compat, JS config path), `@source` (v4 content
268
+ * globbing), `@theme` (v4 design-token block), `theme(` (the function, both
269
+ * versions' syntax). Deliberately NOT a bare utility-class-in-selector scan
270
+ * (e.g. `.flex{}`) — an ordinary hand-written class named `.flex` is exactly
271
+ * the false-positive shape this fix removes; only genuine Tailwind-specific
272
+ * at-rules/functions count.
273
+ */
274
+ const TAILWIND_CSS_CONTENT = /@tailwind\b|@apply\b|@config\b|@source\b|@theme\b|\btheme\(/;
264
275
  /** Derive the raw signal an extension + content carry (no filesystem access). */
265
276
  function fileSignal(filePath, content) {
266
277
  if (/\.swift$/.test(filePath)) return { definitive: "swift" };
@@ -269,7 +280,7 @@ function fileSignal(filePath, content) {
269
280
  if (/\.go$/.test(filePath)) return { definitive: "go" };
270
281
  if (/\.rb$/.test(filePath)) return { definitive: "ruby" };
271
282
  if (/\.rs$/.test(filePath)) return { definitive: "rust" };
272
- if (/\.css$/.test(filePath) || /@tailwind|@apply/.test(content)) return { definitive: "tailwind" };
283
+ if (/\.css$/.test(filePath) && TAILWIND_CSS_CONTENT.test(content)) return { definitive: "tailwind" };
273
284
  const masked = maskCommentsAndStrings(content, "c");
274
285
  const isTs = TANSTACK_CONTENT.test(masked);
275
286
  const isNext = !isTs && (NEXT_ROUTE.test(filePath) || NEXT_CONTENT.test(masked));
@@ -3,11 +3,11 @@ import { s as resolveTtlSec } from "./dotenv-DoqNlALG.mjs";
3
3
  import { r as projectLayout } from "./layout-KWoE_Mqn.mjs";
4
4
  import { i as walkUpFor, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-3kk7gCOp.mjs";
5
5
  import { t as detectHarness } from "./harness-BMuLJ9lm.mjs";
6
- import { D as isVendorPath, G as isFileSizeScoped, K as resolveSolidRefFramework, W as computeEditResultLines, b as interfaceDeclLevel, et as detectFramework, g as conventionsMode, lt as requiredArchSkill, n as FAIL_CLOSED, ot as detectModularArchitecture, rt as maskCommentsAndStrings, st as detectProjectType$1, t as evaluate } from "./evaluate-B4-MhOy_.mjs";
6
+ import { D as isVendorPath, G as isFileSizeScoped, K as resolveSolidRefFramework, W as computeEditResultLines, b as interfaceDeclLevel, et as detectFramework, g as conventionsMode, lt as requiredArchSkill, n as FAIL_CLOSED, ot as detectModularArchitecture, rt as maskCommentsAndStrings, st as detectProjectType$1, t as evaluate } from "./evaluate-9bUzRquQ.mjs";
7
7
  import { a as sanitizeSessionId, c as sessionsDir, d as countFrameworkCodeLines, f as countLines, i as loadSessionState, l as PLUGINS_DIR, n as fuseHarnessHome, o as saveSessionState, p as evaluateFileSize, r as fusengineCache, t as claudeHome } from "./home-state-oUGFB4ds.mjs";
8
8
  import { a as writeJsonFile, i as readJsonFile, r as hashText, t as atomicWrite } from "./json-io-DisYd2fb.mjs";
9
9
  import { r as isDocConsulted } from "./doc-helpers-CWZegVdR.mjs";
10
- import { D as frameworkSolidGate, F as isExcludedSwiftPath, G as evaluateApex, H as PRE_AUTH_GATES, P as isExcludedJsPath, R as capVerbosity, S as parseField, T as usesTailwindUtilities, V as POST_AUTH_GATES, W as docConsultedGate, b as scanPlugin, c as EXCLUDE_DIRS$1, d as buildApexTaskInjection, g as buildClaudeMdContext, l as PROJECT_INDICATORS, n as missingSeoElements, o as parseEnrichment, p as apexAgentSteps, r as descFromText, s as parseEntry, t as isHtmlLike, v as apexDocName, w as skillTriggerGate, y as harnessHomeSegment, z as detectCreationIntent } from "./validate-Bf-EsbDh.mjs";
10
+ import { D as frameworkSolidGate, F as isExcludedSwiftPath, G as evaluateApex, H as PRE_AUTH_GATES, P as isExcludedJsPath, R as capVerbosity, S as parseField, T as usesTailwindUtilities, V as POST_AUTH_GATES, W as docConsultedGate, b as scanPlugin, c as EXCLUDE_DIRS$1, d as buildApexTaskInjection, g as buildClaudeMdContext, l as PROJECT_INDICATORS, n as missingSeoElements, o as parseEnrichment, p as apexAgentSteps, r as descFromText, s as parseEntry, t as isHtmlLike, v as apexDocName, w as skillTriggerGate, y as harnessHomeSegment, z as detectCreationIntent } from "./validate-C-TB06Mw.mjs";
11
11
  import { n as findMarketplacePlugins, r as readPluginMeta, t as resolveSkillPath } from "./skill-path-DhBGlQe3.mjs";
12
12
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
13
13
  import { a as nowStamp, l as throttleMs, n as readRoots, o as readState, s as setStateField, t as addRoot } from "./registry-IhHk2KlT.mjs";
@@ -15,9 +15,9 @@ import { d as loadIndex, i as cacheLookupMeta, n as webfetchCacheWrite, o as cac
15
15
  import { t as loadRefs } from "./loader-AGz4nK7d.mjs";
16
16
  import { C as apexAuthorizationGate, S as trivialCount, _ as recordBrainstormRequired, a as journalLogPath, b as recordTarget, c as appendEvent, d as signTrack, f as verifyTrack, g as recordAgent, h as emptyTrack, i as withTrack, l as withTrackLockSync, m as agentsFresh, o as readTrackSync, p as writeLastNonce, r as trackJournalEnabled, s as diffTrackEvents, t as loadTrack, u as LOCK_FAILED, v as recordDoc, x as recordTrivialEdit, y as recordRefRead } from "./store-Dw08Amqh.mjs";
17
17
  import { n as parseApplyPatch, t as isBypassPermissions } from "./permission-mode-BN3MNgbm.mjs";
18
- import { _ as commandToString, d as collectFiles, f as pathExists, g as writeText, h as spawnCapture, i as denyResponse, l as systemMessage, m as sleep, n as blockResponse, p as readText$1, r as contextResponse, s as informResponse, t as attachSystemMessage } from "./claude-D93HY8dq.mjs";
19
- import { i as toKimiResponse, n as kimiDenyResponse } from "./kimi-ChbcU2uI.mjs";
20
- import { r as toHermesResponse } from "./hermes-1PUEoY8q.mjs";
18
+ import { _ as commandToString, d as collectFiles, f as pathExists, g as writeText, h as spawnCapture, i as denyResponse, l as systemMessage, m as sleep, n as blockResponse, p as readText$1, r as contextResponse, s as informResponse, t as attachSystemMessage } from "./claude-CEWX-8m9.mjs";
19
+ import { i as toKimiResponse, n as kimiDenyResponse } from "./kimi-CqLkpg1A.mjs";
20
+ import { r as toHermesResponse } from "./hermes-H6qePmBC.mjs";
21
21
  import { basename, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
22
22
  import { appendFileSync, copyFileSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, renameSync, rmSync, rmdirSync, statSync, symlinkSync, unlinkSync, writeFileSync } from "node:fs";
23
23
  import { homedir } from "node:os";
@@ -280,17 +280,17 @@ function maxSemver(versions) {
280
280
  return versions.length === 0 ? null : versions.reduce((a, b) => compareSemver(a, b) >= 0 ? a : b);
281
281
  }
282
282
  //#endregion
283
- //#region src/policy/design/corpus-resolve.ts
283
+ //#region src/policy/design/corpus-fs.ts
284
284
  /**
285
- * Corpus/plugins root resolution (fs) and the write guard over it. Resolution
286
- * is PER RUNTIME (Claude marketplaces, Codex versioned plugin cache — same
287
- * pattern as rules-root.ts); runtimes without a plugin structure (kimi today)
288
- * resolve to "" and the corpus gates stay dormant. There is NO cwd fallback
289
- * anywhere: an agent-controlled directory can never become its own taste
290
- * reference (self-attested proof — the failure this gate exists to prevent).
285
+ * @module corpus-fs
286
+ * Shared fs primitives for corpus/plugins root resolution, split out of
287
+ * `corpus-resolve.ts` so `corpus-resolve-cache.ts` can reuse them without a
288
+ * circular import (both modules feed `corpus-resolve.ts`'s `probeClaude`).
289
+ * @packageDocumentation
291
290
  */
291
+ /** The refs-design/ path suffix common to every design-corpus-bearing plugin tree. */
292
292
  const CORPUS_SUFFIX = join("skills", "design-web", "references", "refs-design");
293
- /** Immediate child dir names of `dir`, or [] when unreadable. */
293
+ /** Immediate child dir names of `dir`, alphabetically sorted, or [] when unreadable. */
294
294
  function children$2(dir) {
295
295
  try {
296
296
  return readdirSync(dir).sort();
@@ -298,8 +298,60 @@ function children$2(dir) {
298
298
  return [];
299
299
  }
300
300
  }
301
- /** Claude: `<home>/.claude/plugins/marketplaces/<mkt>/plugins/design-expert` ("" when absent). */
302
- function probeClaude$1(home) {
301
+ //#endregion
302
+ //#region src/policy/design/corpus-resolve-cache.ts
303
+ /**
304
+ * @module corpus-resolve-cache
305
+ * Claude Code's per-plugin VERSIONED CACHE tree, split out of
306
+ * `corpus-resolve.ts` to keep that file within the SOLID size budget (SRP).
307
+ *
308
+ * Claude Code caches every installed marketplace plugin at
309
+ * `~/.claude/plugins/cache/<mkt>/<plugin>/<version>/` — a tree SEPARATE from
310
+ * `~/.claude/plugins/marketplaces/<mkt>/plugins/<plugin>/` (the marketplace's
311
+ * own checkout), one version dir per `plugin.json` version bump, orphaned
312
+ * versions pruned ~14 days after being superseded (docs: "Plugin caching and
313
+ * file resolution"). The design corpus can ship under EITHER tree, and under
314
+ * a DIFFERENT plugin id in each: a machine observed 2026-07-29 has the corpus
315
+ * at `cache/fusengine-plugins/fuse-design/2.2.3/...` while the marketplace
316
+ * checkout is `marketplaces/fusengine-plugins/plugins/design-expert/...`.
317
+ * Identification here is therefore STRUCTURAL, never by plugin name: a
318
+ * candidate `<mkt>/<plugin>/<version>/` dir qualifies iff it itself contains
319
+ * `CORPUS_SUFFIX` — matching a hardcoded name would silently miss a
320
+ * renamed/relocated corpus (the exact defect this module fixes).
321
+ * @packageDocumentation
322
+ */
323
+ /** Real (non-prerelease) semver dirs, same filter `probeCodex` uses. */
324
+ const SEMVER_RE = /^\d+\.\d+(\.\d+)?$/;
325
+ /**
326
+ * Claude: `<home>/.claude/plugins/cache/<mkt>/<plugin>/<highest STABLE semver
327
+ * containing refs-design>` ("" when no plugin under any marketplace cache
328
+ * ships the corpus). Marketplaces and plugin ids are both walked — neither is
329
+ * assumed — so a corpus shipped under any plugin name is found.
330
+ */
331
+ function probeClaudeCache(home) {
332
+ const cacheRoot = join(home, ".claude", "plugins", "cache");
333
+ for (const mkt of children$2(cacheRoot)) {
334
+ const mktDir = join(cacheRoot, mkt);
335
+ for (const plugin of children$2(mktDir)) {
336
+ const pluginDir = join(mktDir, plugin);
337
+ const latest = maxSemver(children$2(pluginDir).filter((v) => SEMVER_RE.test(v) && existsSync(join(pluginDir, v, CORPUS_SUFFIX))));
338
+ if (latest) return join(pluginDir, latest);
339
+ }
340
+ }
341
+ return "";
342
+ }
343
+ //#endregion
344
+ //#region src/policy/design/corpus-resolve.ts
345
+ /**
346
+ * Corpus/plugins root resolution (fs) and the write guard over it. Resolution
347
+ * is PER RUNTIME (Claude marketplaces, Codex versioned plugin cache — same
348
+ * pattern as rules-root.ts); runtimes without a plugin structure (kimi today)
349
+ * resolve to "" and the corpus gates stay dormant. There is NO cwd fallback
350
+ * anywhere: an agent-controlled directory can never become its own taste
351
+ * reference (self-attested proof — the failure this gate exists to prevent).
352
+ */
353
+ /** Claude marketplace checkout: `<home>/.claude/plugins/marketplaces/<mkt>/plugins/design-expert` ("" when absent). */
354
+ function probeClaudeMarketplace(home) {
303
355
  const markets = join(home, ".claude", "plugins", "marketplaces");
304
356
  for (const m of children$2(markets)) {
305
357
  const de = join(markets, m, "plugins", "design-expert");
@@ -307,6 +359,14 @@ function probeClaude$1(home) {
307
359
  }
308
360
  return "";
309
361
  }
362
+ /**
363
+ * Claude: the marketplace checkout WINS when present (a single unambiguous
364
+ * live git checkout); the versioned plugin CACHE tree is the fallback, since
365
+ * Claude Code keeps orphaned prior-version cache dirs ~14 days after a bump.
366
+ */
367
+ function probeClaude$1(home) {
368
+ return probeClaudeMarketplace(home) || probeClaudeCache(home);
369
+ }
310
370
  /** Codex: `<CODEX_HOME|~/.codex>/plugins/cache/<mkt>/design-expert/<highest STABLE semver>` ("" when absent). */
311
371
  function probeCodex$1(env, home) {
312
372
  const cache = join(env.CODEX_HOME ?? join(home, ".codex"), "plugins", "cache");
@@ -373,14 +433,22 @@ const CORPUS_LINE_RE = /^[-*]\s*Corpus:\s*(.+)$/gim;
373
433
  function classifyCorpusRead(filePath, corpusRoot) {
374
434
  if (!corpusRoot) return null;
375
435
  if (filePath === join(corpusRoot, "README.md")) return "index";
376
- if (filePath.startsWith(`${corpusRoot}/`) && TOKENS_RE.test(basename(filePath))) return "tokens";
436
+ if (!filePath.startsWith(`${corpusRoot}/`)) return null;
437
+ if (TOKENS_RE.test(basename(filePath))) return "tokens";
438
+ if (basename(filePath) === "design-system.md") return "sheet";
377
439
  return null;
378
440
  }
379
- /** Per-mode corpus-read threshold (component >= 1 file, page >= 2 files, full = index + 2 tokens). */
441
+ /**
442
+ * Per-mode corpus-read threshold (component >= 1 file, page >= 2 files,
443
+ * full = index + 3 tokens — C5: raised from 2, since 2 references still let
444
+ * an agent pattern-match by tonal affinity without ever opening the one
445
+ * reference that actually answered the brief). `"sheet"` reads (C6,
446
+ * `design-system.md`) never count toward this — only `TOKENS_RE` matches do.
447
+ */
380
448
  function corpusReady(reads, mode) {
381
449
  if (mode === "component") return reads.length >= 1;
382
450
  if (mode === "page") return reads.length >= 2;
383
- return reads.includes("README.md") && reads.filter((r) => TOKENS_RE.test(basename(r))).length >= 2;
451
+ return reads.includes("README.md") && reads.filter((r) => TOKENS_RE.test(basename(r))).length >= 3;
384
452
  }
385
453
  /** True when the content carries a `- Corpus: ref/section` citation line (form only). */
386
454
  function hasCorpusCitation(content) {
@@ -7905,6 +7973,57 @@ function collectDesignEvidence(sessionId, cwd, baseDir = defaultStateDir(cwd)) {
7905
7973
  };
7906
7974
  }
7907
7975
  //#endregion
7976
+ //#region src/policy/design/screenshot-tools.ts
7977
+ /**
7978
+ * @module screenshot-tools
7979
+ * Screenshot-credit tool set (C1), split out of `runtime/design-helpers.ts` to
7980
+ * keep that file within the SOLID size budget (SRP).
7981
+ * @packageDocumentation
7982
+ */
7983
+ /**
7984
+ * Screenshot-credit tools: the single-shot capture PLUS the two fuse-browser
7985
+ * batch capture primitives (`browser_shots_batch`, `browser_site_shots`) — a
7986
+ * batch call that captures N urls/viewports must credit the quota too, or
7987
+ * capturing efficiently would make the quota infranchissable. LIMITATION
7988
+ * (deliberate, documented): this repo's cross-harness `NormalizedEvent` (see
7989
+ * `runtime/normalize.ts`) never surfaces `tool_response` for any tool — by
7990
+ * design, since its shape is undocumented for MCP tools and harness-specific
7991
+ * for built-ins — so no per-call item count reaches this gate. A batch call
7992
+ * therefore credits EXACTLY 1, same as a unit screenshot, never the N it may
7993
+ * have captured.
7994
+ */
7995
+ const SHOT_TOOLS = /* @__PURE__ */ new Set([
7996
+ "mcp__fuse-browser__browser_screenshot",
7997
+ "mcp__fuse-browser__browser_shots_batch",
7998
+ "mcp__fuse-browser__browser_site_shots"
7999
+ ]);
8000
+ //#endregion
8001
+ //#region src/policy/design/allowed-write.ts
8002
+ /**
8003
+ * @module allowed-write
8004
+ * The design-agent write allowlist, split out of `gates.ts` to keep that file
8005
+ * within the SOLID size budget (SRP).
8006
+ * @packageDocumentation
8007
+ */
8008
+ /** Extensions the design agent may always write: .html/.css/.md/.json. */
8009
+ const ALLOWED_WRITE = /\.(html|css|md|json)$/;
8010
+ /**
8011
+ * C4: `motion*.js` ONLY, matched on the BASENAME — every one of the 11
8012
+ * corpus references ships its animation as a separate `motion.js` /
8013
+ * `motion-nav.js` / `motion-scroll.js` file, so banning every `.js` forced
8014
+ * the agent to inline scripts the corpus explicitly teaches out-of-band.
8015
+ * Deliberately NOT `\.js$` in general (that would open arbitrary app code,
8016
+ * the exact thing this gate exists to block) — after the `motion` prefix,
8017
+ * either nothing (`motion.js`) or `.`/`-` then more (`motion-nav.js`) must
8018
+ * lead into `.js`; `app.js` and `motionless-app.js` — a bare `^motion`
8019
+ * prefix would wrongly pass this — do not match.
8020
+ */
8021
+ const MOTION_JS = /^motion([.-].*)?\.js$/;
8022
+ /** True when `filePath` is a write the design agent may make: .html/.css/.md/.json, or a `motion*.js` file. */
8023
+ function isAllowedWrite(filePath) {
8024
+ return ALLOWED_WRITE.test(filePath) || MOTION_JS.test(basename(filePath));
8025
+ }
8026
+ //#endregion
7908
8027
  //#region src/policy/design/design-system-rules.ts
7909
8028
  /**
7910
8029
  * Content rules for design-system.md — the four hard requirements the
@@ -7917,14 +8036,22 @@ const OKLCH_RE = /oklch\(\s*[\d.]+%?\s+0\.0*[1-9]/;
7917
8036
  * system may SAY "Inter" ("## Interaction states", "we never use Inter"), it
7918
8037
  * may not USE it as a font. Covered forms: CSS declarations (`font:`,
7919
8038
  * `font-family:` in any case, multiline values), JS config (`fontFamily:`),
7920
- * custom properties (`--*font*`/`--*ff*`/`--*type*`), `@import` URLs, and
7921
- * Markdown table cells (`| Body | Inter |`). Explicitly OUT of scope (chosen,
7922
- * not overlooked): unquoted prose in bullet lines distinguishing "usage"
7923
- * from "mention" there is prose parsing, not a regex's job.
8039
+ * custom properties named in English (`--*font*`/`--*ff*`/`--*type*`, value
8040
+ * unquoted or quoted), ANY custom property whose value quotes a forbidden
8041
+ * name (`--police-texte: "Inter", …` a non-English property name has no
8042
+ * keyword to key off, so the quote itself is the usage signal: a quoted
8043
+ * token in a `--*` value is a font-family entry, not prose), `@import`
8044
+ * URLs, and Markdown table cells (`| Body | Inter |`). Explicitly OUT of
8045
+ * scope (chosen, not overlooked): unquoted prose in bullet lines —
8046
+ * distinguishing "usage" from "mention" there is prose parsing, not a
8047
+ * regex's job. Accepted trade-off of the quote signal: `--comment: "we
8048
+ * never use Inter"` is flagged too — a quoted mention reads identically to
8049
+ * a quoted usage once the property name carries no keyword to disambiguate.
7924
8050
  */
7925
8051
  const FONT_DECL_RE = /(?:font(?:-family)?|fontFamily|--[\w-]*(?:font|ff|type)[\w-]*)\s*:[^;\n]*(?:\n\s*)?[^;\n]*\b(?:Inter|Roboto|Arial|Open Sans)\b/i;
7926
8052
  const FONT_IMPORT_RE = /family=[^&"')]*\b(?:Inter|Roboto|Arial|Open Sans)\b/i;
7927
8053
  const FONT_TABLE_RE = /\|\s*\*{0,2}(?:Inter|Roboto|Arial|Open Sans)\*{0,2}\s*\|/;
8054
+ const FONT_QUOTED_PROP_RE = /--[\w-]+\s*:[^;\n]*["'][^;\n]*(?:\n\s*)?[^;\n]*\b(?:Inter|Roboto|Arial|Open Sans)\b/i;
7928
8055
  /**
7929
8056
  * Return the requirements missing from a design-system.md (empty = valid).
7930
8057
  * The corpus citation satisfies the source requirement ONLY when the corpus
@@ -7936,12 +8063,11 @@ function validateDesignSystem(content, corpusCitationOk = false) {
7936
8063
  if (!content.includes("## Design Reference")) missing.push("## Design Reference section");
7937
8064
  if (!/https?:\/\//.test(content) && !(corpusCitationOk && hasCorpusCitation(content))) missing.push("reference URL (https://…) or Corpus citation");
7938
8065
  if (!OKLCH_RE.test(content)) missing.push("oklch() color with chroma > 0");
7939
- if (FONT_DECL_RE.test(content) || FONT_IMPORT_RE.test(content) || FONT_TABLE_RE.test(content)) missing.push("forbidden font (Inter/Roboto/Arial/Open Sans)");
8066
+ if (FONT_DECL_RE.test(content) || FONT_IMPORT_RE.test(content) || FONT_TABLE_RE.test(content) || FONT_QUOTED_PROP_RE.test(content)) missing.push("forbidden font (Inter/Roboto/Arial/Open Sans)");
7940
8067
  return missing;
7941
8068
  }
7942
8069
  //#endregion
7943
8070
  //#region src/policy/design/gates.ts
7944
- const ALLOWED_WRITE = /\.(html|css|md|json)$/;
7945
8071
  const EXEMPT_DIRS = [
7946
8072
  "node_modules/",
7947
8073
  "dist/",
@@ -7949,7 +8075,7 @@ const EXEMPT_DIRS = [
7949
8075
  ".claude/"
7950
8076
  ];
7951
8077
  const NAV$2 = "mcp__fuse-browser__browser_navigate";
7952
- const SHOT$2 = "mcp__fuse-browser__browser_screenshot";
8078
+ const SHOT$1 = "mcp__fuse-browser__browser_screenshot";
7953
8079
  const GEMINI$2 = "mcp__gemini-design__create_frontend";
7954
8080
  const deny = (reason) => ({
7955
8081
  kind: "block",
@@ -7957,10 +8083,10 @@ const deny = (reason) => ({
7957
8083
  reason,
7958
8084
  actions: ["Follow the design pipeline phases (0→identity, 1→inspiration, 2→screenshots, 3→design-system, 4→generate) in order"]
7959
8085
  });
7960
- /** Block the design agent from writing anything but .html/.css/.md/.json. */
8086
+ /** Block the design agent from writing anything but .html/.css/.md/.json (+ motion*.js). */
7961
8087
  function htmlCssOnlyGate(filePath) {
7962
- if (EXEMPT_DIRS.some((d) => filePath.includes(d)) || ALLOWED_WRITE.test(filePath)) return null;
7963
- return deny("BLOCKED: design-expert can only write .html, .css, .md, and .json files. Framework files (.tsx, .astro, .vue, .swift, .php) must be written by the domain expert (astro-expert, react-expert, etc.) AFTER design validation.");
8088
+ if (EXEMPT_DIRS.some((d) => filePath.includes(d)) || isAllowedWrite(filePath)) return null;
8089
+ return deny("BLOCKED: design-expert can only write .html, .css, .json, .md, and motion*.js files. Framework files (.tsx, .astro, .vue, .swift, .php) must be written by the domain expert (astro-expert, react-expert, etc.) AFTER design validation.");
7964
8090
  }
7965
8091
  /** Block edits to the harness-managed `.design-state-*` files (read-only to the agent). */
7966
8092
  function stateFileGate(filePath) {
@@ -7997,7 +8123,7 @@ function designPassNotice(i, cacheDir) {
7997
8123
  if (isWrite && fp && !EXEMPT_DIRS.some((d) => fp.includes(d)) && ALLOWED_WRITE.test(fp)) lines.push(`enforce-html-css-only: allowed: ${basename(fp)}`);
7998
8124
  if (i.tool === NAV$2) lines.push(`check-inspiration-read: pass (${i.url})`);
7999
8125
  if (i.tool === GEMINI$2 && geminiEnabled()) lines.push("validate-design-system: design-system.md ok");
8000
- if (isWrite || i.tool === NAV$2 || i.tool === SHOT$2 || i.tool === GEMINI$2) lines.push(`pipeline-gate: phase ${state.currentPhase} ok`);
8126
+ if (isWrite || i.tool === NAV$2 || i.tool === SHOT$1 || i.tool === GEMINI$2) lines.push(`pipeline-gate: phase ${state.currentPhase} ok`);
8001
8127
  }
8002
8128
  if (state && i.phase === "post" && isWrite) {
8003
8129
  if (basename(fp) === "design-system.md") lines.push("validate-design: design-system.md → phase 3");
@@ -8081,9 +8207,9 @@ const SKILLS = `${PLUGINS_DIR}/design-expert/skills`;
8081
8207
  /** Gate writing design-system.md: requires phase >= 2 and the per-mode screenshot quota. */
8082
8208
  function designSystemWriteGate(filePath, state, corpusRequired = false) {
8083
8209
  if (!filePath.endsWith("design-system.md")) return null;
8084
- if (state.currentPhase < 2) return deny(`BLOCKED: Cannot write design-system.md at phase ${state.currentPhase}. RECOVERY: 1) Read identity templates from skills/design-system/ 2) Read design-inspiration.md 3) Read the refs-design corpus (README.md + relevant tokens-*.md) with the Read tool 4) Screenshot real sector sites with mcp__fuse-browser__browser_screenshot on a LIVE session (note: browser_shots_batch/browser_site_shots do NOT advance the phase) 5) Then write design-system.md`);
8210
+ if (state.currentPhase < 2) return deny(`BLOCKED: Cannot write design-system.md at phase ${state.currentPhase}. RECOVERY: 1) Read identity templates from skills/design-system/ 2) Read design-inspiration.md 3) Read the refs-design corpus (README.md + relevant tokens-*.md) with the Read tool 4) Screenshot real sector sites with mcp__fuse-browser__browser_screenshot on a LIVE session (browser_shots_batch/browser_site_shots also count, 1 credit per call) 5) Then write design-system.md`);
8085
8211
  const needed = quotaFor(state.mode, corpusRequired);
8086
- if (state.screenshotsCount < needed) return deny(`BLOCKED: ${state.screenshotsCount}/${needed} screenshots for mode '${state.mode}'. RECOVERY: 1) Read the refs-design corpus (README.md + tokens-*.md) if not done 2) Take ${needed - state.screenshotsCount} more screenshots of REAL sector sites with mcp__fuse-browser__browser_screenshot (browser_shots_batch/browser_site_shots do NOT count) 3) Use browser_open + browser_navigate + browser_screenshot fullPage:true 4) Then write design-system.md`);
8212
+ if (state.screenshotsCount < needed) return deny(`BLOCKED: ${state.screenshotsCount}/${needed} screenshots for mode '${state.mode}'. RECOVERY: 1) Read the refs-design corpus (README.md + tokens-*.md) if not done 2) Take ${needed - state.screenshotsCount} more screenshots of REAL sector sites with mcp__fuse-browser__browser_screenshot (browser_shots_batch/browser_site_shots also count, 1 credit per call) 3) Use browser_open + browser_navigate + browser_screenshot fullPage:true 4) Then write design-system.md`);
8087
8213
  return null;
8088
8214
  }
8089
8215
  /** Gate Gemini create_frontend: requires phase >= 3 and a validated design system. */
@@ -8230,7 +8356,6 @@ function designSystemContentGate(i) {
8230
8356
  * @packageDocumentation
8231
8357
  */
8232
8358
  const NAV$1 = "mcp__fuse-browser__browser_navigate";
8233
- const SHOT$1 = "mcp__fuse-browser__browser_screenshot";
8234
8359
  const SCROLL = "mcp__fuse-browser__browser_scroll";
8235
8360
  const GEMINI$1 = "mcp__gemini-design__create_frontend";
8236
8361
  /** Read design-system.md walking up to 6 parents from `cwd` ("" if absent/unreadable). */
@@ -8251,7 +8376,7 @@ function findDesignSystem(cwd) {
8251
8376
  }
8252
8377
  /** Apply a PostToolUse fuse-browser transition to the design state. */
8253
8378
  function recordPost(event, cacheDir, state, corpusRoot = "", corpusRequired = false, cwd = "") {
8254
- if (event.tool === SHOT$1) saveDesignState(cacheDir, recordScreenshot(state, corpusRequired));
8379
+ if (SHOT_TOOLS.has(event.tool)) saveDesignState(cacheDir, recordScreenshot(state, corpusRequired));
8255
8380
  else if (event.tool === NAV$1) saveDesignState(cacheDir, recordNavigate(state));
8256
8381
  else if (event.tool === SCROLL) saveDesignState(cacheDir, recordScroll(state));
8257
8382
  else if (event.tool === GEMINI$1) saveDesignState(cacheDir, {
@@ -1,6 +1,6 @@
1
- import { t as evaluate } from "./evaluate-B4-MhOy_.mjs";
1
+ import { t as evaluate } from "./evaluate-9bUzRquQ.mjs";
2
2
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
3
- import { _ as commandToString, c as readClaudeInput } from "./claude-D93HY8dq.mjs";
3
+ import { _ as commandToString, c as readClaudeInput } from "./claude-CEWX-8m9.mjs";
4
4
  //#region src/adapters/hermes/index.ts
5
5
  /**
6
6
  * Hermes Agent adapter (hook-mode). Nous Research's hermes-agent (2026) pipes a
package/dist/index.mjs CHANGED
@@ -4,11 +4,11 @@ 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-BMuLJ9lm.mjs";
7
- import { $ as matchPatterns, B as protectedPathGuard, C as isInterfacesPath, D as isVendorPath, E as isTypesPath, F as FILE_REDIRECT, H as CRITICAL_PATTERNS, I as SAFE_PREFIXES, J as GIT_BLOCKED, L as SESSION_STATE_FRAGMENT, M as ASK_WRITERS, N as CODE_MUTATORS, O as langOfPath, P as CODE_REDIRECT, Q as isRalphMode, R as PROTECTED_FRAGMENTS, S as isHooksPath, T as isStoresPath, U as securityGuard, V as ASK_PATTERNS, X as RALPH_SAFE, Y as PROJECT_INSTALL, Z as SYSTEM_INSTALL, a as registerGuard, at as DEV_KEYWORDS, b as interfaceDeclLevel, c as GO_DECL_RE, ct as isApexCommand, d as PY_MODEL_RE, et as detectFramework, f as RUST_DECL_RE, h as interfaceSeparationGuard, i as clearUserGuards, it as maskCommentsOnly, j as bashWriteGuard, k as lexProfileOf, l as JAVA_DECL_RE, lt as requiredArchSkill, m as TS_DECL_RE, n as FAIL_CLOSED, o as runGuards, ot as detectModularArchitecture, p as SWIFT_PROTO_RE, q as GIT_ASK, r as GUARDS, rt as maskCommentsAndStrings, s as installGuard, st as detectProjectType, t as evaluate, u as PHP_DECL_RE, v as declaresExportedTypeAlias, w as isQueryPath, x as isComponentsPath, y as declaresInterface, z as PROTECTED_GIT_RE } from "./evaluate-B4-MhOy_.mjs";
7
+ import { $ as matchPatterns, B as protectedPathGuard, C as isInterfacesPath, D as isVendorPath, E as isTypesPath, F as FILE_REDIRECT, H as CRITICAL_PATTERNS, I as SAFE_PREFIXES, J as GIT_BLOCKED, L as SESSION_STATE_FRAGMENT, M as ASK_WRITERS, N as CODE_MUTATORS, O as langOfPath, P as CODE_REDIRECT, Q as isRalphMode, R as PROTECTED_FRAGMENTS, S as isHooksPath, T as isStoresPath, U as securityGuard, V as ASK_PATTERNS, X as RALPH_SAFE, Y as PROJECT_INSTALL, Z as SYSTEM_INSTALL, a as registerGuard, at as DEV_KEYWORDS, b as interfaceDeclLevel, c as GO_DECL_RE, ct as isApexCommand, d as PY_MODEL_RE, et as detectFramework, f as RUST_DECL_RE, h as interfaceSeparationGuard, i as clearUserGuards, it as maskCommentsOnly, j as bashWriteGuard, k as lexProfileOf, l as JAVA_DECL_RE, lt as requiredArchSkill, m as TS_DECL_RE, n as FAIL_CLOSED, o as runGuards, ot as detectModularArchitecture, p as SWIFT_PROTO_RE, q as GIT_ASK, r as GUARDS, rt as maskCommentsAndStrings, s as installGuard, st as detectProjectType, t as evaluate, u as PHP_DECL_RE, v as declaresExportedTypeAlias, w as isQueryPath, x as isComponentsPath, y as declaresInterface, z as PROTECTED_GIT_RE } from "./evaluate-9bUzRquQ.mjs";
8
8
  import { d as countFrameworkCodeLines, f as countLines, l as PLUGINS_DIR, p as evaluateFileSize, u as SOLID_REF } from "./home-state-oUGFB4ds.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
- import { A as importsTanstackQuery, B as APEX_GATES, C as detectRequiredSkills, D as frameworkSolidGate, E as SKILL_TRIGGERS, G as evaluateApex, H as PRE_AUTH_GATES, I as MAX_EXA_RESULTS, K as freshnessGate, L as MAX_TOKENS, M as countStores, N as declaresStore, O as declaresCustomHook, R as capVerbosity, S as parseField, T as usesTailwindUtilities, U as brainstormGate, V as POST_AUTH_GATES, W as docConsultedGate, _ as detectClaudeMdProjectType, a as firstHeading, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as buildClaudeMdContext, h as buildApexInstruction, i as firstComment, j as queryCapActive, k as declaresQueryHook, l as PROJECT_INDICATORS, m as DEV_VERBS, n as missingSeoElements, o as parseEnrichment, q as solidReadGate, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, w as skillTriggerGate, x as parseBodyDesc, z as detectCreationIntent } from "./validate-Bf-EsbDh.mjs";
11
+ import { A as importsTanstackQuery, B as APEX_GATES, C as detectRequiredSkills, D as frameworkSolidGate, E as SKILL_TRIGGERS, G as evaluateApex, H as PRE_AUTH_GATES, I as MAX_EXA_RESULTS, K as freshnessGate, L as MAX_TOKENS, M as countStores, N as declaresStore, O as declaresCustomHook, R as capVerbosity, S as parseField, T as usesTailwindUtilities, U as brainstormGate, V as POST_AUTH_GATES, W as docConsultedGate, _ as detectClaudeMdProjectType, a as firstHeading, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as buildClaudeMdContext, h as buildApexInstruction, i as firstComment, j as queryCapActive, k as declaresQueryHook, l as PROJECT_INDICATORS, m as DEV_VERBS, n as missingSeoElements, o as parseEnrichment, q as solidReadGate, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, w as skillTriggerGate, x as parseBodyDesc, z as detectCreationIntent } from "./validate-C-TB06Mw.mjs";
12
12
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
13
13
  import { a as nowStamp, c as stateFileFor, i as lessonsFileFor, l as throttleMs, n as readRoots, o as readState, r as registryFile, s as setStateField, t as addRoot, u as ensureMemoryGitignore } from "./registry-IhHk2KlT.mjs";
14
14
  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";
@@ -1,6 +1,6 @@
1
- import { t as evaluate } from "./evaluate-B4-MhOy_.mjs";
1
+ import { t as evaluate } from "./evaluate-9bUzRquQ.mjs";
2
2
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
3
- import { _ as commandToString, c as readClaudeInput } from "./claude-D93HY8dq.mjs";
3
+ import { _ as commandToString, c as readClaudeInput } from "./claude-CEWX-8m9.mjs";
4
4
  //#region src/adapters/kimi/index.ts
5
5
  /**
6
6
  * Kimi Code CLI adapter (hook-mode). Moonshot AI's Kimi Code CLI (v0.27.0,
@@ -1,5 +1,5 @@
1
- import { $ as matchPatterns, B as protectedPathGuard, C as isInterfacesPath, D as isVendorPath, E as isTypesPath, F as FILE_REDIRECT, H as CRITICAL_PATTERNS, I as SAFE_PREFIXES, J as GIT_BLOCKED, L as SESSION_STATE_FRAGMENT, M as ASK_WRITERS, N as CODE_MUTATORS, O as langOfPath, P as CODE_REDIRECT, Q as isRalphMode, R as PROTECTED_FRAGMENTS, S as isHooksPath, T as isStoresPath, U as securityGuard, V as ASK_PATTERNS, X as RALPH_SAFE, Y as PROJECT_INSTALL, Z as SYSTEM_INSTALL, a as registerGuard, at as DEV_KEYWORDS, b as interfaceDeclLevel, c as GO_DECL_RE, ct as isApexCommand, d as PY_MODEL_RE, et as detectFramework, f as RUST_DECL_RE, h as interfaceSeparationGuard, i as clearUserGuards, it as maskCommentsOnly, j as bashWriteGuard, k as lexProfileOf, l as JAVA_DECL_RE, lt as requiredArchSkill, m as TS_DECL_RE, n as FAIL_CLOSED, o as runGuards, ot as detectModularArchitecture, p as SWIFT_PROTO_RE, q as GIT_ASK, r as GUARDS, rt as maskCommentsAndStrings, s as installGuard, st as detectProjectType, t as evaluate, u as PHP_DECL_RE, v as declaresExportedTypeAlias, w as isQueryPath, x as isComponentsPath, y as declaresInterface, z as PROTECTED_GIT_RE } from "../evaluate-B4-MhOy_.mjs";
1
+ import { $ as matchPatterns, B as protectedPathGuard, C as isInterfacesPath, D as isVendorPath, E as isTypesPath, F as FILE_REDIRECT, H as CRITICAL_PATTERNS, I as SAFE_PREFIXES, J as GIT_BLOCKED, L as SESSION_STATE_FRAGMENT, M as ASK_WRITERS, N as CODE_MUTATORS, O as langOfPath, P as CODE_REDIRECT, Q as isRalphMode, R as PROTECTED_FRAGMENTS, S as isHooksPath, T as isStoresPath, U as securityGuard, V as ASK_PATTERNS, X as RALPH_SAFE, Y as PROJECT_INSTALL, Z as SYSTEM_INSTALL, a as registerGuard, at as DEV_KEYWORDS, b as interfaceDeclLevel, c as GO_DECL_RE, ct as isApexCommand, d as PY_MODEL_RE, et as detectFramework, f as RUST_DECL_RE, h as interfaceSeparationGuard, i as clearUserGuards, it as maskCommentsOnly, j as bashWriteGuard, k as lexProfileOf, l as JAVA_DECL_RE, lt as requiredArchSkill, m as TS_DECL_RE, n as FAIL_CLOSED, o as runGuards, ot as detectModularArchitecture, p as SWIFT_PROTO_RE, q as GIT_ASK, r as GUARDS, rt as maskCommentsAndStrings, s as installGuard, st as detectProjectType, t as evaluate, u as PHP_DECL_RE, v as declaresExportedTypeAlias, w as isQueryPath, x as isComponentsPath, y as declaresInterface, z as PROTECTED_GIT_RE } from "../evaluate-9bUzRquQ.mjs";
2
2
  import { d as countFrameworkCodeLines, f as countLines, l as PLUGINS_DIR, p as evaluateFileSize, u as SOLID_REF } from "../home-state-oUGFB4ds.mjs";
3
- import { A as importsTanstackQuery, B as APEX_GATES, C as detectRequiredSkills, D as frameworkSolidGate, E as SKILL_TRIGGERS, G as evaluateApex, H as PRE_AUTH_GATES, I as MAX_EXA_RESULTS, K as freshnessGate, L as MAX_TOKENS, M as countStores, N as declaresStore, O as declaresCustomHook, R as capVerbosity, S as parseField, T as usesTailwindUtilities, U as brainstormGate, V as POST_AUTH_GATES, W as docConsultedGate, _ as detectClaudeMdProjectType, a as firstHeading, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as buildClaudeMdContext, h as buildApexInstruction, i as firstComment, j as queryCapActive, k as declaresQueryHook, l as PROJECT_INDICATORS, m as DEV_VERBS, n as missingSeoElements, o as parseEnrichment, q as solidReadGate, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, w as skillTriggerGate, x as parseBodyDesc, z as detectCreationIntent } from "../validate-Bf-EsbDh.mjs";
3
+ import { A as importsTanstackQuery, B as APEX_GATES, C as detectRequiredSkills, D as frameworkSolidGate, E as SKILL_TRIGGERS, G as evaluateApex, H as PRE_AUTH_GATES, I as MAX_EXA_RESULTS, K as freshnessGate, L as MAX_TOKENS, M as countStores, N as declaresStore, O as declaresCustomHook, R as capVerbosity, S as parseField, T as usesTailwindUtilities, U as brainstormGate, V as POST_AUTH_GATES, W as docConsultedGate, _ as detectClaudeMdProjectType, a as firstHeading, c as EXCLUDE_DIRS, d as buildApexTaskInjection, f as loadApexTaskState, g as buildClaudeMdContext, h as buildApexInstruction, i as firstComment, j as queryCapActive, k as declaresQueryHook, l as PROJECT_INDICATORS, m as DEV_VERBS, n as missingSeoElements, o as parseEnrichment, q as solidReadGate, r as descFromText, s as parseEntry, t as isHtmlLike, u as buildApexTaskContext, w as skillTriggerGate, x as parseBodyDesc, z as detectCreationIntent } from "../validate-C-TB06Mw.mjs";
4
4
  import "../policy-la_KkjCS.mjs";
5
5
  export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, DEV_VERBS, EXCLUDE_DIRS, FAIL_CLOSED, FILE_REDIRECT, GIT_ASK, GIT_BLOCKED, GO_DECL_RE, GUARDS, JAVA_DECL_RE, MAX_EXA_RESULTS, MAX_TOKENS, PHP_DECL_RE, PLUGINS_DIR, POST_AUTH_GATES, PRE_AUTH_GATES, PROJECT_INDICATORS, PROJECT_INSTALL, PROTECTED_FRAGMENTS, PROTECTED_GIT_RE, PY_MODEL_RE, RALPH_SAFE, RUST_DECL_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, countStores, declaresCustomHook, declaresExportedTypeAlias, declaresInterface, declaresQueryHook, declaresStore, descFromText, detectClaudeMdProjectType, detectCreationIntent, detectFramework, detectModularArchitecture, detectProjectType, detectRequiredSkills, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, firstComment, firstHeading, frameworkSolidGate, freshnessGate, importsTanstackQuery, installGuard, interfaceDeclLevel, interfaceSeparationGuard, isApexCommand, isComponentsPath, isHooksPath, isHtmlLike, isInterfacesPath, isQueryPath, isRalphMode, isStoresPath, isTypesPath, isVendorPath, langOfPath, lexProfileOf, loadApexTaskState, maskCommentsAndStrings, maskCommentsOnly, matchPatterns, missingSeoElements, parseBodyDesc, parseEnrichment, parseEntry, parseField, protectedPathGuard, queryCapActive, 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-B4-MhOy_.mjs";
2
+ import { t as evaluate } from "./evaluate-9bUzRquQ.mjs";
3
3
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
4
4
  import { execSync } from "node:child_process";
5
5
  //#region src/cli/run.ts
@@ -1,6 +1,6 @@
1
1
  import { r as projectLayout } from "../layout-KWoE_Mqn.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-oUGFB4ds.mjs";
3
- import { A as trackMcpResearch, At as defaultStateDir, B as generateProjectMap, C as seoPostToolUse, Ct as trimLogFile, D as securityAdvisoryForPatch, Dt as claudeMdKey, E as securityAdvisory, Et as projectContext, F as dispatchAipilot, Ft as loadSecurityState, G as countFiles, H as writeTree, I as dispatchLessons, It as saveSecurityState, J as lessonsArchiveFileFor, K as getFileDesc, L as cartoSessionStart, Lt as securityStateDir, M as trackEnrichment, Mt as trackFile, N as dispatchLifecycle, Nt as normalizeEvent, O as postTrackingSideEffects, Ot as promptSubmitContext, P as aipilotPostToolUse, Pt as isoUtc, R as generateEcosystemMap, Rt as securityStatePath, S as postEditContext, St as removeOldFiles, T as dispatchMemory, Tt as gitContext, U as loadEnriched, V as isProject, W as mergeLines, X as lessonsStateFileFor, Y as lessonsFileFor, _ as preCommitGate, _t as readRules, a as recordActivity, at as saveApexState, b as extractSymbols, bt as pruneEmptyDirs, c as MCP_TTL_MS, ct as trackAgentMemory, d as isMcpTool, dt as validateSolidGate, f as queryOf, ft as checkFileSize, g as gate, gt as injectRules, h as TRIVIAL_BUDGET, ht as solidDetectStart, i as respond, it as cleanupSession, j as trackSkillRead, jt as projectHash, k as trackWatchResearch, kt as taskContext, l as WEBFETCH_TTL_MS, lt as subagentCacheContext, m as REQUIRED_AGENTS, mt as detectSolidProfile, n as activityFor, nt as trackSessionChanges, o as mcpPostStore, ot as logToolFailure, p as DEFAULT_WINDOW_MS, pt as countLoc, q as listChildren, r as handlePre, rt as validateRulesLoaded, s as mcpPreIntercept, st as validateTeammateOutput, t as handleHook, tt as postEditTypescript, u as cacheQueryOf, ut as validateTailwind, v as detectDuplication, vt as runSessionStartCleanups, w as seoPostToolUseResponse, wt as devContext, x as lifecycleStdout, xt as purgeTtlTree, y as dryGate, yt as sessionStartCore, z as writePluginMap, zt as todayUtc } from "../handle-DsP67KZ4.mjs";
3
+ import { A as trackMcpResearch, At as defaultStateDir, B as generateProjectMap, C as seoPostToolUse, Ct as trimLogFile, D as securityAdvisoryForPatch, Dt as claudeMdKey, E as securityAdvisory, Et as projectContext, F as dispatchAipilot, Ft as loadSecurityState, G as countFiles, H as writeTree, I as dispatchLessons, It as saveSecurityState, J as lessonsArchiveFileFor, K as getFileDesc, L as cartoSessionStart, Lt as securityStateDir, M as trackEnrichment, Mt as trackFile, N as dispatchLifecycle, Nt as normalizeEvent, O as postTrackingSideEffects, Ot as promptSubmitContext, P as aipilotPostToolUse, Pt as isoUtc, R as generateEcosystemMap, Rt as securityStatePath, S as postEditContext, St as removeOldFiles, T as dispatchMemory, Tt as gitContext, U as loadEnriched, V as isProject, W as mergeLines, X as lessonsStateFileFor, Y as lessonsFileFor, _ as preCommitGate, _t as readRules, a as recordActivity, at as saveApexState, b as extractSymbols, bt as pruneEmptyDirs, c as MCP_TTL_MS, ct as trackAgentMemory, d as isMcpTool, dt as validateSolidGate, f as queryOf, ft as checkFileSize, g as gate, gt as injectRules, h as TRIVIAL_BUDGET, ht as solidDetectStart, i as respond, it as cleanupSession, j as trackSkillRead, jt as projectHash, k as trackWatchResearch, kt as taskContext, l as WEBFETCH_TTL_MS, lt as subagentCacheContext, m as REQUIRED_AGENTS, mt as detectSolidProfile, n as activityFor, nt as trackSessionChanges, o as mcpPostStore, ot as logToolFailure, p as DEFAULT_WINDOW_MS, pt as countLoc, q as listChildren, r as handlePre, rt as validateRulesLoaded, s as mcpPreIntercept, st as validateTeammateOutput, t as handleHook, tt as postEditTypescript, u as cacheQueryOf, ut as validateTailwind, v as detectDuplication, vt as runSessionStartCleanups, w as seoPostToolUseResponse, wt as devContext, x as lifecycleStdout, xt as purgeTtlTree, y as dryGate, yt as sessionStartCore, z as writePluginMap, zt as todayUtc } from "../handle-Dzf4JbrL.mjs";
4
4
  //#region src/runtime/storage.ts
5
5
  /**
6
6
  * The project's single state dir (`<root>/.harness`) — neutral + harness-agnostic,
@@ -1,6 +1,6 @@
1
1
  import { a as resolveMaxLines, c as storeBudget, i as hookBudget } from "./limits-DG5pl-5s.mjs";
2
2
  import { c as ttlLabel, t as HOME_DIR } from "./dotenv-DoqNlALG.mjs";
3
- import { A as moduleAwarePath, S as isHooksPath, T as isStoresPath, _ as rolloutVerdict, at as DEV_KEYWORDS, it as maskCommentsOnly, nt as projectCaps, rt as maskCommentsAndStrings, tt as nearestManifestDir, x as isComponentsPath, y as declaresInterface } from "./evaluate-B4-MhOy_.mjs";
3
+ import { A as moduleAwarePath, S as isHooksPath, T as isStoresPath, _ as rolloutVerdict, at as DEV_KEYWORDS, it as maskCommentsOnly, nt as projectCaps, rt as maskCommentsAndStrings, tt as nearestManifestDir, x as isComponentsPath, y as declaresInterface } from "./evaluate-9bUzRquQ.mjs";
4
4
  import { d as countFrameworkCodeLines, l as PLUGINS_DIR, u as SOLID_REF } from "./home-state-oUGFB4ds.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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/harness",
3
- "version": "0.1.84",
3
+ "version": "0.1.86",
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",