@lannguyensi/harness 0.15.0 → 0.16.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 +22 -0
- package/README.md +17 -1
- package/dist/cli/doctor/format.js +24 -0
- package/dist/cli/doctor/format.js.map +1 -1
- package/dist/cli/doctor/index.d.ts +7 -0
- package/dist/cli/doctor/index.js +10 -0
- package/dist/cli/doctor/index.js.map +1 -1
- package/dist/cli/doctor/rogue-ledger.d.ts +25 -0
- package/dist/cli/doctor/rogue-ledger.js +106 -0
- package/dist/cli/doctor/rogue-ledger.js.map +1 -0
- package/dist/cli/doctor/types.d.ts +10 -1
- package/dist/cli/doctor/types.js.map +1 -1
- package/dist/cli/index.js +177 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/pack/hook-branch-protection.d.ts +30 -0
- package/dist/cli/pack/hook-branch-protection.js +279 -0
- package/dist/cli/pack/hook-branch-protection.js.map +1 -0
- package/dist/cli/pack/hook-codex-pre-tool-use.js +3 -1
- package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-pre-tool-use.js +7 -2
- package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/understanding-report-schema-hint.d.ts +13 -0
- package/dist/cli/pack/understanding-report-schema-hint.js +54 -0
- package/dist/cli/pack/understanding-report-schema-hint.js.map +1 -0
- package/dist/cli/session-start/branch-check.d.ts +44 -0
- package/dist/cli/session-start/branch-check.js +165 -0
- package/dist/cli/session-start/branch-check.js.map +1 -0
- package/dist/cli/uninstall/index.d.ts +68 -0
- package/dist/cli/uninstall/index.js +586 -0
- package/dist/cli/uninstall/index.js.map +1 -0
- package/dist/cli/uninstall/snapshot.d.ts +40 -0
- package/dist/cli/uninstall/snapshot.js +34 -0
- package/dist/cli/uninstall/snapshot.js.map +1 -0
- package/dist/policy-packs/builtin/branch-protection-runtime.d.ts +47 -0
- package/dist/policy-packs/builtin/branch-protection-runtime.js +92 -0
- package/dist/policy-packs/builtin/branch-protection-runtime.js.map +1 -0
- package/dist/policy-packs/builtin/branch-protection.d.ts +9 -0
- package/dist/policy-packs/builtin/branch-protection.js +146 -0
- package/dist/policy-packs/builtin/branch-protection.js.map +1 -0
- package/dist/policy-packs/registry.d.ts +1 -1
- package/dist/policy-packs/registry.js +10 -3
- package/dist/policy-packs/registry.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// `harness session-start branch-check` — SessionStart hook entrypoint
|
|
2
|
+
// for the `branch-protection` policy pack.
|
|
3
|
+
//
|
|
4
|
+
// Reads `.git/HEAD` for the cwd and, when the current branch is NOT in
|
|
5
|
+
// the operator's protected list, writes a `branch:non-protected:<branch>`
|
|
6
|
+
// fact to the evidence ledger so the pack's PreToolUse blocker has a
|
|
7
|
+
// fresh tag to satisfy its 5-minute freshness window.
|
|
8
|
+
//
|
|
9
|
+
// SessionStart contract: `blocking:false`. Every failure path (no git
|
|
10
|
+
// dir, manifest load fails, no grounding-mcp wired, ledger write
|
|
11
|
+
// fails) logs one line to stderr and exits 0. The only observable
|
|
12
|
+
// effect of a failure is that the blocker stays closed, which is the
|
|
13
|
+
// safe default: a session that can't prove it's NOT on a protected
|
|
14
|
+
// branch is treated as if it might be.
|
|
15
|
+
//
|
|
16
|
+
// Detached HEAD (`branch === ""`) is treated as PROTECTED: we can't
|
|
17
|
+
// audit-by-name what the agent might commit. The producer leaves the
|
|
18
|
+
// tag unwritten and stderr-notes the reason.
|
|
19
|
+
//
|
|
20
|
+
// Re-runnable on demand from the operator's `!` shell with no event
|
|
21
|
+
// JSON piped on stdin — same CLI verb, no SessionStart event needed.
|
|
22
|
+
import { addLedgerFact, resolveGitContext, } from "../../runtime/index.js";
|
|
23
|
+
import { resolveReadSessionId, } from "../../runtime/session-id.js";
|
|
24
|
+
import { DEFAULT_PROTECTED_BRANCHES, isProtectedBranch, NON_PROTECTED_TAG_PREFIX, PACK_NAME, resolveProtectedBranches, } from "../../policy-packs/builtin/branch-protection-runtime.js";
|
|
25
|
+
import { loadManifest } from "../loader.js";
|
|
26
|
+
const FALLBACK_SESSION = "default";
|
|
27
|
+
const LEDGER_SOURCE = "harness-session-start-branch-check";
|
|
28
|
+
async function readStdin(stream) {
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
let data = "";
|
|
31
|
+
stream.setEncoding("utf8");
|
|
32
|
+
stream.on("data", (chunk) => {
|
|
33
|
+
data += chunk;
|
|
34
|
+
});
|
|
35
|
+
stream.on("end", () => resolve(data));
|
|
36
|
+
stream.on("error", reject);
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
function findGroundingMcp(manifest) {
|
|
40
|
+
return manifest.tools.mcp.find((m) => m.name === "grounding-mcp") ?? null;
|
|
41
|
+
}
|
|
42
|
+
function mcpCommandList(server) {
|
|
43
|
+
return Array.isArray(server.command)
|
|
44
|
+
? server.command
|
|
45
|
+
: server.command.trim().split(/\s+/);
|
|
46
|
+
}
|
|
47
|
+
export async function runSessionStartBranchCheck(opts = {}) {
|
|
48
|
+
const stdin = opts.stdin ?? process.stdin;
|
|
49
|
+
const stderr = opts.stderr ?? process.stderr;
|
|
50
|
+
const note = (msg) => {
|
|
51
|
+
stderr.write(`harness session-start branch-check: ${msg}\n`);
|
|
52
|
+
};
|
|
53
|
+
const done = (wrote, branch, isProtected, sessionId, sessionSource, reason) => ({
|
|
54
|
+
exitCode: 0,
|
|
55
|
+
wrote,
|
|
56
|
+
branch,
|
|
57
|
+
protected: isProtected,
|
|
58
|
+
sessionId,
|
|
59
|
+
sessionSource,
|
|
60
|
+
...(reason !== undefined && { reason }),
|
|
61
|
+
});
|
|
62
|
+
let event;
|
|
63
|
+
try {
|
|
64
|
+
event = JSON.parse((await readStdin(stdin)).trim() || "{}");
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
const reason = `malformed event JSON: ${err.message}`;
|
|
68
|
+
note(reason);
|
|
69
|
+
return done(false, "", false, FALLBACK_SESSION, "default", reason);
|
|
70
|
+
}
|
|
71
|
+
const cwd = typeof opts.cwd === "string" && opts.cwd.length > 0
|
|
72
|
+
? opts.cwd
|
|
73
|
+
: typeof event.cwd === "string" && event.cwd.length > 0
|
|
74
|
+
? event.cwd
|
|
75
|
+
: process.cwd();
|
|
76
|
+
const { branch } = resolveGitContext(cwd);
|
|
77
|
+
// Load manifest to resolve the pack's protected_branches override.
|
|
78
|
+
// Fallback to defaults on any load failure (the producer's job is
|
|
79
|
+
// best-effort; an unresolvable manifest still permits a sane gate).
|
|
80
|
+
let manifest = null;
|
|
81
|
+
if (opts.manifest) {
|
|
82
|
+
manifest = opts.manifest;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
try {
|
|
86
|
+
manifest = loadManifest(opts).manifest;
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
note(`manifest load failed: ${err.message}; falling back to default protected list`);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
const pack = manifest?.policy_packs.find((p) => p.name === PACK_NAME);
|
|
93
|
+
const { branches: protectedList, warning: protectedWarning } = pack
|
|
94
|
+
? resolveProtectedBranches(pack)
|
|
95
|
+
: { branches: [...DEFAULT_PROTECTED_BRANCHES], warning: null };
|
|
96
|
+
if (protectedWarning)
|
|
97
|
+
note(protectedWarning);
|
|
98
|
+
// Resolve session id with the same precedence chain as
|
|
99
|
+
// session-start/preflight so the two producers stay symmetric.
|
|
100
|
+
const explicit = typeof opts.session === "string" && opts.session.length > 0
|
|
101
|
+
? opts.session
|
|
102
|
+
: typeof event.session_id === "string" && event.session_id.length > 0
|
|
103
|
+
? event.session_id
|
|
104
|
+
: undefined;
|
|
105
|
+
const resolveSession = opts.resolveSession ?? resolveReadSessionId;
|
|
106
|
+
const sessionId = resolveSession(explicit, {});
|
|
107
|
+
const sessionSource = typeof opts.session === "string" && opts.session.length > 0
|
|
108
|
+
? "flag"
|
|
109
|
+
: typeof event.session_id === "string" && event.session_id.length > 0
|
|
110
|
+
? "stdin"
|
|
111
|
+
: sessionId === FALLBACK_SESSION
|
|
112
|
+
? "default"
|
|
113
|
+
: typeof process.env.CLAUDE_SESSION_ID === "string" &&
|
|
114
|
+
process.env.CLAUDE_SESSION_ID === sessionId
|
|
115
|
+
? "env"
|
|
116
|
+
: "transcript";
|
|
117
|
+
if (branch === "") {
|
|
118
|
+
const reason = `cwd is not on a named branch (detached HEAD or outside a git work tree); leaving the gate closed (treated as protected)`;
|
|
119
|
+
note(reason);
|
|
120
|
+
return done(false, "", true, sessionId, sessionSource, reason);
|
|
121
|
+
}
|
|
122
|
+
const isProtected = isProtectedBranch(branch, protectedList);
|
|
123
|
+
if (isProtected) {
|
|
124
|
+
const reason = `branch "${branch}" is in the protected list (${protectedList.join(", ")}); leaving the gate closed`;
|
|
125
|
+
note(reason);
|
|
126
|
+
return done(false, branch, true, sessionId, sessionSource, reason);
|
|
127
|
+
}
|
|
128
|
+
// Branch is non-protected: write the tag.
|
|
129
|
+
const content = `${NON_PROTECTED_TAG_PREFIX}:${branch}`;
|
|
130
|
+
let writeLedger = opts.writeLedger;
|
|
131
|
+
if (!writeLedger) {
|
|
132
|
+
if (!manifest) {
|
|
133
|
+
const reason = `manifest unavailable; cannot record ${content}`;
|
|
134
|
+
note(reason);
|
|
135
|
+
return done(false, branch, false, sessionId, sessionSource, reason);
|
|
136
|
+
}
|
|
137
|
+
const server = findGroundingMcp(manifest);
|
|
138
|
+
if (!server) {
|
|
139
|
+
const reason = `grounding-mcp not declared in manifest; cannot record ${content}`;
|
|
140
|
+
note(reason);
|
|
141
|
+
return done(false, branch, false, sessionId, sessionSource, reason);
|
|
142
|
+
}
|
|
143
|
+
const command = mcpCommandList(server);
|
|
144
|
+
const env = server.env ?? undefined;
|
|
145
|
+
const timeoutMs = opts.ledgerTimeoutMs ?? server.health?.timeout_ms ?? 5_000;
|
|
146
|
+
writeLedger = (args) => addLedgerFact({
|
|
147
|
+
mcpCommand: command,
|
|
148
|
+
...(env && { mcpEnv: env }),
|
|
149
|
+
timeoutMs,
|
|
150
|
+
...args,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
const result = await writeLedger({ sessionId, content, source: LEDGER_SOURCE });
|
|
154
|
+
if (!result.ok) {
|
|
155
|
+
const reason = `ledger write failed: ${result.reason ?? "unknown error"}`;
|
|
156
|
+
note(reason);
|
|
157
|
+
return done(false, branch, false, sessionId, sessionSource, reason);
|
|
158
|
+
}
|
|
159
|
+
note(`recorded ${content} for session ${sessionId}`);
|
|
160
|
+
if (sessionSource === "default") {
|
|
161
|
+
note("WARNING: session resolved to the literal \"default\". The blocker queries the real Claude Code session id and will NOT see this tag. Pipe SessionStart event JSON on stdin, export $CLAUDE_SESSION_ID, or pass --session <id>.");
|
|
162
|
+
}
|
|
163
|
+
return done(true, branch, false, sessionId, sessionSource);
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=branch-check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"branch-check.js","sourceRoot":"","sources":["../../../src/cli/session-start/branch-check.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export declare class UninstallError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
export interface UninstallOptions {
|
|
5
|
+
/** Override for `~/.claude/`. Falls back to `os.homedir()/.claude`. */
|
|
6
|
+
homeDir?: string;
|
|
7
|
+
/** Override settings.json path (test injection / non-default install). */
|
|
8
|
+
settingsPath?: string;
|
|
9
|
+
/** Mutate when true; pure listing otherwise. */
|
|
10
|
+
apply?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Atomic restore from a specific backup (typically a
|
|
13
|
+
* `settings.json.pre-harness-<TS>` file). Implies `apply`; mutually
|
|
14
|
+
* exclusive with the standard selective-removal flow.
|
|
15
|
+
*/
|
|
16
|
+
restoreFrom?: string;
|
|
17
|
+
/** Override "now" for deterministic timestamps in tests. */
|
|
18
|
+
now?: Date;
|
|
19
|
+
}
|
|
20
|
+
export interface HookGroupRef {
|
|
21
|
+
event: string;
|
|
22
|
+
index: number;
|
|
23
|
+
matcher: string | null;
|
|
24
|
+
/** Short summary of the inner `hooks[].command` list for the listing UI. */
|
|
25
|
+
description: string;
|
|
26
|
+
}
|
|
27
|
+
export interface UninstallInventory {
|
|
28
|
+
/** Resolved `~/.claude/` (or override). */
|
|
29
|
+
homeDir: string;
|
|
30
|
+
/** Resolved settings.json path (or override). */
|
|
31
|
+
settingsPath: string;
|
|
32
|
+
/** `~/.claude/harness.yaml` when present, else null. */
|
|
33
|
+
manifestPath: string | null;
|
|
34
|
+
/** `~/.claude/harness.lock` when present, else null. */
|
|
35
|
+
lockPath: string | null;
|
|
36
|
+
/** `~/.claude/harness.generated/` when present, else null. */
|
|
37
|
+
generatedDir: string | null;
|
|
38
|
+
/** Harness-owned hook groups currently in settings.json. */
|
|
39
|
+
hookGroups: HookGroupRef[];
|
|
40
|
+
/** Harness-owned mcpServers keys currently in settings.json. */
|
|
41
|
+
mcpServers: string[];
|
|
42
|
+
/** Discovered `settings.json.pre-harness-*` backups in the settings directory. */
|
|
43
|
+
preHarnessBackups: string[];
|
|
44
|
+
/** Soft notices (e.g. project-local `~/.claude.json` registers grounding-mcp). */
|
|
45
|
+
warnings: string[];
|
|
46
|
+
}
|
|
47
|
+
export type UninstallResult = {
|
|
48
|
+
mode: "list";
|
|
49
|
+
inventory: UninstallInventory;
|
|
50
|
+
} | {
|
|
51
|
+
mode: "apply";
|
|
52
|
+
inventory: UninstallInventory;
|
|
53
|
+
/** Backup path (null when settings.json had nothing to remove). */
|
|
54
|
+
backupPath: string | null;
|
|
55
|
+
/** Snapshot path (null when no settings.json mutation was needed). */
|
|
56
|
+
snapshotPath: string | null;
|
|
57
|
+
/** Filesystem entries removed from disk (manifest, lock, generated dir). */
|
|
58
|
+
removedFiles: string[];
|
|
59
|
+
} | {
|
|
60
|
+
mode: "restore";
|
|
61
|
+
inventory: UninstallInventory;
|
|
62
|
+
restoredFrom: string;
|
|
63
|
+
backupPath: string;
|
|
64
|
+
snapshotPath: string;
|
|
65
|
+
/** Filesystem entries removed from disk (manifest, lock, generated dir). */
|
|
66
|
+
removedFiles: string[];
|
|
67
|
+
};
|
|
68
|
+
export declare function uninstall(opts?: UninstallOptions): UninstallResult;
|