@fusengine/harness 0.1.9 → 0.1.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- import { a as readClaudeInput, i as guard, n as denyResponse, o as toClaudeResponse, r as fileSizeGuard, t as contextResponse } from "../../claude-DbzjbxmO.mjs";
1
+ import { a as readClaudeInput, i as guard, n as denyResponse, o as toClaudeResponse, r as fileSizeGuard, t as contextResponse } from "../../claude-B3aJwu6O.mjs";
2
2
  export { contextResponse, denyResponse, fileSizeGuard, guard, readClaudeInput, toClaudeResponse };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-CsYyUucy.mjs";
1
+ import { t as evaluate } from "../../evaluate-DkTgwHNh.mjs";
2
2
  import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/cline/index.ts
4
4
  /**
@@ -1,2 +1,2 @@
1
- import { a as readClaudeInput, i as guard, n as denyResponse, t as contextResponse } from "../../claude-DbzjbxmO.mjs";
1
+ import { a as readClaudeInput, i as guard, n as denyResponse, t as contextResponse } from "../../claude-B3aJwu6O.mjs";
2
2
  export { contextResponse, denyResponse, guard, readClaudeInput as readCodexInput };
@@ -1,4 +1,4 @@
1
- import { t as evaluate } from "../../evaluate-CsYyUucy.mjs";
1
+ import { t as evaluate } from "../../evaluate-DkTgwHNh.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-CsYyUucy.mjs";
1
+ import { t as evaluate } from "../../evaluate-DkTgwHNh.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-CsYyUucy.mjs";
1
+ import { t as evaluate } from "./evaluate-DkTgwHNh.mjs";
2
2
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
3
3
  //#region src/adapters/claude/index.ts
4
4
  /**
package/dist/cli/bin.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import { t as detectHarness } from "../harness-C8Nxxyn_.mjs";
3
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-h_2LNEA8.mjs";
3
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-D2na7Z2Z.mjs";
4
4
  import { n as writeInitFile, t as initFor } from "../run-Cdp2Ef9B.mjs";
5
- import { t as handleHook } from "../handle-Lz_thVKr.mjs";
5
+ import { t as handleHook } from "../handle-BUyS6NU6.mjs";
6
6
  //#region src/cli/bin.ts
7
7
  /**
8
8
  * harness — CLI for @fusengine/harness.
@@ -1,2 +1,2 @@
1
- import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-h_2LNEA8.mjs";
1
+ import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-D2na7Z2Z.mjs";
2
2
  export { checkStaged, stagedContent, stagedFiles };
@@ -0,0 +1,316 @@
1
+ import { i as splitTarget, r as resolveMaxLines } from "./limits-CHn8AIL1.mjs";
2
+ import { t as isCodeFile } from "./project-root-C4ks_q1G.mjs";
3
+ //#region src/policy/detect-framework.ts
4
+ /**
5
+ * Detect the framework from a file path extension + content patterns.
6
+ * Aligned with the fusengine require-solid-read detection (distinct from
7
+ * {@link detectProjectType}, which scans config files on disk).
8
+ */
9
+ function detectFramework(filePath, content) {
10
+ if (/\.(tsx?|jsx?|vue|svelte)$/.test(filePath) || /from ['"]react|useState|className=/.test(content)) {
11
+ if (/(page|layout|loading|error|route)\.(ts|tsx)$/.test(filePath) || /use client|use server/.test(content)) return "nextjs";
12
+ return "react";
13
+ }
14
+ if (/\.swift$/.test(filePath)) return "swift";
15
+ if (/\.php$/.test(filePath)) return "laravel";
16
+ if (/\.java$/.test(filePath)) return "java";
17
+ if (/\.go$/.test(filePath)) return "go";
18
+ if (/\.rb$/.test(filePath)) return "ruby";
19
+ if (/\.rs$/.test(filePath)) return "rust";
20
+ if (/\.css$/.test(filePath) || /@tailwind|@apply/.test(content)) return "tailwind";
21
+ return "generic";
22
+ }
23
+ //#endregion
24
+ //#region src/policy/file-size.ts
25
+ /** Count lines in file content (empty string = 0). */
26
+ function countLines(content) {
27
+ return content === "" ? 0 : content.split("\n").length;
28
+ }
29
+ /**
30
+ * Evaluate a file's line count against the SOLID limit.
31
+ * @param lines - the file's line count
32
+ * @param max - the limit (defaults to `resolveMaxLines()`)
33
+ */
34
+ function evaluateFileSize(lines, max = resolveMaxLines()) {
35
+ if (lines <= max) return {
36
+ ok: true,
37
+ lines,
38
+ max,
39
+ message: null
40
+ };
41
+ return {
42
+ ok: false,
43
+ lines,
44
+ max,
45
+ message: `File has ${lines} lines (max: ${max}). Split into modules under ${splitTarget(max)} lines (Single Responsibility).`
46
+ };
47
+ }
48
+ //#endregion
49
+ //#region src/policy/patterns.ts
50
+ /**
51
+ * Guard pattern data, ported verbatim from the fusengine git/install guards.
52
+ * Note (faithful): `git push.*--force` also matches `--force-with-lease` —
53
+ * preserved from the source guard.
54
+ */
55
+ /** Destructive git operations to block outright. */
56
+ const GIT_BLOCKED = [
57
+ /git push.*--force/,
58
+ /git push.*-f/,
59
+ /git reset.*--hard/,
60
+ /git clean.*-fd/,
61
+ /git branch.*-D/,
62
+ /git rebase.*--force/
63
+ ];
64
+ /** Git operations that warrant a confirmation prompt. */
65
+ const GIT_ASK = [
66
+ /git push/,
67
+ /git checkout/,
68
+ /git reset/,
69
+ /git rebase/,
70
+ /git merge/,
71
+ /git stash/,
72
+ /git clean/,
73
+ /git rm/,
74
+ /git mv/,
75
+ /git restore/,
76
+ /git revert/,
77
+ /git cherry-pick/
78
+ ];
79
+ /** System-level package installs (need confirmation). */
80
+ const SYSTEM_INSTALL = [
81
+ /brew install/,
82
+ /brew upgrade/,
83
+ /brew cask/,
84
+ /apt install/,
85
+ /apt-get install/
86
+ ];
87
+ /** Project-level package installs. */
88
+ const PROJECT_INSTALL = [
89
+ /npm install/,
90
+ /npm i /,
91
+ /yarn add/,
92
+ /pnpm add/,
93
+ /pip install/,
94
+ /pip3 install/,
95
+ /composer require/,
96
+ /bun add/,
97
+ /bun install/,
98
+ /cargo install/,
99
+ /go install/,
100
+ /gem install/,
101
+ /pipx install/
102
+ ];
103
+ /** True when `cmd` matches any pattern in `patterns`. */
104
+ function matchPatterns(cmd, patterns) {
105
+ return patterns.some((re) => re.test(cmd));
106
+ }
107
+ //#endregion
108
+ //#region src/policy/guards/security.ts
109
+ /** Critical patterns that must always be blocked. */
110
+ const CRITICAL_PATTERNS = [
111
+ /\brm\s+(?:-[a-z]*\s+)*-[a-z]*[rf][a-z]*\s+(?:-[a-z]+\s+)*(?:\/|~)(?:\s|$)/,
112
+ /:\(\)\s*\{\s*:\s*\|\s*:\s*&\s*\}\s*;\s*:/,
113
+ /\b(?:curl|wget)\b[^|]*\|\s*(?:sudo\s+)?(?:ba|z|da|k)?sh\b/,
114
+ /\bchmod\s+(?:-[a-zA-Z]+\s+)*777\s+\//,
115
+ /\bmkfs(?:\.[a-z0-9]+)?\b/,
116
+ /\bdd\b[^\n]*\bif=\/dev\/zero\b[^\n]*\bof=\/dev\//
117
+ ];
118
+ /** Patterns that warrant explicit confirmation before running. */
119
+ const ASK_PATTERNS = [
120
+ /\bsudo\s/,
121
+ /\bchmod\s+(?:-[a-zA-Z]+\s+)*777\b/,
122
+ /\bchown\s+-R\b/,
123
+ /\beval\s/,
124
+ /(?:>|>>|\btee\b)\s*\/etc\//
125
+ ];
126
+ /** Guards against dangerous Bash commands (critical → block, sensitive → ask). */
127
+ function securityGuard(ctx) {
128
+ if (ctx.tool !== "Bash" || !ctx.command) return null;
129
+ const cmd = ctx.command;
130
+ for (const re of CRITICAL_PATTERNS) if (re.test(cmd)) return {
131
+ kind: "block",
132
+ title: "Dangerous command",
133
+ reason: "Command matches a destructive pattern (recursive root delete, fork bomb, remote-script piped to a shell, world-writable root, filesystem format, or disk overwrite).",
134
+ actions: ["Remove the destructive command", "Scope the operation to a specific safe path"]
135
+ };
136
+ for (const re of ASK_PATTERNS) if (re.test(cmd)) return {
137
+ kind: "ask",
138
+ title: "Dangerous command",
139
+ reason: "Command requests elevated privileges or alters sensitive targets (sudo, chmod 777, recursive chown, eval, or writing to /etc).",
140
+ actions: ["Confirm this command is intended", "Run with least privilege"]
141
+ };
142
+ return null;
143
+ }
144
+ //#endregion
145
+ //#region src/policy/guards/protected-path.ts
146
+ /** Path fragments that mark a location as internal/generated state (off-limits to Write/Edit). */
147
+ const PROTECTED_FRAGMENTS = [
148
+ ".claude/plugins/marketplaces",
149
+ ".claude/plugins/cache",
150
+ ".claude/logs/00-apex",
151
+ ".claude/fusengine-cache",
152
+ ".git/"
153
+ ];
154
+ /** Blocks direct edits to internal/generated state directories. */
155
+ function protectedPathGuard(ctx) {
156
+ if ((ctx.tool === "Write" || ctx.tool === "Edit") && ctx.filePath) {
157
+ const path = ctx.filePath;
158
+ if (PROTECTED_FRAGMENTS.some((fragment) => path.includes(fragment))) return {
159
+ kind: "block",
160
+ title: "Protected path",
161
+ reason: "This is internal/generated state — do not edit it directly.",
162
+ actions: ["Edit the source, not the generated/cache copy"]
163
+ };
164
+ }
165
+ return null;
166
+ }
167
+ //#endregion
168
+ //#region src/policy/guards/bash-write.ts
169
+ /** Redirect (`>`/`>>`) targeting a code-file extension. */
170
+ const CODE_REDIRECT = /(?:>>?)\s*[^\s|;&]*\.(?:ts|tsx|js|jsx|py|go|rb|rs|java|kt|php|swift|vue|svelte|c|cpp|h)\b/;
171
+ /** Interpreters / tools that mutate source in place, plus heredoc-into-file. */
172
+ const CODE_MUTATORS = /\bpython3?\s+-c\b|\bsed\s+-i\b|\bperl\s+-i\b|\bawk\s+-i\s+inplace\b|\bpatch\s+|<<[-~]?\s*['"]?\w+['"]?[\s\S]*?>/;
173
+ /** Redirect to a non-code file, or other ambiguous file writers (ASK). */
174
+ const ASK_WRITERS = /(?:>>?\s*[^\s|;&]+)|\btee\s+|\bdd\s+of=|\bnode\s+-e\b.*(?:writeFile|appendFile)|\bruby\s+-e\b.*File\.write/;
175
+ /**
176
+ * Blocks shell commands that mutate code files in place (and heredocs/redirects
177
+ * to source files); asks before other file-writing shell commands. Forces use
178
+ * of the Write/Edit tool so APEX/SOLID checks are not bypassed.
179
+ */
180
+ function bashWriteGuard(ctx) {
181
+ if (ctx.tool !== "Bash" || !ctx.command) return null;
182
+ const cmd = ctx.command;
183
+ if (CODE_MUTATORS.test(cmd) || CODE_REDIRECT.test(cmd)) return {
184
+ kind: "block",
185
+ title: "Bash write to code file",
186
+ reason: "Shell in-place edits / redirects to source files bypass APEX/SOLID checks.",
187
+ actions: ["Use the Write/Edit tool instead"]
188
+ };
189
+ if (ASK_WRITERS.test(cmd)) return {
190
+ kind: "ask",
191
+ title: "Bash file write",
192
+ reason: "This command writes a file from the shell; confirm it is intended.",
193
+ actions: ["Use the Write/Edit tool instead"]
194
+ };
195
+ return null;
196
+ }
197
+ //#endregion
198
+ //#region src/policy/guards/interface-separation.ts
199
+ /** TS/JS component files: top-level `interface`/`type Foo`. */
200
+ const TS_DECL_RE = /^\s*(export\s+)?(interface|type)\s+[A-Z]/m;
201
+ /** Python view models: class subclassing a schema/protocol base. */
202
+ const PY_MODEL_RE = /^\s*class\s+\w+\((BaseModel|TypedDict|Protocol)\)/m;
203
+ /** PHP controllers: top-level `interface` / `abstract class`. */
204
+ const PHP_DECL_RE = /^\s*(interface|abstract class)\b/m;
205
+ /** Swift views: top-level `protocol Foo`. */
206
+ const SWIFT_PROTO_RE = /^\s*protocol\s+[A-Z]/m;
207
+ /**
208
+ * Blocks top-level interface/type/protocol declarations in component, view or
209
+ * controller files (Interface Segregation). Fires only when BOTH the path
210
+ * category AND the content pattern match.
211
+ */
212
+ function interfaceSeparationGuard(ctx) {
213
+ if (ctx.tool !== "Write" && ctx.tool !== "Edit") return null;
214
+ const path = ctx.filePath;
215
+ const content = ctx.content;
216
+ if (!path || !content) return null;
217
+ const block = {
218
+ kind: "block",
219
+ title: "Separate the interface",
220
+ reason: "Top-level interface/type/protocol declarations belong in their own file, not in a component/view/controller.",
221
+ actions: ["Move the interface/type to its own file (Interface Segregation)"]
222
+ };
223
+ if (/\.(tsx|jsx|vue|svelte)$/.test(path) && TS_DECL_RE.test(content)) return block;
224
+ if (path.includes("views/") && /\.py$/.test(path) && PY_MODEL_RE.test(content)) return block;
225
+ if (path.includes("Controllers/") && /\.php$/.test(path) && PHP_DECL_RE.test(content)) return block;
226
+ if (path.includes("Views/") && /\.swift$/.test(path) && SWIFT_PROTO_RE.test(content)) return block;
227
+ return null;
228
+ }
229
+ //#endregion
230
+ //#region src/policy/guards/install.ts
231
+ /** Project-level dependency installs (npm/yarn/pnpm/bun/pip/cargo/go/gem/composer). */
232
+ const PROJECT_INSTALL_RE = /\b(?:npm\s+(?:install|i)|(?:yarn|pnpm|bun)\s+add|pip3?\s+install|cargo\s+install|go\s+install|gem\s+install|composer\s+require)\b/;
233
+ /** System-level package installs (brew/apt/apt-get/dnf/pacman). */
234
+ const SYSTEM_INSTALL_RE = /\b(?:brew\s+install|apt(?:-get)?\s+install|dnf\s+install|pacman\s+-S)\b/;
235
+ /** Asks for confirmation before a dependency or system package install. */
236
+ function installGuard(ctx) {
237
+ if (ctx.tool !== "Bash" || !ctx.command) return null;
238
+ const cmd = ctx.command;
239
+ if (PROJECT_INSTALL_RE.test(cmd) || SYSTEM_INSTALL_RE.test(cmd)) return {
240
+ kind: "ask",
241
+ title: "Dependency install",
242
+ reason: `This command installs packages: ${cmd.trim()}`,
243
+ actions: ["Confirm this install is intended"]
244
+ };
245
+ return null;
246
+ }
247
+ //#endregion
248
+ //#region src/policy/guards/index.ts
249
+ /** Ordered guard chain: critical/security + protected first, then writes/installs. */
250
+ const GUARDS = [
251
+ securityGuard,
252
+ protectedPathGuard,
253
+ bashWriteGuard,
254
+ interfaceSeparationGuard,
255
+ installGuard
256
+ ];
257
+ /** Run the guard chain; the first firing guard's Prompt wins, else null. */
258
+ function runGuards(ctx) {
259
+ for (const guard of GUARDS) {
260
+ const hit = guard(ctx);
261
+ if (hit) return hit;
262
+ }
263
+ return null;
264
+ }
265
+ //#endregion
266
+ //#region src/policy/evaluate.ts
267
+ /**
268
+ * Evaluate a single tool-use against the bundled policies, returning a pure
269
+ * decision plus a portable {@link Prompt}. Adapters translate the prompt into
270
+ * their harness's native response (Claude `permissionDecision`, etc.).
271
+ */
272
+ function evaluate(ctx) {
273
+ const guard = runGuards(ctx);
274
+ if (guard) return {
275
+ decision: "deny",
276
+ message: guard.reason,
277
+ prompt: guard
278
+ };
279
+ if (ctx.command && matchPatterns(ctx.command, GIT_BLOCKED)) {
280
+ const reason = `Destructive git command: ${ctx.command}`;
281
+ return {
282
+ decision: "deny",
283
+ message: reason,
284
+ prompt: {
285
+ kind: "block",
286
+ title: "Destructive git command",
287
+ reason,
288
+ actions: ["Use a non-destructive alternative (e.g. --force-with-lease; avoid --hard / -D)"]
289
+ }
290
+ };
291
+ }
292
+ if (ctx.filePath && isCodeFile(ctx.filePath) && ctx.content !== void 0) {
293
+ const verdict = evaluateFileSize(countLines(ctx.content), ctx.maxLines);
294
+ if (!verdict.ok) return {
295
+ decision: "deny",
296
+ message: verdict.message,
297
+ prompt: {
298
+ kind: "block",
299
+ title: "SOLID file-size limit",
300
+ reason: verdict.message ?? "",
301
+ actions: [`Split into modules under ${verdict.max} lines (Single Responsibility)`, "Then re-run the write"]
302
+ },
303
+ meta: {
304
+ framework: detectFramework(ctx.filePath, ctx.content),
305
+ lines: verdict.lines,
306
+ max: verdict.max
307
+ }
308
+ };
309
+ }
310
+ return {
311
+ decision: "allow",
312
+ message: null
313
+ };
314
+ }
315
+ //#endregion
316
+ export { PROJECT_INSTALL as C, evaluateFileSize as D, countLines as E, detectFramework as O, GIT_BLOCKED as S, matchPatterns as T, protectedPathGuard as _, SYSTEM_INSTALL_RE as a, securityGuard as b, PY_MODEL_RE as c, interfaceSeparationGuard as d, ASK_WRITERS as f, PROTECTED_FRAGMENTS as g, bashWriteGuard as h, PROJECT_INSTALL_RE as i, SWIFT_PROTO_RE as l, CODE_REDIRECT as m, GUARDS as n, installGuard as o, CODE_MUTATORS as p, runGuards as r, PHP_DECL_RE as s, evaluate as t, TS_DECL_RE as u, ASK_PATTERNS as v, SYSTEM_INSTALL as w, GIT_ASK as x, CRITICAL_PATTERNS as y };
@@ -1,4 +1,4 @@
1
- import { l as detectFramework, t as evaluate } from "./evaluate-CsYyUucy.mjs";
1
+ import { O as detectFramework, t as evaluate } from "./evaluate-DkTgwHNh.mjs";
2
2
  import { r as evaluateApex } from "./apex-gGrHzvM2.mjs";
3
3
  import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
4
4
  import { t as loadRefs } from "./loader-BephwI8n.mjs";
@@ -115,4 +115,73 @@ declare const APEX_GATES: ReadonlyArray<ApexGate>;
115
115
  */
116
116
  declare function evaluateApex(ctx: ApexContext, gates?: ReadonlyArray<ApexGate>): Prompt | null;
117
117
  //#endregion
118
- export { isApexCommand as C, detectProjectType as S, countLines as _, evaluateApex as a, DEV_KEYWORDS as b, PolicyContext as c, GIT_ASK as d, GIT_BLOCKED as f, FileSizeVerdict as g, matchPatterns as h, docConsultedGate as i, PolicyResult as l, SYSTEM_INSTALL as m, ApexContext as n, freshnessGate as o, PROJECT_INSTALL as p, ApexGate as r, solidReadGate as s, APEX_GATES as t, evaluate as u, evaluateFileSize as v, ProjectType as x, detectFramework as y };
118
+ //#region src/policy/guards/context.d.ts
119
+ /** Context handed to every guard in the chain. */
120
+ interface GuardContext {
121
+ tool: string;
122
+ filePath?: string;
123
+ content?: string;
124
+ command?: string;
125
+ }
126
+ /** A single guard: returns a blocking/asking Prompt, or null to continue. */
127
+ type Guard = (ctx: GuardContext) => Prompt | null;
128
+ //#endregion
129
+ //#region src/policy/guards/security.d.ts
130
+ /** Critical patterns that must always be blocked. */
131
+ declare const CRITICAL_PATTERNS: RegExp[];
132
+ /** Patterns that warrant explicit confirmation before running. */
133
+ declare const ASK_PATTERNS: RegExp[];
134
+ /** Guards against dangerous Bash commands (critical → block, sensitive → ask). */
135
+ declare function securityGuard(ctx: GuardContext): Prompt | null;
136
+ //#endregion
137
+ //#region src/policy/guards/protected-path.d.ts
138
+ /** Path fragments that mark a location as internal/generated state (off-limits to Write/Edit). */
139
+ declare const PROTECTED_FRAGMENTS: readonly string[];
140
+ /** Blocks direct edits to internal/generated state directories. */
141
+ declare function protectedPathGuard(ctx: GuardContext): Prompt | null;
142
+ //#endregion
143
+ //#region src/policy/guards/bash-write.d.ts
144
+ /** Redirect (`>`/`>>`) targeting a code-file extension. */
145
+ declare const CODE_REDIRECT: RegExp;
146
+ /** Interpreters / tools that mutate source in place, plus heredoc-into-file. */
147
+ declare const CODE_MUTATORS: RegExp;
148
+ /** Redirect to a non-code file, or other ambiguous file writers (ASK). */
149
+ declare const ASK_WRITERS: RegExp;
150
+ /**
151
+ * Blocks shell commands that mutate code files in place (and heredocs/redirects
152
+ * to source files); asks before other file-writing shell commands. Forces use
153
+ * of the Write/Edit tool so APEX/SOLID checks are not bypassed.
154
+ */
155
+ declare function bashWriteGuard(ctx: GuardContext): Prompt | null;
156
+ //#endregion
157
+ //#region src/policy/guards/interface-separation.d.ts
158
+ /** TS/JS component files: top-level `interface`/`type Foo`. */
159
+ declare const TS_DECL_RE: RegExp;
160
+ /** Python view models: class subclassing a schema/protocol base. */
161
+ declare const PY_MODEL_RE: RegExp;
162
+ /** PHP controllers: top-level `interface` / `abstract class`. */
163
+ declare const PHP_DECL_RE: RegExp;
164
+ /** Swift views: top-level `protocol Foo`. */
165
+ declare const SWIFT_PROTO_RE: RegExp;
166
+ /**
167
+ * Blocks top-level interface/type/protocol declarations in component, view or
168
+ * controller files (Interface Segregation). Fires only when BOTH the path
169
+ * category AND the content pattern match.
170
+ */
171
+ declare function interfaceSeparationGuard(ctx: GuardContext): Prompt | null;
172
+ //#endregion
173
+ //#region src/policy/guards/install.d.ts
174
+ /** Project-level dependency installs (npm/yarn/pnpm/bun/pip/cargo/go/gem/composer). */
175
+ declare const PROJECT_INSTALL_RE: RegExp;
176
+ /** System-level package installs (brew/apt/apt-get/dnf/pacman). */
177
+ declare const SYSTEM_INSTALL_RE: RegExp;
178
+ /** Asks for confirmation before a dependency or system package install. */
179
+ declare function installGuard(ctx: GuardContext): Prompt | null;
180
+ //#endregion
181
+ //#region src/policy/guards/index.d.ts
182
+ /** Ordered guard chain: critical/security + protected first, then writes/installs. */
183
+ declare const GUARDS: ReadonlyArray<Guard>;
184
+ /** Run the guard chain; the first firing guard's Prompt wins, else null. */
185
+ declare function runGuards(ctx: GuardContext): Prompt | null;
186
+ //#endregion
187
+ export { PolicyResult as A, detectFramework as B, ApexContext as C, freshnessGate as D, evaluateApex as E, SYSTEM_INSTALL as F, ProjectType as H, matchPatterns as I, FileSizeVerdict as L, GIT_ASK as M, GIT_BLOCKED as N, solidReadGate as O, PROJECT_INSTALL as P, countLines as R, APEX_GATES as S, docConsultedGate as T, detectProjectType as U, DEV_KEYWORDS as V, isApexCommand as W, ASK_PATTERNS as _, installGuard as a, Guard as b, SWIFT_PROTO_RE as c, ASK_WRITERS as d, CODE_MUTATORS as f, protectedPathGuard as g, PROTECTED_FRAGMENTS as h, SYSTEM_INSTALL_RE as i, evaluate as j, PolicyContext as k, TS_DECL_RE as l, bashWriteGuard as m, runGuards as n, PHP_DECL_RE as o, CODE_REDIRECT as p, PROJECT_INSTALL_RE as r, PY_MODEL_RE as s, GUARDS as t, interfaceSeparationGuard as u, CRITICAL_PATTERNS as v, ApexGate as w, GuardContext as x, securityGuard as y, evaluateFileSize as z };
package/dist/index.d.mts CHANGED
@@ -5,10 +5,10 @@ import { a as detectHarness, i as HarnessVia, n as HarnessInfo, o as detectMode,
5
5
  import { a as isDocConsulted, i as formatDocSatisfactionStatus, n as DocSatisfactionStatus, o as resolveSessions, r as formatDocDeny, t as AuthEntry } from "./doc-helpers-CG1nuf-c.mjs";
6
6
  import { t as incrementTrivialEditCounter } from "./index-BOBXQ91y.mjs";
7
7
  import { i as compactJson, n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./index-C1vLIMwN.mjs";
8
- import { C as isApexCommand, S as detectProjectType, _ as countLines, a as evaluateApex, b as DEV_KEYWORDS, c as PolicyContext, d as GIT_ASK, f as GIT_BLOCKED, g as FileSizeVerdict, h as matchPatterns, i as docConsultedGate, l as PolicyResult, m as SYSTEM_INSTALL, n as ApexContext, o as freshnessGate, p as PROJECT_INSTALL, r as ApexGate, s as solidReadGate, t as APEX_GATES, u as evaluate, v as evaluateFileSize, x as ProjectType, y as detectFramework } from "./index-BbJucvaG.mjs";
8
+ import { A as PolicyResult, B as detectFramework, C as ApexContext, D as freshnessGate, E as evaluateApex, F as SYSTEM_INSTALL, H as ProjectType, I as matchPatterns, L as FileSizeVerdict, M as GIT_ASK, N as GIT_BLOCKED, O as solidReadGate, P as PROJECT_INSTALL, R as countLines, S as APEX_GATES, T as docConsultedGate, U as detectProjectType, V as DEV_KEYWORDS, W as isApexCommand, _ as ASK_PATTERNS, a as installGuard, b as Guard, c as SWIFT_PROTO_RE, d as ASK_WRITERS, f as CODE_MUTATORS, g as protectedPathGuard, h as PROTECTED_FRAGMENTS, i as SYSTEM_INSTALL_RE, j as evaluate, k as PolicyContext, l as TS_DECL_RE, m as bashWriteGuard, n as runGuards, o as PHP_DECL_RE, p as CODE_REDIRECT, r as PROJECT_INSTALL_RE, s as PY_MODEL_RE, t as GUARDS, u as interfaceSeparationGuard, v as CRITICAL_PATTERNS, w as ApexGate, x as GuardContext, y as securityGuard, z as evaluateFileSize } from "./index-uEteukGR.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 setStateField, i as registryFile, l as stateFileFor, n as addRoot, o as nowStamp, r as readRoots, s as readState, t as ensureMemoryGitignore, u as throttleMs } from "./index-BEM-mQMC.mjs";
11
11
  import { a as globToRe, i as scoreReferences, n as toRefMeta, o as parseFrontmatter, r as routeReferences, t as loadRefs } from "./index-hL_r6tlc.mjs";
12
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-CPoF_hLP.mjs";
13
13
  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, ApexContext, ApexGate, ApexState, ApexTask, ApexTaskFile, AuthEntry, COLOR_THRESHOLDS, ColorFn, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, DocSatisfactionStatus, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GRADIENT_BLOCKS, HarnessId, HarnessInfo, HarnessMode, HarnessVia, IndexSummary, MAX_LINES_ENV_KEY, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INSTALL, Palette, PolicyContext, PolicyResult, ProgressBarOptions, ProjectType, Prompt, PromptKind, RefMeta, ReminderState, RouteResult, SYSTEM_INSTALL, ScoredRef, TIME_INTERVALS, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, colors, compactJson, compactMarkdown, countLines, detectFramework, detectHarness, detectMode, detectProjectType, docConsultedGate, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateApex, evaluateFileSize, extractText, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, isApexCommand, isCodeFile, isDocConsulted, jaccardSimilar, loadIndex, loadRefs, loadState, matchPatterns, modeFor, nowStamp, parseEnvInt, parseFrontmatter, progressiveColor, projectRoot, projectRootOrNull, queryHash, readRoots, readState, registryFile, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, saveState, scoreReferences, setStateField, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, toRefMeta, ttlLabel };
14
+ export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, ApexContext, ApexGate, ApexState, ApexTask, ApexTaskFile, AuthEntry, CODE_MUTATORS, CODE_REDIRECT, COLOR_THRESHOLDS, CRITICAL_PATTERNS, ColorFn, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, DocSatisfactionStatus, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GRADIENT_BLOCKS, GUARDS, Guard, GuardContext, HarnessId, HarnessInfo, HarnessMode, HarnessVia, IndexSummary, MAX_LINES_ENV_KEY, PHP_DECL_RE, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INSTALL, PROJECT_INSTALL_RE, PROTECTED_FRAGMENTS, PY_MODEL_RE, Palette, PolicyContext, PolicyResult, ProgressBarOptions, ProjectType, Prompt, PromptKind, RefMeta, ReminderState, RouteResult, SWIFT_PROTO_RE, SYSTEM_INSTALL, SYSTEM_INSTALL_RE, ScoredRef, TIME_INTERVALS, TS_DECL_RE, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, bashWriteGuard, colors, compactJson, compactMarkdown, countLines, detectFramework, detectHarness, detectMode, detectProjectType, docConsultedGate, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateApex, evaluateFileSize, extractText, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, installGuard, interfaceSeparationGuard, isApexCommand, isCodeFile, isDocConsulted, jaccardSimilar, loadIndex, loadRefs, loadState, matchPatterns, modeFor, nowStamp, parseEnvInt, parseFrontmatter, progressiveColor, projectRoot, projectRootOrNull, protectedPathGuard, queryHash, readRoots, readState, registryFile, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, runGuards, saveState, scoreReferences, securityGuard, setStateField, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, toRefMeta, ttlLabel };
package/dist/index.mjs CHANGED
@@ -4,7 +4,7 @@ import { t as compactJson } from "./compact-json-DK2nX-MK.mjs";
4
4
  import { n as projectRoot, r as projectRootOrNull, t as isCodeFile } from "./project-root-C4ks_q1G.mjs";
5
5
  import { n as detectMode, r as modeFor, t as detectHarness } from "./harness-C8Nxxyn_.mjs";
6
6
  import { n as detectProjectType, r as isApexCommand, t as DEV_KEYWORDS } from "./policy-C_pXmeNB.mjs";
7
- import { a as SYSTEM_INSTALL, c as evaluateFileSize, i as PROJECT_INSTALL, l as detectFramework, n as GIT_ASK, o as matchPatterns, r as GIT_BLOCKED, s as countLines, t as evaluate } from "./evaluate-CsYyUucy.mjs";
7
+ import { C as PROJECT_INSTALL, D as evaluateFileSize, E as countLines, O as detectFramework, S as GIT_BLOCKED, T as matchPatterns, _ as protectedPathGuard, a as SYSTEM_INSTALL_RE, b as securityGuard, c as PY_MODEL_RE, d as interfaceSeparationGuard, f as ASK_WRITERS, g as PROTECTED_FRAGMENTS, h as bashWriteGuard, i as PROJECT_INSTALL_RE, l as SWIFT_PROTO_RE, m as CODE_REDIRECT, n as GUARDS, o as installGuard, p as CODE_MUTATORS, r as runGuards, s as PHP_DECL_RE, t as evaluate, u as TS_DECL_RE, v as ASK_PATTERNS, w as SYSTEM_INSTALL, x as GIT_ASK, y as CRITICAL_PATTERNS } from "./evaluate-DkTgwHNh.mjs";
8
8
  import { i as resolveSessions, n as formatDocSatisfactionStatus, r as isDocConsulted, t as formatDocDeny } from "./doc-helpers-Dd_x1-tZ.mjs";
9
9
  import { i as parseFrontmatter, n as scoreReferences, r as globToRe, t as routeReferences } from "./router-Dj3AfgBE.mjs";
10
10
  import { a as solidReadGate, i as freshnessGate, n as docConsultedGate, r as evaluateApex, t as APEX_GATES } from "./apex-gGrHzvM2.mjs";
@@ -15,4 +15,4 @@ import { t as incrementTrivialEditCounter } from "./freshness-BK9Xg6oG.mjs";
15
15
  import { n as toRefMeta, t as loadRefs } from "./loader-BephwI8n.mjs";
16
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-Bc4wdnCG.mjs";
17
17
  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, COLOR_THRESHOLDS, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, GIT_ASK, GIT_BLOCKED, GRADIENT_BLOCKS, MAX_LINES_ENV_KEY, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INSTALL, SYSTEM_INSTALL, TIME_INTERVALS, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, colors, compactJson, compactMarkdown, countLines, detectFramework, detectHarness, detectMode, detectProjectType, docConsultedGate, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateApex, evaluateFileSize, extractText, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, isApexCommand, isCodeFile, isDocConsulted, jaccardSimilar, loadIndex, loadRefs, loadState, matchPatterns, modeFor, nowStamp, parseEnvInt, parseFrontmatter, progressiveColor, projectRoot, projectRootOrNull, queryHash, readRoots, readState, registryFile, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, saveState, scoreReferences, setStateField, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, toRefMeta, ttlLabel };
18
+ export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, COLOR_THRESHOLDS, CRITICAL_PATTERNS, DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, DEV_KEYWORDS, GIT_ASK, GIT_BLOCKED, GRADIENT_BLOCKS, GUARDS, MAX_LINES_ENV_KEY, PHP_DECL_RE, PROGRESS_BAR_DEFAULTS, PROGRESS_CHARS, PROJECT_INSTALL, PROJECT_INSTALL_RE, PROTECTED_FRAGMENTS, PY_MODEL_RE, SWIFT_PROTO_RE, SYSTEM_INSTALL, SYSTEM_INSTALL_RE, TIME_INTERVALS, TS_DECL_RE, TTL_ENV_KEY, acquireLock, addRoot, apexStateDir, bashWriteGuard, colors, compactJson, compactMarkdown, countLines, detectFramework, detectHarness, detectMode, detectProjectType, docConsultedGate, ensureMemoryGitignore, ensureStateDir, evaluate, evaluateApex, evaluateFileSize, extractText, formatBasename, formatCost, formatDocDeny, formatDocSatisfactionStatus, formatPath, formatPrompt, formatTimeLeft, formatTokens, freshnessGate, generateGradientBar, generateProgressBar, globToRe, incrementTrivialEditCounter, installGuard, interfaceSeparationGuard, isApexCommand, isCodeFile, isDocConsulted, jaccardSimilar, loadIndex, loadRefs, loadState, matchPatterns, modeFor, nowStamp, parseEnvInt, parseFrontmatter, progressiveColor, projectRoot, projectRootOrNull, protectedPathGuard, queryHash, readRoots, readState, registryFile, resolveMaxLines, resolveSessions, resolveTtlSec, routeReferences, runGuards, saveState, scoreReferences, securityGuard, setStateField, solidReadGate, splitTarget, stateFileFor, stateFilePath, summarizeIndex, taskComplete, taskCreate, taskStart, throttleMs, toRefMeta, ttlLabel };
@@ -1,2 +1,2 @@
1
- import { C as isApexCommand, S as detectProjectType, _ as countLines, a as evaluateApex, b as DEV_KEYWORDS, c as PolicyContext, d as GIT_ASK, f as GIT_BLOCKED, g as FileSizeVerdict, h as matchPatterns, i as docConsultedGate, l as PolicyResult, m as SYSTEM_INSTALL, n as ApexContext, o as freshnessGate, p as PROJECT_INSTALL, r as ApexGate, s as solidReadGate, t as APEX_GATES, u as evaluate, v as evaluateFileSize, x as ProjectType, y as detectFramework } from "../index-BbJucvaG.mjs";
2
- export { APEX_GATES, ApexContext, ApexGate, DEV_KEYWORDS, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, PROJECT_INSTALL, PolicyContext, PolicyResult, ProjectType, SYSTEM_INSTALL, countLines, detectFramework, detectProjectType, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, freshnessGate, isApexCommand, matchPatterns, solidReadGate };
1
+ import { A as PolicyResult, B as detectFramework, C as ApexContext, D as freshnessGate, E as evaluateApex, F as SYSTEM_INSTALL, H as ProjectType, I as matchPatterns, L as FileSizeVerdict, M as GIT_ASK, N as GIT_BLOCKED, O as solidReadGate, P as PROJECT_INSTALL, R as countLines, S as APEX_GATES, T as docConsultedGate, U as detectProjectType, V as DEV_KEYWORDS, W as isApexCommand, _ as ASK_PATTERNS, a as installGuard, b as Guard, c as SWIFT_PROTO_RE, d as ASK_WRITERS, f as CODE_MUTATORS, g as protectedPathGuard, h as PROTECTED_FRAGMENTS, i as SYSTEM_INSTALL_RE, j as evaluate, k as PolicyContext, l as TS_DECL_RE, m as bashWriteGuard, n as runGuards, o as PHP_DECL_RE, p as CODE_REDIRECT, r as PROJECT_INSTALL_RE, s as PY_MODEL_RE, t as GUARDS, u as interfaceSeparationGuard, v as CRITICAL_PATTERNS, w as ApexGate, x as GuardContext, y as securityGuard, z as evaluateFileSize } from "../index-uEteukGR.mjs";
2
+ export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, ApexContext, ApexGate, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, FileSizeVerdict, GIT_ASK, GIT_BLOCKED, GUARDS, Guard, GuardContext, PHP_DECL_RE, PROJECT_INSTALL, PROJECT_INSTALL_RE, PROTECTED_FRAGMENTS, PY_MODEL_RE, PolicyContext, PolicyResult, ProjectType, SWIFT_PROTO_RE, SYSTEM_INSTALL, SYSTEM_INSTALL_RE, TS_DECL_RE, bashWriteGuard, countLines, detectFramework, detectProjectType, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, freshnessGate, installGuard, interfaceSeparationGuard, isApexCommand, matchPatterns, protectedPathGuard, runGuards, securityGuard, solidReadGate };
@@ -1,4 +1,4 @@
1
1
  import { n as detectProjectType, r as isApexCommand, t as DEV_KEYWORDS } from "../policy-C_pXmeNB.mjs";
