@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.
Files changed (43) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +17 -1
  3. package/dist/cli/doctor/format.js +24 -0
  4. package/dist/cli/doctor/format.js.map +1 -1
  5. package/dist/cli/doctor/index.d.ts +7 -0
  6. package/dist/cli/doctor/index.js +10 -0
  7. package/dist/cli/doctor/index.js.map +1 -1
  8. package/dist/cli/doctor/rogue-ledger.d.ts +25 -0
  9. package/dist/cli/doctor/rogue-ledger.js +106 -0
  10. package/dist/cli/doctor/rogue-ledger.js.map +1 -0
  11. package/dist/cli/doctor/types.d.ts +10 -1
  12. package/dist/cli/doctor/types.js.map +1 -1
  13. package/dist/cli/index.js +177 -0
  14. package/dist/cli/index.js.map +1 -1
  15. package/dist/cli/pack/hook-branch-protection.d.ts +30 -0
  16. package/dist/cli/pack/hook-branch-protection.js +279 -0
  17. package/dist/cli/pack/hook-branch-protection.js.map +1 -0
  18. package/dist/cli/pack/hook-codex-pre-tool-use.js +3 -1
  19. package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
  20. package/dist/cli/pack/hook-pre-tool-use.js +7 -2
  21. package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
  22. package/dist/cli/pack/understanding-report-schema-hint.d.ts +13 -0
  23. package/dist/cli/pack/understanding-report-schema-hint.js +54 -0
  24. package/dist/cli/pack/understanding-report-schema-hint.js.map +1 -0
  25. package/dist/cli/session-start/branch-check.d.ts +44 -0
  26. package/dist/cli/session-start/branch-check.js +165 -0
  27. package/dist/cli/session-start/branch-check.js.map +1 -0
  28. package/dist/cli/uninstall/index.d.ts +68 -0
  29. package/dist/cli/uninstall/index.js +586 -0
  30. package/dist/cli/uninstall/index.js.map +1 -0
  31. package/dist/cli/uninstall/snapshot.d.ts +40 -0
  32. package/dist/cli/uninstall/snapshot.js +34 -0
  33. package/dist/cli/uninstall/snapshot.js.map +1 -0
  34. package/dist/policy-packs/builtin/branch-protection-runtime.d.ts +47 -0
  35. package/dist/policy-packs/builtin/branch-protection-runtime.js +92 -0
  36. package/dist/policy-packs/builtin/branch-protection-runtime.js.map +1 -0
  37. package/dist/policy-packs/builtin/branch-protection.d.ts +9 -0
  38. package/dist/policy-packs/builtin/branch-protection.js +146 -0
  39. package/dist/policy-packs/builtin/branch-protection.js.map +1 -0
  40. package/dist/policy-packs/registry.d.ts +1 -1
  41. package/dist/policy-packs/registry.js +10 -3
  42. package/dist/policy-packs/registry.js.map +1 -1
  43. 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;