@lannguyensi/harness 0.9.1 → 0.10.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/CHANGELOG.md +69 -0
- package/README.md +1 -1
- package/dist/cli/apply/generate-settings.js +36 -4
- package/dist/cli/apply/generate-settings.js.map +1 -1
- package/dist/cli/apply/next-steps.d.ts +7 -0
- package/dist/cli/apply/next-steps.js +21 -4
- package/dist/cli/apply/next-steps.js.map +1 -1
- package/dist/cli/approve/understanding.js +19 -1
- package/dist/cli/approve/understanding.js.map +1 -1
- package/dist/cli/doctor/format.js +4 -1
- package/dist/cli/doctor/format.js.map +1 -1
- package/dist/cli/index.js +6 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/dependencies.d.ts +72 -0
- package/dist/cli/init/dependencies.js +182 -0
- package/dist/cli/init/dependencies.js.map +1 -0
- package/dist/cli/init/interactive.d.ts +14 -1
- package/dist/cli/init/interactive.js +109 -14
- package/dist/cli/init/interactive.js.map +1 -1
- package/dist/cli/init/profiles.d.ts +2 -2
- package/dist/cli/init/profiles.js +23 -8
- package/dist/cli/init/profiles.js.map +1 -1
- package/dist/cli/init/templates.d.ts +1 -1
- package/dist/cli/init/templates.js +65 -43
- package/dist/cli/init/templates.js.map +1 -1
- package/dist/probes/memory.d.ts +13 -0
- package/dist/probes/memory.js +45 -8
- package/dist/probes/memory.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// Per-profile npm dependency declarations + detection + install for the
|
|
2
|
+
// interactive init wizard.
|
|
3
|
+
//
|
|
4
|
+
// Why this module exists: the wizard's templates reference binaries
|
|
5
|
+
// (`memory-router-user-prompt-submit`, `grounding-mcp`, `agent-tasks-
|
|
6
|
+
// mcp-bridge`, `understanding-gate-claude-hook`, etc.) that must be on
|
|
7
|
+
// PATH for the resulting manifest to pass `harness doctor`. Before this
|
|
8
|
+
// module, the wizard wrote a manifest and walked away, leaving the
|
|
9
|
+
// operator to discover the missing binaries via doctor errors. Now the
|
|
10
|
+
// wizard surfaces the expected packages, detects which are present,
|
|
11
|
+
// asks for permission, and runs `npm i -g` for the missing ones.
|
|
12
|
+
//
|
|
13
|
+
// Failure model: install errors abort the wizard before the manifest is
|
|
14
|
+
// written, surfacing the npm output verbatim. The operator fixes their
|
|
15
|
+
// npm setup (sudo / nvm / network) and re-runs `harness init`. We
|
|
16
|
+
// deliberately do NOT auto-sudo or guess at fallbacks — the user
|
|
17
|
+
// approved this trade-off explicitly (2026-05-13).
|
|
18
|
+
import { spawn } from "node:child_process";
|
|
19
|
+
import { existsSync, accessSync, constants } from "node:fs";
|
|
20
|
+
import * as path from "node:path";
|
|
21
|
+
export const PROFILE_DEPENDENCIES = {
|
|
22
|
+
solo: [
|
|
23
|
+
{
|
|
24
|
+
binary: "memory-router-user-prompt-submit",
|
|
25
|
+
npmPackage: "@lannguyensi/memory-router",
|
|
26
|
+
description: "memory router (UserPromptSubmit hook)",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
binary: "understanding-gate-claude-hook",
|
|
30
|
+
npmPackage: "@lannguyensi/understanding-gate",
|
|
31
|
+
description: "understanding gate (UserPromptSubmit injector)",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
binary: "understanding-gate-claude-stop",
|
|
35
|
+
npmPackage: "@lannguyensi/understanding-gate",
|
|
36
|
+
description: "understanding gate (Stop capture)",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
team: [
|
|
40
|
+
// Inherits everything from solo; the wizard concats these lists.
|
|
41
|
+
{
|
|
42
|
+
binary: "agent-tasks-mcp-bridge",
|
|
43
|
+
npmPackage: "@agent-tasks/mcp-bridge",
|
|
44
|
+
description: "agent-tasks MCP bridge",
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
binary: "grounding-mcp",
|
|
48
|
+
npmPackage: "@lannguyensi/grounding-mcp",
|
|
49
|
+
description: "grounding-mcp MCP server",
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
// Full inherits everything from Solo + Team. The Pandora-specific
|
|
53
|
+
// codebase-oracle MCP server is not in the default Full chain because
|
|
54
|
+
// it is not yet published under a non-colliding npm name (the
|
|
55
|
+
// top-level `codebase-oracle` package on the registry is an unrelated
|
|
56
|
+
// CLI). Operators who want it can `harness add mcp codebase-oracle`
|
|
57
|
+
// pointing at their local checkout.
|
|
58
|
+
full: [],
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the full dep list for a profile, including transitive
|
|
62
|
+
* profile deps. Solo is the base; team adds on top; full adds on top
|
|
63
|
+
* of team. Each binary is listed at most once even when several
|
|
64
|
+
* manifest entries reference the same npm package.
|
|
65
|
+
*/
|
|
66
|
+
export function dependenciesForProfile(profile) {
|
|
67
|
+
const chain = [];
|
|
68
|
+
const seen = new Set();
|
|
69
|
+
const layers = profile === "solo" ? ["solo"] : profile === "team" ? ["solo", "team"] : ["solo", "team", "full"];
|
|
70
|
+
for (const layer of layers) {
|
|
71
|
+
for (const dep of PROFILE_DEPENDENCIES[layer]) {
|
|
72
|
+
if (seen.has(dep.binary))
|
|
73
|
+
continue;
|
|
74
|
+
seen.add(dep.binary);
|
|
75
|
+
chain.push(dep);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return chain;
|
|
79
|
+
}
|
|
80
|
+
function isExecutable(filePath) {
|
|
81
|
+
try {
|
|
82
|
+
accessSync(filePath, constants.X_OK);
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function findOnPath(binary, pathEnv) {
|
|
90
|
+
if (binary.includes(path.sep)) {
|
|
91
|
+
return existsSync(binary) && isExecutable(binary) ? binary : null;
|
|
92
|
+
}
|
|
93
|
+
for (const seg of pathEnv.split(path.delimiter)) {
|
|
94
|
+
if (!seg)
|
|
95
|
+
continue;
|
|
96
|
+
const candidate = path.join(seg, binary);
|
|
97
|
+
if (existsSync(candidate) && isExecutable(candidate))
|
|
98
|
+
return candidate;
|
|
99
|
+
}
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* For a given profile, resolve which dependencies are already on PATH
|
|
104
|
+
* and which npm packages need installing. The returned `missingPackages`
|
|
105
|
+
* list is de-duplicated and ready to splice into a single
|
|
106
|
+
* `npm i -g <pkg1> <pkg2>` call.
|
|
107
|
+
*/
|
|
108
|
+
export function checkDependencies(profile, opts = {}) {
|
|
109
|
+
const pathEnv = opts.pathEnv ?? process.env.PATH ?? "";
|
|
110
|
+
const statuses = [];
|
|
111
|
+
const missingPackages = new Set();
|
|
112
|
+
for (const dep of dependenciesForProfile(profile)) {
|
|
113
|
+
const resolved = findOnPath(dep.binary, pathEnv);
|
|
114
|
+
if (resolved) {
|
|
115
|
+
statuses.push({ dep, installed: true, resolvedPath: resolved });
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
statuses.push({ dep, installed: false });
|
|
119
|
+
missingPackages.add(dep.npmPackage);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return { statuses, missingPackages: [...missingPackages] };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Render the dependency table the wizard shows to the operator. Pure
|
|
126
|
+
* function so tests can lock the surface text without spawning a
|
|
127
|
+
* subprocess.
|
|
128
|
+
*/
|
|
129
|
+
export function formatDependencyTable(profile, result) {
|
|
130
|
+
const lines = [];
|
|
131
|
+
lines.push(`Profile "${profile}" depends on these binaries:`);
|
|
132
|
+
for (const status of result.statuses) {
|
|
133
|
+
const mark = status.installed ? "✓" : "✗";
|
|
134
|
+
const where = status.installed
|
|
135
|
+
? `(already installed)`
|
|
136
|
+
: `→ ${status.dep.npmPackage}`;
|
|
137
|
+
lines.push(` ${mark} ${status.dep.binary.padEnd(36)} ${where}`);
|
|
138
|
+
}
|
|
139
|
+
if (result.missingPackages.length === 0) {
|
|
140
|
+
lines.push("All required binaries are already on PATH.");
|
|
141
|
+
}
|
|
142
|
+
return lines.join("\n");
|
|
143
|
+
}
|
|
144
|
+
function realSpawn(cmd, args) {
|
|
145
|
+
return new Promise((resolve) => {
|
|
146
|
+
const child = spawn(cmd, args, { stdio: ["ignore", "inherit", "pipe"] });
|
|
147
|
+
let stderr = "";
|
|
148
|
+
child.stderr?.on("data", (chunk) => {
|
|
149
|
+
const text = chunk.toString("utf8");
|
|
150
|
+
stderr += text;
|
|
151
|
+
// Mirror npm progress to the operator's terminal — they want to
|
|
152
|
+
// see the install happening.
|
|
153
|
+
process.stderr.write(text);
|
|
154
|
+
});
|
|
155
|
+
child.on("error", (err) => {
|
|
156
|
+
resolve({ code: 1, stderr: `${stderr}\n${err.message}` });
|
|
157
|
+
});
|
|
158
|
+
child.on("exit", (code) => {
|
|
159
|
+
resolve({ code: code ?? 1, stderr });
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Install a list of npm packages globally. Empty list short-circuits
|
|
165
|
+
* to a successful no-op. Operator-facing output streams through stderr
|
|
166
|
+
* during the run, the structured result is returned to the wizard so
|
|
167
|
+
* it can decide whether to abort.
|
|
168
|
+
*/
|
|
169
|
+
export async function installPackagesGlobally(packages, opts = {}) {
|
|
170
|
+
if (packages.length === 0) {
|
|
171
|
+
return { ok: true, attempted: [], stderr: "", exitCode: 0 };
|
|
172
|
+
}
|
|
173
|
+
const run = opts.spawn ?? realSpawn;
|
|
174
|
+
const { code, stderr } = await run("npm", ["i", "-g", ...packages]);
|
|
175
|
+
return {
|
|
176
|
+
ok: code === 0,
|
|
177
|
+
attempted: [...packages],
|
|
178
|
+
stderr,
|
|
179
|
+
exitCode: code,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../../src/cli/init/dependencies.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { select, confirm, input } from "@inquirer/prompts";
|
|
2
2
|
import { type InitResult } from "./index.js";
|
|
3
|
-
|
|
3
|
+
import { type ApplyResult } from "../apply/index.js";
|
|
4
|
+
import { type InstallOptions } from "./dependencies.js";
|
|
5
|
+
export type ProfileChoice = "solo" | "team" | "full" | "custom";
|
|
4
6
|
export interface InteractivePrompts {
|
|
5
7
|
select: typeof select;
|
|
6
8
|
confirm: typeof confirm;
|
|
@@ -16,6 +18,15 @@ export interface RunInteractiveOptions {
|
|
|
16
18
|
/** Force-confirm overwrite of existing manifest. Real users go through
|
|
17
19
|
* the prompt; tests can pre-set this. */
|
|
18
20
|
forceOverwrite?: boolean;
|
|
21
|
+
/** Override the `npm i -g` runner. Tests fake success/failure here. */
|
|
22
|
+
installSpawn?: InstallOptions["spawn"];
|
|
23
|
+
/**
|
|
24
|
+
* Override the PATH probed by the dependency check. Tests set this
|
|
25
|
+
* to a directory with no binaries (or a curated one) to exercise the
|
|
26
|
+
* "everything missing" / "partially installed" branches without
|
|
27
|
+
* needing the real packages on the test host.
|
|
28
|
+
*/
|
|
29
|
+
dependencyPathEnv?: string;
|
|
19
30
|
}
|
|
20
31
|
export interface InteractiveResult {
|
|
21
32
|
/** True if the operator (or a Ctrl-C / decline) bailed out. No write happened. */
|
|
@@ -26,5 +37,7 @@ export interface InteractiveResult {
|
|
|
26
37
|
profile?: ProfileChoice;
|
|
27
38
|
/** Whether `harness validate` reported zero errors after the write. */
|
|
28
39
|
validateClean?: boolean;
|
|
40
|
+
/** Present when the wizard ran the post-write merge-apply step. */
|
|
41
|
+
apply?: ApplyResult;
|
|
29
42
|
}
|
|
30
43
|
export declare function runInteractive(opts?: RunInteractiveOptions): Promise<InteractiveResult>;
|
|
@@ -25,6 +25,8 @@ import { EX_FAIL, HarnessExitError } from "../exit-codes.js";
|
|
|
25
25
|
import { detect } from "./detect.js";
|
|
26
26
|
import { init } from "./index.js";
|
|
27
27
|
import { validate } from "../validate/index.js";
|
|
28
|
+
import { apply } from "../apply/index.js";
|
|
29
|
+
import { checkDependencies, formatDependencyTable, installPackagesGlobally, } from "./dependencies.js";
|
|
28
30
|
const DEFAULT_PROMPTS = { select, confirm, input };
|
|
29
31
|
function isAbortError(err) {
|
|
30
32
|
if (!(err instanceof Error))
|
|
@@ -48,7 +50,10 @@ function summariseDetection(d) {
|
|
|
48
50
|
return lines.join("\n");
|
|
49
51
|
}
|
|
50
52
|
function profileNeedsAgentTasks(profile) {
|
|
51
|
-
|
|
53
|
+
// Full inherits the team layer, including the agent-tasks MCP and
|
|
54
|
+
// the review-before-merge policy, so it has the same Claude-side
|
|
55
|
+
// wiring requirement as Team.
|
|
56
|
+
return profile === "team" || profile === "full";
|
|
52
57
|
}
|
|
53
58
|
function detectionHasAgentTasks(d) {
|
|
54
59
|
return d.mcpServers.some((s) => s.name === "agent-tasks");
|
|
@@ -89,26 +94,32 @@ export async function runInteractive(opts = {}) {
|
|
|
89
94
|
value: "team",
|
|
90
95
|
description: "Adds the merge gate that blocks PR merges without a review ledger entry.",
|
|
91
96
|
},
|
|
97
|
+
{
|
|
98
|
+
name: "Full (Team + 5 reference policies wired through harness policy intercept)",
|
|
99
|
+
value: "full",
|
|
100
|
+
description: "Ships the reference manifest with every example policy (dogfood gate, preflight gates, review-subagent gate). All hooks run through the bundled `harness policy intercept` engine, so no external shell scripts are required.",
|
|
101
|
+
},
|
|
92
102
|
{
|
|
93
103
|
name: "Custom (advanced, bail out and hand-edit)",
|
|
94
104
|
value: "custom",
|
|
95
|
-
description: "Print the install layout and exit.
|
|
105
|
+
description: "Print the install layout and exit. Use this when none of the profiles fit and you plan to author the manifest from scratch.",
|
|
96
106
|
},
|
|
97
107
|
],
|
|
98
108
|
}));
|
|
99
109
|
if (profile === "custom") {
|
|
100
110
|
stderr([
|
|
101
|
-
"Custom profile selected. The interactive wizard does not
|
|
102
|
-
"manifests à la carte.
|
|
103
|
-
"
|
|
104
|
-
"above tell you what the
|
|
111
|
+
"Custom profile selected. The interactive wizard does not build",
|
|
112
|
+
"manifests à la carte. Start from `harness init --template minimal`",
|
|
113
|
+
"or `harness init --template full` for the reference manifest, then",
|
|
114
|
+
"edit it directly. Detection results above tell you what the",
|
|
115
|
+
"harness already sees in your environment.",
|
|
105
116
|
"",
|
|
106
117
|
].join("\n"));
|
|
107
118
|
return { aborted: true, profile };
|
|
108
119
|
}
|
|
109
120
|
if (profileNeedsAgentTasks(profile) && !detectionHasAgentTasks(detection)) {
|
|
110
121
|
const proceed = await prompts.confirm({
|
|
111
|
-
message: "The Team profile wires the agent-tasks MCP
|
|
122
|
+
message: "The Team profile wires the agent-tasks MCP via the `agent-tasks-mcp-bridge` binary. Claude's settings.json does not yet declare it; the wizard will offer to install missing packages and wire it in a moment via `harness apply --target ~/.claude/settings.json --merge`. Proceed?",
|
|
112
123
|
default: true,
|
|
113
124
|
});
|
|
114
125
|
if (!proceed) {
|
|
@@ -116,6 +127,43 @@ export async function runInteractive(opts = {}) {
|
|
|
116
127
|
return { aborted: true, profile };
|
|
117
128
|
}
|
|
118
129
|
}
|
|
130
|
+
// Dependency check + install. Runs before the manifest is written
|
|
131
|
+
// so an `npm i -g` failure leaves no half-installed state behind.
|
|
132
|
+
// The operator decision (2026-05-13) is: abort on install error,
|
|
133
|
+
// surface the npm output, let the user fix npm and re-run init.
|
|
134
|
+
const depResult = checkDependencies(profile, opts.dependencyPathEnv !== undefined ? { pathEnv: opts.dependencyPathEnv } : {});
|
|
135
|
+
if (depResult.statuses.length > 0) {
|
|
136
|
+
stderr(`\n${formatDependencyTable(profile, depResult)}\n`);
|
|
137
|
+
}
|
|
138
|
+
if (depResult.missingPackages.length > 0) {
|
|
139
|
+
const installNow = await prompts.confirm({
|
|
140
|
+
message: `Install ${depResult.missingPackages.length} missing package(s) with \`npm i -g ${depResult.missingPackages.join(" ")}\`?`,
|
|
141
|
+
default: true,
|
|
142
|
+
});
|
|
143
|
+
if (!installNow) {
|
|
144
|
+
stderr([
|
|
145
|
+
"",
|
|
146
|
+
"Aborted: dependencies missing and install declined.",
|
|
147
|
+
`To install manually: npm i -g ${depResult.missingPackages.join(" ")}`,
|
|
148
|
+
"Then re-run `harness init --interactive`.",
|
|
149
|
+
"",
|
|
150
|
+
].join("\n"));
|
|
151
|
+
return { aborted: true, profile };
|
|
152
|
+
}
|
|
153
|
+
stderr(`\nRunning npm i -g ${depResult.missingPackages.join(" ")}\n`);
|
|
154
|
+
const installResult = await installPackagesGlobally(depResult.missingPackages, opts.installSpawn ? { spawn: opts.installSpawn } : {});
|
|
155
|
+
if (!installResult.ok) {
|
|
156
|
+
stderr([
|
|
157
|
+
"",
|
|
158
|
+
`Aborted: npm install exited ${installResult.exitCode}. Manifest NOT written.`,
|
|
159
|
+
"Common fixes: re-run with sudo, switch nvm to a writable node, or check network proxy.",
|
|
160
|
+
`Then re-run: harness init --interactive`,
|
|
161
|
+
"",
|
|
162
|
+
].join("\n"));
|
|
163
|
+
return { aborted: true, profile };
|
|
164
|
+
}
|
|
165
|
+
stderr(`Installed ${installResult.attempted.length} package(s) successfully.\n`);
|
|
166
|
+
}
|
|
119
167
|
const defaultMemoryDir = path.join(detection.runtimes[0]?.home ?? "~/.claude", "projects", "{project}", "memory");
|
|
120
168
|
const memoryDir = await prompts.input({
|
|
121
169
|
message: "Memory directory pattern (use {project} for the per-project slug)",
|
|
@@ -133,8 +181,8 @@ export async function runInteractive(opts = {}) {
|
|
|
133
181
|
stderr("Aborted: declined to write manifest.\n");
|
|
134
182
|
return { aborted: true, profile };
|
|
135
183
|
}
|
|
136
|
-
// `custom`
|
|
137
|
-
//
|
|
184
|
+
// `custom` returned early above; the remaining values map 1:1 to
|
|
185
|
+
// TemplateName entries that `init()` understands.
|
|
138
186
|
//
|
|
139
187
|
// Path semantics are deliberately split: detect() treats `homeDir`
|
|
140
188
|
// as the user's $HOME and synthesizes `.claude` from it, while
|
|
@@ -159,13 +207,60 @@ export async function runInteractive(opts = {}) {
|
|
|
159
207
|
for (const d of v.diagnostics) {
|
|
160
208
|
stderr(` [${d.severity}] ${d.path}: ${d.message}\n`);
|
|
161
209
|
}
|
|
162
|
-
if (validateClean) {
|
|
163
|
-
stderr(`\nNext: \`harness apply --runtime claude-code\` to wire ~/.claude/settings.json. The wizard does not run apply for you; review the generated manifest first.\n`);
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
210
|
+
if (!validateClean) {
|
|
166
211
|
stderr(`\nValidate reported errors. Fix the manifest before running \`harness apply\`.\n`);
|
|
212
|
+
return { aborted: false, profile, init: initResult, validateClean };
|
|
213
|
+
}
|
|
214
|
+
// Validate-clean: offer to wire into Claude Code right now. A bare
|
|
215
|
+
// `harness init` leaves the manifest on disk but Claude Code does
|
|
216
|
+
// not see it until `apply --target ... --merge` runs. Without this
|
|
217
|
+
// prompt the operator gets a clean manifest, runs `harness apply`,
|
|
218
|
+
// sees `harness.generated/` files appear, and is stuck wondering
|
|
219
|
+
// why Claude still does not honour any hooks. Auto-offering the
|
|
220
|
+
// merge here collapses that two-step trap into one.
|
|
221
|
+
const claudeSettingsPath = path.join(detection.runtimes.find((r) => r.name === "claude-code")?.home ?? path.join(opts.homeDir ?? process.env.HOME ?? "", ".claude"), "settings.json");
|
|
222
|
+
const wireNow = await prompts.confirm({
|
|
223
|
+
message: `Wire into Claude Code now? (merges hooks + mcpServers into ${claudeSettingsPath})`,
|
|
224
|
+
default: true,
|
|
225
|
+
});
|
|
226
|
+
if (!wireNow) {
|
|
227
|
+
stderr(`\nManifest written. To wire it into Claude Code later:\n harness apply --target ${claudeSettingsPath} --merge\n`);
|
|
228
|
+
return { aborted: false, profile, init: initResult, validateClean };
|
|
229
|
+
}
|
|
230
|
+
const applyOpts = {
|
|
231
|
+
configPath: initResult.path,
|
|
232
|
+
target: claudeSettingsPath,
|
|
233
|
+
merge: true,
|
|
234
|
+
};
|
|
235
|
+
if (opts.homeDir !== undefined) {
|
|
236
|
+
applyOpts.homeDir = path.join(opts.homeDir, ".claude");
|
|
237
|
+
}
|
|
238
|
+
// The merge-apply touches a real file under ~/.claude; permission
|
|
239
|
+
// errors and pre-existing malformed JSON both throw from apply().
|
|
240
|
+
// Catch here so a clean manifest write is not undone by a stack
|
|
241
|
+
// trace, and the operator still sees the manual fallback command
|
|
242
|
+
// they need to recover.
|
|
243
|
+
let applyResult;
|
|
244
|
+
try {
|
|
245
|
+
applyResult = await apply(applyOpts);
|
|
246
|
+
}
|
|
247
|
+
catch (err) {
|
|
248
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
249
|
+
stderr(`\nFailed to wire ${claudeSettingsPath}: ${message}\n`);
|
|
250
|
+
stderr(`Manifest is on disk. To retry the merge manually:\n harness apply --target ${claudeSettingsPath} --merge\n`);
|
|
251
|
+
return { aborted: false, profile, init: initResult, validateClean };
|
|
252
|
+
}
|
|
253
|
+
if (applyResult.targetMergeSummary) {
|
|
254
|
+
stderr(`\n${applyResult.targetMergeSummary}\n`);
|
|
255
|
+
}
|
|
256
|
+
if (applyResult.targetWritten) {
|
|
257
|
+
stderr(`wired into ${applyResult.targetPath}\n`);
|
|
258
|
+
stderr(`verify: claude -p "say hi" --settings ${applyResult.targetPath} --output-format stream-json --include-hook-events\n`);
|
|
259
|
+
}
|
|
260
|
+
for (const hint of applyResult.restartHints) {
|
|
261
|
+
stderr(`restart hint: ${hint}\n`);
|
|
167
262
|
}
|
|
168
|
-
return { aborted: false, profile, init: initResult, validateClean };
|
|
263
|
+
return { aborted: false, profile, init: initResult, validateClean, apply: applyResult };
|
|
169
264
|
}
|
|
170
265
|
catch (err) {
|
|
171
266
|
if (isAbortError(err)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../../src/cli/init/interactive.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,sEAAsE;AACtE,4DAA4D;AAC5D,EAAE;AACF,gBAAgB;AAChB,EAAE;AACF,wEAAwE;AACxE,kEAAkE;AAClE,4DAA4D;AAC5D,sEAAsE;AACtE,uEAAuE;AACvE,qEAAqE;AACrE,mDAAmD;AACnD,mEAAmE;AACnE,8DAA8D;AAC9D,4DAA4D;AAC5D,wBAAwB;AACxB,2EAA2E;AAC3E,oEAAoE;AACpE,uEAAuE;AACvE,4DAA4D;AAE5D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAwB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAmB,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"interactive.js","sourceRoot":"","sources":["../../../src/cli/init/interactive.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,sEAAsE;AACtE,4DAA4D;AAC5D,EAAE;AACF,gBAAgB;AAChB,EAAE;AACF,wEAAwE;AACxE,kEAAkE;AAClE,4DAA4D;AAC5D,sEAAsE;AACtE,uEAAuE;AACvE,qEAAqE;AACrE,mDAAmD;AACnD,mEAAmE;AACnE,8DAA8D;AAC9D,4DAA4D;AAC5D,wBAAwB;AACxB,2EAA2E;AAC3E,oEAAoE;AACpE,uEAAuE;AACvE,4DAA4D;AAE5D,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAwB,MAAM,aAAa,CAAC;AAC3D,OAAO,EAAE,IAAI,EAAmB,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EAAE,KAAK,EAAoB,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,GAExB,MAAM,mBAAmB,CAAC;AA4C3B,MAAM,eAAe,GAAuB,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAEvE,SAAS,YAAY,CAAC,GAAY;IAChC,IAAI,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1C,OAAO,4BAA4B,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAC3F,CAAC;AAED,SAAS,kBAAkB,CAAC,CAAkB;IAC5C,MAAM,KAAK,GAAa,CAAC,oBAAoB,CAAC,CAAC;IAC/C,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;QAC5F,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC;IAC7D,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAC;IAC7F,IAAI,CAAC,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAC;IACtE,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,sBAAsB,CAAC,OAAsB;IACpD,kEAAkE;IAClE,iEAAiE;IACjE,8BAA8B;IAC9B,OAAO,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,MAAM,CAAC;AAClD,CAAC;AAED,SAAS,sBAAsB,CAAC,CAAkB;IAChD,OAAO,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAA8B,EAAE;IAEhC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,eAAe,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEvE,IAAI,SAA0B,CAAC;IAC/B,IAAI,CAAC;QACH,SAAS,GAAG,MAAM,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7F,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,gBAAgB,CACxB,+CAAgD,GAAa,CAAC,OAAO,EAAE,EACvE,OAAO,CACR,CAAC;IACJ,CAAC;IAED,MAAM,CAAC,GAAG,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IAE/C,IAAI,CAAC;QACH,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACtD,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;gBACtC,OAAO,EAAE,gCAAgC,SAAS,CAAC,QAAQ,CAAC,IAAI,iBAAiB;gBACjF,OAAO,EAAE,KAAK;aACf,CAAC,CAAC;YACH,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,CAAC,8CAA8C,CAAC,CAAC;gBACvD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,MAAM,CAAC;YACpC,OAAO,EAAE,sBAAsB;YAC/B,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,wDAAwD;oBAC9D,KAAK,EAAE,MAAM;oBACb,WAAW,EAAE,+DAA+D;iBAC7E;gBACD;oBACE,IAAI,EAAE,6DAA6D;oBACnE,KAAK,EAAE,MAAM;oBACb,WAAW,EAAE,0EAA0E;iBACxF;gBACD;oBACE,IAAI,EAAE,2EAA2E;oBACjF,KAAK,EAAE,MAAM;oBACb,WAAW,EACT,+NAA+N;iBAClO;gBACD;oBACE,IAAI,EAAE,2CAA2C;oBACjD,KAAK,EAAE,QAAQ;oBACf,WAAW,EACT,6HAA6H;iBAChI;aACF;SACF,CAAC,CAAkB,CAAC;QAErB,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;YACzB,MAAM,CACJ;gBACE,gEAAgE;gBAChE,oEAAoE;gBACpE,oEAAoE;gBACpE,6DAA6D;gBAC7D,2CAA2C;gBAC3C,EAAE;aACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACpC,CAAC;QAED,IAAI,sBAAsB,CAAC,OAAO,CAAC,IAAI,CAAC,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1E,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;gBACpC,OAAO,EACL,sRAAsR;gBACxR,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YACH,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,CAAC,wEAAwE,CAAC,CAAC;gBACjF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YACpC,CAAC;QACH,CAAC;QAED,kEAAkE;QAClE,kEAAkE;QAClE,iEAAiE;QACjE,gEAAgE;QAChE,MAAM,SAAS,GAAG,iBAAiB,CACjC,OAAO,EACP,IAAI,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAChF,CAAC;QACF,IAAI,SAAS,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAClC,MAAM,CAAC,KAAK,qBAAqB,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,SAAS,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzC,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;gBACvC,OAAO,EAAE,WAAW,SAAS,CAAC,eAAe,CAAC,MAAM,uCAAuC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK;gBACnI,OAAO,EAAE,IAAI;aACd,CAAC,CAAC;YACH,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,CACJ;oBACE,EAAE;oBACF,qDAAqD;oBACrD,iCAAiC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;oBACtE,2CAA2C;oBAC3C,EAAE;iBACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;gBACF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YACpC,CAAC;YACD,MAAM,CAAC,sBAAsB,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACtE,MAAM,aAAa,GAAG,MAAM,uBAAuB,CACjD,SAAS,CAAC,eAAe,EACzB,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CACtD,CAAC;YACF,IAAI,CAAC,aAAa,CAAC,EAAE,EAAE,CAAC;gBACtB,MAAM,CACJ;oBACE,EAAE;oBACF,+BAA+B,aAAa,CAAC,QAAQ,yBAAyB;oBAC9E,wFAAwF;oBACxF,yCAAyC;oBACzC,EAAE;iBACH,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;gBACF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;YACpC,CAAC;YACD,MAAM,CAAC,aAAa,aAAa,CAAC,SAAS,CAAC,MAAM,6BAA6B,CAAC,CAAC;QACnF,CAAC;QAED,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;QAClH,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC;YACpC,OAAO,EAAE,mEAAmE;YAC5E,OAAO,EAAE,gBAAgB;SAC1B,CAAC,CAAC;QACH,IAAI,SAAS,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC5B,MAAM,CAAC,yCAAyC,CAAC,CAAC;YAClD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACpC,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;YACzC,OAAO,EAAE,yBAAyB,SAAS,CAAC,QAAQ,CAAC,IAAI,GAAG;YAC5D,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,CAAC,wCAAwC,CAAC,CAAC;YACjD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QACpC,CAAC;QAED,iEAAiE;QACjE,kDAAkD;QAClD,EAAE;QACF,mEAAmE;QACnE,+DAA+D;QAC/D,kEAAkE;QAClE,mEAAmE;QACnE,oEAAoE;QACpE,8BAA8B;QAC9B,MAAM,QAAQ,GAA6E;YACzF,QAAQ,EAAE,OAAO;YACjB,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,MAAM;SACjC,CAAC;QACF,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC/B,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QAExC,IAAI,UAAU,CAAC,MAAM;YAAE,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACjD,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAE1B,MAAM,CAAC,GAAG,QAAQ,CAAC,EAAE,UAAU,EAAE,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QACpD,MAAM,aAAa,GAAG,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC;QACzC,MAAM,CACJ,uBAAuB,CAAC,CAAC,UAAU,cAAc,CAAC,CAAC,YAAY,eAAe,CAC/E,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC9B,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC;QACxD,CAAC;QAED,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,CACJ,kFAAkF,CACnF,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;QACtE,CAAC;QAED,mEAAmE;QACnE,kEAAkE;QAClE,mEAAmE;QACnE,mEAAmE;QACnE,iEAAiE;QACjE,gEAAgE;QAChE,oDAAoD;QACpD,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAClC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,aAAa,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,EAAE,SAAS,CAAC,EAC9H,eAAe,CAChB,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC;YACpC,OAAO,EAAE,8DAA8D,kBAAkB,GAAG;YAC5F,OAAO,EAAE,IAAI;SACd,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,CACJ,oFAAoF,kBAAkB,YAAY,CACnH,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;QACtE,CAAC;QAED,MAAM,SAAS,GAAgC;YAC7C,UAAU,EAAE,UAAU,CAAC,IAAI;YAC3B,MAAM,EAAE,kBAAkB;YAC1B,KAAK,EAAE,IAAI;SACZ,CAAC;QACF,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC/B,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QACzD,CAAC;QACD,kEAAkE;QAClE,kEAAkE;QAClE,gEAAgE;QAChE,iEAAiE;QACjE,wBAAwB;QACxB,IAAI,WAAoC,CAAC;QACzC,IAAI,CAAC;YACH,WAAW,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;QACvC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,CAAC,oBAAoB,kBAAkB,KAAK,OAAO,IAAI,CAAC,CAAC;YAC/D,MAAM,CACJ,+EAA+E,kBAAkB,YAAY,CAC9G,CAAC;YACF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC;QACtE,CAAC;QACD,IAAI,WAAW,CAAC,kBAAkB,EAAE,CAAC;YACnC,MAAM,CAAC,KAAK,WAAW,CAAC,kBAAkB,IAAI,CAAC,CAAC;QAClD,CAAC;QACD,IAAI,WAAW,CAAC,aAAa,EAAE,CAAC;YAC9B,MAAM,CAAC,cAAc,WAAW,CAAC,UAAU,IAAI,CAAC,CAAC;YACjD,MAAM,CACJ,yCAAyC,WAAW,CAAC,UAAU,sDAAsD,CACtH,CAAC;QACJ,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;YAC5C,MAAM,CAAC,iBAAiB,IAAI,IAAI,CAAC,CAAC;QACpC,CAAC;QAED,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,aAAa,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC;IAC1F,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YACtB,MAAM,CAAC,gEAAgE,CAAC,CAAC;YACzE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC3B,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SOLO_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template solo`.\n#\n# Single-operator profile: memory-router for cross-conversation memory\n# routing + understanding-before-execution policy pack to force an\n# explicit interpretation confirmation before any write-capable tool\n# fires. No agent-tasks loop (use --template team if you want PR\n# review-gating).\n#\n# Adapt the paths under `command:` to your install layout, or move\n# host-specific paths to ~/.claude/machines/<host>.harness.overrides.yaml.\n\nversion: 1\n\ngrounding:\n session:\n auto_start: true\n id_format: \"gs-{repo}-{rand:8}\"\n evidence_ledger:\n path: ~/.evidence-ledger/ledger.db\n retention_days: 90\n\ntools:\n builtin:\n known: [Read, Edit, Write, Bash, Agent, Skill, TaskCreate, Glob, Grep]\n\nmemory:\n directories:\n - path: ~/.claude/projects/{project}/memory\n scope: project\n router:\n command: [
|
|
2
|
-
export declare const TEAM_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template team`.\n#\n# Solo profile + agent-tasks MCP + the review-before-merge policy. Block\n# pull_requests_merge MCP calls unless a ledger entry tagged\n# review:<pr-number> exists for the current grounding session, the\n# standard team workflow where every PR gets a review-subagent pass\n# before it can land.\n#\n# Adapt the paths under `command:` to your install layout, or move\n# host-specific paths to ~/.claude/machines/<host>.harness.overrides.yaml.\n\nversion: 1\n\ngrounding:\n session:\n auto_start: true\n id_format: \"gs-{repo}-{rand:8}\"\n evidence_ledger:\n path: ~/.evidence-ledger/ledger.db\n retention_days: 90\n\ntools:\n mcp:\n - name: agent-tasks\n
|
|
1
|
+
export declare const SOLO_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template solo`.\n#\n# Single-operator profile: memory-router for cross-conversation memory\n# routing + understanding-before-execution policy pack to force an\n# explicit interpretation confirmation before any write-capable tool\n# fires. No agent-tasks loop (use --template team if you want PR\n# review-gating).\n#\n# Adapt the paths under `command:` to your install layout, or move\n# host-specific paths to ~/.claude/machines/<host>.harness.overrides.yaml.\n\nversion: 1\n\ngrounding:\n session:\n auto_start: true\n id_format: \"gs-{repo}-{rand:8}\"\n evidence_ledger:\n path: ~/.evidence-ledger/ledger.db\n retention_days: 90\n\ntools:\n builtin:\n known: [Read, Edit, Write, Bash, Agent, Skill, TaskCreate, Glob, Grep]\n\nmemory:\n directories:\n - path: ~/.claude/projects/{project}/memory\n scope: project\n router:\n # `memory-router-user-prompt-submit` is the published bin from\n # `@lannguyensi/memory-router`. `harness init` offers to\n # `npm i -g` it for you; doctor expects it on PATH.\n command: [memory-router-user-prompt-submit]\n enabled: true\n retention:\n staleness_days: 180\n broken_refs: warn\n scopes:\n default: project\n allowed: [project, user]\n\npolicy_packs:\n - name: understanding-before-execution\n source: builtin\n enabled: true\n description: Force agents to expose their task interpretation and wait for explicit human approval before any write-capable tool fires.\n config:\n mode: grill_me\n";
|
|
2
|
+
export declare const TEAM_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template team`.\n#\n# Solo profile + agent-tasks MCP + the review-before-merge policy. Block\n# pull_requests_merge MCP calls unless a ledger entry tagged\n# review:<pr-number> exists for the current grounding session, the\n# standard team workflow where every PR gets a review-subagent pass\n# before it can land.\n#\n# Adapt the paths under `command:` to your install layout, or move\n# host-specific paths to ~/.claude/machines/<host>.harness.overrides.yaml.\n\nversion: 1\n\ngrounding:\n session:\n auto_start: true\n id_format: \"gs-{repo}-{rand:8}\"\n evidence_ledger:\n path: ~/.evidence-ledger/ledger.db\n retention_days: 90\n\ntools:\n mcp:\n - name: agent-tasks\n # Zero-setup entry: `@agent-tasks/mcp-bridge` exposes the\n # `agent-tasks-mcp-bridge` binary on PATH after\n # `npm i -g @agent-tasks/mcp-bridge`. The bridge owns token\n # storage (OS keychain or file fallback) and defaults the base\n # URL to https://agent-tasks.opentriologue.ai, so no env is\n # required here. Override with `AGENT_TASKS_BASE_URL` /\n # `AGENT_TASKS_TOKEN` if you self-host or want explicit creds.\n command: [agent-tasks-mcp-bridge]\n health:\n verb: projects_list\n timeout_ms: 5000\n enabled: true\n - name: grounding-mcp\n # `grounding-mcp` bin is published in `@lannguyensi/grounding-mcp`.\n # `harness init` offers to `npm i -g` it for you. No env is set:\n # the bundled default resolves to `~/.evidence-ledger/ledger.db`\n # via os.homedir() at startup. Passing a literal tilde in env\n # bypasses shell expansion and creates rogue cwd-relative DB files\n # (see agent-tasks/42d224a6 incident).\n command: [grounding-mcp]\n health:\n verb: ledger_status\n timeout_ms: 5000\n enabled: true\n builtin:\n known: [Read, Edit, Write, Bash, Agent, Skill, TaskCreate, Glob, Grep]\n\nmemory:\n directories:\n - path: ~/.claude/projects/{project}/memory\n scope: project\n router:\n # `memory-router-user-prompt-submit` is the published bin from\n # `@lannguyensi/memory-router`. `harness init` offers to\n # `npm i -g` it for you; doctor expects it on PATH.\n command: [memory-router-user-prompt-submit]\n enabled: true\n retention:\n staleness_days: 180\n broken_refs: warn\n scopes:\n default: project\n allowed: [project, user]\n\nhooks:\n - name: require-review-evidence\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n # The built-in `harness policy intercept` CLI verb is the generic\n # deny-on-missing-evidence hook entrypoint. It reads the tool event\n # JSON on stdin, evaluates all policies whose triggers match, emits\n # Claude Code's deny envelope on block. Using it here removes the\n # need to ship a per-policy shell script under ~/.claude/hooks/ for\n # the team setup; operators with custom logic can swap in their own\n # script path.\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\npolicies:\n - name: review-before-merge\n description: Block PR merges unless a ledger entry tagged review:<pr-number> exists for this session.\n trigger:\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n extract:\n PR_NUMBER: \"toolArgs.prNumber\"\n requires:\n ledger_tag: \"review:${PR_NUMBER}\"\n hook: require-review-evidence\n enforcement: block\n\npolicy_packs:\n - name: understanding-before-execution\n source: builtin\n enabled: true\n description: Force agents to expose their task interpretation and wait for explicit human approval before any write-capable tool fires.\n config:\n mode: grill_me\n";
|
|
@@ -49,7 +49,10 @@ memory:
|
|
|
49
49
|
- path: ~/.claude/projects/{project}/memory
|
|
50
50
|
scope: project
|
|
51
51
|
router:
|
|
52
|
-
|
|
52
|
+
# \`memory-router-user-prompt-submit\` is the published bin from
|
|
53
|
+
# \`@lannguyensi/memory-router\`. \`harness init\` offers to
|
|
54
|
+
# \`npm i -g\` it for you; doctor expects it on PATH.
|
|
55
|
+
command: [memory-router-user-prompt-submit]
|
|
53
56
|
enabled: true
|
|
54
57
|
retention:
|
|
55
58
|
staleness_days: 180
|
|
@@ -92,17 +95,26 @@ grounding:
|
|
|
92
95
|
tools:
|
|
93
96
|
mcp:
|
|
94
97
|
- name: agent-tasks
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
+
# Zero-setup entry: \`@agent-tasks/mcp-bridge\` exposes the
|
|
99
|
+
# \`agent-tasks-mcp-bridge\` binary on PATH after
|
|
100
|
+
# \`npm i -g @agent-tasks/mcp-bridge\`. The bridge owns token
|
|
101
|
+
# storage (OS keychain or file fallback) and defaults the base
|
|
102
|
+
# URL to https://agent-tasks.opentriologue.ai, so no env is
|
|
103
|
+
# required here. Override with \`AGENT_TASKS_BASE_URL\` /
|
|
104
|
+
# \`AGENT_TASKS_TOKEN\` if you self-host or want explicit creds.
|
|
105
|
+
command: [agent-tasks-mcp-bridge]
|
|
98
106
|
health:
|
|
99
107
|
verb: projects_list
|
|
100
108
|
timeout_ms: 5000
|
|
101
109
|
enabled: true
|
|
102
110
|
- name: grounding-mcp
|
|
103
|
-
|
|
104
|
-
env:
|
|
105
|
-
|
|
111
|
+
# \`grounding-mcp\` bin is published in \`@lannguyensi/grounding-mcp\`.
|
|
112
|
+
# \`harness init\` offers to \`npm i -g\` it for you. No env is set:
|
|
113
|
+
# the bundled default resolves to \`~/.evidence-ledger/ledger.db\`
|
|
114
|
+
# via os.homedir() at startup. Passing a literal tilde in env
|
|
115
|
+
# bypasses shell expansion and creates rogue cwd-relative DB files
|
|
116
|
+
# (see agent-tasks/42d224a6 incident).
|
|
117
|
+
command: [grounding-mcp]
|
|
106
118
|
health:
|
|
107
119
|
verb: ledger_status
|
|
108
120
|
timeout_ms: 5000
|
|
@@ -115,7 +127,10 @@ memory:
|
|
|
115
127
|
- path: ~/.claude/projects/{project}/memory
|
|
116
128
|
scope: project
|
|
117
129
|
router:
|
|
118
|
-
|
|
130
|
+
# \`memory-router-user-prompt-submit\` is the published bin from
|
|
131
|
+
# \`@lannguyensi/memory-router\`. \`harness init\` offers to
|
|
132
|
+
# \`npm i -g\` it for you; doctor expects it on PATH.
|
|
133
|
+
command: [memory-router-user-prompt-submit]
|
|
119
134
|
enabled: true
|
|
120
135
|
retention:
|
|
121
136
|
staleness_days: 180
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../../src/cli/init/profiles.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,uEAAuE;AACvE,yCAAyC;AACzC,EAAE;AACF,sEAAsE;AACtE,kEAAkE;AAClE,kEAAkE;AAClE,kEAAkE;AAClE,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,kEAAkE;AAClE,gDAAgD;AAChD,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AAExE,MAAM,CAAC,MAAM,aAAa,GAAG
|
|
1
|
+
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../../src/cli/init/profiles.ts"],"names":[],"mappings":"AAAA,sEAAsE;AACtE,EAAE;AACF,uEAAuE;AACvE,yCAAyC;AACzC,EAAE;AACF,sEAAsE;AACtE,kEAAkE;AAClE,kEAAkE;AAClE,kEAAkE;AAClE,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,kEAAkE;AAClE,gDAAgD;AAChD,EAAE;AACF,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AAExE,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmD5B,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyG5B,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const MINIMAL_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template minimal`.\n#\n# This is the empty-but-valid manifest. Run `harness validate` to confirm it\n# parses, then add entries under the five top-level keys:\n#\n# grounding: evidence-ledger + claim-gate config (see docs/ARCHITECTURE.md \u00A72)\n# tools: mcp / cli / skills / builtin inventory (\u00A73)\n# memory: directories, retention, scopes (\u00A74)\n# hooks: event-bound shell commands (\u00A75)\n# policies: named rules that bind hooks to triggers (\u00A76)\n#\n# Phase 2 verbs to add entries safely: `harness add mcp <name> ...`,\n# `harness add cli`, `harness add hook`, `harness add skill`.\n# Per-machine overrides live at ~/.claude/machines/<discriminator>.harness.overrides.yaml\n# (ARCHITECTURE.md \u00A78) for paths that vary per host.\n#\n# Docs: https://github.com/LanNguyenSi/harness\n\nversion: 1\n";
|
|
2
|
-
export declare const FULL_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template full`.
|
|
2
|
+
export declare const FULL_TEMPLATE = "# ~/.claude/harness.yaml\n#\n# Bootstrapped by `harness init --template full`. The reference manifest:\n# all 5 example policies wired through the generic `harness policy intercept`\n# engine, so no external shell scripts under ~/.claude/hooks/ are required.\n#\n# What you still need on PATH (the wizard offers to `npm i -g` these on\n# init): agent-tasks-mcp-bridge, grounding-mcp, memory-router-*,\n# understanding-gate-claude-*. Optional add-on: a local codebase-oracle\n# MCP server (see comment under tools.mcp below).\n\nversion: 1\n\ngrounding:\n session:\n auto_start: true\n id_format: \"gs-{repo}-{rand:8}\"\n evidence_ledger:\n path: ~/.evidence-ledger/ledger.db\n retention_days: 90\n policies_source: ~/.claude/harness.d/policies/claim-gate.yaml\n\ntools:\n mcp:\n # codebase-oracle (the Pandora RAG MCP server) is intentionally NOT\n # in this default. The npm name `codebase-oracle` is already taken\n # by an unrelated CLI, and the Pandora variant is not yet published\n # under a non-colliding scope. Operators who run from a local\n # checkout can add it back with (note: `harness add` splits the\n # command on commas, not whitespace):\n # harness add mcp codebase-oracle \\\n # --command 'npx,tsx,~/git/pandora/codebase-oracle/src/mcp-server.ts'\n - name: agent-tasks\n # Zero-setup entry: `@agent-tasks/mcp-bridge` exposes the\n # `agent-tasks-mcp-bridge` binary on PATH. The bridge owns token\n # storage and defaults to the hosted backend; override with\n # `AGENT_TASKS_BASE_URL` / `AGENT_TASKS_TOKEN` for self-hosted.\n command: [agent-tasks-mcp-bridge]\n health:\n verb: projects_list\n timeout_ms: 5000\n enabled: true\n - name: grounding-mcp\n # Published bin from `@lannguyensi/grounding-mcp`. No env is set:\n # the bundled default resolves to `~/.evidence-ledger/ledger.db`\n # via os.homedir() at startup. Passing a literal tilde in env\n # bypasses shell expansion and creates rogue cwd-relative DB files\n # (see agent-tasks/42d224a6 incident).\n command: [grounding-mcp]\n health:\n verb: ledger_status\n timeout_ms: 5000\n enabled: true\n\n cli:\n - name: gh\n binary: gh\n required: true\n\n skills:\n enabled:\n - simplify\n - init\n - review\n - security-review\n source_dirs:\n - ~/.claude/skills\n\n builtin:\n known: [Read, Edit, Write, Bash, Agent, Skill, TaskCreate, Glob, Grep]\n\nmemory:\n directories:\n - path: ~/.claude/projects/{project}/memory\n scope: project\n router:\n # Published bin from `@lannguyensi/memory-router`.\n command: [memory-router-user-prompt-submit]\n enabled: true\n retention:\n staleness_days: 180\n broken_refs: warn\n scopes:\n default: project\n allowed: [project, user]\n\n# All PreToolUse hooks share the generic `harness policy intercept` CLI\n# entrypoint. The engine reads the tool event on stdin, evaluates whichever\n# policy below has a matching trigger (`match` + optional `bash_match`),\n# and emits Claude Code's deny envelope when the required ledger tag is\n# absent. No external shell scripts are required.\n#\n# Operators who want a SessionStart producer that writes `preflight:${REPO}`\n# (so the `preflight-before-investigation` policy unblocks) need an\n# agent-preflight-style runner; the bundled `harness session-start preflight`\n# builtin is on the roadmap (agent-tasks follow-up). Until then, supply your\n# own `~/.claude/hooks/git-preflight.sh` and add an entry here.\nhooks:\n - name: require-review-evidence\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\n - name: require-dogfood-evidence\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*(npm publish\\b|git( -C \\S+)* tag v)'\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\n - name: require-preflight-evidence\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* (status|log|diff|branch)\\b'\n command: harness policy intercept\n blocking: hard\n budget_ms: 1000\n\n - name: require-review-subagent-evidence\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_create\"\n command: harness policy intercept\n blocking: hard\n budget_ms: 2000\n\n - name: require-preflight-push-evidence\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* push\\b'\n command: harness policy intercept\n blocking: hard\n budget_ms: 1000\n\npolicies:\n - name: review-before-merge\n description: Block PR merges unless a ledger entry tagged review:<pr-number> exists for this session.\n trigger:\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_merge\"\n extract:\n PR_NUMBER: \"toolArgs.prNumber\"\n requires:\n ledger_tag: \"review:${PR_NUMBER}\"\n hook: require-review-evidence\n enforcement: block\n\n - name: dogfood-before-release\n description: Block npm publish / git tag v* without a recent dogfood ledger entry.\n trigger:\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*(npm publish\\b|git( -C \\S+)* tag v)'\n requires:\n ledger_tag: \"dogfood:${SESSION_ID}\"\n within: 24h\n hook: require-dogfood-evidence\n enforcement: block\n\n - name: preflight-before-investigation\n description: Block investigative git reads (status/log/diff/branch) when agent-preflight has not run recently with ready:true for the current repo.\n trigger:\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* (status|log|diff|branch)\\b'\n requires:\n ledger_tag: \"preflight:${REPO}\"\n within: 1h\n hook: require-preflight-evidence\n enforcement: block\n\n - name: review-subagent-before-pr-create\n description: Block agent-tasks PR creation unless a review-subagent ledger entry tagged for this task already exists. Forces the rigorous review BEFORE the PR opens, not after.\n trigger:\n event: PreToolUse\n match: \"mcp__agent-tasks__pull_requests_create\"\n extract:\n TASK_ID: \"toolArgs.taskId\"\n requires:\n ledger_tag: \"review-subagent:${TASK_ID}\"\n hook: require-review-subagent-evidence\n enforcement: block\n\n - name: preflight-before-push\n description: Block git push unless a fresh preflight ledger entry exists for the current branch. Catches the stale-checkout class of incident at the last reversible step.\n trigger:\n event: PreToolUse\n match: \"Bash\"\n bash_match: '(^|\\n|;|\\||&&|\\()\\s*(\\w+=\\S+\\s+)*git( -C \\S+)* push\\b'\n requires:\n ledger_tag: \"preflight:${BRANCH}\"\n within: 10m\n hook: require-preflight-push-evidence\n enforcement: block\n\n# Full inherits the Solo/Team understanding-gate stack: the Stop hook\n# persists each Understanding Report and the PreToolUse pre-tool-use\n# blocker refuses Edit/Write/Bash until the report is approved. Drop\n# this block if you want the reference policies above without the\n# baseline gate.\npolicy_packs:\n - name: understanding-before-execution\n source: builtin\n enabled: true\n description: Force agents to expose their task interpretation and wait for explicit human approval before any write-capable tool fires.\n config:\n mode: grill_me\n";
|
|
3
3
|
export type TemplateName = "minimal" | "full" | "solo" | "team";
|
|
4
4
|
export declare function getTemplate(name: TemplateName): string;
|