@fusengine/harness 0.1.48 → 0.1.50
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 +2 -2
- package/dist/adapters/claude/index.mjs +2 -2
- package/dist/adapters/cline/index.mjs +1 -1
- package/dist/adapters/codex/index.d.mts +1 -1
- package/dist/adapters/codex/index.mjs +1 -1
- package/dist/adapters/cursor/index.d.mts +10 -3
- package/dist/adapters/cursor/index.mjs +3 -3
- package/dist/adapters/gemini/index.mjs +1 -1
- package/dist/adapters/hermes/index.d.mts +54 -0
- package/dist/adapters/hermes/index.mjs +2 -0
- package/dist/apex-Wdi1nq_w.d.mts +73 -0
- package/dist/{claude-U1KTaRG4.mjs → claude-BxC9semG.mjs} +30 -9
- package/dist/cli/bin.mjs +5 -5
- package/dist/cli/index.mjs +1 -1
- package/dist/config/index.d.mts +1 -1
- package/dist/config/index.mjs +1 -1
- package/dist/detect/index.d.mts +1 -1
- package/dist/detect/index.mjs +1 -1
- package/dist/{doc-helpers-BNfYWvYv.d.mts → doc-helpers-CEKzGg2u.d.mts} +2 -0
- package/dist/{dotenv-B9nM4cuQ.mjs → dotenv-Jj8aL1FL.mjs} +2 -1
- package/dist/{evaluate-qYC5xClb.mjs → evaluate-CNAzgxnN.mjs} +3 -85
- package/dist/freshness/index.d.mts +1 -1
- package/dist/{handle-CCV0ycdr.mjs → handle-DzPjaPS-.mjs} +868 -71
- package/dist/{harness-C8Nxxyn_.mjs → harness-Cb9xR8dC.mjs} +6 -3
- package/dist/{harness-BPPu5CrN.d.mts → harness-s1Fce_dL.d.mts} +1 -1
- package/dist/hermes-DWXCRFZU.mjs +54 -0
- package/dist/home-state-D0RLWP8J.mjs +134 -0
- package/dist/{index-BqfOFKm7.d.mts → index-BfMsILmg.d.mts} +2 -63
- package/dist/{index-BxjzFraL.d.mts → index-DZCLmSoO.d.mts} +11 -9
- package/dist/{index-BXPySPxE.d.mts → index-jj_EzZRv.d.mts} +1 -1
- package/dist/index.d.mts +7 -6
- package/dist/index.mjs +6 -5
- package/dist/init/index.d.mts +1 -1
- package/dist/policy/index.d.mts +3 -2
- package/dist/policy/index.mjs +4 -3
- package/dist/prompt/index.d.mts +1 -1
- package/dist/{run-CaqeQFYp.mjs → run-DZvP_9xB.mjs} +1 -1
- package/dist/runtime/index.d.mts +39 -9
- package/dist/runtime/index.mjs +3 -3
- package/dist/{session-state-V8Jp-KE5.d.mts → session-state-DMpotbRz.d.mts} +26 -4
- package/dist/skill-path-DhItkBzk.mjs +95 -0
- package/dist/store-QSSTO3lY.mjs +349 -0
- package/dist/tracking/index.d.mts +2 -2
- package/dist/tracking/index.mjs +2 -2
- package/dist/{types-D56jSgD9.d.mts → types-DVbIl9md.d.mts} +6 -0
- package/dist/{validate-ebDjIyOa.mjs → validate-DCQ8dkdL.mjs} +16 -100
- package/package.json +7 -2
- package/dist/home-state-mKZxP4oZ.mjs +0 -52
- package/dist/store-ARx-GQSQ.mjs +0 -200
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { ClaudeHookInput, blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, readClaudeInput, systemMessage, toClaudeResponse };
|
|
1
|
+
import { a as denyResponse, c as informResponse, d as toClaudeResponse, i as contextResponse, l as readClaudeInput, n as attachSystemMessage, o as fileSizeGuard, r as blockResponse, s as guard, t as ClaudeHookInput, u as systemMessage } from "../../index-DZCLmSoO.mjs";
|
|
2
|
+
export { ClaudeHookInput, attachSystemMessage, blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, informResponse, readClaudeInput, systemMessage, toClaudeResponse };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, readClaudeInput, systemMessage, toClaudeResponse };
|
|
1
|
+
import { a as fileSizeGuard, c as readClaudeInput, i as denyResponse, l as systemMessage, n as blockResponse, o as guard, r as contextResponse, s as informResponse, t as attachSystemMessage, u as toClaudeResponse } from "../../claude-BxC9semG.mjs";
|
|
2
|
+
export { attachSystemMessage, blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, informResponse, readClaudeInput, systemMessage, toClaudeResponse };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as denyResponse, i as contextResponse, l as readClaudeInput, s as guard, t as ClaudeHookInput } from "../../index-DZCLmSoO.mjs";
|
|
2
2
|
export { type ClaudeHookInput as CodexHookInput, contextResponse, denyResponse, guard, readClaudeInput as readCodexInput };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { c as readClaudeInput, i as denyResponse, o as guard, r as contextResponse } from "../../claude-BxC9semG.mjs";
|
|
2
2
|
export { contextResponse, denyResponse, guard, readClaudeInput as readCodexInput };
|
|
@@ -14,12 +14,19 @@ interface CursorEditPayload {
|
|
|
14
14
|
new_string: string;
|
|
15
15
|
}[];
|
|
16
16
|
}
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* `beforeShellExecution` stdout response. Message keys are snake_case:
|
|
19
|
+
* Cursor silently ignores camelCase `userMessage`/`agentMessage` (#141516,
|
|
20
|
+
* regression persists through v2.0.77+ — forum #142589), matching the
|
|
21
|
+
* schema respond.ts emits for the cursor harness.
|
|
22
|
+
*/
|
|
18
23
|
interface CursorResponse {
|
|
19
24
|
permission: "allow" | "deny" | "ask";
|
|
20
25
|
continue?: boolean;
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
/** User-visible message — snake_case required (#141516, #142589). */
|
|
27
|
+
user_message?: string;
|
|
28
|
+
/** Agent-visible message — snake_case required (#141516, #142589). */
|
|
29
|
+
agent_message?: string;
|
|
23
30
|
}
|
|
24
31
|
//#endregion
|
|
25
32
|
//#region src/adapters/cursor/index.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as evaluate } from "../../evaluate-
|
|
1
|
+
import { t as evaluate } from "../../evaluate-CNAzgxnN.mjs";
|
|
2
2
|
import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
|
|
3
3
|
//#region src/adapters/cursor/index.ts
|
|
4
4
|
/**
|
|
@@ -19,8 +19,8 @@ function beforeShellExecution(payload) {
|
|
|
19
19
|
return {
|
|
20
20
|
permission: toPermission(r.prompt.kind),
|
|
21
21
|
continue: false,
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
user_message: msg,
|
|
23
|
+
agent_message: msg
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
/** Observe a file edit (Cursor cannot block here). Returns the verdict for logging. */
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { t as Prompt } from "../../types-DVbIl9md.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/hermes/interfaces/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Hermes Agent (NousResearch/hermes-agent) shell-hook wire types. Verified 2026
|
|
6
|
+
* against hermes-agent.nousresearch.com/docs/user-guide/features/hooks: hooks
|
|
7
|
+
* are configured in `~/.hermes/config.yaml` under `hooks:`, receive a JSON
|
|
8
|
+
* payload on stdin, and answer with JSON on stdout.
|
|
9
|
+
*/
|
|
10
|
+
/** `pre_tool_call` stdin payload (subset). Same wire shape as Claude Code. */
|
|
11
|
+
interface HermesHookInput {
|
|
12
|
+
hook_event_name?: string;
|
|
13
|
+
tool_name?: string;
|
|
14
|
+
tool_input?: {
|
|
15
|
+
path?: string;
|
|
16
|
+
file_path?: string;
|
|
17
|
+
content?: string;
|
|
18
|
+
command?: string;
|
|
19
|
+
};
|
|
20
|
+
session_id?: string;
|
|
21
|
+
cwd?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Hook stdout response. `{}` allows; `{ decision: "block", reason }` cancels
|
|
25
|
+
* the tool call; `{ context }` injects LLM context (honored on `pre_llm_call`).
|
|
26
|
+
* Hermes has NO Claude-style `permissionDecision` and no interactive "ask".
|
|
27
|
+
*/
|
|
28
|
+
interface HermesResponse {
|
|
29
|
+
decision?: "block";
|
|
30
|
+
reason?: string;
|
|
31
|
+
context?: string;
|
|
32
|
+
}
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region src/adapters/hermes/index.d.ts
|
|
35
|
+
/** Read & parse the Hermes hook stdin payload (same wire shape as Claude). */
|
|
36
|
+
declare function readHermesInput(): Promise<HermesHookInput>;
|
|
37
|
+
/**
|
|
38
|
+
* Render a portable {@link Prompt} as a Hermes hook response string:
|
|
39
|
+
* `block` -> `{decision:"block",reason}`; `ask`/`inform` -> non-blocking
|
|
40
|
+
* `{context}` — Hermes has no interactive "ask" state, so both degrade to
|
|
41
|
+
* context injection, mirroring the gemini-cli/cline routing in `respond()`.
|
|
42
|
+
* @param prompt - The portable policy prompt.
|
|
43
|
+
* @returns The native Hermes JSON response string.
|
|
44
|
+
*/
|
|
45
|
+
declare function toHermesResponse(prompt: Prompt): string;
|
|
46
|
+
/**
|
|
47
|
+
* Run the bundled policy over a Hermes `pre_tool_call` payload and return the
|
|
48
|
+
* native response string, or null to allow (the hook then prints `{}`).
|
|
49
|
+
* @param input - Parsed `pre_tool_call` stdin payload.
|
|
50
|
+
* @returns Native response JSON, or null when the tool use is allowed.
|
|
51
|
+
*/
|
|
52
|
+
declare function guard(input: HermesHookInput): string | null;
|
|
53
|
+
//#endregion
|
|
54
|
+
export { type HermesHookInput, type HermesResponse, guard, readHermesInput, toHermesResponse };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { t as Prompt } from "./types-DVbIl9md.mjs";
|
|
2
|
+
import { t as AuthEntry } from "./doc-helpers-CEKzGg2u.mjs";
|
|
3
|
+
import { t as RefMeta } from "./types-CY5qT2X1.mjs";
|
|
4
|
+
|
|
5
|
+
//#region src/policy/apex-gates.d.ts
|
|
6
|
+
/** Gate: the routed SOLID references for this edit must have been read within the TTL. */
|
|
7
|
+
declare const solidReadGate: ApexGate;
|
|
8
|
+
/** Gate: the required prior agents (explore + research) must have run within the window. */
|
|
9
|
+
declare const freshnessGate: ApexGate;
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/policy/apex.d.ts
|
|
12
|
+
/**
|
|
13
|
+
* Session context for the stateful APEX gates. The harness adapter supplies this
|
|
14
|
+
* (the package owns the gate LOGIC; recording the session activity is the
|
|
15
|
+
* adapter's tracking layer).
|
|
16
|
+
*/
|
|
17
|
+
interface ApexContext {
|
|
18
|
+
sessionId: string;
|
|
19
|
+
framework: string;
|
|
20
|
+
filePath: string;
|
|
21
|
+
content: string;
|
|
22
|
+
/** Doc-consultation authorizations from session state (Context7/Exa). */
|
|
23
|
+
authorizations?: Record<string, AuthEntry>;
|
|
24
|
+
/** Available SOLID references for the framework's skill. */
|
|
25
|
+
refs?: RefMeta[];
|
|
26
|
+
/** Absolute paths of SOLID refs already read this session. */
|
|
27
|
+
refsRead?: string[];
|
|
28
|
+
/**
|
|
29
|
+
* Epoch-ms read timestamp per `refsRead` path (parity track-solid-reads.py
|
|
30
|
+
* `solid_reads[].timestamp`). PARITY: the TTL applies ONLY to solidReadGate —
|
|
31
|
+
* Python TTL-izes SOLID reads exclusively (require-solid-read.py); the
|
|
32
|
+
* skill-trigger/design/shadcn gates stay session-scoped (no TTL). A path in
|
|
33
|
+
* `refsRead` with no stamp here (tracks recorded before this field existed)
|
|
34
|
+
* counts as read — backward compat.
|
|
35
|
+
*/
|
|
36
|
+
refsReadAt?: Record<string, number>;
|
|
37
|
+
/** Current epoch ms for the SOLID-read TTL check; absent → reads never expire. */
|
|
38
|
+
now?: number;
|
|
39
|
+
/** Whether the required prior agents (explore + research) ran within the freshness window. */
|
|
40
|
+
agentsFresh?: boolean;
|
|
41
|
+
/** Names of REQUIRED_AGENTS that have NOT run fresh (subset), for a precise freshnessGate message. Absent → generic wording. */
|
|
42
|
+
missingAgents?: string[];
|
|
43
|
+
/** Freshness window in ms: labels the block messages' TTL (e.g. "2min") and bounds the SOLID-read TTL in solidReadGate. */
|
|
44
|
+
windowMs?: number;
|
|
45
|
+
/** Whether brainstorming is required for this edit (creation intent on a new file). */
|
|
46
|
+
brainstormRequired?: boolean;
|
|
47
|
+
/** Whether the brainstorming agent ran within the window. */
|
|
48
|
+
brainstormFresh?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/** A single APEX gate: returns a blocking {@link Prompt}, or null to pass. */
|
|
51
|
+
type ApexGate = (ctx: ApexContext) => Prompt | null;
|
|
52
|
+
/** Gate: BOTH Context7 AND Exa (or a web fallback alone) must have been consulted this session. */
|
|
53
|
+
declare const docConsultedGate: ApexGate;
|
|
54
|
+
/** Gate: brainstorming must precede creating new files when flagged. */
|
|
55
|
+
declare const brainstormGate: ApexGate;
|
|
56
|
+
/** Gates that run BEFORE Check 1 (harness-specific brainstorm + agent freshness, pre-dating enforce-apex-phases). */
|
|
57
|
+
declare const PRE_AUTH_GATES: ReadonlyArray<ApexGate>;
|
|
58
|
+
/** Gates that run AFTER Check 1: Check 2 (doc consulted once per session) then the SOLID refs. */
|
|
59
|
+
declare const POST_AUTH_GATES: ReadonlyArray<ApexGate>;
|
|
60
|
+
/**
|
|
61
|
+
* Default APEX gate chain (brainstorm, freshness, docs, SOLID refs). Check 1
|
|
62
|
+
* (`apexAuthorizationGate`, policy/apex-authorization.ts) is wired BETWEEN the
|
|
63
|
+
* PRE and POST sub-chains by the runtime (gate-apex.ts), which owns its
|
|
64
|
+
* target-write side effect — parity enforce-apex-phases.ts Check1 -> Check2.
|
|
65
|
+
*/
|
|
66
|
+
declare const APEX_GATES: ReadonlyArray<ApexGate>;
|
|
67
|
+
/**
|
|
68
|
+
* Run the APEX gates (chain-of-responsibility): the first failing gate's prompt
|
|
69
|
+
* wins; null means every gate passed (allow).
|
|
70
|
+
*/
|
|
71
|
+
declare function evaluateApex(ctx: ApexContext, gates?: ReadonlyArray<ApexGate>): Prompt | null;
|
|
72
|
+
//#endregion
|
|
73
|
+
export { PRE_AUTH_GATES as a, evaluateApex as c, POST_AUTH_GATES as i, freshnessGate as l, ApexContext as n, brainstormGate as o, ApexGate as r, docConsultedGate as s, APEX_GATES as t, solidReadGate as u };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as evaluate } from "./evaluate-
|
|
1
|
+
import { t as evaluate } from "./evaluate-CNAzgxnN.mjs";
|
|
2
2
|
import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
@@ -96,12 +96,9 @@ function denyResponse(event, reason) {
|
|
|
96
96
|
} });
|
|
97
97
|
}
|
|
98
98
|
/**
|
|
99
|
-
* A PostToolUse (and Stop/UserPromptSubmit) `block` response
|
|
100
|
-
* ignore `
|
|
101
|
-
*
|
|
102
|
-
* to Claude as automated feedback.
|
|
103
|
-
* @param reason - The block feedback shown to Claude.
|
|
104
|
-
* @returns The native `{decision:"block",reason}` response string.
|
|
99
|
+
* A PostToolUse (and Stop/UserPromptSubmit) `block` response: those events
|
|
100
|
+
* ignore `permissionDecision` (PreToolUse-only) and only honor the top-level
|
|
101
|
+
* `decision`/`reason` keys, which feed `reason` back to Claude.
|
|
105
102
|
*/
|
|
106
103
|
function blockResponse(reason) {
|
|
107
104
|
return JSON.stringify({
|
|
@@ -120,10 +117,33 @@ function contextResponse(event, text) {
|
|
|
120
117
|
function systemMessage(text) {
|
|
121
118
|
return JSON.stringify({ systemMessage: text });
|
|
122
119
|
}
|
|
120
|
+
/** An `inform` response with a user-visible notice (Python `allow_pass`/`post_pass` parity): a pure pass reuses {@link systemMessage} alone; with agent-facing `context` both channels merge in one JSON. */
|
|
121
|
+
function informResponse(event, notice, context) {
|
|
122
|
+
if (!context) return systemMessage(notice);
|
|
123
|
+
return JSON.stringify({
|
|
124
|
+
systemMessage: notice,
|
|
125
|
+
hookSpecificOutput: {
|
|
126
|
+
hookEventName: event,
|
|
127
|
+
additionalContext: context
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/** Attach a user-visible `systemMessage` onto an already-rendered hook stdout JSON ({@link systemMessage} alone when empty/unparseable). */
|
|
132
|
+
function attachSystemMessage(stdout, notice) {
|
|
133
|
+
try {
|
|
134
|
+
return JSON.stringify({
|
|
135
|
+
...JSON.parse(stdout),
|
|
136
|
+
systemMessage: notice
|
|
137
|
+
});
|
|
138
|
+
} catch {
|
|
139
|
+
return systemMessage(notice);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
123
142
|
/**
|
|
124
143
|
* Render a portable {@link Prompt} as a Claude Code hook response:
|
|
125
144
|
* `block` → `permissionDecision: deny`, `ask` → `permissionDecision: ask`
|
|
126
|
-
* (interactive confirm), `inform` → `additionalContext
|
|
145
|
+
* (interactive confirm), `inform` → `additionalContext` — plus the user-visible
|
|
146
|
+
* `systemMessage` channel when the prompt carries a `userMessage`.
|
|
127
147
|
*/
|
|
128
148
|
function toClaudeResponse(event, prompt) {
|
|
129
149
|
const reason = formatPrompt(prompt);
|
|
@@ -133,6 +153,7 @@ function toClaudeResponse(event, prompt) {
|
|
|
133
153
|
permissionDecision: "ask",
|
|
134
154
|
permissionDecisionReason: reason
|
|
135
155
|
} });
|
|
156
|
+
if (prompt.userMessage) return informResponse(event, prompt.userMessage, prompt.reason ? reason : "");
|
|
136
157
|
return contextResponse(event, reason);
|
|
137
158
|
}
|
|
138
159
|
/**
|
|
@@ -152,4 +173,4 @@ function guard(input) {
|
|
|
152
173
|
/** @deprecated use {@link guard}. Kept for back-compat. */
|
|
153
174
|
const fileSizeGuard = guard;
|
|
154
175
|
//#endregion
|
|
155
|
-
export {
|
|
176
|
+
export { fileSizeGuard as a, readClaudeInput as c, collectFiles as d, pathExists as f, writeText as g, spawnCapture as h, denyResponse as i, systemMessage as l, sleep as m, blockResponse as n, guard as o, readText as p, contextResponse as r, informResponse as s, attachSystemMessage as t, toClaudeResponse as u };
|
package/dist/cli/bin.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { r as loadDotenv, s as resolveTtlSec } from "../dotenv-
|
|
3
|
-
import { t as detectHarness } from "../harness-
|
|
4
|
-
import { t as claudeHome } from "../home-state-
|
|
5
|
-
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-
|
|
2
|
+
import { r as loadDotenv, s as resolveTtlSec } from "../dotenv-Jj8aL1FL.mjs";
|
|
3
|
+
import { t as detectHarness } from "../harness-Cb9xR8dC.mjs";
|
|
4
|
+
import { t as claudeHome } from "../home-state-D0RLWP8J.mjs";
|
|
5
|
+
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-DZvP_9xB.mjs";
|
|
6
6
|
import { n as writeInitFile, t as initFor } from "../run-Do2JltgU.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { Nt as todayUtc, t as handleHook } from "../handle-DzPjaPS-.mjs";
|
|
8
8
|
import { delimiter, dirname, join } from "node:path";
|
|
9
9
|
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
10
10
|
import { homedir } from "node:os";
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-
|
|
1
|
+
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-DZvP_9xB.mjs";
|
|
2
2
|
export { checkStaged, stagedContent, stagedFiles };
|
package/dist/config/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as parseEnvInt, a as ProjectLayout, c as projectLayout, d as resolveMaxLines, f as splitTarget, g as ttlLabel, h as resolveTtlSec, i as parseEnvFile, l as DEFAULT_MAX_LINES, m as TTL_ENV_KEY, n as envCandidates, o as STATE_GITIGNORE, p as DEFAULT_TTL_SEC, r as loadDotenv, s as STATE_ROOT, t as HOME_DIR, u as MAX_LINES_ENV_KEY } from "../index-
|
|
1
|
+
import { _ as parseEnvInt, a as ProjectLayout, c as projectLayout, d as resolveMaxLines, f as splitTarget, g as ttlLabel, h as resolveTtlSec, i as parseEnvFile, l as DEFAULT_MAX_LINES, m as TTL_ENV_KEY, n as envCandidates, o as STATE_GITIGNORE, p as DEFAULT_TTL_SEC, r as loadDotenv, s as STATE_ROOT, t as HOME_DIR, u as MAX_LINES_ENV_KEY } from "../index-jj_EzZRv.mjs";
|
|
2
2
|
export { DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, HOME_DIR, MAX_LINES_ENV_KEY, ProjectLayout, STATE_GITIGNORE, STATE_ROOT, TTL_ENV_KEY, envCandidates, loadDotenv, parseEnvFile, parseEnvInt, projectLayout, resolveMaxLines, resolveTtlSec, splitTarget, ttlLabel };
|
package/dist/config/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as parseEnvInt, i as splitTarget, n as MAX_LINES_ENV_KEY, r as resolveMaxLines, t as DEFAULT_MAX_LINES } from "../limits-CHn8AIL1.mjs";
|
|
2
|
-
import { a as DEFAULT_TTL_SEC, c as ttlLabel, i as parseEnvFile, n as envCandidates, o as TTL_ENV_KEY, r as loadDotenv, s as resolveTtlSec, t as HOME_DIR } from "../dotenv-
|
|
2
|
+
import { a as DEFAULT_TTL_SEC, c as ttlLabel, i as parseEnvFile, n as envCandidates, o as TTL_ENV_KEY, r as loadDotenv, s as resolveTtlSec, t as HOME_DIR } from "../dotenv-Jj8aL1FL.mjs";
|
|
3
3
|
import { n as STATE_ROOT, r as projectLayout, t as STATE_GITIGNORE } from "../layout-C0jaaCQC.mjs";
|
|
4
4
|
import "../config-la_KkjCS.mjs";
|
|
5
5
|
export { DEFAULT_MAX_LINES, DEFAULT_TTL_SEC, HOME_DIR, MAX_LINES_ENV_KEY, STATE_GITIGNORE, STATE_ROOT, TTL_ENV_KEY, envCandidates, loadDotenv, parseEnvFile, parseEnvInt, projectLayout, resolveMaxLines, resolveTtlSec, splitTarget, ttlLabel };
|
package/dist/detect/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as HarnessInfo, i as HarnessId, n as detectMode, o as HarnessMode, r as modeFor, s as HarnessVia, t as detectHarness } from "../harness-
|
|
1
|
+
import { a as HarnessInfo, i as HarnessId, n as detectMode, o as HarnessMode, r as modeFor, s as HarnessVia, t as detectHarness } from "../harness-s1Fce_dL.mjs";
|
|
2
2
|
export { type HarnessId, type HarnessInfo, type HarnessMode, type HarnessVia, detectHarness, detectMode, modeFor };
|
package/dist/detect/index.mjs
CHANGED
|
@@ -12,6 +12,8 @@ interface AuthEntry {
|
|
|
12
12
|
session?: string;
|
|
13
13
|
doc_sessions?: string[];
|
|
14
14
|
read_paths?: string[];
|
|
15
|
+
/** ISO stamp of the latest doc/skill consultation for this framework (Check-1 TTL, parity enforce-apex-phases.ts). */
|
|
16
|
+
doc_consulted?: string;
|
|
15
17
|
}
|
|
16
18
|
/** Resolve the sessions array from an auth entry (legacy fallback). */
|
|
17
19
|
declare function resolveSessions(auth: AuthEntry | undefined): string[];
|
|
@@ -41,7 +41,8 @@ const HOME_DIR = {
|
|
|
41
41
|
cursor: ".cursor",
|
|
42
42
|
cline: ".clinerules",
|
|
43
43
|
"gemini-cli": ".gemini",
|
|
44
|
-
opencode: ".opencode"
|
|
44
|
+
opencode: ".opencode",
|
|
45
|
+
hermes: ".hermes"
|
|
45
46
|
};
|
|
46
47
|
/** Parse a `.env` file into a key→value map (`export KEY="v"` or `KEY=v`). */
|
|
47
48
|
function parseEnvFile(path) {
|
|
@@ -1,89 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { basename, dirname, join, normalize } from "node:path";
|
|
1
|
+
import { f as countLines, p as evaluateFileSize, r as fusengineCache, t as claudeHome } from "./home-state-D0RLWP8J.mjs";
|
|
2
|
+
import { dirname, join, normalize } from "node:path";
|
|
4
3
|
import { existsSync } from "node:fs";
|
|
5
4
|
import { homedir } from "node:os";
|
|
6
|
-
//#region src/policy/file-size.ts
|
|
7
|
-
/**
|
|
8
|
-
* Fixed marketplace plugins root — parity with Python `enforce-file-size.py`'s
|
|
9
|
-
* literal, unexpanded `~/...` string. Exported: reused by
|
|
10
|
-
* `policy/apex.ts::solidReadGate` for its "no reference matched" deny message.
|
|
11
|
-
*/
|
|
12
|
-
const PLUGINS_DIR = "~/.claude/plugins/marketplaces/fusengine-plugins/plugins";
|
|
13
|
-
/**
|
|
14
|
-
* Skill-dir fragment per framework — parity with Python
|
|
15
|
-
* `enforce-file-size.py::get_solid_ref()` (falls back to `generic/`). Exported:
|
|
16
|
-
* reused by `policy/apex.ts::solidReadGate` (see {@link PLUGINS_DIR}).
|
|
17
|
-
*/
|
|
18
|
-
const SOLID_REF = {
|
|
19
|
-
react: "react-expert/skills/solid-react/",
|
|
20
|
-
nextjs: "nextjs-expert/skills/solid-nextjs/",
|
|
21
|
-
laravel: "laravel-expert/skills/solid-php/",
|
|
22
|
-
swift: "swift-apple-expert/skills/solid-swift/"
|
|
23
|
-
};
|
|
24
|
-
/**
|
|
25
|
-
* Count physical lines — parity with the Python `enforce-file-size.py`
|
|
26
|
-
* (`sum(1 for _ in f)`): every line counts (blanks and comments included), and a
|
|
27
|
-
* single trailing newline does not add a phantom line. The SOLID ceiling is
|
|
28
|
-
* measured on raw file length, not substantive code, to match the upstream plugin.
|
|
29
|
-
*/
|
|
30
|
-
function countLines(content) {
|
|
31
|
-
if (content === "") return 0;
|
|
32
|
-
return content.split("\n").length - (content.endsWith("\n") ? 1 : 0);
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Count non-empty, non-comment lines — parity with the Python `count_code_lines`
|
|
36
|
-
* shared by the framework-specific SOLID validators: `_shared/scripts/validate_solid_common.py`
|
|
37
|
-
* (imported by `nextjs-expert/scripts/validate-nextjs-solid.py` and
|
|
38
|
-
* `swift-apple-expert/scripts/validate-swift-solid.py`), duplicated verbatim in
|
|
39
|
-
* `react-expert/scripts/validate-react-solid.py` / `laravel-expert/scripts/validate-laravel-solid.py`.
|
|
40
|
-
* Strips blank lines and lines starting with `//` or `*` — a SINGLE fixed rule
|
|
41
|
-
* for all 4 callers (the Python `comment` param defaults to, and every real
|
|
42
|
-
* call site leaves it at, `"//"` — never per-language despite covering
|
|
43
|
-
* ts/tsx/js/jsx, php and swift).
|
|
44
|
-
*
|
|
45
|
-
* Deliberately distinct from two other "code-only" counters already in this
|
|
46
|
-
* repo, neither of which is a faithful substitute here:
|
|
47
|
-
* - `countLoc` (`runtime/lifecycle/check-file-size.ts`): a genuinely
|
|
48
|
-
* per-language table (PHP additionally strips `#`, Python strips
|
|
49
|
-
* `#`/`"""`/`'''`) — ported from the unrelated `solid/scripts/check-file-size.py`.
|
|
50
|
-
* - `countCodeLines` (`runtime/lifecycle/aipilot/solid-compliance.ts`): also
|
|
51
|
-
* strips `#` — ported from `ai-pilot/scripts/check-solid-compliance.py`.
|
|
52
|
-
* Reusing either would silently strip PHP `#`/Python-style comments that the
|
|
53
|
-
* real react/nextjs/laravel/swift validators do NOT strip.
|
|
54
|
-
* @param content - The file content to measure.
|
|
55
|
-
*/
|
|
56
|
-
function countFrameworkCodeLines(content) {
|
|
57
|
-
let count = 0;
|
|
58
|
-
for (const raw of content.split("\n")) {
|
|
59
|
-
const line = raw.trim();
|
|
60
|
-
if (!line || line.startsWith("//") || line.startsWith("*")) continue;
|
|
61
|
-
count++;
|
|
62
|
-
}
|
|
63
|
-
return count;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Evaluate a file's line count against the SOLID limit.
|
|
67
|
-
* @param lines - the file's line count
|
|
68
|
-
* @param max - the limit (defaults to `resolveMaxLines()`)
|
|
69
|
-
*/
|
|
70
|
-
function evaluateFileSize(lines, max = resolveMaxLines(), filePath = "", framework = "generic", displayLines = lines) {
|
|
71
|
-
if (lines <= max) return {
|
|
72
|
-
ok: true,
|
|
73
|
-
lines,
|
|
74
|
-
max,
|
|
75
|
-
message: null
|
|
76
|
-
};
|
|
77
|
-
const split = splitTarget(max);
|
|
78
|
-
const fname = filePath ? basename(filePath) : "file";
|
|
79
|
-
return {
|
|
80
|
-
ok: false,
|
|
81
|
-
lines,
|
|
82
|
-
max,
|
|
83
|
-
message: `BLOCKED: '${fname}' has ${displayLines} lines (max: ${max}). TO SPLIT: 1) Read SOLID rules: ${PLUGINS_DIR}/${SOLID_REF[framework] ?? "generic/"} 2) Create new module files (<${split} lines each) 3) Use Write to replace '${fname}' with <${max} lines version.`
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
//#endregion
|
|
87
5
|
//#region src/policy/patterns.ts
|
|
88
6
|
/**
|
|
89
7
|
* Guard pattern data, ported verbatim from the fusengine git/install guards.
|
|
@@ -820,4 +738,4 @@ function evaluate(ctx) {
|
|
|
820
738
|
};
|
|
821
739
|
}
|
|
822
740
|
//#endregion
|
|
823
|
-
export { PROJECT_INSTALL as A, PROTECTED_GIT_RE as C, securityGuard as D, CRITICAL_PATTERNS as E,
|
|
741
|
+
export { PROJECT_INSTALL as A, PROTECTED_GIT_RE as C, securityGuard as D, CRITICAL_PATTERNS as E, SYSTEM_INSTALL as M, isRalphMode as N, GIT_ASK as O, matchPatterns as P, PROTECTED_FRAGMENTS as S, ASK_PATTERNS as T, CODE_MUTATORS as _, registerGuard as a, SAFE_PREFIXES as b, GO_DECL_RE as c, PY_MODEL_RE as d, SWIFT_PROTO_RE as f, ASK_WRITERS as g, bashWriteGuard as h, clearUserGuards as i, RALPH_SAFE as j, GIT_BLOCKED as k, JAVA_DECL_RE as l, interfaceSeparationGuard as m, FAIL_CLOSED as n, runGuards as o, TS_DECL_RE as p, GUARDS as r, installGuard as s, evaluate as t, PHP_DECL_RE as u, CODE_REDIRECT as v, protectedPathGuard as w, SESSION_STATE_FRAGMENT as x, FILE_REDIRECT as y };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as isDocConsulted, i as formatDocSatisfactionStatus, n as DocSatisfactionStatus, o as resolveSessions, r as formatDocDeny, t as AuthEntry } from "../doc-helpers-
|
|
1
|
+
import { a as isDocConsulted, i as formatDocSatisfactionStatus, n as DocSatisfactionStatus, o as resolveSessions, r as formatDocDeny, t as AuthEntry } from "../doc-helpers-CEKzGg2u.mjs";
|
|
2
2
|
import { t as incrementTrivialEditCounter } from "../index-BOBXQ91y.mjs";
|
|
3
3
|
export { AuthEntry, DocSatisfactionStatus, formatDocDeny, formatDocSatisfactionStatus, incrementTrivialEditCounter, isDocConsulted, resolveSessions };
|