2
- import { a as SYSTEM_INSTALL, c as evaluateFileSize, i as PROJECT_INSTALL, l as detectFramework, n as GIT_ASK, o as matchPatterns, r as GIT_BLOCKED, s as countLines, t as evaluate } from "../evaluate-CsYyUucy.mjs";
2
+ import { C as PROJECT_INSTALL, D as evaluateFileSize, E as countLines, O as detectFramework, S as GIT_BLOCKED, T as matchPatterns, _ as protectedPathGuard, a as SYSTEM_INSTALL_RE, b as securityGuard, c as PY_MODEL_RE, d as interfaceSeparationGuard, f as ASK_WRITERS, g as PROTECTED_FRAGMENTS, h as bashWriteGuard, i as PROJECT_INSTALL_RE, l as SWIFT_PROTO_RE, m as CODE_REDIRECT, n as GUARDS, o as installGuard, p as CODE_MUTATORS, r as runGuards, s as PHP_DECL_RE, t as evaluate, u as TS_DECL_RE, v as ASK_PATTERNS, w as SYSTEM_INSTALL, x as GIT_ASK, y as CRITICAL_PATTERNS } from "../evaluate-DkTgwHNh.mjs";
3
3
  import { a as solidReadGate, i as freshnessGate, n as docConsultedGate, r as evaluateApex, t as APEX_GATES } from "../apex-gGrHzvM2.mjs";
