@fusengine/harness 0.1.7 → 0.1.8
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/cli/bin.mjs +5 -4
- package/dist/init/index.d.mts +16 -15
- package/dist/init/index.mjs +1 -1
- package/dist/run-Cdp2Ef9B.mjs +128 -0
- package/package.json +1 -1
- package/dist/run-Cc98348q.mjs +0 -94
package/dist/cli/bin.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { t as detectHarness } from "../harness-C8Nxxyn_.mjs";
|
|
3
3
|
import { n as stagedContent, r as stagedFiles, t as checkStaged } from "../run-h_2LNEA8.mjs";
|
|
4
|
-
import { n as writeInitFile, t as initFor } from "../run-
|
|
4
|
+
import { n as writeInitFile, t as initFor } from "../run-Cdp2Ef9B.mjs";
|
|
5
5
|
import { t as handleHook } from "../handle-BGe0QZvQ.mjs";
|
|
6
6
|
//#region src/cli/bin.ts
|
|
7
7
|
/**
|
|
@@ -32,12 +32,13 @@ if (cmd === "hook") {
|
|
|
32
32
|
process.exit(outcome.exit);
|
|
33
33
|
} else if (cmd === "init") {
|
|
34
34
|
const id = process.argv[3] ?? detectHarness().id;
|
|
35
|
-
const
|
|
36
|
-
if (!
|
|
35
|
+
const files = initFor(id);
|
|
36
|
+
if (!files) {
|
|
37
37
|
process.stderr.write(`harness: no hook integration for "${id}" — use \`harness check\` in a pre-commit step\n`);
|
|
38
38
|
process.exit(1);
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
const written = files.map((f) => writeInitFile(process.cwd(), f));
|
|
41
|
+
process.stdout.write(`harness: wired ${id} -> ${written.join(", ")}\n`);
|
|
41
42
|
process.exit(0);
|
|
42
43
|
} else {
|
|
43
44
|
const files = stagedFiles();
|
package/dist/init/index.d.mts
CHANGED
|
@@ -2,8 +2,9 @@ import { t as HarnessId } from "../harness-DwJskkz_.mjs";
|
|
|
2
2
|
|
|
3
3
|
//#region src/init/templates.d.ts
|
|
4
4
|
/**
|
|
5
|
-
* Wiring file templates per harness,
|
|
6
|
-
*
|
|
5
|
+
* Wiring file templates per harness, registering `harness hook <id>` for BOTH
|
|
6
|
+
* phases: PRE (gate the edit) and POST (catch-all → `activityFor` filters what
|
|
7
|
+
* to record). Formats verified against each harness's 2026 hook docs.
|
|
7
8
|
*/
|
|
8
9
|
/** A file to write during `harness init`. */
|
|
9
10
|
interface InitFile {
|
|
@@ -11,23 +12,23 @@ interface InitFile {
|
|
|
11
12
|
content: string;
|
|
12
13
|
executable?: boolean;
|
|
13
14
|
}
|
|
14
|
-
/** Claude Code: PreToolUse(Write|Edit)
|
|
15
|
-
declare function claudeInit(command: string): InitFile;
|
|
16
|
-
/** Codex CLI: `.codex/hooks.json`
|
|
17
|
-
declare function codexInit(command: string): InitFile;
|
|
18
|
-
/** Cursor: `.cursor/hooks.json` (version 1) — shell + file-edit
|
|
19
|
-
declare function cursorInit(command: string): InitFile;
|
|
20
|
-
/** Gemini CLI: `.gemini/settings.json` — BeforeTool
|
|
21
|
-
declare function geminiInit(command: string): InitFile;
|
|
22
|
-
/** Cline:
|
|
23
|
-
declare function clineInit(command: string): InitFile;
|
|
15
|
+
/** Claude Code: `.claude/settings.json` — PreToolUse(Write|Edit) + PostToolUse(all). */
|
|
16
|
+
declare function claudeInit(command: string): InitFile[];
|
|
17
|
+
/** Codex CLI: `.codex/hooks.json` (Claude-compatible shape). */
|
|
18
|
+
declare function codexInit(command: string): InitFile[];
|
|
19
|
+
/** Cursor: `.cursor/hooks.json` (version 1) — shell + tool gate + file-edit observe. */
|
|
20
|
+
declare function cursorInit(command: string): InitFile[];
|
|
21
|
+
/** Gemini CLI: `.gemini/settings.json` — BeforeTool(edits) + AfterTool(all, regex). */
|
|
22
|
+
declare function geminiInit(command: string): InitFile[];
|
|
23
|
+
/** Cline: executable `.clinerules/hooks/PreToolUse` + `PostToolUse` piping stdin. */
|
|
24
|
+
declare function clineInit(command: string): InitFile[];
|
|
24
25
|
//#endregion
|
|
25
26
|
//#region src/init/run.d.ts
|
|
26
27
|
/**
|
|
27
|
-
* Build the wiring file for a harness, or null when it has no hook
|
|
28
|
-
* (cli-mode harnesses use `harness check` in a pre-commit step
|
|
28
|
+
* Build the wiring file(s) for a harness, or null when it has no hook
|
|
29
|
+
* integration (cli-mode harnesses use `harness check` in a pre-commit step).
|
|
29
30
|
*/
|
|
30
|
-
declare function initFor(id: HarnessId, command?: string): InitFile | null;
|
|
31
|
+
declare function initFor(id: HarnessId, command?: string): InitFile[] | null;
|
|
31
32
|
/** Write an {@link InitFile} under `root` (creates dirs; `chmod +x` when executable). */
|
|
32
33
|
declare function writeInitFile(root: string, file: InitFile): string;
|
|
33
34
|
//#endregion
|
package/dist/init/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as codexInit, i as clineInit, n as writeInitFile, o as cursorInit, r as claudeInit, s as geminiInit, t as initFor } from "../run-
|
|
1
|
+
import { a as codexInit, i as clineInit, n as writeInitFile, o as cursorInit, r as claudeInit, s as geminiInit, t as initFor } from "../run-Cdp2Ef9B.mjs";
|
|
2
2
|
export { claudeInit, clineInit, codexInit, cursorInit, geminiInit, initFor, writeInitFile };
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { chmodSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
//#region src/init/templates.ts
|
|
4
|
+
function json(obj) {
|
|
5
|
+
return `${JSON.stringify(obj, null, 2)}\n`;
|
|
6
|
+
}
|
|
7
|
+
/** Claude Code: `.claude/settings.json` — PreToolUse(Write|Edit) + PostToolUse(all). */
|
|
8
|
+
function claudeInit(command) {
|
|
9
|
+
return [{
|
|
10
|
+
path: ".claude/settings.json",
|
|
11
|
+
content: json({ hooks: {
|
|
12
|
+
PreToolUse: [{
|
|
13
|
+
matcher: "Write|Edit",
|
|
14
|
+
hooks: [{
|
|
15
|
+
type: "command",
|
|
16
|
+
command
|
|
17
|
+
}]
|
|
18
|
+
}],
|
|
19
|
+
PostToolUse: [{
|
|
20
|
+
matcher: "",
|
|
21
|
+
hooks: [{
|
|
22
|
+
type: "command",
|
|
23
|
+
command
|
|
24
|
+
}]
|
|
25
|
+
}]
|
|
26
|
+
} })
|
|
27
|
+
}];
|
|
28
|
+
}
|
|
29
|
+
/** Codex CLI: `.codex/hooks.json` (Claude-compatible shape). */
|
|
30
|
+
function codexInit(command) {
|
|
31
|
+
return [{
|
|
32
|
+
path: ".codex/hooks.json",
|
|
33
|
+
content: json({ hooks: {
|
|
34
|
+
PreToolUse: [{
|
|
35
|
+
matcher: "Bash|apply_patch",
|
|
36
|
+
hooks: [{
|
|
37
|
+
type: "command",
|
|
38
|
+
command
|
|
39
|
+
}]
|
|
40
|
+
}],
|
|
41
|
+
PostToolUse: [{
|
|
42
|
+
matcher: "",
|
|
43
|
+
hooks: [{
|
|
44
|
+
type: "command",
|
|
45
|
+
command
|
|
46
|
+
}]
|
|
47
|
+
}]
|
|
48
|
+
} })
|
|
49
|
+
}];
|
|
50
|
+
}
|
|
51
|
+
/** Cursor: `.cursor/hooks.json` (version 1) — shell + tool gate + file-edit observe. */
|
|
52
|
+
function cursorInit(command) {
|
|
53
|
+
return [{
|
|
54
|
+
path: ".cursor/hooks.json",
|
|
55
|
+
content: json({
|
|
56
|
+
version: 1,
|
|
57
|
+
hooks: {
|
|
58
|
+
beforeShellExecution: [{ command }],
|
|
59
|
+
preToolUse: [{ command }],
|
|
60
|
+
afterFileEdit: [{ command }]
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
}];
|
|
64
|
+
}
|
|
65
|
+
/** Gemini CLI: `.gemini/settings.json` — BeforeTool(edits) + AfterTool(all, regex). */
|
|
66
|
+
function geminiInit(command) {
|
|
67
|
+
return [{
|
|
68
|
+
path: ".gemini/settings.json",
|
|
69
|
+
content: json({ hooks: {
|
|
70
|
+
BeforeTool: [{
|
|
71
|
+
matcher: "write_file|edit_file|replace",
|
|
72
|
+
hooks: [{
|
|
73
|
+
type: "command",
|
|
74
|
+
command,
|
|
75
|
+
timeout: 3e4
|
|
76
|
+
}]
|
|
77
|
+
}],
|
|
78
|
+
AfterTool: [{
|
|
79
|
+
matcher: ".*",
|
|
80
|
+
hooks: [{
|
|
81
|
+
type: "command",
|
|
82
|
+
command,
|
|
83
|
+
timeout: 3e4
|
|
84
|
+
}]
|
|
85
|
+
}]
|
|
86
|
+
} })
|
|
87
|
+
}];
|
|
88
|
+
}
|
|
89
|
+
/** Cline: executable `.clinerules/hooks/PreToolUse` + `PostToolUse` piping stdin. */
|
|
90
|
+
function clineInit(command) {
|
|
91
|
+
const script = (phase) => `#!/usr/bin/env bash\n# fuse-harness Cline ${phase} hook\ncat | ${command}\n`;
|
|
92
|
+
return [{
|
|
93
|
+
path: ".clinerules/hooks/PreToolUse",
|
|
94
|
+
content: script("pre"),
|
|
95
|
+
executable: true
|
|
96
|
+
}, {
|
|
97
|
+
path: ".clinerules/hooks/PostToolUse",
|
|
98
|
+
content: script("post"),
|
|
99
|
+
executable: true
|
|
100
|
+
}];
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/init/run.ts
|
|
104
|
+
const RUNNERS = {
|
|
105
|
+
"claude-code": claudeInit,
|
|
106
|
+
codex: codexInit,
|
|
107
|
+
cursor: cursorInit,
|
|
108
|
+
"gemini-cli": geminiInit,
|
|
109
|
+
cline: clineInit
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* Build the wiring file(s) for a harness, or null when it has no hook
|
|
113
|
+
* integration (cli-mode harnesses use `harness check` in a pre-commit step).
|
|
114
|
+
*/
|
|
115
|
+
function initFor(id, command = `npx harness hook ${id}`) {
|
|
116
|
+
const make = RUNNERS[id];
|
|
117
|
+
return make ? make(command) : null;
|
|
118
|
+
}
|
|
119
|
+
/** Write an {@link InitFile} under `root` (creates dirs; `chmod +x` when executable). */
|
|
120
|
+
function writeInitFile(root, file) {
|
|
121
|
+
const full = join(root, file.path);
|
|
122
|
+
mkdirSync(dirname(full), { recursive: true });
|
|
123
|
+
writeFileSync(full, file.content);
|
|
124
|
+
if (file.executable) chmodSync(full, 493);
|
|
125
|
+
return full;
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
export { codexInit as a, clineInit as i, writeInitFile as n, cursorInit as o, claudeInit as r, geminiInit as s, initFor as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fusengine/harness",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Harness-agnostic toolkit for AI coding agents: runtime harness detection (Claude Code, Codex, Cursor, Cline, Gemini, Aider...), pure policy core (env config, project/framework detection, SOLID/file-size limits, APEX freshness, guard patterns, portable prompts), cache, project memory, ref routing, state/locks, statusline, per-harness adapters (Claude/Cursor/Cline/Gemini) and a cli-mode harness-check binary. Bun-native, with a built dist for Node + bundlers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"module": "src/index.ts",
|
package/dist/run-Cc98348q.mjs
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { chmodSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { dirname, join } from "node:path";
|
|
3
|
-
//#region src/init/templates.ts
|
|
4
|
-
function json(obj) {
|
|
5
|
-
return `${JSON.stringify(obj, null, 2)}\n`;
|
|
6
|
-
}
|
|
7
|
-
/** Claude Code: PreToolUse(Write|Edit) -> command. Target: `.claude/settings.json`. */
|
|
8
|
-
function claudeInit(command) {
|
|
9
|
-
return {
|
|
10
|
-
path: ".claude/settings.json",
|
|
11
|
-
content: json({ hooks: { PreToolUse: [{
|
|
12
|
-
matcher: "Write|Edit",
|
|
13
|
-
hooks: [{
|
|
14
|
-
type: "command",
|
|
15
|
-
command
|
|
16
|
-
}]
|
|
17
|
-
}] } })
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
/** Codex CLI: `.codex/hooks.json` — PreToolUse (Claude-compatible shape). */
|
|
21
|
-
function codexInit(command) {
|
|
22
|
-
return {
|
|
23
|
-
path: ".codex/hooks.json",
|
|
24
|
-
content: json({ hooks: { PreToolUse: [{
|
|
25
|
-
matcher: "Bash|apply_patch",
|
|
26
|
-
hooks: [{
|
|
27
|
-
type: "command",
|
|
28
|
-
command
|
|
29
|
-
}]
|
|
30
|
-
}] } })
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
/** Cursor: `.cursor/hooks.json` (version 1) — shell + file-edit hooks. */
|
|
34
|
-
function cursorInit(command) {
|
|
35
|
-
return {
|
|
36
|
-
path: ".cursor/hooks.json",
|
|
37
|
-
content: json({
|
|
38
|
-
version: 1,
|
|
39
|
-
hooks: {
|
|
40
|
-
beforeShellExecution: [{ command }],
|
|
41
|
-
afterFileEdit: [{ command }]
|
|
42
|
-
}
|
|
43
|
-
})
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
/** Gemini CLI: `.gemini/settings.json` — BeforeTool, timeout in ms. */
|
|
47
|
-
function geminiInit(command) {
|
|
48
|
-
return {
|
|
49
|
-
path: ".gemini/settings.json",
|
|
50
|
-
content: json({ hooks: { BeforeTool: [{
|
|
51
|
-
matcher: "write_file|edit_file|replace",
|
|
52
|
-
hooks: [{
|
|
53
|
-
type: "command",
|
|
54
|
-
command,
|
|
55
|
-
timeout: 3e4
|
|
56
|
-
}]
|
|
57
|
-
}] } })
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
/** Cline: an executable `.clinerules/hooks/PreToolUse` that pipes stdin to the command. */
|
|
61
|
-
function clineInit(command) {
|
|
62
|
-
return {
|
|
63
|
-
path: ".clinerules/hooks/PreToolUse",
|
|
64
|
-
content: `#!/usr/bin/env bash\n# fuse-harness Cline hook — evaluate each tool use\ncat | ${command}\n`,
|
|
65
|
-
executable: true
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
//#endregion
|
|
69
|
-
//#region src/init/run.ts
|
|
70
|
-
const RUNNERS = {
|
|
71
|
-
"claude-code": claudeInit,
|
|
72
|
-
codex: codexInit,
|
|
73
|
-
cursor: cursorInit,
|
|
74
|
-
"gemini-cli": geminiInit,
|
|
75
|
-
cline: clineInit
|
|
76
|
-
};
|
|
77
|
-
/**
|
|
78
|
-
* Build the wiring file for a harness, or null when it has no hook integration
|
|
79
|
-
* (cli-mode harnesses use `harness check` in a pre-commit step instead).
|
|
80
|
-
*/
|
|
81
|
-
function initFor(id, command = `npx harness hook ${id}`) {
|
|
82
|
-
const make = RUNNERS[id];
|
|
83
|
-
return make ? make(command) : null;
|
|
84
|
-
}
|
|
85
|
-
/** Write an {@link InitFile} under `root` (creates dirs; `chmod +x` when executable). */
|
|
86
|
-
function writeInitFile(root, file) {
|
|
87
|
-
const full = join(root, file.path);
|
|
88
|
-
mkdirSync(dirname(full), { recursive: true });
|
|
89
|
-
writeFileSync(full, file.content);
|
|
90
|
-
if (file.executable) chmodSync(full, 493);
|
|
91
|
-
return full;
|
|
92
|
-
}
|
|
93
|
-
//#endregion
|
|
94
|
-
export { codexInit as a, clineInit as i, writeInitFile as n, cursorInit as o, claudeInit as r, geminiInit as s, initFor as t };
|