@lannguyensi/harness 0.21.1 → 0.22.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 +20 -0
- package/dist/cli/index.js +90 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/pack/hook-branch-protection.js +13 -0
- package/dist/cli/pack/hook-branch-protection.js.map +1 -1
- package/dist/cli/pack/hook-codex-pre-tool-use.js +15 -0
- package/dist/cli/pack/hook-codex-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-post-tool-use.js +15 -0
- package/dist/cli/pack/hook-post-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-pre-tool-use.js +22 -0
- package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
- package/dist/cli/pack/hook-track-active-claim.js +14 -0
- package/dist/cli/pack/hook-track-active-claim.js.map +1 -1
- package/dist/cli/pack/pause-check.d.ts +22 -0
- package/dist/cli/pack/pause-check.js +51 -0
- package/dist/cli/pack/pause-check.js.map +1 -0
- package/dist/cli/pause/index.d.ts +99 -0
- package/dist/cli/pause/index.js +218 -0
- package/dist/cli/pause/index.js.map +1 -0
- package/dist/runtime/pause-sentinel.d.ts +60 -0
- package/dist/runtime/pause-sentinel.js +145 -0
- package/dist/runtime/pause-sentinel.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export declare const SENTINEL_BASENAME = ".harness-paused";
|
|
2
|
+
export interface PauseSentinel {
|
|
3
|
+
/** ISO-8601 of when `harness pause` ran. */
|
|
4
|
+
pausedAt: string;
|
|
5
|
+
/** ISO-8601 expiry, or null for `--indefinite`. */
|
|
6
|
+
expiresAt: string | null;
|
|
7
|
+
/** Operator-supplied reason, or null when none was passed. */
|
|
8
|
+
reason: string | null;
|
|
9
|
+
/** Caller identity recorded by the CLI (host/user). */
|
|
10
|
+
pausedBy: string | null;
|
|
11
|
+
}
|
|
12
|
+
export declare function sentinelPath(generatedDir: string): string;
|
|
13
|
+
export type ReadSentinelResult = {
|
|
14
|
+
kind: "absent";
|
|
15
|
+
} | {
|
|
16
|
+
kind: "active";
|
|
17
|
+
sentinel: PauseSentinel;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "expired";
|
|
20
|
+
sentinel: PauseSentinel;
|
|
21
|
+
};
|
|
22
|
+
export declare function readSentinel(generatedDir: string, now?: Date): ReadSentinelResult;
|
|
23
|
+
export declare function writeSentinel(generatedDir: string, sentinel: PauseSentinel): void;
|
|
24
|
+
/** Returns true when a sentinel existed and was removed. */
|
|
25
|
+
export declare function deleteSentinel(generatedDir: string): boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Format a short human-readable relative offset between `from` (the past
|
|
28
|
+
* anchor for "since X ago") or `to` (the future anchor for "in X") and
|
|
29
|
+
* `now`. Always rounds toward 1 so a near-boundary value never reads "0s".
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatRelative(targetIso: string, now: Date): string;
|
|
32
|
+
export interface AnnouncePauseOptions {
|
|
33
|
+
/** Already-resolved generatedDir. Required: hooks resolve this themselves. */
|
|
34
|
+
generatedDir: string;
|
|
35
|
+
/** Override "now" for tests. */
|
|
36
|
+
now?: Date;
|
|
37
|
+
/** Where to write the notice line. Defaults to process.stderr. */
|
|
38
|
+
stderr?: NodeJS.WritableStream;
|
|
39
|
+
/**
|
|
40
|
+
* Hook label inserted into the notice line so an operator scanning a
|
|
41
|
+
* busy stderr can tell which hook fire emitted it. Defaults to a
|
|
42
|
+
* generic "hook" tag.
|
|
43
|
+
*/
|
|
44
|
+
hookLabel?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Hook integration helper. One call from each PreToolUse / PostToolUse
|
|
48
|
+
* hook covers:
|
|
49
|
+
* - active sentinel → emit one stderr line; caller exits 0 (allow).
|
|
50
|
+
* - expired sentinel → silently delete (auto-resume); caller proceeds.
|
|
51
|
+
* - absent sentinel → no-op; caller proceeds.
|
|
52
|
+
*
|
|
53
|
+
* The boolean `paused` return tells the caller whether to short-circuit.
|
|
54
|
+
* Any I/O error in the sentinel read degrades to `paused: false` rather
|
|
55
|
+
* than blocking: a broken state file is a debug nuisance, not a reason
|
|
56
|
+
* to silently freeze the whole session.
|
|
57
|
+
*/
|
|
58
|
+
export declare function maybeAnnouncePause(opts: AnnouncePauseOptions): {
|
|
59
|
+
paused: boolean;
|
|
60
|
+
};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// harness pause/resume sentinel — temporary hook bypass for operator-only
|
|
2
|
+
// recovery, debug, and incident-mode flows.
|
|
3
|
+
//
|
|
4
|
+
// The whole feature is one JSON file at `<generatedDir>/.harness-paused`.
|
|
5
|
+
// While it exists and has not expired, every PreToolUse / PostToolUse hook
|
|
6
|
+
// emits a one-line stderr notice and short-circuits to allow instead of
|
|
7
|
+
// evaluating its normal gate logic. On the first hook fire AFTER expiry,
|
|
8
|
+
// the sentinel is silently deleted (auto-resume) and evaluation resumes.
|
|
9
|
+
//
|
|
10
|
+
// Source-of-truth split:
|
|
11
|
+
// - Hook enforcement reads the sentinel file. Stat() on a known path —
|
|
12
|
+
// no per-call grounding-mcp roundtrip.
|
|
13
|
+
// - Audit trail goes to the evidence ledger via `harness pause` and
|
|
14
|
+
// `harness resume`. The ledger is queryable history; the sentinel is
|
|
15
|
+
// ephemeral state.
|
|
16
|
+
//
|
|
17
|
+
// Operator-only design: the `harness pause` verb refuses to run inside an
|
|
18
|
+
// agent shell (where `$CLAUDE_SESSION_ID` is set) and refuses non-TTY
|
|
19
|
+
// stdin without an explicit `--i-am-the-operator` acknowledgement. This
|
|
20
|
+
// is the load-bearing guardrail against pause becoming an agent bypass.
|
|
21
|
+
import * as fs from "node:fs";
|
|
22
|
+
import * as path from "node:path";
|
|
23
|
+
import { atomicWriteFile } from "../io/atomic-write.js";
|
|
24
|
+
export const SENTINEL_BASENAME = ".harness-paused";
|
|
25
|
+
export function sentinelPath(generatedDir) {
|
|
26
|
+
return path.join(generatedDir, SENTINEL_BASENAME);
|
|
27
|
+
}
|
|
28
|
+
export function readSentinel(generatedDir, now = new Date()) {
|
|
29
|
+
let raw;
|
|
30
|
+
try {
|
|
31
|
+
raw = fs.readFileSync(sentinelPath(generatedDir), "utf8");
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
return { kind: "absent" };
|
|
35
|
+
}
|
|
36
|
+
let sentinel;
|
|
37
|
+
try {
|
|
38
|
+
sentinel = normalizeSentinel(JSON.parse(raw));
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
// A malformed sentinel file is treated as absent: a broken state file
|
|
42
|
+
// must never escalate into a session-wide block. The `harness pause`
|
|
43
|
+
// verb only ever writes well-formed JSON, so this branch is reserved
|
|
44
|
+
// for operator-corrupted files.
|
|
45
|
+
return { kind: "absent" };
|
|
46
|
+
}
|
|
47
|
+
if (sentinel.expiresAt === null)
|
|
48
|
+
return { kind: "active", sentinel };
|
|
49
|
+
const expires = Date.parse(sentinel.expiresAt);
|
|
50
|
+
if (!Number.isFinite(expires))
|
|
51
|
+
return { kind: "active", sentinel };
|
|
52
|
+
if (expires <= now.getTime())
|
|
53
|
+
return { kind: "expired", sentinel };
|
|
54
|
+
return { kind: "active", sentinel };
|
|
55
|
+
}
|
|
56
|
+
function normalizeSentinel(raw) {
|
|
57
|
+
const pausedAt = typeof raw["pausedAt"] === "string" ? raw["pausedAt"] : "";
|
|
58
|
+
if (pausedAt === "")
|
|
59
|
+
throw new Error("missing pausedAt");
|
|
60
|
+
// expiresAt must be either an explicit null (indefinite) or a non-empty
|
|
61
|
+
// string. A typed-wrong value (e.g. number 42) is rejected as malformed
|
|
62
|
+
// rather than silently downgraded to indefinite — without this, a forged
|
|
63
|
+
// sentinel of `{"pausedAt":"...","expiresAt":42}` would read as a no-
|
|
64
|
+
// auto-resume pause that survives every hook fire.
|
|
65
|
+
const expiresAtRaw = raw["expiresAt"];
|
|
66
|
+
let expiresAt;
|
|
67
|
+
if (expiresAtRaw === null || expiresAtRaw === undefined) {
|
|
68
|
+
expiresAt = null;
|
|
69
|
+
}
|
|
70
|
+
else if (typeof expiresAtRaw === "string" && expiresAtRaw.length > 0) {
|
|
71
|
+
expiresAt = expiresAtRaw;
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
throw new Error("expiresAt must be a non-empty ISO string or null");
|
|
75
|
+
}
|
|
76
|
+
const reason = typeof raw["reason"] === "string" ? raw["reason"] : null;
|
|
77
|
+
const pausedBy = typeof raw["pausedBy"] === "string" ? raw["pausedBy"] : null;
|
|
78
|
+
return { pausedAt, expiresAt, reason, pausedBy };
|
|
79
|
+
}
|
|
80
|
+
export function writeSentinel(generatedDir, sentinel) {
|
|
81
|
+
atomicWriteFile(sentinelPath(generatedDir), `${JSON.stringify(sentinel, null, 2)}\n`);
|
|
82
|
+
}
|
|
83
|
+
/** Returns true when a sentinel existed and was removed. */
|
|
84
|
+
export function deleteSentinel(generatedDir) {
|
|
85
|
+
try {
|
|
86
|
+
fs.rmSync(sentinelPath(generatedDir));
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Format a short human-readable relative offset between `from` (the past
|
|
95
|
+
* anchor for "since X ago") or `to` (the future anchor for "in X") and
|
|
96
|
+
* `now`. Always rounds toward 1 so a near-boundary value never reads "0s".
|
|
97
|
+
*/
|
|
98
|
+
export function formatRelative(targetIso, now) {
|
|
99
|
+
const target = Date.parse(targetIso);
|
|
100
|
+
if (!Number.isFinite(target))
|
|
101
|
+
return "?";
|
|
102
|
+
const abs = Math.max(1, Math.round(Math.abs(target - now.getTime()) / 1000));
|
|
103
|
+
if (abs < 90)
|
|
104
|
+
return `${abs}s`;
|
|
105
|
+
const mins = Math.round(abs / 60);
|
|
106
|
+
if (mins < 90)
|
|
107
|
+
return `${mins}m`;
|
|
108
|
+
const hrs = Math.round(mins / 60);
|
|
109
|
+
if (hrs < 36)
|
|
110
|
+
return `${hrs}h`;
|
|
111
|
+
const days = Math.round(hrs / 24);
|
|
112
|
+
return `${days}d`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Hook integration helper. One call from each PreToolUse / PostToolUse
|
|
116
|
+
* hook covers:
|
|
117
|
+
* - active sentinel → emit one stderr line; caller exits 0 (allow).
|
|
118
|
+
* - expired sentinel → silently delete (auto-resume); caller proceeds.
|
|
119
|
+
* - absent sentinel → no-op; caller proceeds.
|
|
120
|
+
*
|
|
121
|
+
* The boolean `paused` return tells the caller whether to short-circuit.
|
|
122
|
+
* Any I/O error in the sentinel read degrades to `paused: false` rather
|
|
123
|
+
* than blocking: a broken state file is a debug nuisance, not a reason
|
|
124
|
+
* to silently freeze the whole session.
|
|
125
|
+
*/
|
|
126
|
+
export function maybeAnnouncePause(opts) {
|
|
127
|
+
const now = opts.now ?? new Date();
|
|
128
|
+
const stderr = opts.stderr ?? process.stderr;
|
|
129
|
+
const hookLabel = opts.hookLabel ?? "hook";
|
|
130
|
+
const result = readSentinel(opts.generatedDir, now);
|
|
131
|
+
if (result.kind === "absent")
|
|
132
|
+
return { paused: false };
|
|
133
|
+
if (result.kind === "expired") {
|
|
134
|
+
deleteSentinel(opts.generatedDir);
|
|
135
|
+
return { paused: false };
|
|
136
|
+
}
|
|
137
|
+
const reason = result.sentinel.reason ?? "(no reason given)";
|
|
138
|
+
const since = formatRelative(result.sentinel.pausedAt, now);
|
|
139
|
+
const remaining = result.sentinel.expiresAt === null
|
|
140
|
+
? "indefinite (no auto-resume)"
|
|
141
|
+
: `auto-resumes in ${formatRelative(result.sentinel.expiresAt, now)}`;
|
|
142
|
+
stderr.write(`harness ${hookLabel}: PAUSED since ${since} ago (reason: ${reason}); ${remaining}. Run \`harness resume\` to re-enable.\n`);
|
|
143
|
+
return { paused: true };
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=pause-sentinel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pause-sentinel.js","sourceRoot":"","sources":["../../src/runtime/pause-sentinel.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lannguyensi/harness",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Declarative control plane for agent harnesses — one YAML for grounding, tools, memory, and hooks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/LanNguyenSi/harness",
|