4
- export { APEX_GATES, DEV_KEYWORDS, GIT_ASK, GIT_BLOCKED, PROJECT_INSTALL, SYSTEM_INSTALL, countLines, detectFramework, detectProjectType, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, freshnessGate, isApexCommand, matchPatterns, solidReadGate };
4
+ export { APEX_GATES, ASK_PATTERNS, ASK_WRITERS, CODE_MUTATORS, CODE_REDIRECT, CRITICAL_PATTERNS, DEV_KEYWORDS, GIT_ASK, GIT_BLOCKED, GUARDS, PHP_DECL_RE, PROJECT_INSTALL, PROJECT_INSTALL_RE, PROTECTED_FRAGMENTS, PY_MODEL_RE, SWIFT_PROTO_RE, SYSTEM_INSTALL, SYSTEM_INSTALL_RE, TS_DECL_RE, bashWriteGuard, countLines, detectFramework, detectProjectType, docConsultedGate, evaluate, evaluateApex, evaluateFileSize, freshnessGate, installGuard, interfaceSeparationGuard, isApexCommand, matchPatterns, protectedPathGuard, runGuards, securityGuard, solidReadGate };
@@ -1,5 +1,5 @@
1
1
  import { t as isCodeFile } from "./project-root-C4ks_q1G.mjs";
