@lannguyensi/harness 0.10.1 → 0.11.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 +78 -7
- package/README.md +1 -1
- package/dist/cli/approve/understanding.d.ts +8 -0
- package/dist/cli/approve/understanding.js +56 -7
- package/dist/cli/approve/understanding.js.map +1 -1
- package/dist/cli/audit.d.ts +8 -0
- package/dist/cli/audit.js +2 -2
- package/dist/cli/audit.js.map +1 -1
- package/dist/cli/doctor/format.js +7 -1
- package/dist/cli/doctor/format.js.map +1 -1
- package/dist/cli/doctor/index.js +62 -5
- package/dist/cli/doctor/index.js.map +1 -1
- package/dist/cli/doctor/types.d.ts +15 -0
- package/dist/cli/dry-run.js +9 -3
- package/dist/cli/dry-run.js.map +1 -1
- package/dist/cli/explain.d.ts +8 -0
- package/dist/cli/explain.js +6 -4
- package/dist/cli/explain.js.map +1 -1
- package/dist/cli/index.js +40 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/dependencies.js +17 -7
- package/dist/cli/init/dependencies.js.map +1 -1
- package/dist/cli/init/templates.d.ts +1 -1
- package/dist/cli/init/templates.js +14 -5
- package/dist/cli/init/templates.js.map +1 -1
- package/dist/cli/pack/hook-pre-tool-use.d.ts +2 -0
- package/dist/cli/pack/hook-pre-tool-use.js +34 -2
- package/dist/cli/pack/hook-pre-tool-use.js.map +1 -1
- package/dist/cli/policy/intercept.d.ts +7 -1
- package/dist/cli/policy/intercept.js +28 -6
- package/dist/cli/policy/intercept.js.map +1 -1
- package/dist/cli/session-start/index.d.ts +52 -0
- package/dist/cli/session-start/index.js +195 -0
- package/dist/cli/session-start/index.js.map +1 -0
- package/dist/runtime/git-context.d.ts +16 -0
- package/dist/runtime/git-context.js +97 -0
- package/dist/runtime/git-context.js.map +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/index.js.map +1 -1
- package/dist/runtime/pending-approval.d.ts +31 -0
- package/dist/runtime/pending-approval.js +80 -0
- package/dist/runtime/pending-approval.js.map +1 -0
- package/dist/runtime/session-id.d.ts +40 -1
- package/dist/runtime/session-id.js +99 -8
- package/dist/runtime/session-id.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-approval.js","sourceRoot":"","sources":["../../src/runtime/pending-approval.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,EAAE;AACF,qEAAqE;AACrE,sEAAsE;AACtE,4EAA4E;AAC5E,sEAAsE;AACtE,uEAAuE;AACvE,oEAAoE;AACpE,EAAE;AACF,yEAAyE;AACzE,gEAAgE;AAChE,0EAA0E;AAC1E,4EAA4E;AAC5E,eAAe;AACf,EAAE;AACF,0EAA0E;AAC1E,wEAAwE;AACxE,qEAAqE;AACrE,wDAAwD;AAExD,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,yEAAyE;AACzE,oEAAoE;AACpE,sEAAsE;AACtE,oBAAoB;AACpB,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AAErD,MAAM,CAAC,MAAM,yBAAyB,GAAG,mBAAmB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAGnC;IACC,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,iBAAiB,CAAC,CAAC;IAClF,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,iBAAiB,CAAC,CAAC;AACvE,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,yBAAyB,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,YAAoB,EAAE,SAAiB;IAC1E,eAAe,CAAC,mBAAmB,CAAC,YAAY,CAAC,EAAE,GAAG,SAAS,IAAI,CAAC,CAAC;AACvE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,mBAAmB,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC;IACnE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAC3B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,YAAoB;IACvD,IAAI,CAAC;QACH,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,YAAY,CAAC,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,2DAA2D;IAC7D,CAAC;AACH,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Resolve the active grounding session id.
|
|
2
|
+
* Resolve the active grounding session id (WRITE path).
|
|
3
3
|
*
|
|
4
4
|
* Empty strings are treated as "not provided" — both for the explicit
|
|
5
5
|
* argument and for the env var, since `--session ''` from a forgetful
|
|
@@ -8,3 +8,42 @@
|
|
|
8
8
|
* empty session.
|
|
9
9
|
*/
|
|
10
10
|
export declare function resolveSessionId(explicit?: string): string;
|
|
11
|
+
export interface DiscoverSessionOptions {
|
|
12
|
+
/** Override the Claude Code projects root (tests). */
|
|
13
|
+
projectsRoot?: string;
|
|
14
|
+
/** Override `$HOME` used to derive the projects root (tests). */
|
|
15
|
+
homeDir?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Discover the current Claude Code session id from the most recently
|
|
19
|
+
* modified transcript JSONL under `~/.claude/projects/<project>/`.
|
|
20
|
+
*
|
|
21
|
+
* Claude Code appends to the active session's transcript live, so the
|
|
22
|
+
* newest-mtime `<uuid>.jsonl` across all project dirs is the running
|
|
23
|
+
* session. Returns `null` when the projects root is absent or holds no
|
|
24
|
+
* transcript files — callers fall through to their own default.
|
|
25
|
+
*/
|
|
26
|
+
export declare function discoverNewestSessionId(opts?: DiscoverSessionOptions): string | null;
|
|
27
|
+
export interface ResolveReadSessionOptions extends DiscoverSessionOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Test seam — override the transcript-discovery tier wholesale. The
|
|
30
|
+
* default scans the real `~/.claude/projects` via
|
|
31
|
+
* `discoverNewestSessionId`.
|
|
32
|
+
*/
|
|
33
|
+
discover?: (opts: DiscoverSessionOptions) => string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the session id for the READ path (`audit`,
|
|
37
|
+
* `explain --trace/--last`).
|
|
38
|
+
*
|
|
39
|
+
* Precedence:
|
|
40
|
+
* 1. explicit value (the `--session` flag)
|
|
41
|
+
* 2. `$CLAUDE_SESSION_ID` env
|
|
42
|
+
* 3. newest Claude Code transcript (the live session)
|
|
43
|
+
* 4. literal `"default"`
|
|
44
|
+
*
|
|
45
|
+
* The WRITE path keeps `resolveSessionId`: it always has
|
|
46
|
+
* `event.session_id`, so it never reaches the discovery tier, and a
|
|
47
|
+
* per-hook-event filesystem scan would be wasteful.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveReadSessionId(explicit?: string, opts?: ResolveReadSessionOptions): string;
|
|
@@ -9,16 +9,28 @@
|
|
|
9
9
|
// audit/trace even though the writes had landed correctly under the
|
|
10
10
|
// real UUID.
|
|
11
11
|
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
// 3. literal `"default"`
|
|
18
|
-
//
|
|
12
|
+
// `resolveSessionId` lifts the precedence chain into one place for the
|
|
13
|
+
// WRITE path (`policy intercept`), which always carries a concrete
|
|
14
|
+
// `event.session_id`:
|
|
15
|
+
// 1. explicit value (the runtime's `event.session_id`)
|
|
16
|
+
// 2. `$CLAUDE_SESSION_ID` env
|
|
17
|
+
// 3. literal `"default"`
|
|
18
|
+
//
|
|
19
|
+
// The READ path (`audit`, `explain --trace/--last`) needs more. The
|
|
20
|
+
// Phase 5 #2 fix assumed `$CLAUDE_SESSION_ID` is exported into the
|
|
21
|
+
// session's shell environment — it is not (Claude Code does not put it
|
|
22
|
+
// in the Bash tool env), so tier 2 is inert in practice and the readers
|
|
23
|
+
// still fell through to `"default"`. `resolveReadSessionId` adds a
|
|
24
|
+
// transcript-discovery tier: when no explicit id and no env, it reads
|
|
25
|
+
// the active session id off the newest Claude Code transcript JSONL.
|
|
26
|
+
// That is the programmatic form of the heuristic `harness approve`'s
|
|
27
|
+
// own help text recommends to humans.
|
|
28
|
+
import * as fs from "node:fs";
|
|
29
|
+
import * as os from "node:os";
|
|
30
|
+
import * as path from "node:path";
|
|
19
31
|
const FALLBACK = "default";
|
|
20
32
|
/**
|
|
21
|
-
* Resolve the active grounding session id.
|
|
33
|
+
* Resolve the active grounding session id (WRITE path).
|
|
22
34
|
*
|
|
23
35
|
* Empty strings are treated as "not provided" — both for the explicit
|
|
24
36
|
* argument and for the env var, since `--session ''` from a forgetful
|
|
@@ -34,4 +46,83 @@ export function resolveSessionId(explicit) {
|
|
|
34
46
|
return env;
|
|
35
47
|
return FALLBACK;
|
|
36
48
|
}
|
|
49
|
+
// Claude Code names each session's transcript `<uuid>.jsonl`. Anchored
|
|
50
|
+
// so sibling files (memory dirs, `.pending-approval`, etc.) are ignored.
|
|
51
|
+
const SESSION_TRANSCRIPT_RE = /^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})\.jsonl$/i;
|
|
52
|
+
/**
|
|
53
|
+
* Discover the current Claude Code session id from the most recently
|
|
54
|
+
* modified transcript JSONL under `~/.claude/projects/<project>/`.
|
|
55
|
+
*
|
|
56
|
+
* Claude Code appends to the active session's transcript live, so the
|
|
57
|
+
* newest-mtime `<uuid>.jsonl` across all project dirs is the running
|
|
58
|
+
* session. Returns `null` when the projects root is absent or holds no
|
|
59
|
+
* transcript files — callers fall through to their own default.
|
|
60
|
+
*/
|
|
61
|
+
export function discoverNewestSessionId(opts = {}) {
|
|
62
|
+
const projectsRoot = opts.projectsRoot ??
|
|
63
|
+
path.join(opts.homeDir ?? os.homedir(), ".claude", "projects");
|
|
64
|
+
let projectDirs;
|
|
65
|
+
try {
|
|
66
|
+
projectDirs = fs.readdirSync(projectsRoot);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
let newest = null;
|
|
72
|
+
for (const dir of projectDirs) {
|
|
73
|
+
const projectPath = path.join(projectsRoot, dir);
|
|
74
|
+
let files;
|
|
75
|
+
try {
|
|
76
|
+
files = fs.readdirSync(projectPath);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
continue; // not a directory, or unreadable — skip
|
|
80
|
+
}
|
|
81
|
+
for (const file of files) {
|
|
82
|
+
const match = SESSION_TRANSCRIPT_RE.exec(file);
|
|
83
|
+
if (!match)
|
|
84
|
+
continue;
|
|
85
|
+
let mtimeMs;
|
|
86
|
+
try {
|
|
87
|
+
mtimeMs = fs.statSync(path.join(projectPath, file)).mtimeMs;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (newest === null || mtimeMs > newest.mtimeMs) {
|
|
93
|
+
newest = { id: match[1], mtimeMs };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return newest === null ? null : newest.id;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Resolve the session id for the READ path (`audit`,
|
|
101
|
+
* `explain --trace/--last`).
|
|
102
|
+
*
|
|
103
|
+
* Precedence:
|
|
104
|
+
* 1. explicit value (the `--session` flag)
|
|
105
|
+
* 2. `$CLAUDE_SESSION_ID` env
|
|
106
|
+
* 3. newest Claude Code transcript (the live session)
|
|
107
|
+
* 4. literal `"default"`
|
|
108
|
+
*
|
|
109
|
+
* The WRITE path keeps `resolveSessionId`: it always has
|
|
110
|
+
* `event.session_id`, so it never reaches the discovery tier, and a
|
|
111
|
+
* per-hook-event filesystem scan would be wasteful.
|
|
112
|
+
*/
|
|
113
|
+
export function resolveReadSessionId(explicit, opts = {}) {
|
|
114
|
+
if (typeof explicit === "string" && explicit.length > 0)
|
|
115
|
+
return explicit;
|
|
116
|
+
const env = process.env.CLAUDE_SESSION_ID;
|
|
117
|
+
if (typeof env === "string" && env.length > 0)
|
|
118
|
+
return env;
|
|
119
|
+
const discover = opts.discover ?? discoverNewestSessionId;
|
|
120
|
+
const discovered = discover({
|
|
121
|
+
...(opts.projectsRoot !== undefined && { projectsRoot: opts.projectsRoot }),
|
|
122
|
+
...(opts.homeDir !== undefined && { homeDir: opts.homeDir }),
|
|
123
|
+
});
|
|
124
|
+
if (typeof discovered === "string" && discovered.length > 0)
|
|
125
|
+
return discovered;
|
|
126
|
+
return FALLBACK;
|
|
127
|
+
}
|
|
37
128
|
//# sourceMappingURL=session-id.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-id.js","sourceRoot":"","sources":["../../src/runtime/session-id.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,EAAE;AACF,uEAAuE;AACvE,iEAAiE;AACjE,qEAAqE;AACrE,8DAA8D;AAC9D,wEAAwE;AACxE,iEAAiE;AACjE,oEAAoE;AACpE,aAAa;AACb,EAAE;AACF,yDAAyD;AACzD,
|
|
1
|
+
{"version":3,"file":"session-id.js","sourceRoot":"","sources":["../../src/runtime/session-id.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.11.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",
|