@fusengine/harness 0.1.79 → 0.1.81

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.
Files changed (76) hide show
  1. package/README.md +14 -1
  2. package/dist/adapters/claude/index.d.mts +1 -1
  3. package/dist/adapters/claude/index.mjs +1 -1
  4. package/dist/adapters/cline/index.mjs +1 -1
  5. package/dist/adapters/codex/index.d.mts +11 -12
  6. package/dist/adapters/codex/index.mjs +3 -3
  7. package/dist/adapters/cursor/index.d.mts +29 -29
  8. package/dist/adapters/cursor/index.mjs +1 -1
  9. package/dist/adapters/gemini/index.mjs +1 -1
  10. package/dist/adapters/hermes/index.d.mts +22 -23
  11. package/dist/adapters/hermes/index.mjs +1 -1
  12. package/dist/adapters/kimi/index.d.mts +87 -0
  13. package/dist/adapters/kimi/index.mjs +2 -0
  14. package/dist/cache/index.d.mts +1 -1
  15. package/dist/{claude-51RSspJ1.mjs → claude-D93HY8dq.mjs} +2 -2
  16. package/dist/cli/bin.d.mts +1 -1
  17. package/dist/cli/bin.mjs +130 -39
  18. package/dist/cli/index.d.mts +3 -3
  19. package/dist/cli/index.mjs +1 -1
  20. package/dist/config/index.d.mts +2 -2
  21. package/dist/config/index.mjs +4 -4
  22. package/dist/detect/index.d.mts +2 -1
  23. package/dist/detect/index.mjs +1 -1
  24. package/dist/{doc-helpers-CEKzGg2u.d.mts → doc-helpers-BGCzP9VF.d.mts} +12 -12
  25. package/dist/{dotenv-Jj8aL1FL.mjs → dotenv-DoqNlALG.mjs} +31 -3
  26. package/dist/{evaluate-ClfbCDiY.mjs → evaluate-B4-MhOy_.mjs} +322 -32
  27. package/dist/freshness/index.d.mts +2 -2
  28. package/dist/{handle-Dthtlp7Z.mjs → handle-J5r2f_O_.mjs} +665 -164
  29. package/dist/{harness-Cb9xR8dC.mjs → harness-BMuLJ9lm.mjs} +4 -2
  30. package/dist/{hermes-rTmVdhUL.mjs → hermes-1PUEoY8q.mjs} +2 -2
  31. package/dist/{home-state-BXf38Zi1.mjs → home-state-oUGFB4ds.mjs} +4 -2
  32. package/dist/index-84heAAm_.d.mts +12 -0
  33. package/dist/index-CaxrMD1A.d.mts +1 -0
  34. package/dist/index-CigBu4K9.d.mts +14 -0
  35. package/dist/{index-DGxNjXW7.d.mts → index-D4C2-IIc.d.mts} +6 -8
  36. package/dist/index-DBgnIZn9.d.mts +756 -0
  37. package/dist/{index-mmRF3KNp.d.mts → index-DEfz82BP.d.mts} +12 -13
  38. package/dist/{index-BUwEmIK-.d.mts → index-DhmV2MPh.d.mts} +31 -31
  39. package/dist/index-oXXPs2xl.d.mts +119 -0
  40. package/dist/index-p9fLrSOD.d.mts +27 -0
  41. package/dist/index.d.mts +11 -11
  42. package/dist/index.mjs +9 -9
  43. package/dist/init/index.d.mts +8 -9
  44. package/dist/init/index.mjs +1 -1
  45. package/dist/kimi-ChbcU2uI.mjs +94 -0
  46. package/dist/{layout-C0jaaCQC.mjs → layout-KWoE_Mqn.mjs} +1 -0
  47. package/dist/limits-DG5pl-5s.mjs +59 -0
  48. package/dist/memory/index.mjs +1 -1
  49. package/dist/policy/index.d.mts +2 -3
  50. package/dist/policy/index.mjs +4 -4
  51. package/dist/prompt/index.d.mts +2 -1
  52. package/dist/refs/index.d.mts +1 -1
  53. package/dist/{registry-CymilZiZ.mjs → registry-IhHk2KlT.mjs} +1 -1
  54. package/dist/{run-3tyTW9Ud.mjs → run-D_WchZ3R.mjs} +1 -1
  55. package/dist/{run-Do2JltgU.mjs → run-TAXNRSpD.mjs} +1 -1
  56. package/dist/runtime/index.d.mts +455 -446
  57. package/dist/runtime/index.mjs +3 -3
  58. package/dist/{session-state-CY4iohn_.d.mts → session-state-D5gLr66m.d.mts} +29 -30
  59. package/dist/{skill-path-BO2N0XvB.mjs → skill-path-DhBGlQe3.mjs} +3 -3
  60. package/dist/{store-Bcn08y9m.mjs → store-yr_QFsZY.mjs} +101 -13
  61. package/dist/tracking/index.d.mts +22 -13
  62. package/dist/tracking/index.mjs +2 -2
  63. package/dist/{types-DVbIl9md.d.mts → types-C0-igRKr.d.mts} +8 -8
  64. package/dist/types-DvXTI71X.d.mts +15 -0
  65. package/dist/util/index.d.mts +1 -1
  66. package/dist/{validate-DhOX5hDK.mjs → validate-Bf-EsbDh.mjs} +348 -32
  67. package/package.json +163 -158
  68. package/dist/apex-Wdi1nq_w.d.mts +0 -73
  69. package/dist/harness-s1Fce_dL.d.mts +0 -27
  70. package/dist/index-BEMumjOw.d.mts +0 -27
  71. package/dist/index-BIGVNQB8.d.mts +0 -576
  72. package/dist/index-BKZ67WMa.d.mts +0 -1
  73. package/dist/index-BOBXQ91y.d.mts +0 -12
  74. package/dist/index-BVVgDSdq.d.mts +0 -1
  75. package/dist/index-jj_EzZRv.d.mts +0 -96
  76. package/dist/limits-CHn8AIL1.mjs +0 -31