2
- import { t as evaluate } from "./evaluate-CsYyUucy.mjs";
2
+ import { t as evaluate } from "./evaluate-DkTgwHNh.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,2 +1,2 @@
1
- import { a as trackFile, c as REQUIRED_AGENTS, i as recordActivity, l as gate, n as harnessTrackDir, o as normalizeEvent, r as respond, s as DEFAULT_WINDOW_MS, t as handleHook, u as activityFor } from "../handle-Lz_thVKr.mjs";
1
+ import { a as trackFile, c as REQUIRED_AGENTS, i as recordActivity, l as gate, n as harnessTrackDir, o as normalizeEvent, r as respond, s as DEFAULT_WINDOW_MS, t as handleHook, u as activityFor } from "../handle-BUyS6NU6.mjs";
2
2
  export { DEFAULT_WINDOW_MS, REQUIRED_AGENTS, activityFor, gate, handleHook, harnessTrackDir, normalizeEvent, recordActivity, respond, trackFile };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusengine/harness",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
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",
@@ -1,152 +0,0 @@
1
- import { i as splitTarget, r as resolveMaxLines } from "./limits-CHn8AIL1.mjs";
2
- import { t as isCodeFile } from "./project-root-C4ks_q1G.mjs";
3
- //#region src/policy/detect-framework.ts
4
- /**
5
- * Detect the framework from a file path extension + content patterns.
6
- * Aligned with the fusengine require-solid-read detection (distinct from
7
- * {@link detectProjectType}, which scans config files on disk).
8
- */
9
- function detectFramework(filePath, content) {
10
- if (/\.(tsx?|jsx?|vue|svelte)$/.test(filePath) || /from ['"]react|useState|className=/.test(content)) {
11
- if (/(page|layout|loading|error|route)\.(ts|tsx)$/.test(filePath) || /use client|use server/.test(content)) return "nextjs";
12
- return "react";
13
- }
14
- if (/\.swift$/.test(filePath)) return "swift";
15
- if (/\.php$/.test(filePath)) return "laravel";
16
- if (/\.java$/.test(filePath)) return "java";
17
- if (/\.go$/.test(filePath)) return "go";
18
- if (/\.rb$/.test(filePath)) return "ruby";
19
- if (/\.rs$/.test(filePath)) return "rust";
20
- if (/\.css$/.test(filePath) || /@tailwind|@apply/.test(content)) return "tailwind";
21
- return "generic";
22
- }
23
- //#endregion
24
- //#region src/policy/file-size.ts
25
- /** Count lines in file content (empty string = 0). */
26
- function countLines(content) {
27
- return content === "" ? 0 : content.split("\n").length;
28
- }
29
- /**
30
- * Evaluate a file's line count against the SOLID limit.
31
- * @param lines - the file's line count
32
- * @param max - the limit (defaults to `resolveMaxLines()`)
33
- */
34
- function evaluateFileSize(lines, max = resolveMaxLines()) {
35
- if (lines <= max) return {
36
- ok: true,
37
- lines,
38
- max,
39
- message: null
40
- };
41
- return {
42
- ok: false,
43
- lines,
44
- max,
45
- message: `File has ${lines} lines (max: ${max}). Split into modules under ${splitTarget(max)} lines (Single Responsibility).`
46
- };
47
- }
48
- //#endregion
49
- //#region src/policy/patterns.ts
50
- /**
51
- * Guard pattern data, ported verbatim from the fusengine git/install guards.
52
- * Note (faithful): `git push.*--force` also matches `--force-with-lease` —
53
- * preserved from the source guard.
54
- */
55
- /** Destructive git operations to block outright. */
56
- const GIT_BLOCKED = [
57
- /git push.*--force/,
58
- /git push.*-f/,
59
- /git reset.*--hard/,
60
- /git clean.*-fd/,
61
- /git branch.*-D/,
62
- /git rebase.*--force/
63
- ];
64
- /** Git operations that warrant a confirmation prompt. */
65
- const GIT_ASK = [
66
- /git push/,
67
- /git checkout/,
68
- /git reset/,
69
- /git rebase/,
70
- /git merge/,
71
- /git stash/,
72
- /git clean/,
73
- /git rm/,
74
- /git mv/,
75
- /git restore/,
76
- /git revert/,
77
- /git cherry-pick/
78
- ];
79
- /** System-level package installs (need confirmation). */
80
- const SYSTEM_INSTALL = [
81
- /brew install/,
82
- /brew upgrade/,
83
- /brew cask/,
84
- /apt install/,
85
- /apt-get install/
86
- ];
87
- /** Project-level package installs. */
88
- const PROJECT_INSTALL = [
89
- /npm install/,
90
- /npm i /,
91
- /yarn add/,
92
- /pnpm add/,
93
- /pip install/,
94
- /pip3 install/,
95
- /composer require/,
96
- /bun add/,
97
- /bun install/,
98
- /cargo install/,
99
- /go install/,
100
- /gem install/,
101
- /pipx install/
102
- ];
103
- /** True when `cmd` matches any pattern in `patterns`. */
104
- function matchPatterns(cmd, patterns) {
105
- return patterns.some((re) => re.test(cmd));
106
- }
107
- //#endregion
108
- //#region src/policy/evaluate.ts
109
- /**
110
- * Evaluate a single tool-use against the bundled policies, returning a pure
111
- * decision plus a portable {@link Prompt}. Adapters translate the prompt into
112
- * their harness's native response (Claude `permissionDecision`, etc.).
113
- */
114
- function evaluate(ctx) {
115
- if (ctx.command && matchPatterns(ctx.command, GIT_BLOCKED)) {
116
- const reason = `Destructive git command: ${ctx.command}`;
117
- return {
118
- decision: "deny",
119
- message: reason,
120
- prompt: {
121
- kind: "block",
122
- title: "Destructive git command",
123
- reason,
124
- actions: ["Use a non-destructive alternative (e.g. --force-with-lease; avoid --hard / -D)"]
125
- }
126
- };
127
- }
128
- if (ctx.filePath && isCodeFile(ctx.filePath) && ctx.content !== void 0) {
129
- const verdict = evaluateFileSize(countLines(ctx.content), ctx.maxLines);
130
- if (!verdict.ok) return {
131
- decision: "deny",
132
- message: verdict.message,
133
- prompt: {
134
- kind: "block",
135
- title: "SOLID file-size limit",
136
- reason: verdict.message ?? "",
137
- actions: [`Split into modules under ${verdict.max} lines (Single Responsibility)`, "Then re-run the write"]
138
- },
139
- meta: {
140
- framework: detectFramework(ctx.filePath, ctx.content),
141
- lines: verdict.lines,
142
- max: verdict.max
143
- }
144
- };
145
- }
146
- return {
147
- decision: "allow",
148
- message: null
149
- };
150
- }
151
- //#endregion
152
- export { SYSTEM_INSTALL as a, evaluateFileSize as c, PROJECT_INSTALL as i, detectFramework as l, GIT_ASK as n, matchPatterns as o, GIT_BLOCKED as r, countLines as s, evaluate as t };