harnery 0.5.0 → 0.7.0
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/README.md +16 -6
- package/dist/commander.d.ts +29 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +4 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +94 -33
- package/dist/commands/browse-ai.js +1 -1
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +41 -9
- package/dist/commands/cookies.js +1 -1
- package/dist/commands/decision.d.ts +4 -0
- package/dist/commands/decision.d.ts.map +1 -0
- package/dist/commands/decision.js +354 -0
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +4 -0
- package/dist/commands/devtools.d.ts +4 -0
- package/dist/commands/devtools.d.ts.map +1 -0
- package/dist/commands/devtools.js +239 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +74 -2
- package/dist/commands/doctor.js +12 -4
- package/dist/commands/env.d.ts.map +1 -1
- package/dist/commands/env.js +3 -63
- package/dist/commands/fetch.js +1 -1
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +54 -14
- package/dist/commands/scratch.js +1 -1
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +273 -62
- package/dist/commands/web-fetch.js +1 -1
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +32 -8
- package/dist/core/agents/events/consume.d.ts +25 -2
- package/dist/core/agents/events/consume.d.ts.map +1 -1
- package/dist/core/agents/events/consume.js +55 -7
- package/dist/core/agents/events/emit.d.ts +2 -1
- package/dist/core/agents/events/emit.d.ts.map +1 -1
- package/dist/core/agents/events/emit.js +6 -1
- package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/claim-conflict.js +16 -5
- package/dist/core/agents/state/scratch.d.ts +1 -1
- package/dist/core/agents/state/scratch.js +2 -2
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +13 -0
- package/dist/core/hooks/cli.js +3 -3
- package/dist/core/hooks/effects/index.d.ts +11 -7
- package/dist/core/hooks/effects/index.d.ts.map +1 -1
- package/dist/core/hooks/effects/index.js +15 -17
- package/dist/core/hooks/events/emit.d.ts.map +1 -1
- package/dist/core/hooks/events/emit.js +4 -0
- package/dist/core/hooks/events/rotate.d.ts +43 -0
- package/dist/core/hooks/events/rotate.d.ts.map +1 -0
- package/dist/core/hooks/events/rotate.js +142 -0
- package/dist/core/hooks/harness/events.d.ts +11 -1
- package/dist/core/hooks/harness/events.d.ts.map +1 -1
- package/dist/core/hooks/harness/events.js +22 -3
- package/dist/core/hooks/harness/wiring.d.ts +8 -0
- package/dist/core/hooks/harness/wiring.d.ts.map +1 -1
- package/dist/core/hooks/harness/wiring.js +34 -5
- package/dist/core/scratch/index.d.ts.map +1 -0
- package/dist/{lib → core}/scratch/index.js +2 -2
- package/dist/lib/agent-browser/client.js +1 -1
- package/dist/lib/browser/client.d.ts +14 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +20 -0
- package/dist/lib/browser/index.d.ts +1 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/runts.d.ts +44 -0
- package/dist/lib/browser/runts.d.ts.map +1 -0
- package/dist/lib/browser/runts.js +193 -0
- package/dist/lib/completion/walk.js +1 -1
- package/dist/lib/cookies/client.d.ts +1 -1
- package/dist/lib/cookies/client.d.ts.map +1 -1
- package/dist/lib/cookies/client.js +1 -1
- package/dist/lib/decision/index.d.ts +212 -0
- package/dist/lib/decision/index.d.ts.map +1 -0
- package/dist/lib/decision/index.js +523 -0
- package/dist/lib/devtools.d.ts +178 -0
- package/dist/lib/devtools.d.ts.map +1 -0
- package/dist/lib/devtools.js +1328 -0
- package/dist/lib/docs-frontmatter-migrate.d.ts +33 -0
- package/dist/lib/docs-frontmatter-migrate.d.ts.map +1 -0
- package/dist/lib/docs-frontmatter-migrate.js +364 -0
- package/dist/lib/docs-frontmatter.d.ts +33 -0
- package/dist/lib/docs-frontmatter.d.ts.map +1 -0
- package/dist/lib/docs-frontmatter.js +130 -0
- package/dist/lib/docs-index.d.ts +1 -0
- package/dist/lib/docs-index.d.ts.map +1 -1
- package/dist/lib/docs-index.js +4 -5
- package/dist/lib/docs-lint.d.ts +3 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +67 -12
- package/dist/lib/docs-meta.d.ts +14 -0
- package/dist/lib/docs-meta.d.ts.map +1 -0
- package/dist/lib/docs-meta.js +34 -0
- package/dist/lib/docs-sweep.d.ts +12 -0
- package/dist/lib/docs-sweep.d.ts.map +1 -1
- package/dist/lib/docs-sweep.js +98 -103
- package/dist/lib/format.js +2 -2
- package/dist/lib/http/index.d.ts +1 -0
- package/dist/lib/http/index.d.ts.map +1 -1
- package/dist/lib/http/index.js +1 -0
- package/dist/lib/http/request.d.ts +77 -0
- package/dist/lib/http/request.d.ts.map +1 -0
- package/dist/lib/http/request.js +105 -0
- package/dist/lib/instructions/apply.d.ts +63 -0
- package/dist/lib/instructions/apply.d.ts.map +1 -0
- package/dist/lib/instructions/apply.js +255 -0
- package/dist/lib/instructions/splice.d.ts +73 -0
- package/dist/lib/instructions/splice.d.ts.map +1 -0
- package/dist/lib/instructions/splice.js +118 -0
- package/dist/lib/instructions/templates.d.ts +45 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -0
- package/dist/lib/instructions/templates.js +258 -0
- package/dist/lib/tunnel/gate.d.ts +1 -0
- package/dist/lib/tunnel/gate.d.ts.map +1 -1
- package/dist/lib/tunnel/gate.js +15 -10
- package/dist/lib/tunnel/state.d.ts +11 -1
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +8 -3
- package/package.json +9 -6
- package/src/commander.ts +35 -0
- package/src/commands/agents.ts +97 -29
- package/src/commands/browse-ai.ts +1 -1
- package/src/commands/browse.ts +63 -8
- package/src/commands/cookies.ts +1 -1
- package/src/commands/decision.ts +438 -0
- package/src/commands/deinit.ts +5 -0
- package/src/commands/devtools.ts +284 -0
- package/src/commands/docs.ts +86 -2
- package/src/commands/doctor.ts +13 -4
- package/src/commands/env.ts +11 -77
- package/src/commands/fetch.ts +1 -1
- package/src/commands/init.ts +66 -15
- package/src/commands/scratch.ts +1 -1
- package/src/commands/tunnel.ts +316 -65
- package/src/commands/web-fetch.ts +1 -1
- package/src/core/agents/coord-client.ts +34 -7
- package/src/core/agents/events/consume.ts +65 -7
- package/src/core/agents/events/emit.ts +7 -1
- package/src/core/agents/rules/claim-conflict.ts +17 -6
- package/src/core/agents/state/scratch.ts +2 -2
- package/src/core/config.ts +15 -1
- package/src/core/hooks/cli.ts +3 -3
- package/src/core/hooks/effects/index.ts +23 -16
- package/src/core/hooks/events/emit.ts +5 -0
- package/src/core/hooks/events/rotate.ts +151 -0
- package/src/core/hooks/harness/events.ts +30 -3
- package/src/core/hooks/harness/wiring.ts +46 -5
- package/src/{lib → core}/scratch/index.ts +2 -2
- package/src/lib/agent-browser/client.ts +1 -1
- package/src/lib/browser/client.ts +28 -0
- package/src/lib/browser/index.ts +4 -0
- package/src/lib/browser/runts.ts +218 -0
- package/src/lib/completion/walk.ts +1 -1
- package/src/lib/cookies/client.ts +2 -2
- package/src/lib/decision/index.ts +685 -0
- package/src/lib/devtools.ts +1653 -0
- package/src/lib/docs-frontmatter-migrate.ts +427 -0
- package/src/lib/docs-frontmatter.ts +151 -0
- package/src/lib/docs-index.ts +4 -5
- package/src/lib/docs-lint.ts +61 -11
- package/src/lib/docs-meta.ts +44 -0
- package/src/lib/docs-sweep.ts +104 -102
- package/src/lib/format.ts +2 -2
- package/src/lib/http/index.ts +1 -0
- package/src/lib/http/request.ts +154 -0
- package/src/lib/instructions/apply.ts +318 -0
- package/src/lib/instructions/splice.ts +148 -0
- package/src/lib/instructions/templates.ts +295 -0
- package/src/lib/tunnel/gate.ts +15 -10
- package/src/lib/tunnel/state.ts +19 -4
- package/dist/lib/scratch/index.d.ts.map +0 -1
- /package/dist/{lib → core}/scratch/index.d.ts +0 -0
package/src/commands/init.ts
CHANGED
|
@@ -22,7 +22,7 @@ import { dirname, relative, resolve } from "node:path";
|
|
|
22
22
|
import { fileURLToPath } from "node:url";
|
|
23
23
|
import type { Command } from "commander";
|
|
24
24
|
import type { EmitContext } from "../commander.ts";
|
|
25
|
-
import { DEFAULT_BIN_NAME, stripJsonComments } from "../core/config.ts";
|
|
25
|
+
import { DEFAULT_BIN_NAME, pinnedBinName, stripJsonComments } from "../core/config.ts";
|
|
26
26
|
import { HARNESS_SPECS, type HarnessId, type HarnessSpec } from "../core/hooks/harness/events.ts";
|
|
27
27
|
import {
|
|
28
28
|
commandWiresSubcommand,
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
makeEntry,
|
|
32
32
|
type SettingsFile,
|
|
33
33
|
} from "../core/hooks/harness/wiring.ts";
|
|
34
|
+
import { applyInstructions, checkInstructions } from "../lib/instructions/apply.ts";
|
|
34
35
|
|
|
35
36
|
// Re-exported for back-compat: callers (deinit, tests) import these names
|
|
36
37
|
// from init.ts. The definitions now live in core/hooks/harness/wiring.ts.
|
|
@@ -42,6 +43,7 @@ const HARNERY_ROOT = resolve(dirname(fileURLToPath(import.meta.url)), "..", ".."
|
|
|
42
43
|
interface InitOpts {
|
|
43
44
|
harness: string;
|
|
44
45
|
dryRun?: boolean;
|
|
46
|
+
check?: boolean;
|
|
45
47
|
projectRoot?: string;
|
|
46
48
|
}
|
|
47
49
|
|
|
@@ -49,11 +51,14 @@ export function registerInitCommand(program: Command, emit: EmitContext, binName
|
|
|
49
51
|
program
|
|
50
52
|
.command("init")
|
|
51
53
|
.description(
|
|
52
|
-
"Bootstrap harnery in this project: create .harnery
|
|
53
|
-
"hooks
|
|
54
|
+
"Bootstrap harnery in this project: create .harnery/, wire the harness " +
|
|
55
|
+
"hooks, and inject the agent-facing instructions block + skills " +
|
|
56
|
+
"(idempotent; safe to re-run). Use --dry-run to preview, --check to " +
|
|
57
|
+
"report drift without writing (exit 0 fresh / 2 drift / 1 error).",
|
|
54
58
|
)
|
|
55
59
|
.option("--harness <id>", "claude-code | cursor | codex", "claude-code")
|
|
56
60
|
.option("--dry-run", "Show what would change without writing")
|
|
61
|
+
.option("--check", "Report instructions/skills drift without writing; exit 0/2/1")
|
|
57
62
|
.option("--project-root <path>", "Project root (default: git toplevel, else cwd)")
|
|
58
63
|
.action((opts: InitOpts) => {
|
|
59
64
|
const harness = opts.harness as HarnessId;
|
|
@@ -65,6 +70,28 @@ export function registerInitCommand(program: Command, emit: EmitContext, binName
|
|
|
65
70
|
}
|
|
66
71
|
|
|
67
72
|
const projectRoot = resolve(opts.projectRoot ?? gitTopLevel() ?? process.cwd());
|
|
73
|
+
// A binName already pinned in this project's config.jsonc beats the
|
|
74
|
+
// invoking CLI's name: the pin is a committed, deliberate declaration;
|
|
75
|
+
// the invoking bin is circumstantial (any embedding host's CLI can run
|
|
76
|
+
// init inside any checkout). Without this, re-running init from a host
|
|
77
|
+
// CLI re-stamps the host's name into committed agent-facing surfaces.
|
|
78
|
+
const bin = pinnedBinName(projectRoot) ?? (binName?.trim() ? binName : DEFAULT_BIN_NAME);
|
|
79
|
+
|
|
80
|
+
// ── --check: read-only drift report on the block + skills ──────────────
|
|
81
|
+
if (opts.check === true) {
|
|
82
|
+
const { status, issues } = checkInstructions(projectRoot, { binName: bin, harness });
|
|
83
|
+
const head =
|
|
84
|
+
status === "fresh"
|
|
85
|
+
? "harn init --check: instructions + skills are current"
|
|
86
|
+
: status === "drift"
|
|
87
|
+
? "harn init --check: drift found (re-run `init` to refresh)"
|
|
88
|
+
: "harn init --check: error";
|
|
89
|
+
const lines = issues.length ? `\n${issues.map((i) => ` ✗ ${i}`).join("\n")}` : "";
|
|
90
|
+
emit.text(`${head}${lines}`);
|
|
91
|
+
emit.setExitCode(status === "fresh" ? 0 : status === "drift" ? 2 : 1);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
68
95
|
const dryRun = opts.dryRun === true;
|
|
69
96
|
const actions: string[] = [];
|
|
70
97
|
|
|
@@ -85,10 +112,11 @@ export function registerInitCommand(program: Command, emit: EmitContext, binName
|
|
|
85
112
|
// The coord binaries (agent-hook/agent-coord) and web UI run as harnery
|
|
86
113
|
// itself, so they can't see a consumer CLI's name; they read it back from
|
|
87
114
|
// config.jsonc. Standalone `harn` is the resolver's default, so only a
|
|
88
|
-
// consumer (
|
|
89
|
-
|
|
115
|
+
// consumer (bin ≠ "harn") needs the stamp. `bin` already honors an
|
|
116
|
+
// existing pin, so this never overwrites a deliberate config value.
|
|
117
|
+
if (bin !== DEFAULT_BIN_NAME) {
|
|
90
118
|
const configPath = resolve(coordDir, "config.jsonc");
|
|
91
|
-
const stamp = stampBinName(configPath,
|
|
119
|
+
const stamp = stampBinName(configPath, bin, dryRun);
|
|
92
120
|
if (stamp) actions.push(stamp);
|
|
93
121
|
}
|
|
94
122
|
|
|
@@ -111,25 +139,31 @@ export function registerInitCommand(program: Command, emit: EmitContext, binName
|
|
|
111
139
|
} else {
|
|
112
140
|
settings = {};
|
|
113
141
|
}
|
|
114
|
-
const { wired, already } = wireHooks(settings, spec, agentHook, harness);
|
|
142
|
+
const { wired, already, removed } = wireHooks(settings, spec, agentHook, harness);
|
|
115
143
|
|
|
116
|
-
if (wired === 0) {
|
|
144
|
+
if (wired === 0 && removed === 0) {
|
|
117
145
|
actions.push(
|
|
118
146
|
`· all ${spec.events.length} ${harness} hooks already wired in ${rel(projectRoot, settingsPath)}`,
|
|
119
147
|
);
|
|
120
148
|
} else if (dryRun) {
|
|
121
149
|
actions.push(
|
|
122
|
-
`+ would wire ${wired} hook(s)
|
|
150
|
+
`+ would wire ${wired} hook(s) and remove ${removed} legacy hook(s) in ` +
|
|
151
|
+
`${rel(projectRoot, settingsPath)} (${already} already present)`,
|
|
123
152
|
);
|
|
124
153
|
} else {
|
|
125
154
|
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
126
155
|
writeFileSync(settingsPath, `${JSON.stringify(settings, null, 2)}\n`);
|
|
127
156
|
actions.push(
|
|
128
|
-
`+ wired ${wired} hook(s)
|
|
157
|
+
`+ wired ${wired} hook(s) and removed ${removed} legacy hook(s) in ` +
|
|
158
|
+
`${rel(projectRoot, settingsPath)} (${already} already present)`,
|
|
129
159
|
);
|
|
130
160
|
}
|
|
131
161
|
|
|
132
|
-
|
|
162
|
+
// ── 3. agent-facing instructions block + skills ────────────────────────
|
|
163
|
+
const applied = applyInstructions(projectRoot, { binName: bin, harness, dryRun });
|
|
164
|
+
actions.push(...applied.actions);
|
|
165
|
+
|
|
166
|
+
emit.text(render(projectRoot, dryRun, actions, applied.warnings));
|
|
133
167
|
});
|
|
134
168
|
}
|
|
135
169
|
|
|
@@ -149,13 +183,24 @@ export function wireHooks(
|
|
|
149
183
|
spec: HarnessSpec,
|
|
150
184
|
agentHookPath: string,
|
|
151
185
|
harness: HarnessId,
|
|
152
|
-
): { wired: number; already: number } {
|
|
186
|
+
): { wired: number; already: number; removed: number } {
|
|
153
187
|
if (spec.rootVersion !== undefined && settings.version === undefined) {
|
|
154
188
|
settings.version = spec.rootVersion;
|
|
155
189
|
}
|
|
156
190
|
if (!settings.hooks) settings.hooks = {};
|
|
157
191
|
let wired = 0;
|
|
158
192
|
let already = 0;
|
|
193
|
+
let removed = 0;
|
|
194
|
+
for (const { settingsKey, subcommand } of spec.legacyEvents ?? []) {
|
|
195
|
+
const groups = settings.hooks[settingsKey] ?? [];
|
|
196
|
+
const kept = groups.filter(
|
|
197
|
+
(group) =>
|
|
198
|
+
!groupCommands(group).some((command) => commandWiresSubcommand(command, subcommand)),
|
|
199
|
+
);
|
|
200
|
+
removed += groups.length - kept.length;
|
|
201
|
+
if (kept.length === 0) delete settings.hooks[settingsKey];
|
|
202
|
+
else settings.hooks[settingsKey] = kept;
|
|
203
|
+
}
|
|
159
204
|
for (const { settingsKey, subcommand } of spec.events) {
|
|
160
205
|
const command = `bash ${agentHookPath} ${subcommand} --harness ${harness}`;
|
|
161
206
|
const groups = settings.hooks[settingsKey] ?? [];
|
|
@@ -170,7 +215,7 @@ export function wireHooks(
|
|
|
170
215
|
settings.hooks[settingsKey] = groups;
|
|
171
216
|
wired++;
|
|
172
217
|
}
|
|
173
|
-
return { wired, already };
|
|
218
|
+
return { wired, already, removed };
|
|
174
219
|
}
|
|
175
220
|
|
|
176
221
|
/**
|
|
@@ -288,12 +333,18 @@ function firstBraceIndex(raw: string): number {
|
|
|
288
333
|
return -1;
|
|
289
334
|
}
|
|
290
335
|
|
|
291
|
-
function render(
|
|
336
|
+
function render(
|
|
337
|
+
projectRoot: string,
|
|
338
|
+
dryRun: boolean,
|
|
339
|
+
actions: string[],
|
|
340
|
+
warnings: string[] = [],
|
|
341
|
+
): string {
|
|
292
342
|
const head = dryRun ? "harn init (dry run): no changes written" : "harn init";
|
|
343
|
+
const warnBlock = warnings.length ? `\n${warnings.map((w) => ` ! ${w}`).join("\n")}` : "";
|
|
293
344
|
const tail = dryRun
|
|
294
345
|
? "\nRe-run without --dry-run to apply."
|
|
295
346
|
: "\nDone. Start a session and check `harn agents whoami`.";
|
|
296
|
-
return `${head}\n root: ${projectRoot}\n${actions.map((a) => ` ${a}`).join("\n")}${tail}`;
|
|
347
|
+
return `${head}\n root: ${projectRoot}\n${actions.map((a) => ` ${a}`).join("\n")}${warnBlock}${tail}`;
|
|
297
348
|
}
|
|
298
349
|
|
|
299
350
|
function gitTopLevel(): string | null {
|
package/src/commands/scratch.ts
CHANGED