@fusengine/harness 0.1.80 → 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.
- 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-J5r2f_O_.mjs} +637 -159
- 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-nDZ3eLBQ.mjs → store-yr_QFsZY.mjs} +101 -13
- package/dist/tracking/index.d.mts +22 -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
|
@@ -1,2 +1,2 @@
|
|
|
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-
|
|
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-D4C2-IIc.mjs";
|
|
2
2
|
export { ClaudeHookInput, attachSystemMessage, blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, informResponse, readClaudeInput, systemMessage, toClaudeResponse };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as fileSizeGuard, c as readClaudeInput, i as denyResponse, l as systemMessage, n as blockResponse, o as guard, r as contextResponse, s as informResponse, t as attachSystemMessage, u as toClaudeResponse } from "../../claude-
|
|
1
|
+
import { a as fileSizeGuard, c as readClaudeInput, i as denyResponse, l as systemMessage, n as blockResponse, o as guard, r as contextResponse, s as informResponse, t as attachSystemMessage, u as toClaudeResponse } from "../../claude-D93HY8dq.mjs";
|
|
2
2
|
export { attachSystemMessage, blockResponse, contextResponse, denyResponse, fileSizeGuard, guard, informResponse, readClaudeInput, systemMessage, toClaudeResponse };
|
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import { t as Prompt } from "../../types-
|
|
2
|
-
import { a as denyResponse, c as informResponse, i as contextResponse, l as readClaudeInput, t as ClaudeHookInput } from "../../index-
|
|
3
|
-
|
|
1
|
+
import { t as Prompt } from "../../types-C0-igRKr.mjs";
|
|
2
|
+
import { a as denyResponse, c as informResponse, i as contextResponse, l as readClaudeInput, t as ClaudeHookInput } from "../../index-D4C2-IIc.mjs";
|
|
4
3
|
//#region src/adapters/codex/index.d.ts
|
|
5
4
|
/**
|
|
6
|
-
* Render a portable {@link Prompt} as a Codex hook response, `ask` → explicit deny.
|
|
7
|
-
* NOTE: the REAL wired route is `harness hook codex` → handleHook → respond.ts
|
|
8
|
-
* (source of truth for the ask→deny downgrade); this thin export exists for
|
|
9
|
-
* direct package consumers and is kept aligned so it never silently diverges.
|
|
10
|
-
*/
|
|
5
|
+
* Render a portable {@link Prompt} as a Codex hook response, `ask` → explicit deny.
|
|
6
|
+
* NOTE: the REAL wired route is `harness hook codex` → handleHook → respond.ts
|
|
7
|
+
* (source of truth for the ask→deny downgrade); this thin export exists for
|
|
8
|
+
* direct package consumers and is kept aligned so it never silently diverges.
|
|
9
|
+
*/
|
|
11
10
|
declare function toCodexResponse(prompt: Prompt): string;
|
|
12
11
|
/**
|
|
13
|
-
* Run the bundled policy over a Codex payload and return the native response
|
|
14
|
-
* string (deny/additionalContext), or null to allow. `apply_patch` is fanned
|
|
15
|
-
* into per-file checks; every other tool routes through the portable policy.
|
|
16
|
-
*/
|
|
12
|
+
* Run the bundled policy over a Codex payload and return the native response
|
|
13
|
+
* string (deny/additionalContext), or null to allow. `apply_patch` is fanned
|
|
14
|
+
* into per-file checks; every other tool routes through the portable policy.
|
|
15
|
+
*/
|
|
17
16
|
declare function guard(input: ClaudeHookInput): string | null;
|
|
18
17
|
//#endregion
|
|
19
18
|
export { type ClaudeHookInput as CodexHookInput, contextResponse, denyResponse, guard, informResponse, readClaudeInput as readCodexInput, toCodexResponse };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { t as evaluate } from "../../evaluate-
|
|
2
|
-
import { f as countLines } from "../../home-state-
|
|
1
|
+
import { t as evaluate } from "../../evaluate-B4-MhOy_.mjs";
|
|
2
|
+
import { f as countLines } from "../../home-state-oUGFB4ds.mjs";
|
|
3
3
|
import { t as formatPrompt } from "../../types-ernB1Dy3.mjs";
|
|
4
4
|
import { n as parseApplyPatch, t as isBypassPermissions } from "../../permission-mode-BN3MNgbm.mjs";
|
|
5
|
-
import { c as readClaudeInput, i as denyResponse, r as contextResponse, s as informResponse
|
|
5
|
+
import { _ as commandToString, c as readClaudeInput, i as denyResponse, r as contextResponse, s as informResponse } from "../../claude-D93HY8dq.mjs";
|
|
6
6
|
//#region src/adapters/codex/index.ts
|
|
7
7
|
/**
|
|
8
8
|
* OpenAI Codex CLI adapter (hook-mode). Codex's `PreToolUse` hook (since 2026)
|
|
@@ -15,24 +15,24 @@ interface CursorEditPayload {
|
|
|
15
15
|
}[];
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
* `afterFileEdit` stdout response. Its schema (cursor.com/docs/hooks#afterFileEdit)
|
|
19
|
-
* is DELIBERATELY narrower than the "before" hooks: `permission` + `user_message`
|
|
20
|
-
* only — there is NO `agent_message` and NO `updated_input`. Since the edit is
|
|
21
|
-
* already on disk when this "after" hook fires, `deny` cannot revert it and the
|
|
22
|
-
* correction reaches only the HUMAN (`user_message`), never the model — so this
|
|
23
|
-
* path is strictly ADVISORY, not an enforceable gate.
|
|
24
|
-
*/
|
|
18
|
+
* `afterFileEdit` stdout response. Its schema (cursor.com/docs/hooks#afterFileEdit)
|
|
19
|
+
* is DELIBERATELY narrower than the "before" hooks: `permission` + `user_message`
|
|
20
|
+
* only — there is NO `agent_message` and NO `updated_input`. Since the edit is
|
|
21
|
+
* already on disk when this "after" hook fires, `deny` cannot revert it and the
|
|
22
|
+
* correction reaches only the HUMAN (`user_message`), never the model — so this
|
|
23
|
+
* path is strictly ADVISORY, not an enforceable gate.
|
|
24
|
+
*/
|
|
25
25
|
interface CursorEditResponse {
|
|
26
26
|
permission: "allow" | "deny";
|
|
27
27
|
/** User-visible correction — snake_case (#141516); the only channel afterFileEdit exposes. */
|
|
28
28
|
user_message?: string;
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* `beforeShellExecution` stdout response. Message keys are snake_case:
|
|
32
|
-
* Cursor silently ignores camelCase `userMessage`/`agentMessage` (#141516,
|
|
33
|
-
* regression persists through v2.0.77+ — forum #142589), matching the
|
|
34
|
-
* schema respond.ts emits for the cursor harness.
|
|
35
|
-
*/
|
|
31
|
+
* `beforeShellExecution` stdout response. Message keys are snake_case:
|
|
32
|
+
* Cursor silently ignores camelCase `userMessage`/`agentMessage` (#141516,
|
|
33
|
+
* regression persists through v2.0.77+ — forum #142589), matching the
|
|
34
|
+
* schema respond.ts emits for the cursor harness.
|
|
35
|
+
*/
|
|
36
36
|
interface CursorResponse {
|
|
37
37
|
permission: "allow" | "deny" | "ask";
|
|
38
38
|
continue?: boolean;
|
|
@@ -46,23 +46,23 @@ interface CursorResponse {
|
|
|
46
46
|
/** Guard a shell command (git/install policies). */
|
|
47
47
|
declare function beforeShellExecution(payload: CursorShellPayload): CursorResponse;
|
|
48
48
|
/**
|
|
49
|
-
* Advise on a file edit AFTER Cursor has written it — a HUMAN-VISIBLE audit note,
|
|
50
|
-
* never a gate. This is an "after" hook: the edit is already on disk. On a
|
|
51
|
-
* SOLID/DRY violation we surface the correction through `user_message` (the only
|
|
52
|
-
* channel afterFileEdit exposes — no `agent_message`, so the model is never
|
|
53
|
-
* re-informed) while ALWAYS returning `permission: "allow"`.
|
|
54
|
-
*
|
|
55
|
-
* We deliberately never emit `permission: "deny"` here, for two distinct reasons:
|
|
56
|
-
* (1) structural — afterFileEdit was "informational only" at launch (Chacon,
|
|
57
|
-
* Cursor hooks beta 1.7, 2025-09: no channel to stop the agent), and a post-write
|
|
58
|
-
* deny has no documented rollback; (2) empirical — Cursor staff confirm the
|
|
59
|
-
* deny-enforcement path is broken for file operations (forum.cursor.com/t/154377,
|
|
60
|
-
* v2.6.18, 2026-03, open) — proven for file READS, plausibly the same for writes.
|
|
61
|
-
* So a `deny` would be a false blocking signal; `allow` + `user_message` is the
|
|
62
|
-
* only proven-safe shape.
|
|
63
|
-
* @param payload - The `afterFileEdit` stdin payload.
|
|
64
|
-
* @returns Always an allow; carries the user-visible correction on a violation.
|
|
65
|
-
*/
|
|
49
|
+
* Advise on a file edit AFTER Cursor has written it — a HUMAN-VISIBLE audit note,
|
|
50
|
+
* never a gate. This is an "after" hook: the edit is already on disk. On a
|
|
51
|
+
* SOLID/DRY violation we surface the correction through `user_message` (the only
|
|
52
|
+
* channel afterFileEdit exposes — no `agent_message`, so the model is never
|
|
53
|
+
* re-informed) while ALWAYS returning `permission: "allow"`.
|
|
54
|
+
*
|
|
55
|
+
* We deliberately never emit `permission: "deny"` here, for two distinct reasons:
|
|
56
|
+
* (1) structural — afterFileEdit was "informational only" at launch (Chacon,
|
|
57
|
+
* Cursor hooks beta 1.7, 2025-09: no channel to stop the agent), and a post-write
|
|
58
|
+
* deny has no documented rollback; (2) empirical — Cursor staff confirm the
|
|
59
|
+
* deny-enforcement path is broken for file operations (forum.cursor.com/t/154377,
|
|
60
|
+
* v2.6.18, 2026-03, open) — proven for file READS, plausibly the same for writes.
|
|
61
|
+
* So a `deny` would be a false blocking signal; `allow` + `user_message` is the
|
|
62
|
+
* only proven-safe shape.
|
|
63
|
+
* @param payload - The `afterFileEdit` stdin payload.
|
|
64
|
+
* @returns Always an allow; carries the user-visible correction on a violation.
|
|
65
|
+
*/
|
|
66
66
|
declare function afterFileEdit(payload: CursorEditPayload): CursorEditResponse;
|
|
67
67
|
//#endregion
|
|
68
68
|
export { type CursorEditPayload, type CursorEditResponse, type CursorResponse, type CursorShellPayload, afterFileEdit, beforeShellExecution };
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import { t as Prompt } from "../../types-
|
|
2
|
-
|
|
1
|
+
import { t as Prompt } from "../../types-C0-igRKr.mjs";
|
|
3
2
|
//#region src/adapters/hermes/interfaces/types.d.ts
|
|
4
3
|
/**
|
|
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
|
-
*/
|
|
4
|
+
* Hermes Agent (NousResearch/hermes-agent) shell-hook wire types. Verified 2026
|
|
5
|
+
* against hermes-agent.nousresearch.com/docs/user-guide/features/hooks: hooks
|
|
6
|
+
* are configured in `~/.hermes/config.yaml` under `hooks:`, receive a JSON
|
|
7
|
+
* payload on stdin, and answer with JSON on stdout.
|
|
8
|
+
*/
|
|
10
9
|
/** `pre_tool_call` stdin payload (subset). Same wire shape as Claude Code. */
|
|
11
10
|
interface HermesHookInput {
|
|
12
11
|
hook_event_name?: string;
|
|
@@ -21,10 +20,10 @@ interface HermesHookInput {
|
|
|
21
20
|
cwd?: string;
|
|
22
21
|
}
|
|
23
22
|
/**
|
|
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
|
-
*/
|
|
23
|
+
* Hook stdout response. `{}` allows; `{ decision: "block", reason }` cancels
|
|
24
|
+
* the tool call; `{ context }` injects LLM context (honored on `pre_llm_call`).
|
|
25
|
+
* Hermes has NO Claude-style `permissionDecision` and no interactive "ask".
|
|
26
|
+
*/
|
|
28
27
|
interface HermesResponse {
|
|
29
28
|
decision?: "block";
|
|
30
29
|
reason?: string;
|
|
@@ -35,20 +34,20 @@ interface HermesResponse {
|
|
|
35
34
|
/** Read & parse the Hermes hook stdin payload (same wire shape as Claude). */
|
|
36
35
|
declare function readHermesInput(): Promise<HermesHookInput>;
|
|
37
36
|
/**
|
|
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
|
-
*/
|
|
37
|
+
* Render a portable {@link Prompt} as a Hermes hook response string:
|
|
38
|
+
* `block` -> `{decision:"block",reason}`; `ask`/`inform` -> non-blocking
|
|
39
|
+
* `{context}` — Hermes has no interactive "ask" state, so both degrade to
|
|
40
|
+
* context injection, mirroring the gemini-cli/cline routing in `respond()`.
|
|
41
|
+
* @param prompt - The portable policy prompt.
|
|
42
|
+
* @returns The native Hermes JSON response string.
|
|
43
|
+
*/
|
|
45
44
|
declare function toHermesResponse(prompt: Prompt): string;
|
|
46
45
|
/**
|
|
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
|
-
*/
|
|
46
|
+
* Run the bundled policy over a Hermes `pre_tool_call` payload and return the
|
|
47
|
+
* native response string, or null to allow (the hook then prints `{}`).
|
|
48
|
+
* @param input - Parsed `pre_tool_call` stdin payload.
|
|
49
|
+
* @returns Native response JSON, or null when the tool use is allowed.
|
|
50
|
+
*/
|
|
52
51
|
declare function guard(input: HermesHookInput): string | null;
|
|
53
52
|
//#endregion
|
|
54
53
|
export { type HermesHookInput, type HermesResponse, guard, readHermesInput, toHermesResponse };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-
|
|
1
|
+
import { n as readHermesInput, r as toHermesResponse, t as guard } from "../../hermes-1PUEoY8q.mjs";
|
|
2
2
|
export { guard, readHermesInput, toHermesResponse };
|
|
@@ -1,37 +1,36 @@
|
|
|
1
|
-
import { t as Prompt } from "../../types-
|
|
2
|
-
|
|
1
|
+
import { t as Prompt } from "../../types-C0-igRKr.mjs";
|
|
3
2
|
//#region src/adapters/kimi/interfaces/types.d.ts
|
|
4
3
|
/**
|
|
5
|
-
* Kimi Code CLI shell-hook wire types. Verified 2026 against
|
|
6
|
-
* kimi.com/code/docs/en/kimi-code-cli/customization/hooks.html (v0.27.0):
|
|
7
|
-
* hooks are configured in `~/.kimi-code/config.toml` under `[[hooks]]`,
|
|
8
|
-
* receive a snake_case JSON payload on stdin, and answer with a camelCase
|
|
9
|
-
* JSON envelope on stdout (a real, documented casing inconsistency).
|
|
10
|
-
*/
|
|
4
|
+
* Kimi Code CLI shell-hook wire types. Verified 2026 against
|
|
5
|
+
* kimi.com/code/docs/en/kimi-code-cli/customization/hooks.html (v0.27.0):
|
|
6
|
+
* hooks are configured in `~/.kimi-code/config.toml` under `[[hooks]]`,
|
|
7
|
+
* receive a snake_case JSON payload on stdin, and answer with a camelCase
|
|
8
|
+
* JSON envelope on stdout (a real, documented casing inconsistency).
|
|
9
|
+
*/
|
|
11
10
|
/**
|
|
12
|
-
* `PreToolUse`/`UserPromptSubmit`/`Stop` stdin payload (subset). Same base
|
|
13
|
-
* wire shape as Claude Code (`hook_event_name`/`tool_name`/`tool_input`/
|
|
14
|
-
* `cwd`); `tool_input.command` is confirmed for `Bash` by the docs' example
|
|
15
|
-
* script (`payload.tool_input?.command`). Verified live against kimi-code
|
|
16
|
-
* v0.27.0 on `PreToolUse`/`Bash`: `tool_name` is present at top level (the
|
|
17
|
-
* docs never name it as a stdin key) and `tool_input.command` carries the
|
|
18
|
-
* shell string. The live payload also carries an UNDOCUMENTED `tool_call_id`
|
|
19
|
-
* (e.g. `"tool_LsTnl0gBxM62XuWvKw0GFGHs"`); the harness does not consume it,
|
|
20
|
-
* so it is deliberately absent from this interface. `cwd` is the
|
|
21
|
-
* symlink-resolved path (macOS: `/private/tmp/…` for a shell in `/tmp/…`).
|
|
22
|
-
*/
|
|
11
|
+
* `PreToolUse`/`UserPromptSubmit`/`Stop` stdin payload (subset). Same base
|
|
12
|
+
* wire shape as Claude Code (`hook_event_name`/`tool_name`/`tool_input`/
|
|
13
|
+
* `cwd`); `tool_input.command` is confirmed for `Bash` by the docs' example
|
|
14
|
+
* script (`payload.tool_input?.command`). Verified live against kimi-code
|
|
15
|
+
* v0.27.0 on `PreToolUse`/`Bash`: `tool_name` is present at top level (the
|
|
16
|
+
* docs never name it as a stdin key) and `tool_input.command` carries the
|
|
17
|
+
* shell string. The live payload also carries an UNDOCUMENTED `tool_call_id`
|
|
18
|
+
* (e.g. `"tool_LsTnl0gBxM62XuWvKw0GFGHs"`); the harness does not consume it,
|
|
19
|
+
* so it is deliberately absent from this interface. `cwd` is the
|
|
20
|
+
* symlink-resolved path (macOS: `/private/tmp/…` for a shell in `/tmp/…`).
|
|
21
|
+
*/
|
|
23
22
|
interface KimiHookInput {
|
|
24
23
|
hook_event_name?: string;
|
|
25
24
|
tool_name?: string;
|
|
26
25
|
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
26
|
+
* Verified against the official tool reference (`docs/en/reference/tools.md`,
|
|
27
|
+
* moonshotai/kimi-code) AND live against kimi-code v0.27.0: `Write` sends
|
|
28
|
+
* `{ path, content, mode? }`, `Edit` sends
|
|
29
|
+
* `{ path, old_string, new_string, replace_all? }` — the path key is `path`,
|
|
30
|
+
* NOT Claude's `file_path`. `file_path` is kept as a tolerated alias (read
|
|
31
|
+
* second) for Claude-shaped replay payloads, mirroring
|
|
32
|
+
* `runtime/normalize.ts` which resolves both on the CLI path.
|
|
33
|
+
*/
|
|
35
34
|
tool_input?: {
|
|
36
35
|
path?: string;
|
|
37
36
|
file_path?: string;
|
|
@@ -43,11 +42,11 @@ interface KimiHookInput {
|
|
|
43
42
|
cwd?: string;
|
|
44
43
|
}
|
|
45
44
|
/**
|
|
46
|
-
* Hook stdout response. Only `"deny"` is documented for `permissionDecision`
|
|
47
|
-
* — no `"ask"`/`"allow"` value, and no `additionalContext` field exists on
|
|
48
|
-
* this envelope. Blocking events are `UserPromptSubmit`, `PreToolUse`, and
|
|
49
|
-
* `Stop` only; every other event's return value is ignored.
|
|
50
|
-
*/
|
|
45
|
+
* Hook stdout response. Only `"deny"` is documented for `permissionDecision`
|
|
46
|
+
* — no `"ask"`/`"allow"` value, and no `additionalContext` field exists on
|
|
47
|
+
* this envelope. Blocking events are `UserPromptSubmit`, `PreToolUse`, and
|
|
48
|
+
* `Stop` only; every other event's return value is ignored.
|
|
49
|
+
*/
|
|
51
50
|
interface KimiResponse {
|
|
52
51
|
hookSpecificOutput?: {
|
|
53
52
|
permissionDecision?: "deny";
|
|
@@ -59,21 +58,30 @@ interface KimiResponse {
|
|
|
59
58
|
/** Read & parse the Kimi hook stdin payload (same wire shape as Claude for the fields we consume). */
|
|
60
59
|
declare function readKimiInput(): Promise<KimiHookInput>;
|
|
61
60
|
/**
|
|
62
|
-
* Render a portable {@link Prompt} as a Kimi hook response string:
|
|
63
|
-
* `block`/`ask` -> `{hookSpecificOutput:{permissionDecision:"deny",...}}`
|
|
64
|
-
* (only `"deny"` is documented; `ask` is downgraded with {@link ASK_PREFIX});
|
|
65
|
-
* `inform` -> raw text (Kimi appends stdout to context on exit 0 — no
|
|
66
|
-
* documented JSON envelope for non-blocking context injection).
|
|
67
|
-
* @param prompt - The portable policy prompt.
|
|
68
|
-
* @returns The native Kimi response string.
|
|
69
|
-
*/
|
|
61
|
+
* Render a portable {@link Prompt} as a Kimi hook response string:
|
|
62
|
+
* `block`/`ask` -> `{hookSpecificOutput:{permissionDecision:"deny",...}}`
|
|
63
|
+
* (only `"deny"` is documented; `ask` is downgraded with {@link ASK_PREFIX});
|
|
64
|
+
* `inform` -> raw text (Kimi appends stdout to context on exit 0 — no
|
|
65
|
+
* documented JSON envelope for non-blocking context injection).
|
|
66
|
+
* @param prompt - The portable policy prompt.
|
|
67
|
+
* @returns The native Kimi response string.
|
|
68
|
+
*/
|
|
70
69
|
declare function toKimiResponse(prompt: Prompt): string;
|
|
71
70
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* @
|
|
75
|
-
*
|
|
76
|
-
|
|
71
|
+
* Render a raw deny reason as a Kimi hook response — for callers that already
|
|
72
|
+
* hold a fully-formatted message (e.g. the MCP cache-hit notice) rather than a
|
|
73
|
+
* portable {@link Prompt}. Same envelope as {@link toKimiResponse}, minus the
|
|
74
|
+
* `[BLOCKED]` prompt framing and without `hookEventName` (undocumented upstream).
|
|
75
|
+
* @param reason - The fully-formatted deny message.
|
|
76
|
+
* @returns The native Kimi response string.
|
|
77
|
+
*/
|
|
78
|
+
declare function kimiDenyResponse(reason: string): string;
|
|
79
|
+
/**
|
|
80
|
+
* Run the bundled policy over a Kimi hook payload and return the native
|
|
81
|
+
* response string, or null to allow (the hook then exits 0 with empty stdout).
|
|
82
|
+
* @param input - Parsed hook stdin payload.
|
|
83
|
+
* @returns Native response string, or null when the tool use is allowed.
|
|
84
|
+
*/
|
|
77
85
|
declare function guard(input: KimiHookInput): string | null;
|
|
78
86
|
//#endregion
|
|
79
|
-
export { type KimiHookInput, type KimiResponse, guard, readKimiInput, toKimiResponse };
|
|
87
|
+
export { type KimiHookInput, type KimiResponse, guard, kimiDenyResponse, readKimiInput, toKimiResponse };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as
|
|
2
|
-
export { guard, readKimiInput, toKimiResponse };
|
|
1
|
+
import { i as toKimiResponse, n as kimiDenyResponse, r as readKimiInput, t as guard } from "../../kimi-ChbcU2uI.mjs";
|
|
2
|
+
export { guard, kimiDenyResponse, readKimiInput, toKimiResponse };
|
package/dist/cache/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as queryHash, a as cacheLookupSubstringMeta, c as mcpCacheKey, d as extractText, f as IndexSummary, g as jaccardSimilar, h as compactMarkdown, i as cacheLookupSubstring, l as mcpCacheWrite, m as summarizeIndex, n as cacheLookup, o as cachePath, p as loadIndex, r as cacheLookupMeta, s as cacheStore, t as CacheHit, u as webfetchCacheWrite } from "../index-
|
|
1
|
+
import { _ as queryHash, a as cacheLookupSubstringMeta, c as mcpCacheKey, d as extractText, f as IndexSummary, g as jaccardSimilar, h as compactMarkdown, i as cacheLookupSubstring, l as mcpCacheWrite, m as summarizeIndex, n as cacheLookup, o as cachePath, p as loadIndex, r as cacheLookupMeta, s as cacheStore, t as CacheHit, u as webfetchCacheWrite } from "../index-DhmV2MPh.mjs";
|
|
2
2
|
export { CacheHit, IndexSummary, cacheLookup, cacheLookupMeta, cacheLookupSubstring, cacheLookupSubstringMeta, cachePath, cacheStore, compactMarkdown, extractText, jaccardSimilar, loadIndex, mcpCacheKey, mcpCacheWrite, queryHash, summarizeIndex, webfetchCacheWrite };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as evaluate } from "./evaluate-
|
|
1
|
+
import { t as evaluate } from "./evaluate-B4-MhOy_.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";
|
|
@@ -216,4 +216,4 @@ function guard(input) {
|
|
|
216
216
|
/** @deprecated use {@link guard}. Kept for back-compat. */
|
|
217
217
|
const fileSizeGuard = guard;
|
|
218
218
|
//#endregion
|
|
219
|
-
export {
|
|
219
|
+
export { commandToString as _, 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.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
package/dist/cli/bin.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { o as resolveStdinMaxBytes } from "../limits-DG5pl-5s.mjs";
|
|
3
|
+
import { r as loadDotenv, s as resolveTtlSec } from "../dotenv-DoqNlALG.mjs";
|
|
3
4
|
import { t as detectHarness } from "../harness-BMuLJ9lm.mjs";
|
|
4
|
-
import { t as claudeHome } from "../home-state-
|
|
5
|
-
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-
|
|
6
|
-
import { n as writeInitFile, t as initFor } from "../run-
|
|
7
|
-
import { $ as runningVersion, Q as runDoctor, Z as notify, et as versionBanner, t as handleHook, zt as todayUtc } from "../handle-
|
|
8
|
-
import { p as readStdin$1 } from "../claude-51RSspJ1.mjs";
|
|
5
|
+
import { t as claudeHome } from "../home-state-oUGFB4ds.mjs";
|
|
6
|
+
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-D_WchZ3R.mjs";
|
|
7
|
+
import { n as writeInitFile, t as initFor } from "../run-TAXNRSpD.mjs";
|
|
8
|
+
import { $ as runningVersion, Q as runDoctor, Z as notify, et as versionBanner, i as respond, t as handleHook, zt as todayUtc } from "../handle-J5r2f_O_.mjs";
|
|
9
9
|
import { delimiter, join } from "node:path";
|
|
10
|
-
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, readSync, readdirSync, writeFileSync } from "node:fs";
|
|
11
11
|
import { homedir } from "node:os";
|
|
12
12
|
//#region src/changelog/fetch.ts
|
|
13
13
|
/**
|
|
@@ -908,7 +908,9 @@ function renderPrefixRules(rules) {
|
|
|
908
908
|
const HEADER = "# Codex execpolicy rules — generated from @fusengine/harness src/policy/guards/security.ts\n# DO NOT hand-edit: regenerate via `harness codex-rules`.\n#\n# security.ts is the source of truth for dangerous-command detection; every\n# CRITICAL_PATTERNS label maps to decision = \"forbidden\", every ASK_PATTERNS\n# label maps to decision = \"prompt\". Strictest decision wins across matches.\n# The harness remains the AUTHORITATIVE enforcement layer — this file is a\n# complementary defense layer on the Codex side, not a replacement.\n#\n# IRREDUCIBLE gaps (shell syntax, invisible to argv-prefix matching, no\n# prefix_rule can express them) — compensated by sandbox_mode +\n# approval_policy.granular.sandbox_approval, not by this file:\n# - fork bomb: `:(){ :|:& };:`\n# - redirect to a raw disk device: `> /dev/sda`\n# - write to /etc via redirection: `> /etc/...`\n#\n# ASSUMED over-width (intentionally broader than security.ts, chosen to\n# avoid a silent gap rather than an exact-but-brittle translation):\n# - dd: prompts on every dd invocation; security.ts only fires on of=/dev/*\n# - rm: prompts even on paths security.ts exempts via a 'trash' substring\n# - rm/eval/unlink: prompts even on a bare token with no trailing argument;\n# security.ts requires a space (i.e. an argument) after the command\n# - chmod 777: prompts on relative paths too, not only absolute ones\n# - sudo (/usr/bin/sudo alias): forbids the absolute-path form too;\n# security.ts's word-boundary regex does not match a preceding '/'\n# - curl/wget: prompts on EVERY curl/wget invocation, not only when piped\n# into a shell; security.ts's \"remote script piped to a shell\" label\n# only fires on `curl|wget ... | sh`. A simple plain-word pipe IS split\n# by Codex into separate argv commands (a bare-shell rule would also\n# catch that case), but this rule additionally targets the download\n# half for compound chains and non-shell payload execution where\n# sh/bash never appears as argv[0] (curl -o x && chmod +x x && ./x,\n# curl ... | python3); it replaces a former bare sh/bash/zsh heuristic\n# that prompted on ~50% of Codex's own `bash -lc \"...\"` command\n# wrapping and rarely caught the actual download\n#\n# NOT covered (out of scope, not an over-width — a purely local pipe with no\n# network fetch is invisible to this rule AND to security.ts, which only\n# matches curl/wget as the left-hand side of the pipe):\n# - `cat file | sh`: local pipe, no curl/wget involved\n# - quoted-variable/redirection installer one-liners, e.g.\n# `curl -fsSL \"$URL\" | sh`: variable substitution disables Codex's\n# pipe-splitting, collapsing the whole invocation to a single\n# ['bash', '-lc', '<script>'] where curl is not argv[0] — this exact\n# form was covered by the removed bare sh/bash heuristic and is no\n# longer covered by any rule here\n#\n# The following labels have NO argv-prefix equivalent at all (shell syntax\n# not visible to execpolicy's argv matching) and are intentionally NOT\n# expressed as prefix_rule() below — covered instead by sandbox_mode/approval_policy:";
|
|
909
909
|
/** Render the full Codex execpolicy `.rules` Starlark file as a string. */
|
|
910
910
|
function buildCodexRules() {
|
|
911
|
-
|
|
911
|
+
const skipComment = SKIP_LIST.map((s) => `# - ${sanitizeComment(s.sourceLabel)}: ${sanitizeComment(s.reason)}`).join("\n");
|
|
912
|
+
const body = renderPrefixRules(ALL_RULES);
|
|
913
|
+
return `${HEADER}\n${skipComment}\n\n${body}\n`;
|
|
912
914
|
}
|
|
913
915
|
//#endregion
|
|
914
916
|
//#region src/refs/discover.ts
|
|
@@ -972,6 +974,117 @@ function discoverRefs(home, cwd, marketplaces) {
|
|
|
972
974
|
return [...bySkill.values()].join(delimiter);
|
|
973
975
|
}
|
|
974
976
|
//#endregion
|
|
977
|
+
//#region src/cli/scope.ts
|
|
978
|
+
/** Closed set of plugin scopes accepted after `harness hook <id>`. */
|
|
979
|
+
const VALID_SCOPES = /* @__PURE__ */ new Set([
|
|
980
|
+
"solid",
|
|
981
|
+
"rules",
|
|
982
|
+
"carto",
|
|
983
|
+
"security",
|
|
984
|
+
"changelog",
|
|
985
|
+
"aipilot",
|
|
986
|
+
"lessons",
|
|
987
|
+
"seo",
|
|
988
|
+
"memory",
|
|
989
|
+
"tailwindcss"
|
|
990
|
+
]);
|
|
991
|
+
/**
|
|
992
|
+
* Parse the optional scope argument.
|
|
993
|
+
* @param scopeArg - `process.argv[4]`, when present.
|
|
994
|
+
* @param err - Warning sink (defaults to stderr; injectable for tests).
|
|
995
|
+
* @returns The valid scope, or `"core"` (with a warning) otherwise.
|
|
996
|
+
*/
|
|
997
|
+
function parseScope(scopeArg, err = (m) => process.stderr.write(m)) {
|
|
998
|
+
if (scopeArg !== void 0 && scopeArg !== "core" && !VALID_SCOPES.has(scopeArg)) err(`harness: unknown scope "${scopeArg}", falling back to "core"\n`);
|
|
999
|
+
return scopeArg !== void 0 && VALID_SCOPES.has(scopeArg) ? scopeArg : "core";
|
|
1000
|
+
}
|
|
1001
|
+
//#endregion
|
|
1002
|
+
//#region src/cli/hook-io.ts
|
|
1003
|
+
/**
|
|
1004
|
+
* Hook stdin reading + debug tracing for `harness hook` — extracted from
|
|
1005
|
+
* `bin.ts` so the command dispatcher stays under the SOLID line ceiling.
|
|
1006
|
+
* Tracing is stderr-only and active only when FUSE_HARNESS_DEBUG=1 AND
|
|
1007
|
+
* CI=true (both set by test/sim/exec.ts; never in an interactive session).
|
|
1008
|
+
*
|
|
1009
|
+
* Stdin is read BOUNDED (`resolveStdinMaxBytes`, default 16 MiB): the reader
|
|
1010
|
+
* never buffers past the cap, so an oversized payload cannot exhaust memory
|
|
1011
|
+
* nor slip an uninspected tool call through (fail-closed — see `bin.ts`).
|
|
1012
|
+
*/
|
|
1013
|
+
const hookDebug = process.env.FUSE_HARNESS_DEBUG === "1" && process.env.CI === "true";
|
|
1014
|
+
/** stderr-only trace, no-op outside the debug flag combination above. */
|
|
1015
|
+
function traceHook(label, data) {
|
|
1016
|
+
if (hookDebug) process.stderr.write(`[hook-debug] ${label}: ${typeof data === "string" ? data : JSON.stringify(data)}\n`);
|
|
1017
|
+
}
|
|
1018
|
+
/** Type guard for the oversize variant (narrows the readStdin union). */
|
|
1019
|
+
function isOversize(x) {
|
|
1020
|
+
return typeof x === "object" && x !== null && x.kind === "oversize";
|
|
1021
|
+
}
|
|
1022
|
+
/** First 4 KiB are kept on oversize for event-name sniffing downstream. */
|
|
1023
|
+
const HEAD_BYTES = 4096;
|
|
1024
|
+
const CHUNK = 64 * 1024;
|
|
1025
|
+
/**
|
|
1026
|
+
* Read a file descriptor to EOF, bounded at `maxBytes` (+1 byte to detect
|
|
1027
|
+
* the overflow). Injectable fd so tests never touch process stdin.
|
|
1028
|
+
* @param fd - The descriptor to read (0 in production).
|
|
1029
|
+
* @param maxBytes - Cap from {@link resolveStdinMaxBytes}.
|
|
1030
|
+
*/
|
|
1031
|
+
function readBounded(fd, maxBytes) {
|
|
1032
|
+
const buf = Buffer.alloc(CHUNK);
|
|
1033
|
+
const parts = [];
|
|
1034
|
+
let total = 0;
|
|
1035
|
+
for (;;) {
|
|
1036
|
+
const n = readSync(fd, buf, 0, CHUNK, null);
|
|
1037
|
+
if (n === 0) break;
|
|
1038
|
+
total += n;
|
|
1039
|
+
parts.push(Buffer.from(buf.subarray(0, n)));
|
|
1040
|
+
if (total > maxBytes) return {
|
|
1041
|
+
kind: "oversize",
|
|
1042
|
+
head: Buffer.concat(parts).subarray(0, HEAD_BYTES).toString("utf8")
|
|
1043
|
+
};
|
|
1044
|
+
}
|
|
1045
|
+
traceHook("stdin-text-length", total);
|
|
1046
|
+
return {
|
|
1047
|
+
kind: "ok",
|
|
1048
|
+
text: Buffer.concat(parts).toString("utf8")
|
|
1049
|
+
};
|
|
1050
|
+
}
|
|
1051
|
+
/** Read the hook payload from stdin; `{}` on empty or invalid JSON (fail-open parity). */
|
|
1052
|
+
async function readStdin() {
|
|
1053
|
+
const read = readBounded(0, resolveStdinMaxBytes());
|
|
1054
|
+
if (read.kind === "oversize") return read;
|
|
1055
|
+
const text = read.text.trim();
|
|
1056
|
+
if (!text) return {};
|
|
1057
|
+
try {
|
|
1058
|
+
const parsed = JSON.parse(text);
|
|
1059
|
+
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
1060
|
+
} catch (e) {
|
|
1061
|
+
traceHook("stdin-parse-error", e instanceof Error ? e.message : String(e));
|
|
1062
|
+
return {};
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
/** Blockable hook events (fail-closed on oversize); others are observation-only. */
|
|
1066
|
+
const BLOCKABLE = /* @__PURE__ */ new Set([
|
|
1067
|
+
"PreToolUse",
|
|
1068
|
+
"UserPromptSubmit",
|
|
1069
|
+
"Stop"
|
|
1070
|
+
]);
|
|
1071
|
+
/**
|
|
1072
|
+
* Native stdout for an oversize payload: a deny on blockable (or
|
|
1073
|
+
* undeterminable) events — never an uninspected passthrough — and a neutral
|
|
1074
|
+
* empty string on observation-only events (no crash, no noise).
|
|
1075
|
+
* @param id - Harness id (selects the native deny shape via `respond`).
|
|
1076
|
+
* @param head - The first bytes of the payload (event-name sniffing).
|
|
1077
|
+
*/
|
|
1078
|
+
function oversizeStdout(id, head) {
|
|
1079
|
+
const event = /"hook_event_name"\s*:\s*"([^"]+)"/.exec(head)?.[1] ?? "";
|
|
1080
|
+
if (event && !BLOCKABLE.has(event)) return "";
|
|
1081
|
+
return respond(id, {
|
|
1082
|
+
kind: "block",
|
|
1083
|
+
title: "Oversize hook payload",
|
|
1084
|
+
reason: `stdin payload exceeds ${resolveStdinMaxBytes()} bytes — denied uninspected`
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
//#endregion
|
|
975
1088
|
//#region src/cli/hook-sound.ts
|
|
976
1089
|
/**
|
|
977
1090
|
* @module hook-sound
|
|
@@ -1032,22 +1145,6 @@ function maybePlaySound(argv) {
|
|
|
1032
1145
|
* harness changelog fetch + diff the Claude Code changelog, print a JSON summary (changelog-watcher)
|
|
1033
1146
|
* harness codex-rules generate a Codex execpolicy .rules (Starlark) file from security.ts; stdout or --out <path>
|
|
1034
1147
|
*/
|
|
1035
|
-
const hookDebug = process.env.FUSE_HARNESS_DEBUG === "1" && process.env.CI === "true";
|
|
1036
|
-
function traceHook(label, data) {
|
|
1037
|
-
if (hookDebug) process.stderr.write(`[hook-debug] ${label}: ${typeof data === "string" ? data : JSON.stringify(data)}\n`);
|
|
1038
|
-
}
|
|
1039
|
-
async function readStdin() {
|
|
1040
|
-
const text = (await readStdin$1()).trim();
|
|
1041
|
-
traceHook("stdin-text-length", text.length);
|
|
1042
|
-
if (!text) return {};
|
|
1043
|
-
try {
|
|
1044
|
-
const parsed = JSON.parse(text);
|
|
1045
|
-
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
1046
|
-
} catch (e) {
|
|
1047
|
-
traceHook("stdin-parse-error", e instanceof Error ? e.message : String(e));
|
|
1048
|
-
return {};
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
1148
|
const cmd = process.argv[2];
|
|
1052
1149
|
if (cmd === "--version" || cmd === "-v") {
|
|
1053
1150
|
process.stderr.write(versionBanner(import.meta.url) + "\n");
|
|
@@ -1059,19 +1156,7 @@ if (cmd === "--version" || cmd === "-v") {
|
|
|
1059
1156
|
} else if (cmd === "hook") {
|
|
1060
1157
|
const id = process.argv[3] ?? detectHarness().id;
|
|
1061
1158
|
loadDotenv(id);
|
|
1062
|
-
const
|
|
1063
|
-
const scope = scopeArg !== void 0 && (/* @__PURE__ */ new Set([
|
|
1064
|
-
"solid",
|
|
1065
|
-
"rules",
|
|
1066
|
-
"carto",
|
|
1067
|
-
"security",
|
|
1068
|
-
"changelog",
|
|
1069
|
-
"aipilot",
|
|
1070
|
-
"lessons",
|
|
1071
|
-
"seo",
|
|
1072
|
-
"memory",
|
|
1073
|
-
"tailwindcss"
|
|
1074
|
-
])).has(scopeArg) ? scopeArg : "core";
|
|
1159
|
+
const scope = parseScope(process.argv[4]);
|
|
1075
1160
|
if (maybePlaySound(process.argv)) process.exit(0);
|
|
1076
1161
|
const marketplaces = (process.env.FUSE_HARNESS_MARKETPLACES ?? "fusengine-plugins").split(",").map((s) => s.trim()).filter(Boolean);
|
|
1077
1162
|
const refsDir = process.env.FUSE_HARNESS_REFS || discoverRefs(homedir(), process.cwd(), marketplaces) || void 0;
|
|
@@ -1081,7 +1166,13 @@ if (cmd === "--version" || cmd === "-v") {
|
|
|
1081
1166
|
});
|
|
1082
1167
|
let outcome;
|
|
1083
1168
|
try {
|
|
1084
|
-
|
|
1169
|
+
const stdin = await readStdin();
|
|
1170
|
+
if (isOversize(stdin)) {
|
|
1171
|
+
const stdout = oversizeStdout(id, stdin.head);
|
|
1172
|
+
if (stdout) process.stdout.write(stdout);
|
|
1173
|
+
process.exit(0);
|
|
1174
|
+
}
|
|
1175
|
+
outcome = await handleHook(id, stdin, {
|
|
1085
1176
|
now: Date.now(),
|
|
1086
1177
|
cwd: process.cwd(),
|
|
1087
1178
|
refsDir,
|
package/dist/cli/index.d.mts
CHANGED
|
@@ -4,9 +4,9 @@ declare function stagedFiles(): string[];
|
|
|
4
4
|
/** Read a file's staged (index) content — not the working-tree version. */
|
|
5
5
|
declare function stagedContent(path: string): string;
|
|
6
6
|
/**
|
|
7
|
-
* Evaluate staged code files against the policy core; return violation blocks.
|
|
8
|
-
* `read` is injected (the real impl is {@link stagedContent}) so this is pure + testable.
|
|
9
|
-
*/
|
|
7
|
+
* Evaluate staged code files against the policy core; return violation blocks.
|
|
8
|
+
* `read` is injected (the real impl is {@link stagedContent}) so this is pure + testable.
|
|
9
|
+
*/
|
|
10
10
|
declare function checkStaged(files: string[], read: (path: string) => string): string[];
|
|
11
11
|
//#endregion
|
|
12
12
|
export { checkStaged, stagedContent, stagedFiles };
|
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-D_WchZ3R.mjs";
|
|
2
2
|
export { checkStaged, stagedContent, stagedFiles };
|
package/dist/config/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as
|
|
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 };
|
|
1
|
+
import { _ as DEFAULT_TTL_SEC, a as ProjectLayout, b as ttlLabel, c as projectLayout, d as MAX_LINES_ENV_KEY, f as hookBudget, g as storeBudget, h as splitTarget, i as parseEnvFile, l as DEFAULT_MAX_LINES, m as resolveStdinMaxBytes, n as envCandidates, o as STATE_GITIGNORE, p as resolveMaxLines, r as loadDotenv, s as STATE_ROOT, t as HOME_DIR, u as DEFAULT_STDIN_MAX_BYTES, v as TTL_ENV_KEY, x as parseEnvInt, y as resolveTtlSec } from "../index-oXXPs2xl.mjs";
|
|
2
|
+
export { DEFAULT_MAX_LINES, DEFAULT_STDIN_MAX_BYTES, DEFAULT_TTL_SEC, HOME_DIR, MAX_LINES_ENV_KEY, ProjectLayout, STATE_GITIGNORE, STATE_ROOT, TTL_ENV_KEY, envCandidates, hookBudget, loadDotenv, parseEnvFile, parseEnvInt, projectLayout, resolveMaxLines, resolveStdinMaxBytes, resolveTtlSec, splitTarget, storeBudget, ttlLabel };
|