@fusengine/harness 0.1.31 → 0.1.33
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.mjs +1 -1
- package/dist/adapters/cline/index.mjs +1 -1
- package/dist/adapters/codex/index.mjs +1 -1
- package/dist/adapters/cursor/index.mjs +1 -1
- package/dist/adapters/gemini/index.mjs +1 -1
- package/dist/claude-BatVYnAf.mjs +137 -0
- package/dist/cli/bin.mjs +6 -4
- package/dist/cli/index.mjs +1 -1
- package/dist/{evaluate-j3gRJ_ng.mjs → evaluate-9ch1K2kt.mjs} +1 -1
- package/dist/{handle-DW9cWdVt.mjs → handle-Cxgzd4pZ.mjs} +516 -81
- package/dist/{index-C1vLIMwN.d.mts → index-BEMumjOw.d.mts} +8 -1
- package/dist/{index-mISsk0ff.d.mts → index-DmbOUJK8.d.mts} +12 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +5 -5
- package/dist/init/index.mjs +1 -1
- package/dist/memory/index.mjs +2 -1
- package/dist/memory-la_KkjCS.mjs +1 -0
- package/dist/policy/index.d.mts +2 -2
- package/dist/policy/index.mjs +3 -3
- package/dist/{project-root-ff0_poWU.mjs → project-root-3kk7gCOp.mjs} +7 -1
- package/dist/{run-CXsV-wIJ.mjs → run-CQbtlAKa.mjs} +2 -2
- package/dist/{run-D91N4ul1.mjs → run-Do2JltgU.mjs} +2 -2
- package/dist/runtime/index.d.mts +77 -8
- package/dist/runtime/index.mjs +2 -2
- package/dist/util/index.d.mts +2 -2
- package/dist/util/index.mjs +2 -2
- package/dist/{describe-BYqhoV4c.mjs → validate-CccewDwk.mjs} +47 -2
- package/package.json +1 -1
- package/dist/claude-B9FYp0Yw.mjs +0 -66
- /package/dist/{memory-BkoEbdec.mjs → registry-BkoEbdec.mjs} +0 -0
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as readClaudeInput, i as guard, n as denyResponse, o as toClaudeResponse, r as fileSizeGuard, t as contextResponse } from "../../claude-
|
|
1
|
+
import { a as readClaudeInput, i as guard, n as denyResponse, o as toClaudeResponse, r as fileSizeGuard, t as contextResponse } from "../../claude-BatVYnAf.mjs";
|
|
2
2
|
export { contextResponse, denyResponse, fileSizeGuard, guard, readClaudeInput, toClaudeResponse };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as readClaudeInput, i as guard, n as denyResponse, t as contextResponse } from "../../claude-
|
|
1
|
+
import { a as readClaudeInput, i as guard, n as denyResponse, t as contextResponse } from "../../claude-BatVYnAf.mjs";
|
|
2
2
|
export { contextResponse, denyResponse, guard, readClaudeInput as readCodexInput };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { t as evaluate } from "./evaluate-9ch1K2kt.mjs";
|
|
2
|
+
import { t as formatPrompt } from "./types-ernB1Dy3.mjs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { spawnSync } from "node:child_process";
|
|
6
|
+
//#region src/util/runtime-io.ts
|
|
7
|
+
/**
|
|
8
|
+
* Cross-runtime I/O helpers (Node + Bun). The published CLI ships a `node`
|
|
9
|
+
* shebang and is invoked via `npx`/`npm`/`bunx`/`bun`; using only `node:*` APIs
|
|
10
|
+
* here keeps the bundle runnable under EVERY runtime — replacing the Bun-only
|
|
11
|
+
* `Bun.file/write/spawn/sleep/stdin` calls and the `bun` `Glob` import that made
|
|
12
|
+
* the package crash with `Cannot find package 'bun'` under plain Node.
|
|
13
|
+
*/
|
|
14
|
+
/** Read a file as UTF-8 text (throws on missing/unreadable — callers catch). */
|
|
15
|
+
function readText(path) {
|
|
16
|
+
return readFileSync(path, "utf8");
|
|
17
|
+
}
|
|
18
|
+
/** True when `path` exists. */
|
|
19
|
+
function pathExists(path) {
|
|
20
|
+
return existsSync(path);
|
|
21
|
+
}
|
|
22
|
+
/** Write `data` to `path`, creating parent dirs (mirrors `Bun.write`). */
|
|
23
|
+
function writeText(path, data) {
|
|
24
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
25
|
+
writeFileSync(path, data, { encoding: "utf8" });
|
|
26
|
+
}
|
|
27
|
+
/** Resolve after `ms` milliseconds (`Bun.sleep` replacement). */
|
|
28
|
+
function sleep(ms) {
|
|
29
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
30
|
+
}
|
|
31
|
+
/** Run `cmd args` in `cwd` and capture stdout text ("" on failure/non-zero). */
|
|
32
|
+
function spawnCapture(cmd, args, cwd) {
|
|
33
|
+
try {
|
|
34
|
+
const r = spawnSync(cmd, args, {
|
|
35
|
+
cwd,
|
|
36
|
+
encoding: "utf8"
|
|
37
|
+
});
|
|
38
|
+
return r.status === 0 ? r.stdout ?? "" : "";
|
|
39
|
+
} catch {
|
|
40
|
+
return "";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Read the full process stdin as UTF-8 text (works under Node and Bun). */
|
|
44
|
+
async function readStdin() {
|
|
45
|
+
const chunks = [];
|
|
46
|
+
for await (const chunk of process.stdin) chunks.push(chunk);
|
|
47
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Recursively collect files under `dir` whose extension is in `exts`, skipping
|
|
51
|
+
* `node_modules` and dot-dirs, capped at `cap`. `Bun.Glob().scan()` replacement.
|
|
52
|
+
* @param dir - Directory to walk.
|
|
53
|
+
* @param exts - Allowed extensions including the dot (e.g. `.ts`).
|
|
54
|
+
* @param out - Accumulator (mutated in place).
|
|
55
|
+
* @param cap - Max files to collect.
|
|
56
|
+
*/
|
|
57
|
+
function collectFiles(dir, exts, out, cap) {
|
|
58
|
+
if (out.length >= cap) return;
|
|
59
|
+
let entries;
|
|
60
|
+
try {
|
|
61
|
+
entries = readdirSync(dir, { withFileTypes: true });
|
|
62
|
+
} catch {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
for (const e of entries) {
|
|
66
|
+
if (out.length >= cap) return;
|
|
67
|
+
if (e.name === "node_modules" || e.name.startsWith(".")) continue;
|
|
68
|
+
const full = join(dir, e.name);
|
|
69
|
+
if (e.isDirectory()) collectFiles(full, exts, out, cap);
|
|
70
|
+
else if (exts.has(e.name.slice(e.name.lastIndexOf(".")))) out.push(full);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//#endregion
|
|
74
|
+
//#region src/adapters/claude/index.ts
|
|
75
|
+
/**
|
|
76
|
+
* Claude Code adapter — the thin Claude-only shim over the portable policy core.
|
|
77
|
+
* Reads the hook stdin payload and emits hookSpecificOutput responses.
|
|
78
|
+
*/
|
|
79
|
+
/** Read & parse the Claude hook payload from stdin (empty object on bad input). */
|
|
80
|
+
async function readClaudeInput() {
|
|
81
|
+
const text = await readStdin();
|
|
82
|
+
if (!text.trim()) return {};
|
|
83
|
+
try {
|
|
84
|
+
const parsed = JSON.parse(text);
|
|
85
|
+
return typeof parsed === "object" && parsed !== null ? parsed : {};
|
|
86
|
+
} catch {
|
|
87
|
+
return {};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** A `deny` hook response for a given event. */
|
|
91
|
+
function denyResponse(event, reason) {
|
|
92
|
+
return JSON.stringify({ hookSpecificOutput: {
|
|
93
|
+
hookEventName: event,
|
|
94
|
+
permissionDecision: "deny",
|
|
95
|
+
permissionDecisionReason: reason
|
|
96
|
+
} });
|
|
97
|
+
}
|
|
98
|
+
/** An `additionalContext` injection response. */
|
|
99
|
+
function contextResponse(event, text) {
|
|
100
|
+
return JSON.stringify({ hookSpecificOutput: {
|
|
101
|
+
hookEventName: event,
|
|
102
|
+
additionalContext: text
|
|
103
|
+
} });
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Render a portable {@link Prompt} as a Claude Code hook response:
|
|
107
|
+
* `block` → `permissionDecision: deny`, `ask` → `permissionDecision: ask`
|
|
108
|
+
* (interactive confirm), `inform` → `additionalContext`.
|
|
109
|
+
*/
|
|
110
|
+
function toClaudeResponse(event, prompt) {
|
|
111
|
+
const reason = formatPrompt(prompt);
|
|
112
|
+
if (prompt.kind === "block") return denyResponse(event, reason);
|
|
113
|
+
if (prompt.kind === "ask") return JSON.stringify({ hookSpecificOutput: {
|
|
114
|
+
hookEventName: event,
|
|
115
|
+
permissionDecision: "ask",
|
|
116
|
+
permissionDecisionReason: reason
|
|
117
|
+
} });
|
|
118
|
+
return contextResponse(event, reason);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Run the bundled policy over a Claude payload and return the native response
|
|
122
|
+
* string (deny/ask/additionalContext), or null to allow.
|
|
123
|
+
*/
|
|
124
|
+
function guard(input) {
|
|
125
|
+
const result = evaluate({
|
|
126
|
+
tool: input.tool_name ?? "Write",
|
|
127
|
+
filePath: input.tool_input?.file_path,
|
|
128
|
+
content: input.tool_input?.content ?? input.tool_input?.new_string,
|
|
129
|
+
command: input.tool_input?.command
|
|
130
|
+
});
|
|
131
|
+
if (result.decision === "allow" || !result.prompt) return null;
|
|
132
|
+
return toClaudeResponse(input.hook_event_name ?? "PreToolUse", result.prompt);
|
|
133
|
+
}
|
|
134
|
+
/** @deprecated use {@link guard}. Kept for back-compat. */
|
|
135
|
+
const fileSizeGuard = guard;
|
|
136
|
+
//#endregion
|
|
137
|
+
export { readClaudeInput as a, pathExists as c, spawnCapture as d, writeText as f, guard as i, readText as l, denyResponse as n, toClaudeResponse as o, fileSizeGuard as r, collectFiles as s, contextResponse as t, sleep as u };
|
package/dist/cli/bin.mjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { r as resolveTtlSec } from "../ttl-BG55s6HZ.mjs";
|
|
3
3
|
import { t as detectHarness } from "../harness-C8Nxxyn_.mjs";
|
|
4
|
-
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-
|
|
5
|
-
import { n as writeInitFile, t as initFor } from "../run-
|
|
6
|
-
import { t as handleHook } from "../handle-
|
|
4
|
+
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-CQbtlAKa.mjs";
|
|
5
|
+
import { n as writeInitFile, t as initFor } from "../run-Do2JltgU.mjs";
|
|
6
|
+
import { t as handleHook } from "../handle-Cxgzd4pZ.mjs";
|
|
7
7
|
//#region src/cli/bin.ts
|
|
8
8
|
/**
|
|
9
9
|
* harness — CLI for @fusengine/harness.
|
|
@@ -33,7 +33,9 @@ if (cmd === "hook") {
|
|
|
33
33
|
"carto",
|
|
34
34
|
"security",
|
|
35
35
|
"changelog",
|
|
36
|
-
"aipilot"
|
|
36
|
+
"aipilot",
|
|
37
|
+
"lessons",
|
|
38
|
+
"seo"
|
|
37
39
|
])).has(scopeArg) ? scopeArg : "core";
|
|
38
40
|
const outcome = await handleHook(id, await readStdin(), {
|
|
39
41
|
now: Date.now(),
|
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-CQbtlAKa.mjs";
|
|
2
2
|
export { checkStaged, stagedContent, stagedFiles };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as splitTarget, r as resolveMaxLines } from "./limits-CHn8AIL1.mjs";
|
|
2
|
-
import { t as isCodeFile } from "./project-root-
|
|
2
|
+
import { t as isCodeFile } from "./project-root-3kk7gCOp.mjs";
|
|
3
3
|
//#region src/policy/detect-framework.ts
|
|
4
4
|
/**
|
|
5
5
|
* Detect the framework from a file path extension + content patterns.
|