@code-yeongyu/senpi-agent-core 2026.9.15 → 2026.9.16

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 (40) hide show
  1. package/dist/empty-assistant-recovery.d.ts.map +1 -1
  2. package/dist/empty-assistant-recovery.js +51 -12
  3. package/dist/empty-assistant-recovery.js.map +1 -1
  4. package/dist/harness/tools/read.d.ts +3 -0
  5. package/dist/harness/tools/read.d.ts.map +1 -1
  6. package/dist/harness/tools/read.js +18 -3
  7. package/dist/harness/tools/read.js.map +1 -1
  8. package/dist/harness/utils/read-folders/brace-scanner.d.ts +4 -0
  9. package/dist/harness/utils/read-folders/brace-scanner.d.ts.map +1 -0
  10. package/dist/harness/utils/read-folders/brace-scanner.js +268 -0
  11. package/dist/harness/utils/read-folders/brace-scanner.js.map +1 -0
  12. package/dist/harness/utils/read-folders/header-protection.d.ts +18 -0
  13. package/dist/harness/utils/read-folders/header-protection.d.ts.map +1 -0
  14. package/dist/harness/utils/read-folders/header-protection.js +69 -0
  15. package/dist/harness/utils/read-folders/header-protection.js.map +1 -0
  16. package/dist/harness/utils/read-folders/index.d.ts +27 -0
  17. package/dist/harness/utils/read-folders/index.d.ts.map +1 -0
  18. package/dist/harness/utils/read-folders/index.js +118 -0
  19. package/dist/harness/utils/read-folders/index.js.map +1 -0
  20. package/dist/harness/utils/read-folders/lexical-context.d.ts +21 -0
  21. package/dist/harness/utils/read-folders/lexical-context.d.ts.map +1 -0
  22. package/dist/harness/utils/read-folders/lexical-context.js +24 -0
  23. package/dist/harness/utils/read-folders/lexical-context.js.map +1 -0
  24. package/dist/harness/utils/read-folders/lexical-spans.d.ts +12 -0
  25. package/dist/harness/utils/read-folders/lexical-spans.d.ts.map +1 -0
  26. package/dist/harness/utils/read-folders/lexical-spans.js +92 -0
  27. package/dist/harness/utils/read-folders/lexical-spans.js.map +1 -0
  28. package/dist/harness/utils/read-folders/types.d.ts +47 -0
  29. package/dist/harness/utils/read-folders/types.d.ts.map +1 -0
  30. package/dist/harness/utils/read-folders/types.js +8 -0
  31. package/dist/harness/utils/read-folders/types.js.map +1 -0
  32. package/dist/harness/utils/segmented-read-view.d.ts +52 -0
  33. package/dist/harness/utils/segmented-read-view.d.ts.map +1 -0
  34. package/dist/harness/utils/segmented-read-view.js +155 -0
  35. package/dist/harness/utils/segmented-read-view.js.map +1 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js +2 -0
  39. package/dist/index.js.map +1 -1
  40. package/package.json +3 -3
