agent-sanitizer 2.66.6 → 2.67.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/README.md +26 -18
- package/bin/sanitize-cli.mjs +5 -7
- package/claude-hooks/lib/authored-content.mjs +25 -25
- package/claude-hooks/lib/env-config.mjs +3 -3
- package/claude-hooks/lib/hook-io.mjs +4 -12
- package/claude-hooks/lib/placeholder-grammar.mjs +7 -12
- package/claude-hooks/lib/redactor-client.mjs +2 -2
- package/claude-hooks/lib/secret-annotate.mjs +1 -1
- package/claude-hooks/pretooluse-sanitize.mjs +10 -14
- package/claude-hooks/scan-invisible-chars.mjs +6 -35
- package/package.json +1 -1
- package/src/claude-context.mjs +22 -0
- package/src/credential-names.mjs +14 -20
- package/src/err-message.mjs +21 -0
- package/src/file-write-tools.mjs +96 -0
- package/src/gates.mjs +32 -5
- package/src/instructions.mjs +54 -56
- package/src/output.mjs +1 -12
- package/src/rehydrate.mjs +39 -41
- package/types/claude-context.d.mts +17 -0
- package/types/claude-hooks/lib/authored-content.d.mts +4 -4
- package/types/claude-hooks/lib/hook-io.d.mts +2 -8
- package/types/claude-hooks/lib/placeholder-grammar.d.mts +0 -1
- package/types/claude-hooks/pretooluse-sanitize.d.mts +6 -2
- package/types/credential-names.d.mts +5 -4
- package/types/err-message.d.mts +16 -0
- package/types/file-write-tools.d.mts +64 -0
- package/types/gates.d.mts +1 -15
- package/types/instructions.d.mts +25 -16
- package/types/src/claude-context.d.mts +17 -0
- package/types/src/err-message.d.mts +16 -0
- package/types/src/file-write-tools.d.mts +64 -0
- package/types/src/instructions.d.mts +25 -16
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when `tool` is one of {@link FILE_WRITE_TOOLS}.
|
|
3
|
+
* @param {unknown} tool
|
|
4
|
+
* @returns {boolean}
|
|
5
|
+
*/
|
|
6
|
+
export function isFileWriteTool(tool: unknown): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* A field spec, parsed: `{ key }` for a top-level field, or `{ arr, sub }` for
|
|
9
|
+
* `sub` on every element of the array at `arr`.
|
|
10
|
+
* @param {string} spec
|
|
11
|
+
* @returns {{ key: string } | { arr: string, sub: string }}
|
|
12
|
+
*/
|
|
13
|
+
export function parseFieldSpec(spec: string): {
|
|
14
|
+
key: string;
|
|
15
|
+
} | {
|
|
16
|
+
arr: string;
|
|
17
|
+
sub: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Every value the field `spec` addresses in `input`: one for a top-level
|
|
21
|
+
* field, one per array element for a nested one. `null` when the array a
|
|
22
|
+
* nested spec names is absent, not an array, or empty.
|
|
23
|
+
* @param {string} spec
|
|
24
|
+
* @param {any} input
|
|
25
|
+
* @returns {unknown[] | null}
|
|
26
|
+
*/
|
|
27
|
+
export function fieldValues(spec: string, input: any): unknown[] | null;
|
|
28
|
+
/**
|
|
29
|
+
* The file-editing tools whose input fields are the bytes persisted to disk, as
|
|
30
|
+
* ONE table, and the reader for the field specs it holds.
|
|
31
|
+
*
|
|
32
|
+
* PROBLEM CLASS — the set of file-writing tools restated per consumer. The
|
|
33
|
+
* fault carve-out that refuses a placeholder-bearing write, the advisories that
|
|
34
|
+
* stay silent on rehydrated tools, the authored-content sanitizer and the
|
|
35
|
+
* rehydration layer each kept their own list. A tool added to one list (a new
|
|
36
|
+
* write-shaped tool, or a renamed field) left the others silently stale, which
|
|
37
|
+
* is a placeholder persisted over a secret on disk. Every consumer reads this
|
|
38
|
+
* table instead.
|
|
39
|
+
*
|
|
40
|
+
* Package-free and dependency-free by construction: the PreToolUse fault path
|
|
41
|
+
* imports it relatively and must work exactly when the agent-sanitizer package
|
|
42
|
+
* failed to load.
|
|
43
|
+
*
|
|
44
|
+
* Each entry:
|
|
45
|
+
* - `authored` — the fields the model writes, which Layer 3 sanitizes.
|
|
46
|
+
* - `placeholders` — every field a redaction placeholder can sit in.
|
|
47
|
+
* - `rehydrates` — whether the rehydration layer re-anchors the call onto
|
|
48
|
+
* disk bytes (`false`: it refuses a placeholder-bearing call instead).
|
|
49
|
+
*
|
|
50
|
+
* A field spec is `key`, or `key[].sub` for `sub` on every element of the
|
|
51
|
+
* array at `key` (MultiEdit batches its writes as `edits[]`).
|
|
52
|
+
*/
|
|
53
|
+
/** @typedef {{ authored: readonly string[], placeholders: readonly string[], rehydrates: boolean }} FileWriteTool */
|
|
54
|
+
/**
|
|
55
|
+
* Null-prototype: the tool name comes from an untrusted payload, and on a plain
|
|
56
|
+
* object literal `TABLE["constructor"]` answers a truthy inherited value.
|
|
57
|
+
* @type {Readonly<Record<string, FileWriteTool>>}
|
|
58
|
+
*/
|
|
59
|
+
export const FILE_WRITE_TOOLS: Readonly<Record<string, FileWriteTool>>;
|
|
60
|
+
export type FileWriteTool = {
|
|
61
|
+
authored: readonly string[];
|
|
62
|
+
placeholders: readonly string[];
|
|
63
|
+
rehydrates: boolean;
|
|
64
|
+
};
|
package/types/gates.d.mts
CHANGED
|
@@ -30,7 +30,7 @@ export function needsUrlScan(text: string): boolean;
|
|
|
30
30
|
*/
|
|
31
31
|
export function isHtmlShaped(text: string): boolean;
|
|
32
32
|
/**
|
|
33
|
-
* True when
|
|
33
|
+
* True when any pre-gate arm shape-matches `text`, or the same text
|
|
34
34
|
* with every `\n` removed (the view the engine's `_redact_cross_line` scans, so
|
|
35
35
|
* this stays a superset of the redactor). Two literals OR'd so neither grows
|
|
36
36
|
* into a polynomial-backtracking shape (see SECRET_HINT).
|
|
@@ -38,20 +38,6 @@ export function isHtmlShaped(text: string): boolean;
|
|
|
38
38
|
* @returns {boolean}
|
|
39
39
|
*/
|
|
40
40
|
export function matchesSecretHint(text: string): boolean;
|
|
41
|
-
/**
|
|
42
|
-
* Cheap, dependency-free pre-gates shared by the HTML layer (Layers 2 & 3) and
|
|
43
|
-
* re-exported from both the package root and the `./html` subpath.
|
|
44
|
-
*
|
|
45
|
-
* These are pulled out of `html.mjs` so the package root can re-export them
|
|
46
|
-
* without dragging in the heavy remark/rehype/unified graph: a static
|
|
47
|
-
* `export … from "./html.mjs"` would eagerly evaluate that ~200ms module on
|
|
48
|
-
* every root import, defeating the lazy-load design. This module imports
|
|
49
|
-
* nothing, so re-exporting it is free.
|
|
50
|
-
*
|
|
51
|
-
* INVARIANT: every gate is a SUPERSET of its parser (a narrower one silently
|
|
52
|
-
* turns its layer off; a needless fire only costs a parse), checked by
|
|
53
|
-
* test/gates-superset.test.mjs.
|
|
54
|
-
*/
|
|
55
41
|
/**
|
|
56
42
|
* Matches every point where the HTML tokenizer leaves the data state: `<` then
|
|
57
43
|
* an ASCII letter, `/`, `!` or `?`. No closing `>` on purpose: a comment holding
|
package/types/instructions.d.mts
CHANGED
|
@@ -55,14 +55,12 @@ export function walkContextGlobs(globs: string[], cwd: string, exclude?: (entry:
|
|
|
55
55
|
* Expand `globs` (relative to `cwd`) to absolute file paths, skipping
|
|
56
56
|
* `node_modules`. The glob set is the caller's instruction-file convention.
|
|
57
57
|
*
|
|
58
|
-
* Containment is enforced per match (see {@link
|
|
59
|
-
* glob pattern itself escapes `cwd` — via `..` or an absolute-path glob
|
|
58
|
+
* Containment is enforced per match (see {@link assertContained}): a match
|
|
59
|
+
* whose glob pattern itself escapes `cwd` — via `..` or an absolute-path glob
|
|
60
60
|
* outside the tree — THROWS, since reaching outside the tree is a caller
|
|
61
|
-
* misconfiguration. A match that lexically stays inside `cwd`
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* tree), is SKIPPED, so one bad symlink never aborts scanning the rest of the
|
|
65
|
-
* project.
|
|
61
|
+
* misconfiguration. A match that lexically stays inside `cwd` is RETURNED even
|
|
62
|
+
* when an in-tree symlink resolves it outside the tree or to nothing, so the
|
|
63
|
+
* reader decides what an unreadable one means.
|
|
66
64
|
*
|
|
67
65
|
* `exclude` prunes the walk via {@link walkContextGlobs}, so it is handed one
|
|
68
66
|
* root-relative, `/`-separated path per entry. It is composed with, never
|
|
@@ -78,21 +76,32 @@ export function findInstructionFiles(globs: string[], { cwd, exclude }?: {
|
|
|
78
76
|
exclude?: (entry: string) => boolean;
|
|
79
77
|
}): string[];
|
|
80
78
|
/**
|
|
81
|
-
* Scan every instruction file matched by `globs`
|
|
82
|
-
* findings
|
|
83
|
-
*
|
|
79
|
+
* Scan every instruction file matched by `globs`. `findings` lists only the
|
|
80
|
+
* files with findings; `skipped` lists every file that exists but could not be
|
|
81
|
+
* read, so a caller never reports an unread file as clean. A missing file
|
|
82
|
+
* (ENOENT, a dangling symlink) is in neither: no bytes of it can load. Paths
|
|
83
|
+
* are relative to `cwd`. Pure scan — no mutation; pair with {@link cleanFile}.
|
|
84
84
|
* @param {string[]} globs
|
|
85
85
|
* @param {{ cwd?: string, exclude?: (entry: string) => boolean }} [options]
|
|
86
86
|
* `exclude` is forwarded to {@link findInstructionFiles}
|
|
87
|
-
* @returns {
|
|
87
|
+
* @returns {{
|
|
88
|
+
* findings: Array<{ file: string, findings: ReturnType<typeof scanText> }>,
|
|
89
|
+
* skipped: Array<{ file: string, reason: string }>,
|
|
90
|
+
* }}
|
|
88
91
|
*/
|
|
89
92
|
export function scanInstructionFiles(globs: string[], { cwd, exclude }?: {
|
|
90
93
|
cwd?: string;
|
|
91
94
|
exclude?: (entry: string) => boolean;
|
|
92
|
-
}):
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
}): {
|
|
96
|
+
findings: Array<{
|
|
97
|
+
file: string;
|
|
98
|
+
findings: ReturnType<typeof scanText>;
|
|
99
|
+
}>;
|
|
100
|
+
skipped: Array<{
|
|
101
|
+
file: string;
|
|
102
|
+
reason: string;
|
|
103
|
+
}>;
|
|
104
|
+
};
|
|
96
105
|
/**
|
|
97
106
|
* Strip payload-capable invisible characters from `absPath` in place. Returns
|
|
98
107
|
* `true` when the file's bytes actually changed (a payload {@link scanText}
|
|
@@ -151,4 +160,4 @@ export function cleanFile(absPath: string, { root, lstat }?: {
|
|
|
151
160
|
lstat?: (path: string) => import("node:fs").Stats;
|
|
152
161
|
}): boolean;
|
|
153
162
|
export { contextScanExclude } from "./repo-scope.mjs";
|
|
154
|
-
export { ancestorInstructionFiles, announcedByInstructionsLoaded, CLAUDE_CONTEXT_KINDS, CLAUDE_CONTEXT_SUBDIRS, CLAUDE_DIR_INSTRUCTION_FILES, CLAUDE_INSTRUCTION_GLOBS, CLAUDE_LAUNCH_GLOBS, CLAUDE_MEMORY_FILES, contextScopeContradiction, excludeFromContextScan, USER_GLOBAL_EVENT_NAMED_GLOBS } from "./claude-context.mjs";
|
|
163
|
+
export { ancestorInstructionFiles, announcedByInstructionsLoaded, CLAUDE_CONTEXT_KINDS, CLAUDE_CONTEXT_SUBDIRS, CLAUDE_DIR_INSTRUCTION_FILES, CLAUDE_INSTRUCTION_GLOBS, CLAUDE_LAUNCH_GLOBS, CLAUDE_MEMORY_FILES, classifyReadFailure, contextScopeContradiction, excludeFromContextScan, USER_GLOBAL_EVENT_NAMED_GLOBS } from "./claude-context.mjs";
|
|
@@ -37,6 +37,23 @@ export function isInsideDir(dir: string, file: string): boolean;
|
|
|
37
37
|
* @returns {string}
|
|
38
38
|
*/
|
|
39
39
|
export function displayUntrusted(text: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* PROBLEM CLASS — how a failed instruction-file read is classified. Every
|
|
42
|
+
* scanner reads this one bucketing; nothing re-derives it from an errno.
|
|
43
|
+
*
|
|
44
|
+
* A read failure is never swallowed into an empty findings list — that turns
|
|
45
|
+
* "we could not read this file" into "this file is fine". Three buckets:
|
|
46
|
+
*
|
|
47
|
+
* - SKIPPED — the file exists and this uid cannot read it (EACCES, EISDIR,
|
|
48
|
+
* ELOOP…). Unvetted context, which the caller must report.
|
|
49
|
+
* - ABSENT — ENOENT. The path resolves to nothing, and the host loads
|
|
50
|
+
* instruction files through the same open, so no bytes can reach the model.
|
|
51
|
+
* - THROWN — no errno at all, i.e. a bug. Nothing can be trusted, so the
|
|
52
|
+
* error propagates to the caller's failure posture.
|
|
53
|
+
* @param {unknown} err
|
|
54
|
+
* @returns {"absent" | "skipped"} never returns for a non-errno throw
|
|
55
|
+
*/
|
|
56
|
+
export function classifyReadFailure(err: unknown): "absent" | "skipped";
|
|
40
57
|
/**
|
|
41
58
|
* The one directory no instruction-file walk ever descends into. Its own
|
|
42
59
|
* function so the name is spelled once, and so the two predicates that need it
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The message of a caught value, which is `unknown` under strict mode.
|
|
3
|
+
*
|
|
4
|
+
* PROBLEM CLASS — rendering a caught error as text. The library's warnings and
|
|
5
|
+
* every hook's failure reason read this one definition, so a wrapped failure
|
|
6
|
+
* reads "outer: root" everywhere rather than "outer" in some copies.
|
|
7
|
+
* Dependency-free: the hooks import it relatively and must keep it when the
|
|
8
|
+
* agent-sanitizer package failed to load.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Message from a caught value, with one level of cause chain appended when the
|
|
12
|
+
* cause is itself an Error.
|
|
13
|
+
* @param {unknown} err
|
|
14
|
+
* @returns {string}
|
|
15
|
+
*/
|
|
16
|
+
export function errMessage(err: unknown): string;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when `tool` is one of {@link FILE_WRITE_TOOLS}.
|
|
3
|
+
* @param {unknown} tool
|
|
4
|
+
* @returns {boolean}
|
|
5
|
+
*/
|
|
6
|
+
export function isFileWriteTool(tool: unknown): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* A field spec, parsed: `{ key }` for a top-level field, or `{ arr, sub }` for
|
|
9
|
+
* `sub` on every element of the array at `arr`.
|
|
10
|
+
* @param {string} spec
|
|
11
|
+
* @returns {{ key: string } | { arr: string, sub: string }}
|
|
12
|
+
*/
|
|
13
|
+
export function parseFieldSpec(spec: string): {
|
|
14
|
+
key: string;
|
|
15
|
+
} | {
|
|
16
|
+
arr: string;
|
|
17
|
+
sub: string;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Every value the field `spec` addresses in `input`: one for a top-level
|
|
21
|
+
* field, one per array element for a nested one. `null` when the array a
|
|
22
|
+
* nested spec names is absent, not an array, or empty.
|
|
23
|
+
* @param {string} spec
|
|
24
|
+
* @param {any} input
|
|
25
|
+
* @returns {unknown[] | null}
|
|
26
|
+
*/
|
|
27
|
+
export function fieldValues(spec: string, input: any): unknown[] | null;
|
|
28
|
+
/**
|
|
29
|
+
* The file-editing tools whose input fields are the bytes persisted to disk, as
|
|
30
|
+
* ONE table, and the reader for the field specs it holds.
|
|
31
|
+
*
|
|
32
|
+
* PROBLEM CLASS — the set of file-writing tools restated per consumer. The
|
|
33
|
+
* fault carve-out that refuses a placeholder-bearing write, the advisories that
|
|
34
|
+
* stay silent on rehydrated tools, the authored-content sanitizer and the
|
|
35
|
+
* rehydration layer each kept their own list. A tool added to one list (a new
|
|
36
|
+
* write-shaped tool, or a renamed field) left the others silently stale, which
|
|
37
|
+
* is a placeholder persisted over a secret on disk. Every consumer reads this
|
|
38
|
+
* table instead.
|
|
39
|
+
*
|
|
40
|
+
* Package-free and dependency-free by construction: the PreToolUse fault path
|
|
41
|
+
* imports it relatively and must work exactly when the agent-sanitizer package
|
|
42
|
+
* failed to load.
|
|
43
|
+
*
|
|
44
|
+
* Each entry:
|
|
45
|
+
* - `authored` — the fields the model writes, which Layer 3 sanitizes.
|
|
46
|
+
* - `placeholders` — every field a redaction placeholder can sit in.
|
|
47
|
+
* - `rehydrates` — whether the rehydration layer re-anchors the call onto
|
|
48
|
+
* disk bytes (`false`: it refuses a placeholder-bearing call instead).
|
|
49
|
+
*
|
|
50
|
+
* A field spec is `key`, or `key[].sub` for `sub` on every element of the
|
|
51
|
+
* array at `key` (MultiEdit batches its writes as `edits[]`).
|
|
52
|
+
*/
|
|
53
|
+
/** @typedef {{ authored: readonly string[], placeholders: readonly string[], rehydrates: boolean }} FileWriteTool */
|
|
54
|
+
/**
|
|
55
|
+
* Null-prototype: the tool name comes from an untrusted payload, and on a plain
|
|
56
|
+
* object literal `TABLE["constructor"]` answers a truthy inherited value.
|
|
57
|
+
* @type {Readonly<Record<string, FileWriteTool>>}
|
|
58
|
+
*/
|
|
59
|
+
export const FILE_WRITE_TOOLS: Readonly<Record<string, FileWriteTool>>;
|
|
60
|
+
export type FileWriteTool = {
|
|
61
|
+
authored: readonly string[];
|
|
62
|
+
placeholders: readonly string[];
|
|
63
|
+
rehydrates: boolean;
|
|
64
|
+
};
|
|
@@ -55,14 +55,12 @@ export function walkContextGlobs(globs: string[], cwd: string, exclude?: (entry:
|
|
|
55
55
|
* Expand `globs` (relative to `cwd`) to absolute file paths, skipping
|
|
56
56
|
* `node_modules`. The glob set is the caller's instruction-file convention.
|
|
57
57
|
*
|
|
58
|
-
* Containment is enforced per match (see {@link
|
|
59
|
-
* glob pattern itself escapes `cwd` — via `..` or an absolute-path glob
|
|
58
|
+
* Containment is enforced per match (see {@link assertContained}): a match
|
|
59
|
+
* whose glob pattern itself escapes `cwd` — via `..` or an absolute-path glob
|
|
60
60
|
* outside the tree — THROWS, since reaching outside the tree is a caller
|
|
61
|
-
* misconfiguration. A match that lexically stays inside `cwd`
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
* tree), is SKIPPED, so one bad symlink never aborts scanning the rest of the
|
|
65
|
-
* project.
|
|
61
|
+
* misconfiguration. A match that lexically stays inside `cwd` is RETURNED even
|
|
62
|
+
* when an in-tree symlink resolves it outside the tree or to nothing, so the
|
|
63
|
+
* reader decides what an unreadable one means.
|
|
66
64
|
*
|
|
67
65
|
* `exclude` prunes the walk via {@link walkContextGlobs}, so it is handed one
|
|
68
66
|
* root-relative, `/`-separated path per entry. It is composed with, never
|
|
@@ -78,21 +76,32 @@ export function findInstructionFiles(globs: string[], { cwd, exclude }?: {
|
|
|
78
76
|
exclude?: (entry: string) => boolean;
|
|
79
77
|
}): string[];
|
|
80
78
|
/**
|
|
81
|
-
* Scan every instruction file matched by `globs`
|
|
82
|
-
* findings
|
|
83
|
-
*
|
|
79
|
+
* Scan every instruction file matched by `globs`. `findings` lists only the
|
|
80
|
+
* files with findings; `skipped` lists every file that exists but could not be
|
|
81
|
+
* read, so a caller never reports an unread file as clean. A missing file
|
|
82
|
+
* (ENOENT, a dangling symlink) is in neither: no bytes of it can load. Paths
|
|
83
|
+
* are relative to `cwd`. Pure scan — no mutation; pair with {@link cleanFile}.
|
|
84
84
|
* @param {string[]} globs
|
|
85
85
|
* @param {{ cwd?: string, exclude?: (entry: string) => boolean }} [options]
|
|
86
86
|
* `exclude` is forwarded to {@link findInstructionFiles}
|
|
87
|
-
* @returns {
|
|
87
|
+
* @returns {{
|
|
88
|
+
* findings: Array<{ file: string, findings: ReturnType<typeof scanText> }>,
|
|
89
|
+
* skipped: Array<{ file: string, reason: string }>,
|
|
90
|
+
* }}
|
|
88
91
|
*/
|
|
89
92
|
export function scanInstructionFiles(globs: string[], { cwd, exclude }?: {
|
|
90
93
|
cwd?: string;
|
|
91
94
|
exclude?: (entry: string) => boolean;
|
|
92
|
-
}):
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
}): {
|
|
96
|
+
findings: Array<{
|
|
97
|
+
file: string;
|
|
98
|
+
findings: ReturnType<typeof scanText>;
|
|
99
|
+
}>;
|
|
100
|
+
skipped: Array<{
|
|
101
|
+
file: string;
|
|
102
|
+
reason: string;
|
|
103
|
+
}>;
|
|
104
|
+
};
|
|
96
105
|
/**
|
|
97
106
|
* Strip payload-capable invisible characters from `absPath` in place. Returns
|
|
98
107
|
* `true` when the file's bytes actually changed (a payload {@link scanText}
|
|
@@ -151,4 +160,4 @@ export function cleanFile(absPath: string, { root, lstat }?: {
|
|
|
151
160
|
lstat?: (path: string) => import("node:fs").Stats;
|
|
152
161
|
}): boolean;
|
|
153
162
|
export { contextScanExclude } from "./repo-scope.mjs";
|
|
154
|
-
export { ancestorInstructionFiles, announcedByInstructionsLoaded, CLAUDE_CONTEXT_KINDS, CLAUDE_CONTEXT_SUBDIRS, CLAUDE_DIR_INSTRUCTION_FILES, CLAUDE_INSTRUCTION_GLOBS, CLAUDE_LAUNCH_GLOBS, CLAUDE_MEMORY_FILES, contextScopeContradiction, excludeFromContextScan, USER_GLOBAL_EVENT_NAMED_GLOBS } from "./claude-context.mjs";
|
|
163
|
+
export { ancestorInstructionFiles, announcedByInstructionsLoaded, CLAUDE_CONTEXT_KINDS, CLAUDE_CONTEXT_SUBDIRS, CLAUDE_DIR_INSTRUCTION_FILES, CLAUDE_INSTRUCTION_GLOBS, CLAUDE_LAUNCH_GLOBS, CLAUDE_MEMORY_FILES, classifyReadFailure, contextScopeContradiction, excludeFromContextScan, USER_GLOBAL_EVENT_NAMED_GLOBS } from "./claude-context.mjs";
|