@fusengine/harness 0.1.80 → 0.1.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/claude/index.d.mts +1 -1
- package/dist/adapters/claude/index.mjs +1 -1
- package/dist/adapters/cline/index.mjs +1 -1
- package/dist/adapters/codex/index.d.mts +11 -12
- package/dist/adapters/codex/index.mjs +3 -3
- package/dist/adapters/cursor/index.d.mts +29 -29
- package/dist/adapters/cursor/index.mjs +1 -1
- package/dist/adapters/gemini/index.mjs +1 -1
- package/dist/adapters/hermes/index.d.mts +22 -23
- package/dist/adapters/hermes/index.mjs +1 -1
- package/dist/adapters/kimi/index.d.mts +54 -46
- package/dist/adapters/kimi/index.mjs +2 -2
- package/dist/cache/index.d.mts +1 -1
- package/dist/{claude-51RSspJ1.mjs → claude-D93HY8dq.mjs} +2 -2
- package/dist/cli/bin.d.mts +1 -1
- package/dist/cli/bin.mjs +129 -38
- package/dist/cli/index.d.mts +3 -3
- package/dist/cli/index.mjs +1 -1
- package/dist/config/index.d.mts +2 -2
- package/dist/config/index.mjs +4 -4
- package/dist/detect/index.d.mts +2 -1
- package/dist/{doc-helpers-CEKzGg2u.d.mts → doc-helpers-BGCzP9VF.d.mts} +12 -12
- package/dist/{dotenv-B26N_uGr.mjs → dotenv-DoqNlALG.mjs} +29 -2
- package/dist/{evaluate-ClfbCDiY.mjs → evaluate-B4-MhOy_.mjs} +322 -32
- package/dist/freshness/index.d.mts +2 -2
- package/dist/{handle-B7YufFz9.mjs → handle-F35Gx-QS.mjs} +596 -174
- package/dist/{hermes-rTmVdhUL.mjs → hermes-1PUEoY8q.mjs} +2 -2
- package/dist/{home-state-BXf38Zi1.mjs → home-state-oUGFB4ds.mjs} +4 -2
- package/dist/index-84heAAm_.d.mts +12 -0
- package/dist/index-CaxrMD1A.d.mts +1 -0
- package/dist/index-CigBu4K9.d.mts +14 -0
- package/dist/{index-DGxNjXW7.d.mts → index-D4C2-IIc.d.mts} +6 -8
- package/dist/index-DBgnIZn9.d.mts +756 -0
- package/dist/{index-mmRF3KNp.d.mts → index-DEfz82BP.d.mts} +12 -13
- package/dist/{index-BUwEmIK-.d.mts → index-DhmV2MPh.d.mts} +31 -31
- package/dist/index-oXXPs2xl.d.mts +119 -0
- package/dist/index-p9fLrSOD.d.mts +27 -0
- package/dist/index.d.mts +11 -11
- package/dist/index.mjs +8 -8
- package/dist/init/index.d.mts +8 -9
- package/dist/init/index.mjs +1 -1
- package/dist/{kimi-C7FGprQz.mjs → kimi-ChbcU2uI.mjs} +17 -3
- package/dist/{layout-C0jaaCQC.mjs → layout-KWoE_Mqn.mjs} +1 -0
- package/dist/limits-DG5pl-5s.mjs +59 -0
- package/dist/memory/index.mjs +1 -1
- package/dist/policy/index.d.mts +2 -3
- package/dist/policy/index.mjs +4 -4
- package/dist/prompt/index.d.mts +2 -1
- package/dist/refs/index.d.mts +1 -1
- package/dist/{registry-CymilZiZ.mjs → registry-IhHk2KlT.mjs} +1 -1
- package/dist/{run-3tyTW9Ud.mjs → run-D_WchZ3R.mjs} +1 -1
- package/dist/{run-Do2JltgU.mjs → run-TAXNRSpD.mjs} +1 -1
- package/dist/runtime/index.d.mts +453 -451
- package/dist/runtime/index.mjs +3 -3
- package/dist/{session-state-CY4iohn_.d.mts → session-state-D5gLr66m.d.mts} +29 -30
- package/dist/{skill-path-CDvR4bbF.mjs → skill-path-DhBGlQe3.mjs} +2 -2
- package/dist/store-Dw08Amqh.mjs +845 -0
- package/dist/tracking/index.d.mts +23 -13
- package/dist/tracking/index.mjs +2 -2
- package/dist/{types-DVbIl9md.d.mts → types-C0-igRKr.d.mts} +8 -8
- package/dist/types-DvXTI71X.d.mts +15 -0
- package/dist/util/index.d.mts +1 -1
- package/dist/{validate-CkmquRDV.mjs → validate-Bf-EsbDh.mjs} +279 -20
- package/package.json +163 -163
- package/dist/apex-Wdi1nq_w.d.mts +0 -73
- package/dist/harness-BQ5_Wnva.d.mts +0 -27
- package/dist/index-BEMumjOw.d.mts +0 -27
- package/dist/index-BIGVNQB8.d.mts +0 -576
- package/dist/index-BKZ67WMa.d.mts +0 -1
- package/dist/index-BOBXQ91y.d.mts +0 -12
- package/dist/index-BVVgDSdq.d.mts +0 -1
- package/dist/index-B_VHbsaJ.d.mts +0 -96
- package/dist/limits-CHn8AIL1.mjs +0 -31
- package/dist/store-nDZ3eLBQ.mjs +0 -349
|
@@ -0,0 +1,756 @@
|
|
|
1
|
+
import { t as Prompt } from "./types-C0-igRKr.mjs";
|
|
2
|
+
import { t as AuthEntry } from "./doc-helpers-BGCzP9VF.mjs";
|
|
3
|
+
import { t as RefMeta } from "./types-CY5qT2X1.mjs";
|
|
4
|
+
//#region src/policy/detect-project.d.ts
|
|
5
|
+
/** Project types detected from filesystem indicators. */
|
|
6
|
+
type ProjectType = "nextjs" | "nuxt" | "angular" | "svelte" | "vue" | "react" | "tailwind" | "laravel" | "rails" | "django" | "python" | "go" | "rust" | "swift" | "java" | "scala" | "elixir" | "ruby" | "generic";
|
|
7
|
+
/** Keywords that signal a development task (APEX trigger). */
|
|
8
|
+
declare const DEV_KEYWORDS: RegExp;
|
|
9
|
+
/** True when the prompt invokes the /apex command. */
|
|
10
|
+
declare function isApexCommand(prompt: string): boolean;
|
|
11
|
+
/** Modular architecture variants layered on top of the framework. */
|
|
12
|
+
type ModularArchitecture = "fusecore" | "nextjs-modular" | null;
|
|
13
|
+
/**
|
|
14
|
+
* Detect a project-internal modular architecture (a sub-architecture the
|
|
15
|
+
* framework-level {@link detectProjectType} doesn't capture): Fusengine's
|
|
16
|
+
* FuseCore (Laravel) or a `modules/`-based Next.js layout.
|
|
17
|
+
*/
|
|
18
|
+
declare function detectModularArchitecture(dir: string): ModularArchitecture;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the skill a detected modular architecture forces.
|
|
21
|
+
*
|
|
22
|
+
* Ports the Python `check-nextjs-skill.py` / `check-laravel-skill.py` gates:
|
|
23
|
+
* when the project is detected on disk as a modular architecture, a specific
|
|
24
|
+
* skill is required ('solid-nextjs' for nextjs-modular, 'fusecore' for
|
|
25
|
+
* fusecore). Returns `null` when no modular architecture is detected.
|
|
26
|
+
*
|
|
27
|
+
* @param cwd - Project root directory to scan.
|
|
28
|
+
* @returns The forced skill name, or `null` when none applies.
|
|
29
|
+
*/
|
|
30
|
+
declare function requiredArchSkill(cwd: string): string | null;
|
|
31
|
+
/** Detect the project type by scanning config files in `dir`. */
|
|
32
|
+
declare function detectProjectType(dir: string): ProjectType;
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/policy/detect-framework.d.ts
|
|
35
|
+
/**
|
|
36
|
+
* Detect a file's framework as the intersection of the REAL project (its nearest
|
|
37
|
+
* manifest's capabilities) and the file's own extension/content signal. A
|
|
38
|
+
* backend `.ts` in a react project is `generic` (no react signal) — fixing the
|
|
39
|
+
* old extension-only default that flagged every `.ts` as react. Fail-open: any
|
|
40
|
+
* error yields `"generic"`, never throws. Return values stay within the label
|
|
41
|
+
* union ("react" | "nextjs" | "tanstack-start" | "laravel" | "swift" |
|
|
42
|
+
* "tailwind" | "java" | "go" | "ruby" | "rust" | "generic") — `tanstack-start`
|
|
43
|
+
* added 2026-07 (owner spec: first-class framework, Next.js-equivalent).
|
|
44
|
+
* @param filePath - Path of the file being written/edited.
|
|
45
|
+
* @param content - Its (incoming) content, for JS content signals.
|
|
46
|
+
* @param cwd - Root to resolve a relative `filePath` against (default cwd).
|
|
47
|
+
* @returns A framework label from the union.
|
|
48
|
+
*/
|
|
49
|
+
declare function detectFramework(filePath: string, content: string, cwd?: string): string;
|
|
50
|
+
//#endregion
|
|
51
|
+
//#region src/policy/file-size.d.ts
|
|
52
|
+
/**
|
|
53
|
+
* Fixed marketplace plugins root — parity with Python `enforce-file-size.py`'s
|
|
54
|
+
* literal, unexpanded `~/...` string. Exported: reused by
|
|
55
|
+
* `policy/apex.ts::solidReadGate` for its "no reference matched" deny message.
|
|
56
|
+
*/
|
|
57
|
+
declare const PLUGINS_DIR = "~/.claude/plugins/marketplaces/fusengine-plugins/plugins";
|
|
58
|
+
/**
|
|
59
|
+
* Skill-dir fragment per framework — parity with Python
|
|
60
|
+
* `enforce-file-size.py::get_solid_ref()` (falls back to `generic/`). Exported:
|
|
61
|
+
* reused by `policy/apex.ts::solidReadGate` (see {@link PLUGINS_DIR}).
|
|
62
|
+
*/
|
|
63
|
+
declare const SOLID_REF: Record<string, string>;
|
|
64
|
+
/** Verdict from {@link evaluateFileSize}. */
|
|
65
|
+
interface FileSizeVerdict {
|
|
66
|
+
ok: boolean;
|
|
67
|
+
lines: number;
|
|
68
|
+
max: number;
|
|
69
|
+
message: string | null;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Count physical lines — parity with the Python `enforce-file-size.py`
|
|
73
|
+
* (`sum(1 for _ in f)`): every line counts (blanks and comments included), and a
|
|
74
|
+
* single trailing newline does not add a phantom line. The SOLID ceiling is
|
|
75
|
+
* measured on raw file length, not substantive code, to match the upstream plugin.
|
|
76
|
+
*/
|
|
77
|
+
declare function countLines(content: string): number;
|
|
78
|
+
/**
|
|
79
|
+
* Count non-empty, non-comment lines — parity with the Python `count_code_lines`
|
|
80
|
+
* shared by the framework-specific SOLID validators: `_shared/scripts/validate_solid_common.py`
|
|
81
|
+
* (imported by `nextjs-expert/scripts/validate-nextjs-solid.py` and
|
|
82
|
+
* `swift-apple-expert/scripts/validate-swift-solid.py`), duplicated verbatim in
|
|
83
|
+
* `react-expert/scripts/validate-react-solid.py` / `laravel-expert/scripts/validate-laravel-solid.py`.
|
|
84
|
+
* Strips blank lines and lines starting with `//` or `*` — a SINGLE fixed rule
|
|
85
|
+
* for all 4 callers (the Python `comment` param defaults to, and every real
|
|
86
|
+
* call site leaves it at, `"//"` — never per-language despite covering
|
|
87
|
+
* ts/tsx/js/jsx, php and swift).
|
|
88
|
+
*
|
|
89
|
+
* Deliberately distinct from two other "code-only" counters already in this
|
|
90
|
+
* repo, neither of which is a faithful substitute here:
|
|
91
|
+
* - `countLoc` (`runtime/lifecycle/check-file-size.ts`): a genuinely
|
|
92
|
+
* per-language table (PHP additionally strips `#`, Python strips
|
|
93
|
+
* `#`/`"""`/`'''`) — ported from the unrelated `solid/scripts/check-file-size.py`.
|
|
94
|
+
* - `countCodeLines` (`runtime/lifecycle/aipilot/solid-compliance.ts`): also
|
|
95
|
+
* strips `#` — ported from `ai-pilot/scripts/check-solid-compliance.py`.
|
|
96
|
+
* Reusing either would silently strip PHP `#`/Python-style comments that the
|
|
97
|
+
* real react/nextjs/laravel/swift validators do NOT strip.
|
|
98
|
+
* @param content - The file content to measure.
|
|
99
|
+
*/
|
|
100
|
+
declare function countFrameworkCodeLines(content: string): number;
|
|
101
|
+
/**
|
|
102
|
+
* Evaluate a file's line count against the SOLID limit.
|
|
103
|
+
* @param lines - the file's line count
|
|
104
|
+
* @param max - the limit (defaults to `resolveMaxLines()`)
|
|
105
|
+
*/
|
|
106
|
+
declare function evaluateFileSize(lines: number, max?: number, filePath?: string, framework?: string, displayLines?: number): FileSizeVerdict;
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/policy/patterns.d.ts
|
|
109
|
+
/** Destructive git operations to block outright. */
|
|
110
|
+
declare const GIT_BLOCKED: ReadonlyArray<RegExp>;
|
|
111
|
+
/** Git operations that warrant a confirmation prompt. */
|
|
112
|
+
declare const GIT_ASK: ReadonlyArray<RegExp>;
|
|
113
|
+
/** System-level package installs (need confirmation). */
|
|
114
|
+
declare const SYSTEM_INSTALL: ReadonlyArray<RegExp>;
|
|
115
|
+
/** Project-level package installs. */
|
|
116
|
+
declare const PROJECT_INSTALL: ReadonlyArray<RegExp>;
|
|
117
|
+
/** True when `cmd` matches any pattern in `patterns`. */
|
|
118
|
+
declare function matchPatterns(cmd: string, patterns: ReadonlyArray<RegExp>): boolean;
|
|
119
|
+
/** Git commands exempt from confirmation when Ralph mode is on (parity git-guard.py RALPH_SAFE). */
|
|
120
|
+
declare const RALPH_SAFE: ReadonlyArray<string>;
|
|
121
|
+
/**
|
|
122
|
+
* OPT-IN autonomous "Ralph" mode: OFF unless `RALPH_MODE` is `1`/`true`, read
|
|
123
|
+
* fresh on each call. Only the env var activates it — the Python source also
|
|
124
|
+
* auto-enabled on a `.claude/ralph/prd.json` file or a `feature/*` branch, but
|
|
125
|
+
* those silent activations are dropped here: a mode that removes git/install
|
|
126
|
+
* confirmations must never turn on implicitly (owner: default OFF, env opt-in).
|
|
127
|
+
*/
|
|
128
|
+
declare function isRalphMode(): boolean;
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region src/policy/interfaces/types.d.ts
|
|
131
|
+
/** Harness-agnostic input to {@link evaluate}. */
|
|
132
|
+
interface PolicyContext {
|
|
133
|
+
/** Tool name (e.g. "Write", "Edit", "Bash"). */
|
|
134
|
+
tool: string;
|
|
135
|
+
filePath?: string;
|
|
136
|
+
content?: string;
|
|
137
|
+
command?: string;
|
|
138
|
+
/** Optional override for the SOLID max-lines limit. */
|
|
139
|
+
maxLines?: number;
|
|
140
|
+
/** Subagent type — `Explore`/`Plan` are exempt from the file-size gate. */
|
|
141
|
+
agentType?: string;
|
|
142
|
+
/** Line count of the existing on-disk file (so an Edit on an oversized file blocks). */
|
|
143
|
+
existingLines?: number;
|
|
144
|
+
/** 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). */
|
|
145
|
+
existingContent?: string;
|
|
146
|
+
/** Edit only: the tool_input.old_string being replaced (runtime/normalize.ts). Undefined for Write (no such field) — fail-closed. */
|
|
147
|
+
oldString?: string;
|
|
148
|
+
/** Edit only: the tool_input.replace_all flag — every occurrence of old_string is replaced, not just the first. */
|
|
149
|
+
isReplaceAll?: boolean;
|
|
150
|
+
/** 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. */
|
|
151
|
+
neverApproval?: boolean;
|
|
152
|
+
}
|
|
153
|
+
/** Harness-agnostic policy decision (+ a portable prompt for adapters to render). */
|
|
154
|
+
interface PolicyResult {
|
|
155
|
+
decision: "allow" | "deny" | "warn";
|
|
156
|
+
message: string | null;
|
|
157
|
+
prompt?: Prompt;
|
|
158
|
+
meta?: Record<string, unknown>;
|
|
159
|
+
}
|
|
160
|
+
//#endregion
|
|
161
|
+
//#region src/policy/evaluate.d.ts
|
|
162
|
+
/**
|
|
163
|
+
* Evaluate a single tool-use against the bundled policies, returning a pure
|
|
164
|
+
* decision plus a portable {@link Prompt}. Adapters translate the prompt into
|
|
165
|
+
* their harness's native response (Claude `permissionDecision`, etc.).
|
|
166
|
+
*/
|
|
167
|
+
declare function evaluate(ctx: PolicyContext): PolicyResult;
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/policy/apex-gates.d.ts
|
|
170
|
+
/** Gate: the routed SOLID references for this edit must have been read within the TTL. */
|
|
171
|
+
declare const solidReadGate: ApexGate;
|
|
172
|
+
/** Gate: the required prior agents (explore + research) must have run within the window. */
|
|
173
|
+
declare const freshnessGate: ApexGate;
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/policy/apex.d.ts
|
|
176
|
+
/**
|
|
177
|
+
* Session context for the stateful APEX gates. The harness adapter supplies this
|
|
178
|
+
* (the package owns the gate LOGIC; recording the session activity is the
|
|
179
|
+
* adapter's tracking layer).
|
|
180
|
+
*/
|
|
181
|
+
interface ApexContext {
|
|
182
|
+
sessionId: string;
|
|
183
|
+
framework: string;
|
|
184
|
+
filePath: string;
|
|
185
|
+
content: string;
|
|
186
|
+
/** Doc-consultation authorizations from session state (Context7/Exa). */
|
|
187
|
+
authorizations?: Record<string, AuthEntry>;
|
|
188
|
+
/** Available SOLID references for the framework's skill. */
|
|
189
|
+
refs?: RefMeta[];
|
|
190
|
+
/** Absolute paths of SOLID refs already read this session. */
|
|
191
|
+
refsRead?: string[];
|
|
192
|
+
/**
|
|
193
|
+
* Epoch-ms read timestamp per `refsRead` path (parity track-solid-reads.py
|
|
194
|
+
* `solid_reads[].timestamp`). PARITY: the TTL applies ONLY to solidReadGate —
|
|
195
|
+
* Python TTL-izes SOLID reads exclusively (require-solid-read.py); the
|
|
196
|
+
* skill-trigger/design/shadcn gates stay session-scoped (no TTL). A path in
|
|
197
|
+
* `refsRead` with no stamp here (tracks recorded before this field existed)
|
|
198
|
+
* counts as read — backward compat.
|
|
199
|
+
*/
|
|
200
|
+
refsReadAt?: Record<string, number>;
|
|
201
|
+
/** Current epoch ms for the SOLID-read TTL check; absent → reads never expire. */
|
|
202
|
+
now?: number;
|
|
203
|
+
/** Whether the required prior agents (explore + research) ran within the freshness window. */
|
|
204
|
+
agentsFresh?: boolean;
|
|
205
|
+
/** Names of REQUIRED_AGENTS that have NOT run fresh (subset), for a precise freshnessGate message. Absent → generic wording. */
|
|
206
|
+
missingAgents?: string[];
|
|
207
|
+
/** Freshness window in ms: labels the block messages' TTL (e.g. "2min") and bounds the SOLID-read TTL in solidReadGate. */
|
|
208
|
+
windowMs?: number;
|
|
209
|
+
/** Whether brainstorming is required for this edit (creation intent on a new file). */
|
|
210
|
+
brainstormRequired?: boolean;
|
|
211
|
+
/** Whether the brainstorming agent ran within the window. */
|
|
212
|
+
brainstormFresh?: boolean;
|
|
213
|
+
}
|
|
214
|
+
/** A single APEX gate: returns a blocking {@link Prompt}, or null to pass. */
|
|
215
|
+
type ApexGate = (ctx: ApexContext) => Prompt | null;
|
|
216
|
+
/** Gate: BOTH Context7 AND Exa (or a web fallback alone) must have been consulted this session. */
|
|
217
|
+
declare const docConsultedGate: ApexGate;
|
|
218
|
+
/** Gate: brainstorming must precede creating new files when flagged. */
|
|
219
|
+
declare const brainstormGate: ApexGate;
|
|
220
|
+
/** Gates that run BEFORE Check 1 (harness-specific brainstorm + agent freshness, pre-dating enforce-apex-phases). */
|
|
221
|
+
declare const PRE_AUTH_GATES: ReadonlyArray<ApexGate>;
|
|
222
|
+
/** Gates that run AFTER Check 1: Check 2 (doc consulted once per session) then the SOLID refs. */
|
|
223
|
+
declare const POST_AUTH_GATES: ReadonlyArray<ApexGate>;
|
|
224
|
+
/**
|
|
225
|
+
* Default APEX gate chain (brainstorm, freshness, docs, SOLID refs). Check 1
|
|
226
|
+
* (`apexAuthorizationGate`, policy/apex-authorization.ts) is wired BETWEEN the
|
|
227
|
+
* PRE and POST sub-chains by the runtime (gate-apex.ts), which owns its
|
|
228
|
+
* target-write side effect — parity enforce-apex-phases.ts Check1 -> Check2.
|
|
229
|
+
*/
|
|
230
|
+
declare const APEX_GATES: ReadonlyArray<ApexGate>;
|
|
231
|
+
/**
|
|
232
|
+
* Run the APEX gates (chain-of-responsibility): the first failing gate's prompt
|
|
233
|
+
* wins; null means every gate passed (allow).
|
|
234
|
+
*/
|
|
235
|
+
declare function evaluateApex(ctx: ApexContext, gates?: ReadonlyArray<ApexGate>): Prompt | null;
|
|
236
|
+
//#endregion
|
|
237
|
+
//#region src/policy/guards/context.d.ts
|
|
238
|
+
/** Context handed to every guard in the chain. */
|
|
239
|
+
interface GuardContext {
|
|
240
|
+
tool: string;
|
|
241
|
+
filePath?: string;
|
|
242
|
+
content?: string;
|
|
243
|
+
command?: string;
|
|
244
|
+
}
|
|
245
|
+
/** A single guard: returns a blocking/asking Prompt, or null to continue. */
|
|
246
|
+
type Guard = (ctx: GuardContext) => Prompt | null;
|
|
247
|
+
//#endregion
|
|
248
|
+
//#region src/policy/guards/security.d.ts
|
|
249
|
+
/** A pattern paired with the violation label to name in the deny/ask reason. */
|
|
250
|
+
interface LabeledPattern {
|
|
251
|
+
re: RegExp;
|
|
252
|
+
label: string;
|
|
253
|
+
}
|
|
254
|
+
/** Critical patterns that must always be blocked — parity `security_rules.py`'s cumulated violation names. */
|
|
255
|
+
declare const CRITICAL_PATTERNS: LabeledPattern[];
|
|
256
|
+
/** Patterns that warrant explicit confirmation before running — parity `security_rules.py`'s ask-level violation names. */
|
|
257
|
+
declare const ASK_PATTERNS: LabeledPattern[];
|
|
258
|
+
/**
|
|
259
|
+
* Guards against dangerous Bash commands. Parity `security_rules.validate_command`
|
|
260
|
+
* + `security-guard.py`: ACCUMULATE every matched violation, then deny when any
|
|
261
|
+
* critical matched else ask, joining all violation labels in the reason. The
|
|
262
|
+
* generic `rm` ask is exempt when the command targets a trash location (parity
|
|
263
|
+
* `not re.search('trash', cmd)`).
|
|
264
|
+
*/
|
|
265
|
+
declare function securityGuard(ctx: GuardContext): Prompt | null;
|
|
266
|
+
//#endregion
|
|
267
|
+
//#region src/policy/guards/protected-path.d.ts
|
|
268
|
+
/**
|
|
269
|
+
* Path fragments that mark a location as internal/generated state.
|
|
270
|
+
*
|
|
271
|
+
* Parity with safe_paths.py: `~/.fuse-harness/cache` is a *writable*
|
|
272
|
+
* cache the harness owns (lessons, MCP cache, per-type state) — only the
|
|
273
|
+
* `cache/sessions` subtree is protected, not the whole cache.
|
|
274
|
+
*/
|
|
275
|
+
declare const PROTECTED_FRAGMENTS: readonly string[];
|
|
276
|
+
/**
|
|
277
|
+
* Matches a real `.git` directory segment (`/.git/`, `~/.git`, leading or
|
|
278
|
+
* trailing `.git`) without matching unrelated names like `foo.git/` or
|
|
279
|
+
* `.github/`. Kept separate from the substring fragments for precise scoping.
|
|
280
|
+
*/
|
|
281
|
+
declare const PROTECTED_GIT_RE: RegExp;
|
|
282
|
+
/**
|
|
283
|
+
* Blocks direct edits to internal/generated state directories.
|
|
284
|
+
*
|
|
285
|
+
* Covers:
|
|
286
|
+
* - Write / Edit tool calls whose `filePath` targets a protected fragment.
|
|
287
|
+
* - Bash commands whose actual write *target* is a protected fragment
|
|
288
|
+
* (read sources are ignored; see `extractWriteTargets`).
|
|
289
|
+
*
|
|
290
|
+
* @param ctx - The guard context (tool, filePath, command).
|
|
291
|
+
* @returns A blocking {@link Prompt}, or null to allow.
|
|
292
|
+
*/
|
|
293
|
+
declare function protectedPathGuard(ctx: GuardContext): Prompt | null;
|
|
294
|
+
//#endregion
|
|
295
|
+
//#region src/policy/guards/bash-write-patterns.d.ts
|
|
296
|
+
/** Redirect (`>`/`>>`) targeting a code-file extension. */
|
|
297
|
+
declare const CODE_REDIRECT: RegExp;
|
|
298
|
+
/**
|
|
299
|
+
* Interpreters / tools that mutate source in place, plus heredoc-into-file —
|
|
300
|
+
* split into labeled sub-patterns (parity bash-write-guard.py `DENY_PATTERNS`,
|
|
301
|
+
* each with its own `desc`) so the deny reason names which motif matched
|
|
302
|
+
* instead of a single generic message. Every command-named motif is
|
|
303
|
+
* {@link CMD}-anchored (start/separator + optional wrapper chain); only the
|
|
304
|
+
* structural heredoc-into-file motif is position-free.
|
|
305
|
+
*/
|
|
306
|
+
declare const CODE_MUTATORS: readonly {
|
|
307
|
+
re: RegExp;
|
|
308
|
+
desc: string;
|
|
309
|
+
}[];
|
|
310
|
+
/** Redirect to a non-code file. Excludes `/dev/null`, `2>`/`N>` and `>&N` fd
|
|
311
|
+
* redirects via the `(?<![0-9&])` lookbehind + `(?!…|&)` (parity has_file_redirect). */
|
|
312
|
+
declare const FILE_REDIRECT: RegExp;
|
|
313
|
+
/** Other ambiguous file writers (ASK): `tee <file>` (not `tee -a`/path) and `dd … of=` —
|
|
314
|
+
* labeled sub-patterns (parity bash-write-guard.py `ASK_PATTERNS`). */
|
|
315
|
+
declare const ASK_WRITERS: readonly {
|
|
316
|
+
re: RegExp;
|
|
317
|
+
desc: string;
|
|
318
|
+
}[];
|
|
319
|
+
/** Commands whose first token never writes, skipped when a real redirect is
|
|
320
|
+
* present (parity bash-write-guard.py `SAFE_PREFIXES`). */
|
|
321
|
+
declare const SAFE_PREFIXES: readonly string[];
|
|
322
|
+
/**
|
|
323
|
+
* Session-state directory the freshness/APEX gates rely on. Any Bash command
|
|
324
|
+
* touching it is a hook-bypass vector, so it is blocked outright — a blunt
|
|
325
|
+
* substring match (read OR write), parity with bash-write-guard.py DENY_PATTERNS
|
|
326
|
+
* `fusengine-cache/sessions` (rebranded to the harness cache path).
|
|
327
|
+
*/
|
|
328
|
+
declare const SESSION_STATE_FRAGMENT = ".fuse-harness/cache/sessions";
|
|
329
|
+
//#endregion
|
|
330
|
+
//#region src/policy/guards/bash-write.d.ts
|
|
331
|
+
/**
|
|
332
|
+
* Blocks shell commands that mutate code files in place (and heredocs/redirects
|
|
333
|
+
* to source files); asks before other file-writing shell commands unless the
|
|
334
|
+
* target is a harness-owned safe path. Forces use of the Write/Edit tool so
|
|
335
|
+
* APEX/SOLID checks are not bypassed.
|
|
336
|
+
*
|
|
337
|
+
* The code-write detectors (CODE_MUTATORS, CODE_COMMAND_WRITE) run BEFORE the
|
|
338
|
+
* SAFE_PREFIXES short-circuit: they are command-position anchored
|
|
339
|
+
* (bash-command-anchor.ts), so a transparent wrapper (`env sed -i src/x.ts`,
|
|
340
|
+
* `timeout 5 patch`, `cp a b; tee src/y.ts`) can no longer smuggle a code write
|
|
341
|
+
* past its safe first token, while a quoted mention (`git commit -m "fix sed -i"`)
|
|
342
|
+
* still falls through. The short-circuit becomes the terminal allow — "first
|
|
343
|
+
* token never writes, nothing above matched".
|
|
344
|
+
*/
|
|
345
|
+
declare function bashWriteGuard(ctx: GuardContext): Prompt | null;
|
|
346
|
+
//#endregion
|
|
347
|
+
//#region src/policy/guards/interface-separation.d.ts
|
|
348
|
+
/** TS/JS component files: top-level `interface`/`type Foo`. */
|
|
349
|
+
declare const TS_DECL_RE: RegExp;
|
|
350
|
+
/** Python view models: class subclassing a schema/protocol base. */
|
|
351
|
+
declare const PY_MODEL_RE: RegExp;
|
|
352
|
+
/**
|
|
353
|
+
* PHP controllers: top-level `interface`, `abstract class`, or a concrete
|
|
354
|
+
* `class …Interface/DTO/Request`. Union of the TS-only `abstract class` rule
|
|
355
|
+
* and the Python rule (`class [A-Z].*(Interface|DTO|Request)`, enforce-interfaces.py:16).
|
|
356
|
+
*/
|
|
357
|
+
declare const PHP_DECL_RE: RegExp;
|
|
358
|
+
/** Swift views: top-level `protocol Foo`. */
|
|
359
|
+
declare const SWIFT_PROTO_RE: RegExp;
|
|
360
|
+
/** Go handlers/controllers: top-level `type Foo interface`. */
|
|
361
|
+
declare const GO_DECL_RE: RegExp;
|
|
362
|
+
/** Java/Kotlin controllers/handlers: top-level `interface`/`record`. */
|
|
363
|
+
declare const JAVA_DECL_RE: RegExp;
|
|
364
|
+
/** Rust: top-level `trait Foo` declaration (captures the name for impl co-location). */
|
|
365
|
+
declare const RUST_DECL_RE: RegExp;
|
|
366
|
+
/**
|
|
367
|
+
* Blocks top-level interface/type/protocol declarations in component, view or
|
|
368
|
+
* controller files (Interface Segregation), when BOTH the path category AND
|
|
369
|
+
* the content pattern match. Content is MASKED first (conventions/strip.ts):
|
|
370
|
+
* declarations in comments/strings/templates/heredocs never trigger. Legacy
|
|
371
|
+
* regexes keep their exact values (parity tests) — every case that blocked
|
|
372
|
+
* before still blocks with the same message (byte-parity). Two extension
|
|
373
|
+
* classes ship ADVISORY via {@link rolloutVerdict} (`FUSE_CONVENTIONS_MODE`,
|
|
374
|
+
* Amendment 5): exported type aliases redirected to `src/types/` (Amendment 2),
|
|
375
|
+
* and the widenings of `interface-separation-ext.ts` (public protocol,
|
|
376
|
+
* sealed/fun interface, unexported Go top-level). Rust `impl<T>` stays a
|
|
377
|
+
* known FN. Parity: the Python port inspected `Write` only; we also fire on
|
|
378
|
+
* `Edit`, and fragments accept singular+plural dirs (`view/` + `views/`).
|
|
379
|
+
*/
|
|
380
|
+
declare function interfaceSeparationGuard(ctx: GuardContext): Prompt | null;
|
|
381
|
+
//#endregion
|
|
382
|
+
//#region src/policy/guards/install.d.ts
|
|
383
|
+
/**
|
|
384
|
+
* Asks for confirmation before a dependency or system package install. In Ralph
|
|
385
|
+
* mode (opt-in `RALPH_MODE`) a PROJECT install is auto-approved for autonomous
|
|
386
|
+
* runs (parity install-guard.py:52), but a SYSTEM install always asks.
|
|
387
|
+
*/
|
|
388
|
+
declare function installGuard(ctx: GuardContext): Prompt | null;
|
|
389
|
+
//#endregion
|
|
390
|
+
//#region src/policy/guards/index.d.ts
|
|
391
|
+
/** Ordered guard chain: critical/security + protected first, then writes/installs. */
|
|
392
|
+
declare const GUARDS: ReadonlyArray<Guard>;
|
|
393
|
+
/** Block prompt returned when a guard or gate throws (fail-closed). */
|
|
394
|
+
declare const FAIL_CLOSED: Prompt;
|
|
395
|
+
/** Register a user guard — runs AFTER the privileged core chain (two-tier). */
|
|
396
|
+
declare function registerGuard(guard: Guard): void;
|
|
397
|
+
/** Remove all registered user guards (mainly for tests). */
|
|
398
|
+
declare function clearUserGuards(): void;
|
|
399
|
+
/**
|
|
400
|
+
* Run the guard chain — privileged core guards first, then user guards — and
|
|
401
|
+
* return the first firing Prompt, else null. Fail-closed: a guard that throws
|
|
402
|
+
* blocks (never silently passes).
|
|
403
|
+
*/
|
|
404
|
+
declare function runGuards(ctx: GuardContext): Prompt | null;
|
|
405
|
+
//#endregion
|
|
406
|
+
//#region src/policy/creation-intent.d.ts
|
|
407
|
+
/**
|
|
408
|
+
* True when a prompt expresses creation intent (a new feature/component) and is
|
|
409
|
+
* not a fix/refactor — the signal that brainstorming should precede creation.
|
|
410
|
+
* The harness calls this on UserPromptSubmit, then `recordBrainstormRequired`.
|
|
411
|
+
*/
|
|
412
|
+
declare function detectCreationIntent(prompt: string): boolean;
|
|
413
|
+
//#endregion
|
|
414
|
+
//#region src/policy/verbosity.d.ts
|
|
415
|
+
/** Max results an exa MCP call may request. */
|
|
416
|
+
declare const MAX_EXA_RESULTS = 3;
|
|
417
|
+
/** Max token budget for exa `tokensNum` / context7 `tokens`. */
|
|
418
|
+
declare const MAX_TOKENS = 2e3;
|
|
419
|
+
/**
|
|
420
|
+
* Cap an MCP call's verbosity — exa `numResults` ≤ 3 (+ `tokensNum` ≤ 2000),
|
|
421
|
+
* Context7 `tokens` ≤ 2000. Returns the capped input (a mutation for the harness
|
|
422
|
+
* to apply) when a change is needed, else null.
|
|
423
|
+
*/
|
|
424
|
+
declare function capVerbosity(tool: string, input: Record<string, unknown>): Record<string, unknown> | null;
|
|
425
|
+
//#endregion
|
|
426
|
+
//#region src/policy/framework-solid.d.ts
|
|
427
|
+
/**
|
|
428
|
+
* Framework-specific SOLID gate. Dispatches by extension/path to the matching
|
|
429
|
+
* validator (React, Next.js, Laravel, Swift, Go, Rust) and returns a blocking
|
|
430
|
+
* {@link Prompt} when any BLOCKING rule fires, or `null` when clean. Excluded
|
|
431
|
+
* build/dependency paths (node_modules, dist, build, .next, vendor, .build,
|
|
432
|
+
* DerivedData, Pods) early-return `null` to avoid false positives. Go and Rust
|
|
433
|
+
* have no exclusion list yet (no vendor/target FPs reported) — additive only.
|
|
434
|
+
* @param filePath - absolute path of the file being written/edited
|
|
435
|
+
* @param content - the file (or new) content under validation
|
|
436
|
+
* @param fileLines - full on-disk line count (set on Edit so a partial
|
|
437
|
+
* `new_string` snippet still judges the whole file, mirroring the base
|
|
438
|
+
* file-size guard / Python `get_full_file_content`). Omit on Write.
|
|
439
|
+
*/
|
|
440
|
+
declare function frameworkSolidGate(filePath: string, content: string, fileLines?: number): Prompt | null;
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region src/policy/skill-trigger-patterns.d.ts
|
|
443
|
+
/** Map of required sub-skill name → triggering code patterns, keyed by framework. */
|
|
444
|
+
declare const SKILL_TRIGGERS: Readonly<Record<string, Readonly<Record<string, ReadonlyArray<string>>>>>;
|
|
445
|
+
//#endregion
|
|
446
|
+
//#region src/policy/skill-triggers.d.ts
|
|
447
|
+
/**
|
|
448
|
+
* Detect which sub-skills the written `content` requires for a `framework`.
|
|
449
|
+
* Faithful to the Python `detect_required_skills`: first matching pattern per
|
|
450
|
+
* skill wins. Most frameworks match case-insensitively (source `re.IGNORECASE`);
|
|
451
|
+
* `swift` matches case-sensitively (see {@link CASE_SENSITIVE_FRAMEWORKS}).
|
|
452
|
+
* @param framework - "react" | "nextjs" | "laravel" | "swift".
|
|
453
|
+
* @param content - the code being written.
|
|
454
|
+
* @returns required sub-skill names (empty when framework unknown / no match).
|
|
455
|
+
*/
|
|
456
|
+
declare function detectRequiredSkills(framework: string, content: string): string[];
|
|
457
|
+
/**
|
|
458
|
+
* True when `filePath`/`content` match the Python Tailwind gate's trigger
|
|
459
|
+
* condition. React/Next.js components embed Tailwind utility classes in
|
|
460
|
+
* `className` — this check fires IN ADDITION TO the primary framework gate,
|
|
461
|
+
* never instead of it: {@link detectFramework} keeps returning "react"/
|
|
462
|
+
* "nextjs" for these files (framework SOLID rules stay correct).
|
|
463
|
+
*/
|
|
464
|
+
declare function usesTailwindUtilities(filePath: string, content: string): boolean;
|
|
465
|
+
/**
|
|
466
|
+
* Block when a required sub-skill's `skills/<name>/` path is absent from
|
|
467
|
+
* `refsRead`. Mirrors `specific_skill_consulted`, which confirms a skill was
|
|
468
|
+
* read by checking the tracking file contains `skills/<name>/`.
|
|
469
|
+
* @param framework - "react" | "nextjs" | "laravel".
|
|
470
|
+
* @param content - the code being written.
|
|
471
|
+
* @param refsRead - in-session read reference paths.
|
|
472
|
+
* @param forcedSkill - a skill the detected modular architecture forces (optional).
|
|
473
|
+
* @param cwd - project root; when set and not a shadcn project, `*-shadcn`
|
|
474
|
+
* requirements are skipped (ports the Python `is_shadcn_project` filter).
|
|
475
|
+
* @param filePath - the file being written; when it's a `.tsx`/`.jsx` file
|
|
476
|
+
* with Tailwind utility classes in `className`, the "tailwind" domain
|
|
477
|
+
* skills are merged in alongside `framework`'s own (ports the separate
|
|
478
|
+
* `check-tailwind-skill.py` gate, independent of react/nextjs).
|
|
479
|
+
* @returns a `block` Prompt naming the missing sub-skills, or `null` when satisfied.
|
|
480
|
+
*/
|
|
481
|
+
declare function skillTriggerGate(framework: string, content: string, refsRead: readonly string[], forcedSkill?: string | null, cwd?: string, filePath?: string): Prompt | null;
|
|
482
|
+
//#endregion
|
|
483
|
+
//#region src/policy/detect-claude-md-project-type.d.ts
|
|
484
|
+
/**
|
|
485
|
+
* Detect the project type from the cwd, reproducing the legacy Python logic:
|
|
486
|
+
* package.json containing "next" → nextjs, else "react" → react; else
|
|
487
|
+
* composer.json+artisan → laravel; else Package.swift / *.xcodeproj → swift;
|
|
488
|
+
* else generic.
|
|
489
|
+
* @param cwd - Project root to scan.
|
|
490
|
+
* @returns The detected project type label.
|
|
491
|
+
*/
|
|
492
|
+
declare function detectClaudeMdProjectType(cwd: string): ProjectType;
|
|
493
|
+
//#endregion
|
|
494
|
+
//#region src/policy/claude-md-context.d.ts
|
|
495
|
+
/** Dev-verb regex (FR/EN) that triggers the APEX preamble (case-insensitive). */
|
|
496
|
+
declare const DEV_VERBS: RegExp;
|
|
497
|
+
/**
|
|
498
|
+
* Build the APEX instruction preamble for a development task.
|
|
499
|
+
* @param projectType - Detected project type label.
|
|
500
|
+
* @param maxLines - SOLID per-file line ceiling.
|
|
501
|
+
* @param id - Harness target id (defaults to "claude-code" — zero-regression default).
|
|
502
|
+
* @returns The APEX instruction text.
|
|
503
|
+
*/
|
|
504
|
+
declare function buildApexInstruction(projectType: ProjectType, maxLines: number, id?: string): string;
|
|
505
|
+
/**
|
|
506
|
+
* Build the UserPromptSubmit injection text: read the target's root
|
|
507
|
+
* instructions doc (`~/.claude/CLAUDE.md`, `~/.codex/AGENTS.md`, ...) and,
|
|
508
|
+
* when the prompt matches a dev verb, prepend the APEX instruction. Returns
|
|
509
|
+
* `null` when the doc is absent/unreadable (the hook then emits nothing).
|
|
510
|
+
* @param prompt - The raw user prompt.
|
|
511
|
+
* @param cwd - Project root (for project-type detection).
|
|
512
|
+
* @param id - Harness target id (defaults to "claude-code" — zero-regression default).
|
|
513
|
+
* @returns The injection text, or `null` to emit nothing.
|
|
514
|
+
*/
|
|
515
|
+
declare function buildClaudeMdContext(prompt: string, cwd: string, id?: string): string | null;
|
|
516
|
+
//#endregion
|
|
517
|
+
//#region src/policy/apex-task-context.d.ts
|
|
518
|
+
/** Parsed task state injected into a Task sub-agent prompt. */
|
|
519
|
+
interface ApexTaskState {
|
|
520
|
+
/** Current task id (defaults to "1"). */
|
|
521
|
+
id: string;
|
|
522
|
+
/** Task subject (defaults to ""). */
|
|
523
|
+
subject: string;
|
|
524
|
+
/** Current phase (defaults to "analyze"). */
|
|
525
|
+
phase: string;
|
|
526
|
+
/** Comma-joined consulted doc keys, or "none". */
|
|
527
|
+
docs: string;
|
|
528
|
+
}
|
|
529
|
+
/**
|
|
530
|
+
* Read the current task state from `task.json`, reproducing the legacy Python
|
|
531
|
+
* logic. Any read/parse error falls back to `("1", "", "analyze", "none")`.
|
|
532
|
+
* @param taskFile - Absolute path to `.claude/apex/task.json`.
|
|
533
|
+
* @returns The parsed {@link ApexTaskState}.
|
|
534
|
+
*/
|
|
535
|
+
declare function loadApexTaskState(taskFile: string): ApexTaskState;
|
|
536
|
+
/**
|
|
537
|
+
* Build the APEX context string injected into a Task sub-agent prompt.
|
|
538
|
+
* @param state - The parsed task state.
|
|
539
|
+
* @param maxLines - SOLID per-file line ceiling.
|
|
540
|
+
* @param id - Harness target id (defaults to "claude-code" — zero-regression default).
|
|
541
|
+
* @returns The injection text.
|
|
542
|
+
*/
|
|
543
|
+
declare function buildApexTaskContext(state: ApexTaskState, maxLines: number, id?: string): string;
|
|
544
|
+
/**
|
|
545
|
+
* Build the PreToolUse Task injection, gated on the existence of the
|
|
546
|
+
* project's target apex dir (`.claude/apex/`, `.codex/apex/`, ...). Returns
|
|
547
|
+
* `null` when APEX is not active (no dir).
|
|
548
|
+
* @param projectRoot - `CLAUDE_PROJECT_DIR` or cwd.
|
|
549
|
+
* @param id - Harness target id (defaults to "claude-code" — zero-regression default).
|
|
550
|
+
* @returns The injection text, or `null` to emit nothing.
|
|
551
|
+
*/
|
|
552
|
+
declare function buildApexTaskInjection(projectRoot: string, id?: string): string | null;
|
|
553
|
+
//#endregion
|
|
554
|
+
//#region src/policy/cartographer/indicators.d.ts
|
|
555
|
+
/**
|
|
556
|
+
* Cartographer indicators — pure data sets used to detect a project root and to
|
|
557
|
+
* exclude noise directories when walking a tree. Ports the constant tables from
|
|
558
|
+
* `generate_project_map.py` / `write_recursive.py`.
|
|
559
|
+
*/
|
|
560
|
+
/** Filenames whose presence marks a directory as a project root. */
|
|
561
|
+
declare const PROJECT_INDICATORS: ReadonlySet<string>;
|
|
562
|
+
/** Directory names skipped entirely during the tree walk. */
|
|
563
|
+
declare const EXCLUDE_DIRS: ReadonlySet<string>;
|
|
564
|
+
//#endregion
|
|
565
|
+
//#region src/policy/cartographer/frontmatter.d.ts
|
|
566
|
+
/**
|
|
567
|
+
* Extract a single frontmatter field's value from `text`. Strips surrounding
|
|
568
|
+
* quotes; skips YAML block-scalar markers. Returns "" when absent.
|
|
569
|
+
* @param text - The full document text.
|
|
570
|
+
* @param field - The frontmatter key to read.
|
|
571
|
+
* @returns The field value, or "".
|
|
572
|
+
*/
|
|
573
|
+
declare function parseField(text: string, field: string): string;
|
|
574
|
+
/**
|
|
575
|
+
* Derive a short description from the body following the frontmatter: the first
|
|
576
|
+
* non-empty trimmed line, sliced to `maxLen`. Returns "" when none.
|
|
577
|
+
* @param text - The full document text.
|
|
578
|
+
* @param maxLen - Maximum length of the returned description.
|
|
579
|
+
* @returns The body-derived description, or "".
|
|
580
|
+
*/
|
|
581
|
+
declare function parseBodyDesc(text: string, maxLen?: number): string;
|
|
582
|
+
//#endregion
|
|
583
|
+
//#region src/policy/cartographer/entry.d.ts
|
|
584
|
+
/**
|
|
585
|
+
* Tree-entry parsing — pure line regexes. Ports the line parsers of
|
|
586
|
+
* `merge_index.py` and `track-enrichment.py`.
|
|
587
|
+
*/
|
|
588
|
+
/** A parsed `prefix[name](path) — desc` tree line. */
|
|
589
|
+
interface TreeEntry {
|
|
590
|
+
prefix: string;
|
|
591
|
+
name: string;
|
|
592
|
+
path: string;
|
|
593
|
+
desc: string;
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Parse a `merge_index` tree line into its parts. Returns null on no match.
|
|
597
|
+
* @param line - The raw tree line.
|
|
598
|
+
* @returns The parsed entry, or null.
|
|
599
|
+
*/
|
|
600
|
+
declare function parseEntry(line: string): TreeEntry | null;
|
|
601
|
+
/**
|
|
602
|
+
* Parse an enrichment line into `[path, desc]`, requiring a non-empty desc.
|
|
603
|
+
* @param line - The raw index line.
|
|
604
|
+
* @returns The `[path, desc]` pair, or null.
|
|
605
|
+
*/
|
|
606
|
+
declare function parseEnrichment(line: string): [string, string] | null;
|
|
607
|
+
//#endregion
|
|
608
|
+
//#region src/policy/cartographer/describe.d.ts
|
|
609
|
+
/**
|
|
610
|
+
* First `# ` Markdown heading text (sans hashes), sliced to 60. "" when none.
|
|
611
|
+
* @param text - The document text.
|
|
612
|
+
* @returns The heading text, or "".
|
|
613
|
+
*/
|
|
614
|
+
declare function firstHeading(text: string): string;
|
|
615
|
+
/**
|
|
616
|
+
* First leading comment among the first 10 lines (`//`, `#` but not `#!`, or a
|
|
617
|
+
* `"""`/`'''` docstring), sliced to 60. "" when none.
|
|
618
|
+
* @param text - The source text.
|
|
619
|
+
* @returns The comment text, or "".
|
|
620
|
+
*/
|
|
621
|
+
declare function firstComment(text: string): string;
|
|
622
|
+
/**
|
|
623
|
+
* Derive a description from a file's suffix + text. For `.md`, the supplied
|
|
624
|
+
* frontmatter `description` (truncated) wins over the first heading; for known
|
|
625
|
+
* source suffixes, the first comment; else "".
|
|
626
|
+
* @param suffix - The file extension (with dot).
|
|
627
|
+
* @param text - The file text.
|
|
628
|
+
* @param mdField - The pre-parsed frontmatter `description` (md only).
|
|
629
|
+
* @returns The derived description, or "".
|
|
630
|
+
*/
|
|
631
|
+
declare function descFromText(suffix: string, text: string, mdField: string): string;
|
|
632
|
+
//#endregion
|
|
633
|
+
//#region src/policy/seo/validate.d.ts
|
|
634
|
+
/** True when `path` is an HTML-like file the SEO hook should validate. */
|
|
635
|
+
declare function isHtmlLike(path: string): boolean;
|
|
636
|
+
/**
|
|
637
|
+
* Report the SEO elements missing from HTML-like content (title, meta
|
|
638
|
+
* description, OG title/description/image, canonical, JSON-LD schema).
|
|
639
|
+
* @param html - The file content.
|
|
640
|
+
* @returns The missing element labels (empty when complete).
|
|
641
|
+
*/
|
|
642
|
+
declare function missingSeoElements(html: string): string[];
|
|
643
|
+
//#endregion
|
|
644
|
+
//#region src/policy/conventions/strip.d.ts
|
|
645
|
+
/**
|
|
646
|
+
* Lexical comment/string masking for convention detectors. Every convention
|
|
647
|
+
* rule (interfaces, types, hooks, stores, query) matches against MASKED
|
|
648
|
+
* content so a declaration-looking line inside a comment, string, template
|
|
649
|
+
* literal, or heredoc can never trigger a verdict. Masking replaces the
|
|
650
|
+
* covered CHARACTERS with spaces but keeps every newline: line offsets and
|
|
651
|
+
* `^…/m` anchors stay valid, and the output has the same line count.
|
|
652
|
+
* Not a parser — a per-family state machine (c-like, python, ruby, php).
|
|
653
|
+
*/
|
|
654
|
+
/** Lexical profile of a language family. */
|
|
655
|
+
type LexProfile = "c" | "py" | "rb" | "php";
|
|
656
|
+
/**
|
|
657
|
+
* Mask comments and strings of `content` according to its lexical profile.
|
|
658
|
+
* @param content - Source text.
|
|
659
|
+
* @param profile - Lexical family (see `langs.ts` `lexProfileOf`).
|
|
660
|
+
* @returns Same-length text with comment/string interiors blanked.
|
|
661
|
+
*/
|
|
662
|
+
declare function maskCommentsAndStrings(content: string, profile: LexProfile): string;
|
|
663
|
+
/**
|
|
664
|
+
* Mask COMMENTS only (strings kept) — for detectors whose signal IS a string
|
|
665
|
+
* literal (module imports like `from "zustand"`): a `// import …` comment
|
|
666
|
+
* cannot match, while the real import line stays readable.
|
|
667
|
+
* @param content - Source text.
|
|
668
|
+
* @param profile - Lexical family.
|
|
669
|
+
* @returns Same-length text with comment interiors blanked.
|
|
670
|
+
*/
|
|
671
|
+
declare function maskCommentsOnly(content: string, profile: LexProfile): string;
|
|
672
|
+
//#endregion
|
|
673
|
+
//#region src/policy/conventions/langs.d.ts
|
|
674
|
+
/** Language family a convention rule applies to, or null when out of scope. */
|
|
675
|
+
type LangFamily = "ts" | "py" | "go" | "rs" | "java" | "php" | "swift" | "rb" | "vue";
|
|
676
|
+
/** Language family for a file path (by extension), or null when unsupported. */
|
|
677
|
+
declare function langOfPath(filePath: string): LangFamily | null;
|
|
678
|
+
/** Lexical profile for masking, derived from the language family. */
|
|
679
|
+
declare function lexProfileOf(lang: LangFamily): LexProfile;
|
|
680
|
+
/** True for dotfiles/dependency dirs never subject to conventions. */
|
|
681
|
+
declare function isVendorPath(filePath: string): boolean;
|
|
682
|
+
/** Path predicates — canonical convention directories. */
|
|
683
|
+
declare const isInterfacesPath: (p: string) => boolean;
|
|
684
|
+
declare const isTypesPath: (p: string) => boolean;
|
|
685
|
+
declare const isHooksPath: (p: string) => boolean;
|
|
686
|
+
declare const isStoresPath: (p: string) => boolean;
|
|
687
|
+
declare const isQueryPath: (p: string) => boolean;
|
|
688
|
+
declare const isComponentsPath: (p: string) => boolean;
|
|
689
|
+
//#endregion
|
|
690
|
+
//#region src/policy/conventions/interfaces.d.ts
|
|
691
|
+
/** Detection level: historical semantics (hard deny) vs advisory widening. */
|
|
692
|
+
type InterfaceDeclLevel = "legacy" | "extended";
|
|
693
|
+
/**
|
|
694
|
+
* Classify the interface declaration level of a file (masked scan), or null.
|
|
695
|
+
* @param filePath - File path (extension selects the language).
|
|
696
|
+
* @param content - Raw file content (masked internally).
|
|
697
|
+
*/
|
|
698
|
+
declare function interfaceDeclLevel(filePath: string, content: string): InterfaceDeclLevel | null;
|
|
699
|
+
/**
|
|
700
|
+
* True when the file declares an interface-like contract at any level.
|
|
701
|
+
* @param filePath - File path (extension selects the language).
|
|
702
|
+
* @param content - Raw file content (masked internally).
|
|
703
|
+
*/
|
|
704
|
+
declare function declaresInterface(filePath: string, content: string): boolean;
|
|
705
|
+
/**
|
|
706
|
+
* True when a TS-family file declares an EXPORTED type alias (masked scan).
|
|
707
|
+
* @param content - Raw file content.
|
|
708
|
+
*/
|
|
709
|
+
declare function declaresExportedTypeAlias(content: string): boolean;
|
|
710
|
+
//#endregion
|
|
711
|
+
//#region src/policy/conventions/react-hooks.d.ts
|
|
712
|
+
/**
|
|
713
|
+
* True when the file declares an exported custom `use*` hook (masked scan).
|
|
714
|
+
* @param content - Raw file content.
|
|
715
|
+
*/
|
|
716
|
+
declare function declaresCustomHook(content: string): boolean;
|
|
717
|
+
//#endregion
|
|
718
|
+
//#region src/policy/conventions/stores.d.ts
|
|
719
|
+
/** Store library whose declarations are being scanned. */
|
|
720
|
+
type StoreLib = "zustand" | "pinia";
|
|
721
|
+
/**
|
|
722
|
+
* True when the file declares a store of the given library (masked scan,
|
|
723
|
+
* signature-strict).
|
|
724
|
+
* @param content - Raw file content.
|
|
725
|
+
* @param lib - Store library to detect.
|
|
726
|
+
*/
|
|
727
|
+
declare function declaresStore(content: string, lib: StoreLib): boolean;
|
|
728
|
+
/**
|
|
729
|
+
* Count store declarations in one file (multi-store advisory: one per domain).
|
|
730
|
+
* @param content - Raw file content.
|
|
731
|
+
* @param lib - Store library to count.
|
|
732
|
+
*/
|
|
733
|
+
declare function countStores(content: string, lib: StoreLib): number;
|
|
734
|
+
//#endregion
|
|
735
|
+
//#region src/policy/conventions/query.d.ts
|
|
736
|
+
/**
|
|
737
|
+
* True when the file imports a TanStack Query package (raw scan, anchored to
|
|
738
|
+
* real import lines so `// import …` comments cannot match).
|
|
739
|
+
* @param content - Raw file content.
|
|
740
|
+
*/
|
|
741
|
+
declare function importsTanstackQuery(content: string): boolean;
|
|
742
|
+
/**
|
|
743
|
+
* True when the file DEFINES an exported query/mutation hook (export +
|
|
744
|
+
* query call, masked scan) — as opposed to merely consuming one inline.
|
|
745
|
+
* @param content - Raw file content.
|
|
746
|
+
*/
|
|
747
|
+
declare function declaresQueryHook(content: string): boolean;
|
|
748
|
+
/**
|
|
749
|
+
* True when the nearest manifest of `filePath` declares a TanStack Query
|
|
750
|
+
* dependency (`@tanstack/react-query` or `@tanstack/vue-query`) — the
|
|
751
|
+
* cap gate of every query convention (owner: no cap, no query rule).
|
|
752
|
+
* @param filePath - The file being judged (its nearest manifest wins).
|
|
753
|
+
*/
|
|
754
|
+
declare function queryCapActive(filePath: string): boolean;
|
|
755
|
+
//#endregion
|
|
756
|
+
export { detectCreationIntent as $, countFrameworkCodeLines as $t, TreeEntry as A, APEX_GATES as At, loadApexTaskState as B, evaluate as Bt, maskCommentsAndStrings as C, protectedPathGuard as Ct, descFromText as D, securityGuard as Dt, missingSeoElements as E, LabeledPattern as Et, EXCLUDE_DIRS as F, brainstormGate as Ft, detectRequiredSkills as G, PROJECT_INSTALL as Gt, buildApexInstruction as H, PolicyResult as Ht, PROJECT_INDICATORS as I, docConsultedGate as It, SKILL_TRIGGERS as J, isRalphMode as Jt, skillTriggerGate as K, RALPH_SAFE as Kt, ApexTaskState as L, evaluateApex as Lt, parseEntry as M, ApexGate as Mt, parseBodyDesc as N, POST_AUTH_GATES as Nt, firstComment as O, Guard as Ot, parseField as P, PRE_AUTH_GATES as Pt, capVerbosity as Q, SOLID_REF as Qt, buildApexTaskContext as R, freshnessGate as Rt, LexProfile as S, PROTECTED_GIT_RE as St, isHtmlLike as T, CRITICAL_PATTERNS as Tt, buildClaudeMdContext as U, GIT_ASK as Ut, DEV_VERBS as V, PolicyContext as Vt, detectClaudeMdProjectType as W, GIT_BLOCKED as Wt, MAX_EXA_RESULTS as X, FileSizeVerdict as Xt, frameworkSolidGate as Y, matchPatterns as Yt, MAX_TOKENS as Z, PLUGINS_DIR as Zt, isStoresPath as _, CODE_REDIRECT as _t, countStores as a, ProjectType as an, installGuard as at, langOfPath as b, SESSION_STATE_FRAGMENT as bt, InterfaceDeclLevel as c, isApexCommand as cn, PHP_DECL_RE as ct, interfaceDeclLevel as d, SWIFT_PROTO_RE as dt, countLines as en, FAIL_CLOSED as et, LangFamily as f, TS_DECL_RE as ft, isQueryPath as g, CODE_MUTATORS as gt, isInterfacesPath as h, ASK_WRITERS as ht, StoreLib as i, ModularArchitecture as in, runGuards as it, parseEnrichment as j, ApexContext as jt, firstHeading as k, GuardContext as kt, declaresExportedTypeAlias as l, requiredArchSkill as ln, PY_MODEL_RE as lt, isHooksPath as m, bashWriteGuard as mt, importsTanstackQuery as n, detectFramework as nn, clearUserGuards as nt, declaresStore as o, detectModularArchitecture as on, GO_DECL_RE as ot, isComponentsPath as p, interfaceSeparationGuard as pt, usesTailwindUtilities as q, SYSTEM_INSTALL as qt, queryCapActive as r, DEV_KEYWORDS as rn, registerGuard as rt, declaresCustomHook as s, detectProjectType as sn, JAVA_DECL_RE as st, declaresQueryHook as t, evaluateFileSize as tn, GUARDS as tt, declaresInterface as u, RUST_DECL_RE as ut, isTypesPath as v, FILE_REDIRECT as vt, maskCommentsOnly as w, ASK_PATTERNS as wt, lexProfileOf as x, PROTECTED_FRAGMENTS as xt, isVendorPath as y, SAFE_PREFIXES as yt, buildApexTaskInjection as z, solidReadGate as zt };
|