@@ -1,576 +0,0 @@
1
- import { t as Prompt } from "./types-DVbIl9md.mjs";
2
-
3
- //#region src/policy/detect-project.d.ts
4
- /** Project types detected from filesystem indicators. */
5
- type ProjectType = "nextjs" | "nuxt" | "angular" | "svelte" | "vue" | "react" | "tailwind" | "laravel" | "rails" | "django" | "python" | "go" | "rust" | "swift" | "java" | "scala" | "elixir" | "ruby" | "generic";
6
- /** Keywords that signal a development task (APEX trigger). */
7
- declare const DEV_KEYWORDS: RegExp;
8
- /** True when the prompt invokes the /apex command. */
9
- declare function isApexCommand(prompt: string): boolean;
10
- /** Modular architecture variants layered on top of the framework. */
11
- type ModularArchitecture = "fusecore" | "nextjs-modular" | null;
12
- /**
13
- * Detect a project-internal modular architecture (a sub-architecture the
14
- * framework-level {@link detectProjectType} doesn't capture): Fusengine's
15
- * FuseCore (Laravel) or a `modules/`-based Next.js layout.
16
- */
17
- declare function detectModularArchitecture(dir: string): ModularArchitecture;
18
- /**
19
- * Resolve the skill a detected modular architecture forces.
20
- *
21
- * Ports the Python `check-nextjs-skill.py` / `check-laravel-skill.py` gates:
22
- * when the project is detected on disk as a modular architecture, a specific
23
- * skill is required ('solid-nextjs' for nextjs-modular, 'fusecore' for
24
- * fusecore). Returns `null` when no modular architecture is detected.
25
- *
26
- * @param cwd - Project root directory to scan.
27
- * @returns The forced skill name, or `null` when none applies.
28
- */
29
- declare function requiredArchSkill(cwd: string): string | null;
30
- /** Detect the project type by scanning config files in `dir`. */
31
- declare function detectProjectType(dir: string): ProjectType;
32
- //#endregion
33
- //#region src/policy/detect-framework.d.ts
34
- /**
35
- * Detect a file's framework as the intersection of the REAL project (its nearest
36
- * manifest's capabilities) and the file's own extension/content signal. A
37
- * backend `.ts` in a react project is `generic` (no react signal) — fixing the
38
- * old extension-only default that flagged every `.ts` as react. Fail-open: any
39
- * error yields `"generic"`, never throws. Return values stay within the existing
40
- * union ("react" | "nextjs" | "laravel" | "swift" | "tailwind" | "java" | "go" |
41
- * "ruby" | "rust" | "generic") — no new labels.
42
- * @param filePath - Path of the file being written/edited.
43
- * @param content - Its (incoming) content, for JS content signals.
44
- * @param cwd - Root to resolve a relative `filePath` against (default cwd).
45
- * @returns A framework label from the existing union.
46
- */
47
- declare function detectFramework(filePath: string, content: string, cwd?: string): string;
48
- //#endregion
49
- //#region src/policy/file-size.d.ts
50
- /**
51
- * Fixed marketplace plugins root — parity with Python `enforce-file-size.py`'s
52
- * literal, unexpanded `~/...` string. Exported: reused by
53
- * `policy/apex.ts::solidReadGate` for its "no reference matched" deny message.
54
- */
55
- declare const PLUGINS_DIR = "~/.claude/plugins/marketplaces/fusengine-plugins/plugins";
56
- /**
57
- * Skill-dir fragment per framework — parity with Python
58
- * `enforce-file-size.py::get_solid_ref()` (falls back to `generic/`). Exported:
59
- * reused by `policy/apex.ts::solidReadGate` (see {@link PLUGINS_DIR}).
60
- */
61
- declare const SOLID_REF: Record<string, string>;
62
- /** Verdict from {@link evaluateFileSize}. */
63
- interface FileSizeVerdict {
64
- ok: boolean;
65
- lines: number;
66
- max: number;
67
- message: string | null;
68
- }
69
- /**
70
- * Count physical lines — parity with the Python `enforce-file-size.py`
71
- * (`sum(1 for _ in f)`): every line counts (blanks and comments included), and a
72
- * single trailing newline does not add a phantom line. The SOLID ceiling is
73
- * measured on raw file length, not substantive code, to match the upstream plugin.
74
- */
75
- declare function countLines(content: string): number;
76
- /**
77
- * Count non-empty, non-comment lines — parity with the Python `count_code_lines`
78
- * shared by the framework-specific SOLID validators: `_shared/scripts/validate_solid_common.py`
79
- * (imported by `nextjs-expert/scripts/validate-nextjs-solid.py` and
80
- * `swift-apple-expert/scripts/validate-swift-solid.py`), duplicated verbatim in
81
- * `react-expert/scripts/validate-react-solid.py` / `laravel-expert/scripts/validate-laravel-solid.py`.
82
- * Strips blank lines and lines starting with `//` or `*` — a SINGLE fixed rule
83
- * for all 4 callers (the Python `comment` param defaults to, and every real
84
- * call site leaves it at, `"//"` — never per-language despite covering
85
- * ts/tsx/js/jsx, php and swift).
86
- *
87
- * Deliberately distinct from two other "code-only" counters already in this
88
- * repo, neither of which is a faithful substitute here:
89
- * - `countLoc` (`runtime/lifecycle/check-file-size.ts`): a genuinely
90
- * per-language table (PHP additionally strips `#`, Python strips
91
- * `#`/`"""`/`'''`) — ported from the unrelated `solid/scripts/check-file-size.py`.
92
- * - `countCodeLines` (`runtime/lifecycle/aipilot/solid-compliance.ts`): also
93
- * strips `#` — ported from `ai-pilot/scripts/check-solid-compliance.py`.
94
- * Reusing either would silently strip PHP `#`/Python-style comments that the
95
- * real react/nextjs/laravel/swift validators do NOT strip.
96
- * @param content - The file content to measure.
97
- */
98
- declare function countFrameworkCodeLines(content: string): number;
99
- /**
100
- * Evaluate a file's line count against the SOLID limit.
101
- * @param lines - the file's line count
102
- * @param max - the limit (defaults to `resolveMaxLines()`)
103
- */
104
- declare function evaluateFileSize(lines: number, max?: number, filePath?: string, framework?: string, displayLines?: number): FileSizeVerdict;
105
- //#endregion
106
- //#region src/policy/patterns.d.ts
107
- /** Destructive git operations to block outright. */
108
- declare const GIT_BLOCKED: ReadonlyArray<RegExp>;
109
- /** Git operations that warrant a confirmation prompt. */
110
- declare const GIT_ASK: ReadonlyArray<RegExp>;
111
- /** System-level package installs (need confirmation). */
112
- declare const SYSTEM_INSTALL: ReadonlyArray<RegExp>;
113
- /** Project-level package installs. */
114
- declare const PROJECT_INSTALL: ReadonlyArray<RegExp>;
115
- /** True when `cmd` matches any pattern in `patterns`. */
116
- declare function matchPatterns(cmd: string, patterns: ReadonlyArray<RegExp>): boolean;
117
- /** Git commands exempt from confirmation when Ralph mode is on (parity git-guard.py RALPH_SAFE). */
118
- declare const RALPH_SAFE: ReadonlyArray<string>;
119
- /**
120
- * OPT-IN autonomous "Ralph" mode: OFF unless `RALPH_MODE` is `1`/`true`, read
121
- * fresh on each call. Only the env var activates it — the Python source also
122
- * auto-enabled on a `.claude/ralph/prd.json` file or a `feature/*` branch, but
123
- * those silent activations are dropped here: a mode that removes git/install
124
- * confirmations must never turn on implicitly (owner: default OFF, env opt-in).
125
- */
126
- declare function isRalphMode(): boolean;
127
- //#endregion
128
- //#region src/policy/interfaces/types.d.ts
129
- /** Harness-agnostic input to {@link evaluate}. */
130
- interface PolicyContext {
131
- /** Tool name (e.g. "Write", "Edit", "Bash"). */
132
- tool: string;
133
- filePath?: string;
134
- content?: string;
135
- command?: string;
136
- /** Optional override for the SOLID max-lines limit. */
137
- maxLines?: number;
138
- /** Subagent type — `Explore`/`Plan` are exempt from the file-size gate. */
139
- agentType?: string;
140
- /** Line count of the existing on-disk file (so an Edit on an oversized file blocks). */
141
- existingLines?: number;
142
- /** Edit only: full on-disk content, read once by the runtime (runtime/gate-helpers.ts::existingLineCounts) — lets evaluate() compute the exact post-edit line count instead of judging the stale pre-edit count alone. Undefined when unreadable/missing (fail-closed to the existingLines-only behavior). */
143
- existingContent?: string;
144
- /** Edit only: the tool_input.old_string being replaced (runtime/normalize.ts). Undefined for Write (no such field) — fail-closed. */
145
- oldString?: string;
146
- /** Edit only: the tool_input.replace_all flag — every occurrence of old_string is replaced, not just the first. */
147
- isReplaceAll?: boolean;
148
- /** Codex-only, populated by handle-pre.ts from the resolved `permission_mode` of an `approval_policy=never` session (adapters/codex/permission-mode.ts) — auto-approve gate, wired through evaluate.ts's anti-chaining check. */
149
- neverApproval?: boolean;
150
- }
151
- /** Harness-agnostic policy decision (+ a portable prompt for adapters to render). */
152
- interface PolicyResult {
153
- decision: "allow" | "deny" | "warn";
154
- message: string | null;
155
- prompt?: Prompt;
156
- meta?: Record<string, unknown>;
157
- }
158
- //#endregion
159
- //#region src/policy/evaluate.d.ts
160
- /**
161
- * Evaluate a single tool-use against the bundled policies, returning a pure
162
- * decision plus a portable {@link Prompt}. Adapters translate the prompt into
163
- * their harness's native response (Claude `permissionDecision`, etc.).
164
- */
165
- declare function evaluate(ctx: PolicyContext): PolicyResult;
166
- //#endregion
167
- //#region src/policy/guards/context.d.ts
168
- /** Context handed to every guard in the chain. */
169
- interface GuardContext {
170
- tool: string;
171
- filePath?: string;
172
- content?: string;
173
- command?: string;
174
- }
175
- /** A single guard: returns a blocking/asking Prompt, or null to continue. */
176
- type Guard = (ctx: GuardContext) => Prompt | null;
177
- //#endregion
178
- //#region src/policy/guards/security.d.ts
179
- /** A pattern paired with the violation label to name in the deny/ask reason. */
180
- interface LabeledPattern {
181
- re: RegExp;
182
- label: string;
183
- }
184
- /** Critical patterns that must always be blocked — parity `security_rules.py`'s cumulated violation names. */
185
- declare const CRITICAL_PATTERNS: LabeledPattern[];
186
- /** Patterns that warrant explicit confirmation before running — parity `security_rules.py`'s ask-level violation names. */
187
- declare const ASK_PATTERNS: LabeledPattern[];
188
- /**
189
- * Guards against dangerous Bash commands. Parity `security_rules.validate_command`
190
- * + `security-guard.py`: ACCUMULATE every matched violation, then deny when any
191
- * critical matched else ask, joining all violation labels in the reason. The
192
- * generic `rm` ask is exempt when the command targets a trash location (parity
193
- * `not re.search('trash', cmd)`).
194
- */
195
- declare function securityGuard(ctx: GuardContext): Prompt | null;
196
- //#endregion
197
- //#region src/policy/guards/protected-path.d.ts
198
- /**
199
- * Path fragments that mark a location as internal/generated state.
200
- *
201
- * Parity with safe_paths.py: `~/.fuse-harness/cache` is a *writable*
202
- * cache the harness owns (lessons, MCP cache, per-type state) — only the
203
- * `cache/sessions` subtree is protected, not the whole cache.
204
- */
205
- declare const PROTECTED_FRAGMENTS: readonly string[];
206
- /**
207
- * Matches a real `.git` directory segment (`/.git/`, `~/.git`, leading or
208
- * trailing `.git`) without matching unrelated names like `foo.git/` or
209
- * `.github/`. Kept separate from the substring fragments for precise scoping.
210
- */
211
- declare const PROTECTED_GIT_RE: RegExp;
212
- /**
213
- * Blocks direct edits to internal/generated state directories.
214
- *
215
- * Covers:
216
- * - Write / Edit tool calls whose `filePath` targets a protected fragment.
217
- * - Bash commands whose actual write *target* is a protected fragment
218
- * (read sources are ignored; see `extractWriteTargets`).
219
- *
220
- * @param ctx - The guard context (tool, filePath, command).
221
- * @returns A blocking {@link Prompt}, or null to allow.
222
- */
223
- declare function protectedPathGuard(ctx: GuardContext): Prompt | null;
224
- //#endregion
225
- //#region src/policy/guards/bash-write-patterns.d.ts
226
- /** Redirect (`>`/`>>`) targeting a code-file extension. */
227
- declare const CODE_REDIRECT: RegExp;
228
- /**
229
- * Interpreters / tools that mutate source in place, plus heredoc-into-file —
230
- * split into labeled sub-patterns (parity bash-write-guard.py `DENY_PATTERNS`,
231
- * each with its own `desc`) so the deny reason names which motif matched
232
- * instead of a single generic message. Every command-named motif is
233
- * {@link CMD}-anchored (start/separator + optional wrapper chain); only the
234
- * structural heredoc-into-file motif is position-free.
235
- */
236
- declare const CODE_MUTATORS: readonly {
237
- re: RegExp;
238
- desc: string;
239
- }[];
240
- /** Redirect to a non-code file. Excludes `/dev/null`, `2>`/`N>` and `>&N` fd
241
- * redirects via the `(?<![0-9&])` lookbehind + `(?!…|&)` (parity has_file_redirect). */
242
- declare const FILE_REDIRECT: RegExp;
243
- /** Other ambiguous file writers (ASK): `tee <file>` (not `tee -a`/path) and `dd … of=` —
244
- * labeled sub-patterns (parity bash-write-guard.py `ASK_PATTERNS`). */
245
- declare const ASK_WRITERS: readonly {
246
- re: RegExp;
247
- desc: string;
248
- }[];
249
- /** Commands whose first token never writes, skipped when a real redirect is
250
- * present (parity bash-write-guard.py `SAFE_PREFIXES`). */
251
- declare const SAFE_PREFIXES: readonly string[];
252
- /**
253
- * Session-state directory the freshness/APEX gates rely on. Any Bash command
254
- * touching it is a hook-bypass vector, so it is blocked outright — a blunt
255
- * substring match (read OR write), parity with bash-write-guard.py DENY_PATTERNS
256
- * `fusengine-cache/sessions` (rebranded to the harness cache path).
257
- */
258
- declare const SESSION_STATE_FRAGMENT = ".fuse-harness/cache/sessions";
259
- //#endregion
260
- //#region src/policy/guards/bash-write.d.ts
261
- /**
262
- * Blocks shell commands that mutate code files in place (and heredocs/redirects
263
- * to source files); asks before other file-writing shell commands unless the
264
- * target is a harness-owned safe path. Forces use of the Write/Edit tool so
265
- * APEX/SOLID checks are not bypassed.
266
- *
267
- * The code-write detectors (CODE_MUTATORS, CODE_COMMAND_WRITE) run BEFORE the
268
- * SAFE_PREFIXES short-circuit: they are command-position anchored
269
- * (bash-command-anchor.ts), so a transparent wrapper (`env sed -i src/x.ts`,
270
- * `timeout 5 patch`, `cp a b; tee src/y.ts`) can no longer smuggle a code write
271
- * past its safe first token, while a quoted mention (`git commit -m "fix sed -i"`)
272
- * still falls through. The short-circuit becomes the terminal allow — "first
273
- * token never writes, nothing above matched".
274
- */
275
- declare function bashWriteGuard(ctx: GuardContext): Prompt | null;
276
- //#endregion
277
- //#region src/policy/guards/interface-separation.d.ts
278
- /** TS/JS component files: top-level `interface`/`type Foo`. */
279
- declare const TS_DECL_RE: RegExp;
280
- /** Python view models: class subclassing a schema/protocol base. */
281
- declare const PY_MODEL_RE: RegExp;
282
- /**
283
- * PHP controllers: top-level `interface`, `abstract class`, or a concrete
284
- * `class …Interface/DTO/Request`. Union of the TS-only `abstract class` rule
285
- * and the Python rule (`class [A-Z].*(Interface|DTO|Request)`, enforce-interfaces.py:16).
286
- */
287
- declare const PHP_DECL_RE: RegExp;
288
- /** Swift views: top-level `protocol Foo`. */
289
- declare const SWIFT_PROTO_RE: RegExp;
290
- /** Go handlers/controllers: top-level `type Foo interface`. */
291
- declare const GO_DECL_RE: RegExp;
292
- /** Java/Kotlin controllers/handlers: top-level `interface`/`record`. */
293
- declare const JAVA_DECL_RE: RegExp;
294
- /** Rust: top-level `trait Foo` declaration (captures the name for impl co-location). */
295
- declare const RUST_DECL_RE: RegExp;
296
- /**
297
- * Blocks top-level interface/type/protocol declarations in component, view or
298
- * controller files (Interface Segregation). Fires only when BOTH the path
299
- * category AND the content pattern match.
300
- *
301
- * Destination text for TS/JS/Vue/Svelte, PHP and Swift matches the user's own
302
- * `claude-rules/rules/04-solid-dry-rules.md` ("SOLID Skill per Stack" table),
303
- * the current authoritative convention — NOT the older `enforce-interfaces.py`
304
- * text, which this guard originally ported. Go/Python/Java/Kotlin aren't
305
- * covered by that table, so their destinations stay as a reasonable default.
306
- *
307
- * Parity note: enforce-interfaces.py only inspects `Write` (tool_input.content).
308
- * We deliberately also fire on `Edit` — an in-place edit can introduce the same
309
- * violation — and the path fragments accept singular *and* plural directory
310
- * names (`view/` + `views/`), mirroring the Python `s?` regexes.
311
- */
312
- declare function interfaceSeparationGuard(ctx: GuardContext): Prompt | null;
313
- //#endregion
314
- //#region src/policy/guards/install.d.ts
315
- /**
316
- * Asks for confirmation before a dependency or system package install. In Ralph
317
- * mode (opt-in `RALPH_MODE`) a PROJECT install is auto-approved for autonomous
318
- * runs (parity install-guard.py:52), but a SYSTEM install always asks.
319
- */
320
- declare function installGuard(ctx: GuardContext): Prompt | null;
321
- //#endregion
322
- //#region src/policy/guards/index.d.ts
323
- /** Ordered guard chain: critical/security + protected first, then writes/installs. */
324
- declare const GUARDS: ReadonlyArray<Guard>;
325
- /** Block prompt returned when a guard or gate throws (fail-closed). */
326
- declare const FAIL_CLOSED: Prompt;
327
- /** Register a user guard — runs AFTER the privileged core chain (two-tier). */
328
- declare function registerGuard(guard: Guard): void;
329
- /** Remove all registered user guards (mainly for tests). */
330
- declare function clearUserGuards(): void;
331
- /**
332
- * Run the guard chain — privileged core guards first, then user guards — and
333
- * return the first firing Prompt, else null. Fail-closed: a guard that throws
334
- * blocks (never silently passes).
335
- */
336
- declare function runGuards(ctx: GuardContext): Prompt | null;
337
- //#endregion
338
- //#region src/policy/creation-intent.d.ts
339
- /**
340
- * True when a prompt expresses creation intent (a new feature/component) and is
341
- * not a fix/refactor — the signal that brainstorming should precede creation.
342
- * The harness calls this on UserPromptSubmit, then `recordBrainstormRequired`.
343
- */
344
- declare function detectCreationIntent(prompt: string): boolean;
345
- //#endregion
346
- //#region src/policy/verbosity.d.ts
347
- /** Max results an exa MCP call may request. */
348
- declare const MAX_EXA_RESULTS = 3;
349
- /** Max token budget for exa `tokensNum` / context7 `tokens`. */
350
- declare const MAX_TOKENS = 2e3;
351
- /**
352
- * Cap an MCP call's verbosity — exa `numResults` ≤ 3 (+ `tokensNum` ≤ 2000),
353
- * Context7 `tokens` ≤ 2000. Returns the capped input (a mutation for the harness
354
- * to apply) when a change is needed, else null.
355
- */
356
- declare function capVerbosity(tool: string, input: Record<string, unknown>): Record<string, unknown> | null;
357
- //#endregion
358
- //#region src/policy/framework-solid.d.ts
359
- /**
360
- * Framework-specific SOLID gate. Dispatches by extension/path to the matching
361
- * validator (React, Next.js, Laravel, Swift, Go, Rust) and returns a blocking
362
- * {@link Prompt} when any BLOCKING rule fires, or `null` when clean. Excluded
363
- * build/dependency paths (node_modules, dist, build, .next, vendor, .build,
364
- * DerivedData, Pods) early-return `null` to avoid false positives. Go and Rust
365
- * have no exclusion list yet (no vendor/target FPs reported) — additive only.
366
- * @param filePath - absolute path of the file being written/edited
367
- * @param content - the file (or new) content under validation
368
- * @param fileLines - full on-disk line count (set on Edit so a partial
369
- * `new_string` snippet still judges the whole file, mirroring the base
370
- * file-size guard / Python `get_full_file_content`). Omit on Write.
371
- */
372
- declare function frameworkSolidGate(filePath: string, content: string, fileLines?: number): Prompt | null;
373
- //#endregion
374
- //#region src/policy/skill-trigger-patterns.d.ts
375
- /** Map of required sub-skill name → triggering code patterns, keyed by framework. */
376
- declare const SKILL_TRIGGERS: Readonly<Record<string, Readonly<Record<string, ReadonlyArray<string>>>>>;
377
- //#endregion
378
- //#region src/policy/skill-triggers.d.ts
379
- /**
380
- * Detect which sub-skills the written `content` requires for a `framework`.
381
- * Faithful to the Python `detect_required_skills`: first matching pattern per
382
- * skill wins. Most frameworks match case-insensitively (source `re.IGNORECASE`);
383
- * `swift` matches case-sensitively (see {@link CASE_SENSITIVE_FRAMEWORKS}).
384
- * @param framework - "react" | "nextjs" | "laravel" | "swift".
385
- * @param content - the code being written.
386
- * @returns required sub-skill names (empty when framework unknown / no match).
387
- */
388
- declare function detectRequiredSkills(framework: string, content: string): string[];
389
- /**
390
- * True when `filePath`/`content` match the Python Tailwind gate's trigger
391
- * condition. React/Next.js components embed Tailwind utility classes in
392
- * `className` — this check fires IN ADDITION TO the primary framework gate,
393
- * never instead of it: {@link detectFramework} keeps returning "react"/
394
- * "nextjs" for these files (framework SOLID rules stay correct).
395
- */
396
- declare function usesTailwindUtilities(filePath: string, content: string): boolean;
397
- /**
398
- * Block when a required sub-skill's `skills/<name>/` path is absent from
399
- * `refsRead`. Mirrors `specific_skill_consulted`, which confirms a skill was
400
- * read by checking the tracking file contains `skills/<name>/`.
401
- * @param framework - "react" | "nextjs" | "laravel".
402
- * @param content - the code being written.
403
- * @param refsRead - in-session read reference paths.
404
- * @param forcedSkill - a skill the detected modular architecture forces (optional).
405
- * @param cwd - project root; when set and not a shadcn project, `*-shadcn`
406
- * requirements are skipped (ports the Python `is_shadcn_project` filter).
407
- * @param filePath - the file being written; when it's a `.tsx`/`.jsx` file
408
- * with Tailwind utility classes in `className`, the "tailwind" domain
409
- * skills are merged in alongside `framework`'s own (ports the separate
410
- * `check-tailwind-skill.py` gate, independent of react/nextjs).
411
- * @returns a `block` Prompt naming the missing sub-skills, or `null` when satisfied.
412
- */
413
- declare function skillTriggerGate(framework: string, content: string, refsRead: readonly string[], forcedSkill?: string | null, cwd?: string, filePath?: string): Prompt | null;
414
- //#endregion
415
- //#region src/policy/detect-claude-md-project-type.d.ts
416
- /**
417
- * Detect the project type from the cwd, reproducing the legacy Python logic:
418
- * package.json containing "next" → nextjs, else "react" → react; else
419
- * composer.json+artisan → laravel; else Package.swift / *.xcodeproj → swift;
420
- * else generic.
421
- * @param cwd - Project root to scan.
422
- * @returns The detected project type label.
423
- */
424
- declare function detectClaudeMdProjectType(cwd: string): ProjectType;
425
- //#endregion
426
- //#region src/policy/claude-md-context.d.ts
427
- /** Dev-verb regex (FR/EN) that triggers the APEX preamble (case-insensitive). */
428
- declare const DEV_VERBS: RegExp;
429
- /**
430
- * Build the APEX instruction preamble for a development task.
431
- * @param projectType - Detected project type label.
432
- * @param maxLines - SOLID per-file line ceiling.
433
- * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
434
- * @returns The APEX instruction text.
435
- */
436
- declare function buildApexInstruction(projectType: ProjectType, maxLines: number, id?: string): string;
437
- /**
438
- * Build the UserPromptSubmit injection text: read the target's root
439
- * instructions doc (`~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md`, ...) and,
440
- * when the prompt matches a dev verb, prepend the APEX instruction. Returns
441
- * `null` when the doc is absent/unreadable (the hook then emits nothing).
442
- * @param prompt - The raw user prompt.
443
- * @param cwd - Project root (for project-type detection).
444
- * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
445
- * @returns The injection text, or `null` to emit nothing.
446
- */
447
- declare function buildClaudeMdContext(prompt: string, cwd: string, id?: string): string | null;
448
- //#endregion
449
- //#region src/policy/apex-task-context.d.ts
450
- /** Parsed task state injected into a Task sub-agent prompt. */
451
- interface ApexTaskState {
452
- /** Current task id (defaults to "1"). */
453
- id: string;
454
- /** Task subject (defaults to ""). */
455
- subject: string;
456
- /** Current phase (defaults to "analyze"). */
457
- phase: string;
458
- /** Comma-joined consulted doc keys, or "none". */
459
- docs: string;
460
- }
461
- /**
462
- * Read the current task state from `task.json`, reproducing the legacy Python
463
- * logic. Any read/parse error falls back to `("1", "", "analyze", "none")`.
464
- * @param taskFile - Absolute path to `.claude/apex/task.json`.
465
- * @returns The parsed {@link ApexTaskState}.
466
- */
467
- declare function loadApexTaskState(taskFile: string): ApexTaskState;
468
- /**
469
- * Build the APEX context string injected into a Task sub-agent prompt.
470
- * @param state - The parsed task state.
471
- * @param maxLines - SOLID per-file line ceiling.
472
- * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
473
- * @returns The injection text.
474
- */
475
- declare function buildApexTaskContext(state: ApexTaskState, maxLines: number, id?: string): string;
476
- /**
477
- * Build the PreToolUse Task injection, gated on the existence of the
478
- * project's target apex dir (`.claude/apex/`, `.codex/apex/`, ...). Returns
479
- * `null` when APEX is not active (no dir).
480
- * @param projectRoot - `CLAUDE_PROJECT_DIR` or cwd.
481
- * @param id - Harness target id (defaults to "claude-code" — zero-regression default).
482
- * @returns The injection text, or `null` to emit nothing.
483
- */
484
- declare function buildApexTaskInjection(projectRoot: string, id?: string): string | null;
485
- //#endregion
486
- //#region src/policy/cartographer/indicators.d.ts
487
- /**
488
- * Cartographer indicators — pure data sets used to detect a project root and to
489
- * exclude noise directories when walking a tree. Ports the constant tables from
490
- * `generate_project_map.py` / `write_recursive.py`.
491
- */
492
- /** Filenames whose presence marks a directory as a project root. */
493
- declare const PROJECT_INDICATORS: ReadonlySet<string>;
494
- /** Directory names skipped entirely during the tree walk. */
495
- declare const EXCLUDE_DIRS: ReadonlySet<string>;
496
- //#endregion
497
- //#region src/policy/cartographer/frontmatter.d.ts
498
- /**
499
- * Extract a single frontmatter field's value from `text`. Strips surrounding
500
- * quotes; skips YAML block-scalar markers. Returns "" when absent.
501
- * @param text - The full document text.
502
- * @param field - The frontmatter key to read.
503
- * @returns The field value, or "".
504
- */
505
- declare function parseField(text: string, field: string): string;
506
- /**
507
- * Derive a short description from the body following the frontmatter: the first
508
- * non-empty trimmed line, sliced to `maxLen`. Returns "" when none.
509
- * @param text - The full document text.
510
- * @param maxLen - Maximum length of the returned description.
511
- * @returns The body-derived description, or "".
512
- */
513
- declare function parseBodyDesc(text: string, maxLen?: number): string;
514
- //#endregion
515
- //#region src/policy/cartographer/entry.d.ts
516
- /**
517
- * Tree-entry parsing — pure line regexes. Ports the line parsers of
518
- * `merge_index.py` and `track-enrichment.py`.
519
- */
520
- /** A parsed `prefix[name](path) — desc` tree line. */
521
- interface TreeEntry {
522
- prefix: string;
523
- name: string;
524
- path: string;
525
- desc: string;
526
- }
527
- /**
528
- * Parse a `merge_index` tree line into its parts. Returns null on no match.
529
- * @param line - The raw tree line.
530
- * @returns The parsed entry, or null.
531
- */
532
- declare function parseEntry(line: string): TreeEntry | null;
533
- /**
534
- * Parse an enrichment line into `[path, desc]`, requiring a non-empty desc.
535
- * @param line - The raw index line.
536
- * @returns The `[path, desc]` pair, or null.
537
- */
538
- declare function parseEnrichment(line: string): [string, string] | null;
539
- //#endregion
540
- //#region src/policy/cartographer/describe.d.ts
541
- /**
542
- * First `# ` Markdown heading text (sans hashes), sliced to 60. "" when none.
543
- * @param text - The document text.
544
- * @returns The heading text, or "".
545
- */
546
- declare function firstHeading(text: string): string;
547
- /**
548
- * First leading comment among the first 10 lines (`//`, `#` but not `#!`, or a
549
- * `"""`/`'''` docstring), sliced to 60. "" when none.
550
- * @param text - The source text.
551
- * @returns The comment text, or "".
552
- */
553
- declare function firstComment(text: string): string;
554
- /**
555
- * Derive a description from a file's suffix + text. For `.md`, the supplied
556
- * frontmatter `description` (truncated) wins over the first heading; for known
557
- * source suffixes, the first comment; else "".
558
- * @param suffix - The file extension (with dot).
559
- * @param text - The file text.
560
- * @param mdField - The pre-parsed frontmatter `description` (md only).
561
- * @returns The derived description, or "".
562
- */
563
- declare function descFromText(suffix: string, text: string, mdField: string): string;
564
- //#endregion
565
- //#region src/policy/seo/validate.d.ts
566
- /** True when `path` is an HTML-like file the SEO hook should validate. */
567
- declare function isHtmlLike(path: string): boolean;
568
- /**
569
- * Report the SEO elements missing from HTML-like content (title, meta
570
- * description, OG title/description/image, canonical, JSON-LD schema).
571
- * @param html - The file content.
572
- * @returns The missing element labels (empty when complete).
573
- */
574
- declare function missingSeoElements(html: string): string[];
575
- //#endregion
576
- export { protectedPathGuard as $, FAIL_CLOSED as A, RUST_DECL_RE as B, usesTailwindUtilities as C, DEV_KEYWORDS as Ct, MAX_TOKENS as D, detectProjectType as Dt, MAX_EXA_RESULTS as E, detectModularArchitecture as Et, installGuard as F, ASK_WRITERS as G, TS_DECL_RE as H, GO_DECL_RE as I, FILE_REDIRECT as J, CODE_MUTATORS as K, JAVA_DECL_RE as L, clearUserGuards as M, registerGuard as N, capVerbosity as O, isApexCommand as Ot, runGuards as P, PROTECTED_GIT_RE as Q, PHP_DECL_RE as R, skillTriggerGate as S, detectFramework as St, frameworkSolidGate as T, ProjectType as Tt, interfaceSeparationGuard as U, SWIFT_PROTO_RE as V, bashWriteGuard as W, SESSION_STATE_FRAGMENT as X, SAFE_PREFIXES as Y, PROTECTED_FRAGMENTS as Z, DEV_VERBS as _, PLUGINS_DIR as _t, firstHeading as a, GuardContext as at, detectClaudeMdProjectType as b, countLines as bt, parseEntry as c, PolicyResult as ct, EXCLUDE_DIRS as d, PROJECT_INSTALL as dt, ASK_PATTERNS as et, PROJECT_INDICATORS as f, RALPH_SAFE as ft, loadApexTaskState as g, FileSizeVerdict as gt, buildApexTaskInjection as h, matchPatterns as ht, firstComment as i, Guard as it, GUARDS as j, detectCreationIntent as k, requiredArchSkill as kt, parseBodyDesc as l, GIT_ASK as lt, buildApexTaskContext as m, isRalphMode as mt, missingSeoElements as n, LabeledPattern as nt, TreeEntry as o, evaluate as ot, ApexTaskState as p, SYSTEM_INSTALL as pt, CODE_REDIRECT as q, descFromText as r, securityGuard as rt, parseEnrichment as s, PolicyContext as st, isHtmlLike as t, CRITICAL_PATTERNS as tt, parseField as u, GIT_BLOCKED as ut, buildApexInstruction as v, SOLID_REF as vt, SKILL_TRIGGERS as w, ModularArchitecture as wt, detectRequiredSkills as x, evaluateFileSize as xt, buildClaudeMdContext as y, countFrameworkCodeLines as yt, PY_MODEL_RE as z };
@@ -1 +0,0 @@
1
- export { };
@@ -1,12 +0,0 @@
1
- //#region src/freshness/trivial-edit-counter.d.ts
2
- /**
3
- * Increment a session's trivial-edit counter, evicting timestamps older than
4
- * `windowMs`. Decoupled + injectable `now` for testability.
5
- * @param filePath - session state file path
6
- * @param windowMs - sliding window in ms
7
- * @param now - current epoch ms (defaults to `Date.now()`)
8
- * @returns number of trivial edits within the window (including this one)
9
- */
10
- declare function incrementTrivialEditCounter(filePath: string, windowMs: number, now?: number): Promise<number>;
11
- //#endregion
12
- export { incrementTrivialEditCounter as t };
@@ -1 +0,0 @@
1
- export { };