@@ -0,0 +1,18 @@
1
+ import type { Open } from "./lexical-context.ts";
2
+ import type { ReadLineRange } from "./types.ts";
3
+ /** A lexical proof only: ambiguous headers invalidate the whole parse, not just one fold. */
4
+ export declare class HeaderProtection {
5
+ readonly intervals: ReadLineRange[];
6
+ private pending;
7
+ private target;
8
+ private parameters;
9
+ get active(): boolean;
10
+ get unfinished(): boolean;
11
+ word(word: string, previous: string, depth: number, line: number, typescript: boolean): boolean;
12
+ open(char: string, depth: number, previous: string, line: number): boolean;
13
+ close(open: Open, depth: number, line: number): void;
14
+ punctuation(token: string, depth: number, line: number): boolean;
15
+ protect(startLine: number, endLine: number): void;
16
+ filter(ranges: readonly ReadLineRange[]): ReadLineRange[];
17
+ }
18
+ //# sourceMappingURL=header-protection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header-protection.d.ts","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/header-protection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAIhD,6FAA6F;AAC7F,qBAAa,gBAAgB;IAC5B,QAAQ,CAAC,SAAS,EAAE,aAAa,EAAE,CAAM;IACzC,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,UAAU,CAAqE;IAEvF,IAAI,MAAM,IAAI,OAAO,CAEpB;IACD,IAAI,UAAU,IAAI,OAAO,CAExB;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,GAAG,OAAO,CAU9F;IAED,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQzE;IAED,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAMnD;IAED,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAY/D;IAED,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEhD;IAED,MAAM,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,GAAG,aAAa,EAAE,CAKxD;CACD"}
@@ -0,0 +1,69 @@
1
+ /** A lexical proof only: ambiguous headers invalidate the whole parse, not just one fold. */
2
+ export class HeaderProtection {
3
+ constructor() {
4
+ this.intervals = [];
5
+ }
6
+ get active() {
7
+ return this.pending !== undefined;
8
+ }
9
+ get unfinished() {
10
+ return this.pending !== undefined;
11
+ }
12
+ word(word, previous, depth, line, typescript) {
13
+ this.target = undefined;
14
+ // These operators can hide an arbitrarily shaped type before a real body.
15
+ // No TypeScript grammar is installed: do not infer a boundary from the next brace.
16
+ if (typescript && ["keyof", "typeof", "infer", "readonly", "satisfies", "as"].includes(word))
17
+ return false;
18
+ if ((word === "class" || word === "function") && previous !== ".") {
19
+ if (this.pending)
20
+ return false; // e.g. a nested class expression in heritage
21
+ this.pending = { kind: word, depth, startLine: line };
22
+ }
23
+ return true;
24
+ }
25
+ open(char, depth, previous, line) {
26
+ const header = this.pending;
27
+ if (char !== "{" || header?.depth !== depth)
28
+ return false;
29
+ if (header.kind === "function" && previous !== ")")
30
+ return false;
31
+ this.protect(header.startLine, line);
32
+ this.pending = undefined;
33
+ this.parameters = undefined;
34
+ return header.kind === "class";
35
+ }
36
+ close(open, depth, line) {
37
+ this.target = open.target ? open.line : undefined;
38
+ const startLine = open.headerLine ?? open.line;
39
+ // Every protected member context, not only a proven signature, must survive enclosing folds.
40
+ if (open.protected && (open.signature || open.char !== "("))
41
+ this.protect(startLine, line);
42
+ if (open.char === "(" && !open.call && !open.control)
43
+ this.parameters = { depth, startLine };
44
+ }
45
+ punctuation(token, depth, line) {
46
+ // A value-position array/object reaching '=' is a destructuring assignment target.
47
+ // Protecting it retrospectively rejects both its members and any enclosing body.
48
+ const target = this.target;
49
+ this.target = undefined;
50
+ if (token === "=" && target !== undefined)
51
+ this.protect(target, line);
52
+ if (token === ":" && this.parameters?.depth === depth)
53
+ return false;
54
+ if ((token === "{" || token === "=>") && this.parameters?.depth === depth) {
55
+ this.protect(this.parameters.startLine, line);
56
+ this.parameters = undefined;
57
+ }
58
+ else if (token === ";" || token === "=" || token === ",")
59
+ this.parameters = undefined;
60
+ return true;
61
+ }
62
+ protect(startLine, endLine) {
63
+ this.intervals.push({ startLine, endLine });
64
+ }
65
+ filter(ranges) {
66
+ return ranges.filter((range) => !this.intervals.some((header) => range.startLine <= header.endLine && range.endLine >= header.startLine));
67
+ }
68
+ }
69
+ //# sourceMappingURL=header-protection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header-protection.js","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/header-protection.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Open } from \"./lexical-context.ts\";\nimport type { ReadLineRange } from \"./types.ts\";\n\ntype Header = { readonly kind: \"class\" | \"function\"; readonly depth: number; readonly startLine: number };\n\n/** A lexical proof only: ambiguous headers invalidate the whole parse, not just one fold. */\nexport class HeaderProtection {\n\treadonly intervals: ReadLineRange[] = [];\n\tprivate pending: Header | undefined;\n\tprivate target: number | undefined;\n\tprivate parameters: { readonly depth: number; readonly startLine: number } | undefined;\n\n\tget active(): boolean {\n\t\treturn this.pending !== undefined;\n\t}\n\tget unfinished(): boolean {\n\t\treturn this.pending !== undefined;\n\t}\n\n\tword(word: string, previous: string, depth: number, line: number, typescript: boolean): boolean {\n\t\tthis.target = undefined;\n\t\t// These operators can hide an arbitrarily shaped type before a real body.\n\t\t// No TypeScript grammar is installed: do not infer a boundary from the next brace.\n\t\tif (typescript && [\"keyof\", \"typeof\", \"infer\", \"readonly\", \"satisfies\", \"as\"].includes(word)) return false;\n\t\tif ((word === \"class\" || word === \"function\") && previous !== \".\") {\n\t\t\tif (this.pending) return false; // e.g. a nested class expression in heritage\n\t\t\tthis.pending = { kind: word, depth, startLine: line };\n\t\t}\n\t\treturn true;\n\t}\n\n\topen(char: string, depth: number, previous: string, line: number): boolean {\n\t\tconst header = this.pending;\n\t\tif (char !== \"{\" || header?.depth !== depth) return false;\n\t\tif (header.kind === \"function\" && previous !== \")\") return false;\n\t\tthis.protect(header.startLine, line);\n\t\tthis.pending = undefined;\n\t\tthis.parameters = undefined;\n\t\treturn header.kind === \"class\";\n\t}\n\n\tclose(open: Open, depth: number, line: number): void {\n\t\tthis.target = open.target ? open.line : undefined;\n\t\tconst startLine = open.headerLine ?? open.line;\n\t\t// Every protected member context, not only a proven signature, must survive enclosing folds.\n\t\tif (open.protected && (open.signature || open.char !== \"(\")) this.protect(startLine, line);\n\t\tif (open.char === \"(\" && !open.call && !open.control) this.parameters = { depth, startLine };\n\t}\n\n\tpunctuation(token: string, depth: number, line: number): boolean {\n\t\t// A value-position array/object reaching '=' is a destructuring assignment target.\n\t\t// Protecting it retrospectively rejects both its members and any enclosing body.\n\t\tconst target = this.target;\n\t\tthis.target = undefined;\n\t\tif (token === \"=\" && target !== undefined) this.protect(target, line);\n\t\tif (token === \":\" && this.parameters?.depth === depth) return false;\n\t\tif ((token === \"{\" || token === \"=>\") && this.parameters?.depth === depth) {\n\t\t\tthis.protect(this.parameters.startLine, line);\n\t\t\tthis.parameters = undefined;\n\t\t} else if (token === \";\" || token === \"=\" || token === \",\") this.parameters = undefined;\n\t\treturn true;\n\t}\n\n\tprotect(startLine: number, endLine: number): void {\n\t\tthis.intervals.push({ startLine, endLine });\n\t}\n\n\tfilter(ranges: readonly ReadLineRange[]): ReadLineRange[] {\n\t\treturn ranges.filter(\n\t\t\t(range) =>\n\t\t\t\t!this.intervals.some((header) => range.startLine <= header.endLine && range.endLine >= header.startLine),\n\t\t);\n\t}\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import type { ReadFolder } from "./types.ts";
2
+ export * from "./types.ts";
3
+ /** Frozen row-17 selection, not a runtime registry that can enable unmeasured grammars. */
4
+ export declare const READ_FOLDER_SELECTION: Readonly<{
5
+ readonly head: "0830b8c466e1f0689fa7f6f33cb7cfcd188b5407";
6
+ readonly selectionSha256: "b10b790182c83603cdc66f7e0d3b88464456ad49a45e621aea140d9c033f13a6";
7
+ readonly wasm: false;
8
+ readonly rawReasons: Readonly<{
9
+ readonly ts: "wasm_candidate_pending_owner";
10
+ readonly js: "wasm_candidate_pending_owner";
11
+ }>;
12
+ readonly languages: Readonly<{
13
+ readonly ts: "raw";
14
+ readonly js: "raw";
15
+ readonly json: "heuristic";
16
+ readonly tsx: "unsupported";
17
+ readonly python: "unsupported";
18
+ readonly rust: "unsupported";
19
+ readonly go: "unsupported";
20
+ readonly markdown: "prose_exempt";
21
+ readonly txt: "prose_exempt";
22
+ }>;
23
+ }>;
24
+ /** Reader eligibility stays bound to the frozen selection even with a custom folder. */
25
+ export declare function isReadSummaryPath(path: string): boolean;
26
+ export declare const selectedReadFolder: ReadFolder;
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAmE,MAAM,YAAY,CAAC;AAE9G,cAAc,YAAY,CAAC;AAE3B,2FAA2F;AAC3F,eAAO,MAAM,qBAAqB;mBAC3B,0CAA0C;8BAC/B,kEAAkE;;;qBAEnD,8BAA8B;qBAAM,8BAA8B;;;qBAE7F,KAAK;qBACL,KAAK;uBACH,WAAW;sBACZ,aAAa;yBACV,aAAa;uBACf,aAAa;qBACf,aAAa;2BACP,cAAc;sBACnB,cAAc;;EAEV,CAAC;AAkCZ,wFAAwF;AACxF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAGvD;AA4DD,eAAO,MAAM,kBAAkB,EAAE,UAAwE,CAAC"}
@@ -0,0 +1,118 @@
1
+ import { scanBraces } from "./brace-scanner.js";
2
+ export * from "./types.js";
3
+ /** Frozen row-17 selection, not a runtime registry that can enable unmeasured grammars. */
4
+ export const READ_FOLDER_SELECTION = Object.freeze({
5
+ head: "0830b8c466e1f0689fa7f6f33cb7cfcd188b5407",
6
+ selectionSha256: "b10b790182c83603cdc66f7e0d3b88464456ad49a45e621aea140d9c033f13a6",
7
+ wasm: false,
8
+ rawReasons: Object.freeze({ ts: "wasm_candidate_pending_owner", js: "wasm_candidate_pending_owner" }),
9
+ languages: Object.freeze({
10
+ ts: "raw",
11
+ js: "raw",
12
+ json: "heuristic",
13
+ tsx: "unsupported",
14
+ python: "unsupported",
15
+ rust: "unsupported",
16
+ go: "unsupported",
17
+ markdown: "prose_exempt",
18
+ txt: "prose_exempt",
19
+ }),
20
+ });
21
+ function languageForPath(path) {
22
+ const name = path.split(/[\\/]/).pop()?.toLowerCase() ?? "";
23
+ if (!name.includes("."))
24
+ return undefined;
25
+ switch (name.slice(name.lastIndexOf(".") + 1)) {
26
+ case "ts":
27
+ return "ts";
28
+ case "js":
29
+ return "js";
30
+ case "json":
31
+ return "json";
32
+ case "tsx":
33
+ return "tsx";
34
+ case "py":
35
+ return "python";
36
+ case "rs":
37
+ return "rust";
38
+ case "go":
39
+ return "go";
40
+ case "md":
41
+ case "markdown":
42
+ case "mdown":
43
+ case "mkd":
44
+ case "mkdn":
45
+ return "markdown";
46
+ case "txt":
47
+ return "txt";
48
+ default:
49
+ return undefined;
50
+ }
51
+ }
52
+ /** Reader eligibility stays bound to the frozen selection even with a custom folder. */
53
+ export function isReadSummaryPath(path) {
54
+ const language = languageForPath(path);
55
+ return language !== undefined && READ_FOLDER_SELECTION.languages[language] === "heuristic";
56
+ }
57
+ function hierarchy(ranges) {
58
+ const roots = [];
59
+ const stack = [];
60
+ for (const range of [...ranges].sort((a, b) => a.startLine - b.startLine || b.endLine - a.endLine)) {
61
+ while (stack.length && range.startLine > stack[stack.length - 1].endLine)
62
+ stack.pop();
63
+ const parent = stack[stack.length - 1];
64
+ if (parent && range.startLine === parent.startLine && range.endLine === parent.endLine)
65
+ continue;
66
+ if (parent && (range.startLine <= parent.startLine || range.endLine >= parent.endLine))
67
+ return undefined;
68
+ const node = { ...range, children: [] };
69
+ (parent ? parent.children : roots).push(node);
70
+ stack.push(node);
71
+ }
72
+ return roots;
73
+ }
74
+ function fold({ path, text, settings }) {
75
+ const language = languageForPath(path);
76
+ if (!language)
77
+ return { status: "unsupported", reason: "unsupported_language" };
78
+ const engine = READ_FOLDER_SELECTION.languages[language];
79
+ switch (engine) {
80
+ case "unsupported":
81
+ return { status: "unsupported", reason: "unsupported_language" };
82
+ case "prose_exempt":
83
+ return { status: "unsupported", reason: "prose_exempt" };
84
+ case "raw": // Retain the pure candidate for safety/quality measurement, never default-read eligibility.
85
+ case "heuristic":
86
+ break;
87
+ default:
88
+ return engine;
89
+ }
90
+ // Narrow the language independently: the manifest is the sole enablement authority.
91
+ if (language !== "ts" && language !== "js" && language !== "json")
92
+ return { status: "unsupported", reason: "unsupported_language" };
93
+ if (language === "json") {
94
+ try {
95
+ JSON.parse(text);
96
+ }
97
+ catch (error) {
98
+ if (error instanceof SyntaxError)
99
+ return { status: "parse_failure", reason: "invalid_json" };
100
+ throw error;
101
+ }
102
+ }
103
+ const scan = scanBraces(text, language, settings);
104
+ switch (scan.status) {
105
+ case "parse_failure":
106
+ return scan;
107
+ case "parsed": {
108
+ const ranges = hierarchy(scan.ranges);
109
+ return ranges
110
+ ? { status: "parsed", text, ranges }
111
+ : { status: "parse_failure", reason: "ambiguous_line_boundaries" };
112
+ }
113
+ default:
114
+ return scan;
115
+ }
116
+ }
117
+ export const selectedReadFolder = Object.freeze({ id: "measured-brace", version: "3", fold });
118
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { scanBraces } from \"./brace-scanner.ts\";\nimport type { ReadFolder, ReadFolderInput, ReadFolderResult, ReadFoldRange, ReadLineRange } from \"./types.ts\";\n\nexport * from \"./types.ts\";\n\n/** Frozen row-17 selection, not a runtime registry that can enable unmeasured grammars. */\nexport const READ_FOLDER_SELECTION = Object.freeze({\n\thead: \"0830b8c466e1f0689fa7f6f33cb7cfcd188b5407\",\n\tselectionSha256: \"b10b790182c83603cdc66f7e0d3b88464456ad49a45e621aea140d9c033f13a6\",\n\twasm: false,\n\trawReasons: Object.freeze({ ts: \"wasm_candidate_pending_owner\", js: \"wasm_candidate_pending_owner\" } as const),\n\tlanguages: Object.freeze({\n\t\tts: \"raw\",\n\t\tjs: \"raw\",\n\t\tjson: \"heuristic\",\n\t\ttsx: \"unsupported\",\n\t\tpython: \"unsupported\",\n\t\trust: \"unsupported\",\n\t\tgo: \"unsupported\",\n\t\tmarkdown: \"prose_exempt\",\n\t\ttxt: \"prose_exempt\",\n\t} as const),\n} as const);\n\ntype Language = keyof typeof READ_FOLDER_SELECTION.languages;\nfunction languageForPath(path: string): Language | undefined {\n\tconst name = path.split(/[\\\\/]/).pop()?.toLowerCase() ?? \"\";\n\tif (!name.includes(\".\")) return undefined;\n\tswitch (name.slice(name.lastIndexOf(\".\") + 1)) {\n\t\tcase \"ts\":\n\t\t\treturn \"ts\";\n\t\tcase \"js\":\n\t\t\treturn \"js\";\n\t\tcase \"json\":\n\t\t\treturn \"json\";\n\t\tcase \"tsx\":\n\t\t\treturn \"tsx\";\n\t\tcase \"py\":\n\t\t\treturn \"python\";\n\t\tcase \"rs\":\n\t\t\treturn \"rust\";\n\t\tcase \"go\":\n\t\t\treturn \"go\";\n\t\tcase \"md\":\n\t\tcase \"markdown\":\n\t\tcase \"mdown\":\n\t\tcase \"mkd\":\n\t\tcase \"mkdn\":\n\t\t\treturn \"markdown\";\n\t\tcase \"txt\":\n\t\t\treturn \"txt\";\n\t\tdefault:\n\t\t\treturn undefined;\n\t}\n}\n\n/** Reader eligibility stays bound to the frozen selection even with a custom folder. */\nexport function isReadSummaryPath(path: string): boolean {\n\tconst language = languageForPath(path);\n\treturn language !== undefined && READ_FOLDER_SELECTION.languages[language] === \"heuristic\";\n}\n\nfunction hierarchy(ranges: readonly ReadLineRange[]): readonly ReadFoldRange[] | undefined {\n\t// Builder-owned arrays; no caller-owned ranges are sorted or mutated.\n\ttype Node = ReadLineRange & { readonly children: Node[] };\n\tconst roots: Node[] = [];\n\tconst stack: Node[] = [];\n\tfor (const range of [...ranges].sort((a, b) => a.startLine - b.startLine || b.endLine - a.endLine)) {\n\t\twhile (stack.length && range.startLine > stack[stack.length - 1].endLine) stack.pop();\n\t\tconst parent = stack[stack.length - 1];\n\t\tif (parent && range.startLine === parent.startLine && range.endLine === parent.endLine) continue;\n\t\tif (parent && (range.startLine <= parent.startLine || range.endLine >= parent.endLine)) return undefined;\n\t\tconst node: Node = { ...range, children: [] };\n\t\t(parent ? parent.children : roots).push(node);\n\t\tstack.push(node);\n\t}\n\treturn roots;\n}\n\nfunction fold({ path, text, settings }: ReadFolderInput): ReadFolderResult {\n\tconst language = languageForPath(path);\n\tif (!language) return { status: \"unsupported\", reason: \"unsupported_language\" };\n\tconst engine = READ_FOLDER_SELECTION.languages[language];\n\tswitch (engine) {\n\t\tcase \"unsupported\":\n\t\t\treturn { status: \"unsupported\", reason: \"unsupported_language\" };\n\t\tcase \"prose_exempt\":\n\t\t\treturn { status: \"unsupported\", reason: \"prose_exempt\" };\n\t\tcase \"raw\": // Retain the pure candidate for safety/quality measurement, never default-read eligibility.\n\t\tcase \"heuristic\":\n\t\t\tbreak;\n\t\tdefault:\n\t\t\treturn engine satisfies never;\n\t}\n\t// Narrow the language independently: the manifest is the sole enablement authority.\n\tif (language !== \"ts\" && language !== \"js\" && language !== \"json\")\n\t\treturn { status: \"unsupported\", reason: \"unsupported_language\" };\n\tif (language === \"json\") {\n\t\ttry {\n\t\t\tJSON.parse(text);\n\t\t} catch (error) {\n\t\t\tif (error instanceof SyntaxError) return { status: \"parse_failure\", reason: \"invalid_json\" };\n\t\t\tthrow error;\n\t\t}\n\t}\n\tconst scan = scanBraces(text, language, settings);\n\tswitch (scan.status) {\n\t\tcase \"parse_failure\":\n\t\t\treturn scan;\n\t\tcase \"parsed\": {\n\t\t\tconst ranges = hierarchy(scan.ranges);\n\t\t\treturn ranges\n\t\t\t\t? { status: \"parsed\", text, ranges }\n\t\t\t\t: { status: \"parse_failure\", reason: \"ambiguous_line_boundaries\" };\n\t\t}\n\t\tdefault:\n\t\t\treturn scan satisfies never;\n\t}\n}\n\nexport const selectedReadFolder: ReadFolder = Object.freeze({ id: \"measured-brace\", version: \"3\", fold });\n"]}
@@ -0,0 +1,21 @@
1
+ export type Open = {
2
+ readonly char: "{" | "[" | "(";
3
+ readonly line: number;
4
+ readonly headerLine?: number;
5
+ /** Opened where a value may start, so it can still turn out to be an assignment target. */
6
+ readonly target?: boolean;
7
+ readonly foldable: boolean;
8
+ readonly protected: boolean;
9
+ readonly signature: boolean;
10
+ readonly interpolation: boolean;
11
+ readonly control: boolean;
12
+ readonly call: boolean;
13
+ readonly valueParameters: boolean;
14
+ readonly declaration: boolean;
15
+ };
16
+ export declare const expressionKeywords: Set<string>;
17
+ export declare const controls: Set<string>;
18
+ export declare const signatureDeclarations: Set<string>;
19
+ /** Only expression callees release argument values; declarations retain parameter protection. */
20
+ export declare function isCallCallee(previous: string, beforeWord: string): boolean;
21
+ //# sourceMappingURL=lexical-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexical-context.d.ts","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/lexical-context.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG;IAClB,QAAQ,CAAC,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,aAY7B,CAAC;AACH,eAAO,MAAM,QAAQ,aAA6D,CAAC;AACnF,eAAO,MAAM,qBAAqB,aAA2E,CAAC;AAE9G,iGAAiG;AACjG,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAQ1E"}
@@ -0,0 +1,24 @@
1
+ export const expressionKeywords = new Set([
2
+ "return",
3
+ "throw",
4
+ "yield",
5
+ "await",
6
+ "case",
7
+ "typeof",
8
+ "void",
9
+ "delete",
10
+ "in",
11
+ "of",
12
+ "instanceof",
13
+ ]);
14
+ export const controls = new Set(["if", "while", "for", "switch", "catch", "with"]);
15
+ export const signatureDeclarations = new Set(["type", "interface", "enum", "namespace", "module", "declare"]);
16
+ /** Only expression callees release argument values; declarations retain parameter protection. */
17
+ export function isCallCallee(previous, beforeWord) {
18
+ return (/^[A-Za-z_$][\w$]*$/.test(previous) &&
19
+ !["function", "async", "new"].includes(previous) &&
20
+ !expressionKeywords.has(previous) &&
21
+ !controls.has(previous) &&
22
+ [".", "=", ":", "return", "await", "new"].includes(beforeWord));
23
+ }
24
+ //# sourceMappingURL=lexical-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexical-context.js","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/lexical-context.ts"],"names":[],"mappings":"AAgBA,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACzC,QAAQ;IACR,OAAO;IACP,OAAO;IACP,OAAO;IACP,MAAM;IACN,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,IAAI;IACJ,IAAI;IACJ,YAAY;CACZ,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;AACnF,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC,CAAC;AAE9G,iGAAiG;AACjG,MAAM,UAAU,YAAY,CAAC,QAAgB,EAAE,UAAkB;IAChE,OAAO,CACN,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC;QACnC,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAChD,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC;QACjC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;QACvB,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAC9D,CAAC;AACH,CAAC","sourcesContent":["export type Open = {\n\treadonly char: \"{\" | \"[\" | \"(\";\n\treadonly line: number;\n\treadonly headerLine?: number;\n\t/** Opened where a value may start, so it can still turn out to be an assignment target. */\n\treadonly target?: boolean;\n\treadonly foldable: boolean;\n\treadonly protected: boolean;\n\treadonly signature: boolean;\n\treadonly interpolation: boolean;\n\treadonly control: boolean;\n\treadonly call: boolean;\n\treadonly valueParameters: boolean;\n\treadonly declaration: boolean;\n};\n\nexport const expressionKeywords = new Set([\n\t\"return\",\n\t\"throw\",\n\t\"yield\",\n\t\"await\",\n\t\"case\",\n\t\"typeof\",\n\t\"void\",\n\t\"delete\",\n\t\"in\",\n\t\"of\",\n\t\"instanceof\",\n]);\nexport const controls = new Set([\"if\", \"while\", \"for\", \"switch\", \"catch\", \"with\"]);\nexport const signatureDeclarations = new Set([\"type\", \"interface\", \"enum\", \"namespace\", \"module\", \"declare\"]);\n\n/** Only expression callees release argument values; declarations retain parameter protection. */\nexport function isCallCallee(previous: string, beforeWord: string): boolean {\n\treturn (\n\t\t/^[A-Za-z_$][\\w$]*$/.test(previous) &&\n\t\t![\"function\", \"async\", \"new\"].includes(previous) &&\n\t\t!expressionKeywords.has(previous) &&\n\t\t!controls.has(previous) &&\n\t\t[\".\", \"=\", \":\", \"return\", \"await\", \"new\"].includes(beforeWord)\n\t);\n}\n"]}
@@ -0,0 +1,12 @@
1
+ type Span = {
2
+ readonly end: number;
3
+ readonly newlines: number;
4
+ };
5
+ export declare function stringSpan(source: string, start: number, delimiter: string): Span | undefined;
6
+ /** Skip only brace-free type arguments; constraints/object types still take the protected/raw path. */
7
+ export declare function typeArgumentsSpan(source: string, start: number): Span | undefined;
8
+ export declare function lineCommentEnd(source: string, start: number): number;
9
+ export declare function commentSpan(source: string, start: number): Span | undefined;
10
+ export declare function regexSpan(source: string, start: number): Span | undefined;
11
+ export {};
12
+ //# sourceMappingURL=lexical-spans.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexical-spans.d.ts","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/lexical-spans.ts"],"names":[],"mappings":"AAAA,KAAK,IAAI,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAIhE,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAY7F;AAED,uGAAuG;AACvG,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAkBjF;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAIpE;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAO3E;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAsBzE"}
@@ -0,0 +1,92 @@
1
+ // Selected TS/JS/JSON branches of row 17's measured literal scanner.
2
+ // Offsets are UTF-16 indices; output coordinates always describe whole source lines.
3
+ export function stringSpan(source, start, delimiter) {
4
+ let newlines = 0;
5
+ for (let i = start; i < source.length; i++) {
6
+ if (source[i] === delimiter)
7
+ return { end: i + 1, newlines };
8
+ if (source[i] === "\n" || source[i] === "\r")
9
+ return undefined;
10
+ if (source[i] === "\\") {
11
+ if (source[i + 1] === "\r" && source[i + 2] === "\n")
12
+ i++;
13
+ if (source[i + 1] === "\n")
14
+ newlines++;
15
+ i++;
16
+ }
17
+ }
18
+ return undefined;
19
+ }
20
+ /** Skip only brace-free type arguments; constraints/object types still take the protected/raw path. */
21
+ export function typeArgumentsSpan(source, start) {
22
+ const delimiters = ["<"];
23
+ let newlines = 0;
24
+ for (let i = start; i < source.length; i++) {
25
+ const char = source[i];
26
+ if (char === "\n")
27
+ newlines++;
28
+ if (char === '"' || char === "'") {
29
+ const span = stringSpan(source, i + 1, char);
30
+ if (!span)
31
+ return undefined;
32
+ newlines += span.newlines;
33
+ i = span.end - 1;
34
+ }
35
+ else if (char === "<" || char === "[")
36
+ delimiters.push(char);
37
+ else if (char === ">" || char === "]") {
38
+ if (delimiters.pop() !== (char === ">" ? "<" : "["))
39
+ return undefined;
40
+ if (!delimiters.length)
41
+ return { end: i + 1, newlines };
42
+ }
43
+ else if (!/[A-Za-z_$0-9\s,.?|&]/.test(char))
44
+ return undefined;
45
+ }
46
+ return undefined;
47
+ }
48
+ export function lineCommentEnd(source, start) {
49
+ let end = start;
50
+ while (end < source.length && !/[\n\r\u2028\u2029]/.test(source[end]))
51
+ end++;
52
+ return end;
53
+ }
54
+ export function commentSpan(source, start) {
55
+ let newlines = 0;
56
+ for (let i = start; i < source.length; i++) {
57
+ if (source[i] === "\n")
58
+ newlines++;
59
+ if (source.startsWith("*/", i))
60
+ return { end: i + 2, newlines };
61
+ }
62
+ return undefined;
63
+ }
64
+ export function regexSpan(source, start) {
65
+ let characterClass = false;
66
+ for (let i = start; i < source.length; i++) {
67
+ if (source[i] === "\n" || source[i] === "\r" || source[i] === "\u2028" || source[i] === "\u2029")
68
+ return undefined;
69
+ if (source[i] === "\\") {
70
+ if (/[\r\n\u2028\u2029]/.test(source[i + 1] ?? ""))
71
+ return undefined;
72
+ i++;
73
+ continue;
74
+ }
75
+ if (source[i] === "[")
76
+ characterClass = true;
77
+ if (source[i] === "]")
78
+ characterClass = false;
79
+ if (source[i] === "/" && !characterClass) {
80
+ let end = i + 1;
81
+ while (/[a-z]/i.test(source[end] ?? ""))
82
+ end++;
83
+ const flags = source.slice(i + 1, end);
84
+ // Unicode-set regexes need a different nested-class grammar; do not guess.
85
+ if (/[^dgimsuy]/.test(flags) || new Set(flags).size !== flags.length)
86
+ return undefined;
87
+ return { end, newlines: 0 };
88
+ }
89
+ }
90
+ return undefined;
91
+ }
92
+ //# sourceMappingURL=lexical-spans.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lexical-spans.js","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/lexical-spans.ts"],"names":[],"mappings":"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","sourcesContent":["type Span = { readonly end: number; readonly newlines: number };\n\n// Selected TS/JS/JSON branches of row 17's measured literal scanner.\n// Offsets are UTF-16 indices; output coordinates always describe whole source lines.\nexport function stringSpan(source: string, start: number, delimiter: string): Span | undefined {\n\tlet newlines = 0;\n\tfor (let i = start; i < source.length; i++) {\n\t\tif (source[i] === delimiter) return { end: i + 1, newlines };\n\t\tif (source[i] === \"\\n\" || source[i] === \"\\r\") return undefined;\n\t\tif (source[i] === \"\\\\\") {\n\t\t\tif (source[i + 1] === \"\\r\" && source[i + 2] === \"\\n\") i++;\n\t\t\tif (source[i + 1] === \"\\n\") newlines++;\n\t\t\ti++;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/** Skip only brace-free type arguments; constraints/object types still take the protected/raw path. */\nexport function typeArgumentsSpan(source: string, start: number): Span | undefined {\n\tconst delimiters = [\"<\"];\n\tlet newlines = 0;\n\tfor (let i = start; i < source.length; i++) {\n\t\tconst char = source[i];\n\t\tif (char === \"\\n\") newlines++;\n\t\tif (char === '\"' || char === \"'\") {\n\t\t\tconst span = stringSpan(source, i + 1, char);\n\t\t\tif (!span) return undefined;\n\t\t\tnewlines += span.newlines;\n\t\t\ti = span.end - 1;\n\t\t} else if (char === \"<\" || char === \"[\") delimiters.push(char);\n\t\telse if (char === \">\" || char === \"]\") {\n\t\t\tif (delimiters.pop() !== (char === \">\" ? \"<\" : \"[\")) return undefined;\n\t\t\tif (!delimiters.length) return { end: i + 1, newlines };\n\t\t} else if (!/[A-Za-z_$0-9\\s,.?|&]/.test(char)) return undefined;\n\t}\n\treturn undefined;\n}\n\nexport function lineCommentEnd(source: string, start: number): number {\n\tlet end = start;\n\twhile (end < source.length && !/[\\n\\r\\u2028\\u2029]/.test(source[end])) end++;\n\treturn end;\n}\n\nexport function commentSpan(source: string, start: number): Span | undefined {\n\tlet newlines = 0;\n\tfor (let i = start; i < source.length; i++) {\n\t\tif (source[i] === \"\\n\") newlines++;\n\t\tif (source.startsWith(\"*/\", i)) return { end: i + 2, newlines };\n\t}\n\treturn undefined;\n}\n\nexport function regexSpan(source: string, start: number): Span | undefined {\n\tlet characterClass = false;\n\tfor (let i = start; i < source.length; i++) {\n\t\tif (source[i] === \"\\n\" || source[i] === \"\\r\" || source[i] === \"\\u2028\" || source[i] === \"\\u2029\")\n\t\t\treturn undefined;\n\t\tif (source[i] === \"\\\\\") {\n\t\t\tif (/[\\r\\n\\u2028\\u2029]/.test(source[i + 1] ?? \"\")) return undefined;\n\t\t\ti++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (source[i] === \"[\") characterClass = true;\n\t\tif (source[i] === \"]\") characterClass = false;\n\t\tif (source[i] === \"/\" && !characterClass) {\n\t\t\tlet end = i + 1;\n\t\t\twhile (/[a-z]/i.test(source[end] ?? \"\")) end++;\n\t\t\tconst flags = source.slice(i + 1, end);\n\t\t\t// Unicode-set regexes need a different nested-class grammar; do not guess.\n\t\t\tif (/[^dgimsuy]/.test(flags) || new Set(flags).size !== flags.length) return undefined;\n\t\t\treturn { end, newlines: 0 };\n\t\t}\n\t}\n\treturn undefined;\n}\n"]}
@@ -0,0 +1,47 @@
1
+ export declare const READ_FOLD_SETTINGS: Readonly<{
2
+ readonly minBodyLines: 4;
3
+ readonly minCommentLines: 6;
4
+ readonly minTotalLines: 100;
5
+ readonly unfoldUntil: 50;
6
+ readonly unfoldLimit: 100;
7
+ }>;
8
+ /** Internal policy constants, not a user-configurable settings surface. */
9
+ export type ReadFoldSettings = typeof READ_FOLD_SETTINGS;
10
+ export type ReadLineRange = {
11
+ readonly startLine: number;
12
+ readonly endLine: number;
13
+ };
14
+ export type ReadBraceScan = {
15
+ readonly status: "parsed";
16
+ readonly ranges: readonly ReadLineRange[];
17
+ } | {
18
+ readonly status: "parse_failure";
19
+ readonly reason: string;
20
+ };
21
+ /** Inclusive, 1-based omitted interiors. Children exclude their parent's boundary lines. */
22
+ export type ReadFoldRange = ReadLineRange & {
23
+ readonly children: readonly ReadFoldRange[];
24
+ };
25
+ export type ReadFolderInput = {
26
+ readonly path: string;
27
+ readonly text: string;
28
+ readonly settings: ReadFoldSettings;
29
+ };
30
+ export type ReadFolderResult = {
31
+ readonly status: "parsed";
32
+ readonly text: string;
33
+ readonly ranges: readonly ReadFoldRange[];
34
+ } | {
35
+ readonly status: "unsupported";
36
+ readonly reason: "unsupported_language" | "prose_exempt";
37
+ } | {
38
+ readonly status: "parse_failure";
39
+ readonly reason: string;
40
+ };
41
+ /** Synchronous and pure. I/O, cancellation and unexpected exceptions belong to the caller. */
42
+ export interface ReadFolder {
43
+ readonly id: string;
44
+ readonly version: string;
45
+ fold(input: ReadFolderInput): ReadFolderResult;
46
+ }
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB;2BAChB,CAAC;8BACE,CAAC;4BACH,GAAG;0BACL,EAAE;0BACF,GAAG;EACN,CAAC;AAEZ,2EAA2E;AAC3E,MAAM,MAAM,gBAAgB,GAAG,OAAO,kBAAkB,CAAC;AACzD,MAAM,MAAM,aAAa,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AACrF,MAAM,MAAM,aAAa,GACtB;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AACjE,4FAA4F;AAC5F,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,CAAC;AAC5F,MAAM,MAAM,eAAe,GAAG;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;CACpC,CAAC;AACF,MAAM,MAAM,gBAAgB,GACzB;IAAE,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,aAAa,EAAE,CAAA;CAAE,GAC/F;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,sBAAsB,GAAG,cAAc,CAAA;CAAE,GAC5F;IAAE,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjE,8FAA8F;AAC9F,MAAM,WAAW,UAAU;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,IAAI,CAAC,KAAK,EAAE,eAAe,GAAG,gBAAgB,CAAC;CAC/C"}
@@ -0,0 +1,8 @@
1
+ export const READ_FOLD_SETTINGS = Object.freeze({
2
+ minBodyLines: 4,
3
+ minCommentLines: 6,
4
+ minTotalLines: 100,
5
+ unfoldUntil: 50,
6
+ unfoldLimit: 100,
7
+ });
8
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/harness/utils/read-folders/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;IAC/C,YAAY,EAAE,CAAC;IACf,eAAe,EAAE,CAAC;IAClB,aAAa,EAAE,GAAG;IAClB,WAAW,EAAE,EAAE;IACf,WAAW,EAAE,GAAG;CACP,CAAC,CAAC","sourcesContent":["export const READ_FOLD_SETTINGS = Object.freeze({\n\tminBodyLines: 4,\n\tminCommentLines: 6,\n\tminTotalLines: 100,\n\tunfoldUntil: 50,\n\tunfoldLimit: 100,\n} as const);\n\n/** Internal policy constants, not a user-configurable settings surface. */\nexport type ReadFoldSettings = typeof READ_FOLD_SETTINGS;\nexport type ReadLineRange = { readonly startLine: number; readonly endLine: number };\nexport type ReadBraceScan =\n\t| { readonly status: \"parsed\"; readonly ranges: readonly ReadLineRange[] }\n\t| { readonly status: \"parse_failure\"; readonly reason: string };\n/** Inclusive, 1-based omitted interiors. Children exclude their parent's boundary lines. */\nexport type ReadFoldRange = ReadLineRange & { readonly children: readonly ReadFoldRange[] };\nexport type ReadFolderInput = {\n\treadonly path: string;\n\treadonly text: string;\n\treadonly settings: ReadFoldSettings;\n};\nexport type ReadFolderResult =\n\t| { readonly status: \"parsed\"; readonly text: string; readonly ranges: readonly ReadFoldRange[] }\n\t| { readonly status: \"unsupported\"; readonly reason: \"unsupported_language\" | \"prose_exempt\" }\n\t| { readonly status: \"parse_failure\"; readonly reason: string };\n\n/** Synchronous and pure. I/O, cancellation and unexpected exceptions belong to the caller. */\nexport interface ReadFolder {\n\treadonly id: string;\n\treadonly version: string;\n\tfold(input: ReadFolderInput): ReadFolderResult;\n}\n"]}
@@ -0,0 +1,52 @@
1
+ import { type ReadFolder, type ReadFolderResult, type ReadLineRange } from "./read-folders/types.ts";
2
+ export type ReadSegment = (ReadLineRange & {
3
+ readonly kind: "kept";
4
+ readonly text: string;
5
+ }) | (ReadLineRange & {
6
+ readonly kind: "elided";
7
+ });
8
+ export type RenderedReadView = {
9
+ readonly text: string;
10
+ readonly elidedRanges: readonly ReadLineRange[];
11
+ readonly footer: {
12
+ readonly text: string;
13
+ readonly rereads: readonly {
14
+ readonly offset: number;
15
+ readonly limit: number;
16
+ }[];
17
+ };
18
+ };
19
+ export type ReadSummaryFallback = "unsupported_language" | "prose_exempt" | "parse_failure" | "stale_source" | "invalid_ranges" | "too_short" | "no_elision" | "skeleton_exceeds_budget" | "visible_budget_unreachable" | "no_output_saving";
20
+ export type SegmentedReadView = {
21
+ readonly status: "summary";
22
+ readonly segments: readonly ReadSegment[];
23
+ readonly visibleSourceLines: number;
24
+ readonly rendered: RenderedReadView;
25
+ } | {
26
+ readonly status: "no_summary";
27
+ readonly reason: ReadSummaryFallback;
28
+ };
29
+ /** Compose only untruncated default text reads; each reader owns its existing raw path. */
30
+ export declare function createDefaultReadSummary(input: {
31
+ readonly path: string;
32
+ readonly text: string;
33
+ readonly offset?: number;
34
+ readonly limit?: number;
35
+ readonly folder?: ReadFolder;
36
+ readonly truncated: boolean;
37
+ }): RenderedReadView | undefined;
38
+ export declare class InvalidReadSegmentsError extends Error {
39
+ readonly code = "invalid_segments";
40
+ constructor();
41
+ }
42
+ /** The sole validator/renderer/footer implementation. Synthetic lines are never source slices. */
43
+ export declare function renderSegmentedReadView({ text, segments, }: {
44
+ readonly text: string;
45
+ readonly segments: readonly ReadSegment[];
46
+ }): RenderedReadView;
47
+ /** Breadth-first refinement counts only retained source lines, never sentinels/footer lines. */
48
+ export declare function createSegmentedReadView({ text, parsed, }: {
49
+ readonly text: string;
50
+ readonly parsed: ReadFolderResult;
51
+ }): SegmentedReadView;
52
+ //# sourceMappingURL=segmented-read-view.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"segmented-read-view.d.ts","sourceRoot":"","sources":["../../../src/harness/utils/segmented-read-view.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,UAAU,EACf,KAAK,gBAAgB,EAErB,KAAK,aAAa,EAClB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,MAAM,WAAW,GACpB,CAAC,aAAa,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,GAClE,CAAC,aAAa,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC,CAAC;AACjD,MAAM,MAAM,gBAAgB,GAAG;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,SAAS,aAAa,EAAE,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE;QAChB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,OAAO,EAAE,SAAS;YAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;KACjF,CAAC;CACF,CAAC;AACF,MAAM,MAAM,mBAAmB,GAC5B,sBAAsB,GACtB,cAAc,GACd,eAAe,GACf,cAAc,GACd,gBAAgB,GAChB,WAAW,GACX,YAAY,GACZ,yBAAyB,GACzB,4BAA4B,GAC5B,kBAAkB,CAAC;AACtB,MAAM,MAAM,iBAAiB,GAC1B;IACA,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;IAC1C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC;CACnC,GACD;IAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAE3E,2FAA2F;AAC3F,wBAAgB,wBAAwB,CAAC,KAAK,EAAE;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC5B,GAAG,gBAAgB,GAAG,SAAS,CAc/B;AAED,qBAAa,wBAAyB,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,sBAAsB;IACnC,cAEC;CACD;AAYD,kGAAkG;AAClG,wBAAgB,uBAAuB,CAAC,EACvC,IAAI,EACJ,QAAQ,GACR,EAAE;IACF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,CAAC;CAC1C,GAAG,gBAAgB,CAiCnB;AAkBD,gGAAgG;AAChG,wBAAgB,uBAAuB,CAAC,EACvC,IAAI,EACJ,MAAM,GACN,EAAE;IACF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;CAClC,GAAG,iBAAiB,CAyDpB"}