openwolf-enhanced 1.20.9 → 1.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 +116 -0
- package/README.md +96 -31
- package/dist/dashboard/assets/{AISuggestions-0zrodHvB.js → AISuggestions-Cpup2r93.js} +1 -1
- package/dist/dashboard/assets/{ActivityLog-DYEe6Mh-.js → ActivityLog-vc08HmGa.js} +1 -1
- package/dist/dashboard/assets/{ActivityTimeline-BPomzQWf.js → ActivityTimeline-fatU3zUR.js} +1 -1
- package/dist/dashboard/assets/{AnatomyBrowser-D3m69d-p.js → AnatomyBrowser-CMsbTK8b.js} +1 -1
- package/dist/dashboard/assets/{BugLog-C44GE8m7.js → BugLog-s5Pex7fA.js} +1 -1
- package/dist/dashboard/assets/{CerebrumViewer-CxvLTVFs.js → CerebrumViewer-D5i0Yd88.js} +1 -1
- package/dist/dashboard/assets/{CronStatus-DCiCUVLZ.js → CronStatus-3S4D9sES.js} +1 -1
- package/dist/dashboard/assets/{DesignQC-w7X5uW1P.js → DesignQC-CeR_JqlS.js} +1 -1
- package/dist/dashboard/assets/LinkGraph-BTiwJzrc.js +1 -0
- package/dist/dashboard/assets/{MemoryViewer-CraLooQx.js → MemoryViewer-QOXI9jv8.js} +1 -1
- package/dist/dashboard/assets/{NativeMemory-CaYixCd2.js → NativeMemory-CoSRp5Q2.js} +1 -1
- package/dist/dashboard/assets/{ProjectOverview-DJacADHV.js → ProjectOverview-G0xzHTJm.js} +1 -1
- package/dist/dashboard/assets/{ProjectsAggregate-xpOM2n6T.js → ProjectsAggregate-BGn850vY.js} +1 -1
- package/dist/dashboard/assets/{StatusBadge-CzoOrUrs.js → StatusBadge-DxWVdzKK.js} +1 -1
- package/dist/dashboard/assets/{TokenUsage-BUL-gsby.js → TokenUsage-BTTrcgDP.js} +2 -2
- package/dist/dashboard/assets/{index-BZOA5m43.js → index-CCxQQi4q.js} +3 -3
- package/dist/dashboard/assets/index-CVfvTpSA.css +2 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/hooks/session-start.js +4 -1
- package/dist/hooks/shared.js +103 -2
- package/dist/hooks/stop.js +5 -1
- package/dist/src/cli/find-cmd.js +163 -0
- package/dist/src/cli/find-cmd.js.map +1 -0
- package/dist/src/cli/index.js +10 -0
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/cli/recall-cmd.js +18 -1
- package/dist/src/cli/recall-cmd.js.map +1 -1
- package/dist/src/cli/report-cmd.js +20 -1
- package/dist/src/cli/report-cmd.js.map +1 -1
- package/dist/src/cli/scan.js +31 -0
- package/dist/src/cli/scan.js.map +1 -1
- package/dist/src/cli/status.js +4 -1
- package/dist/src/cli/status.js.map +1 -1
- package/dist/src/daemon/cron-engine.js +9 -1
- package/dist/src/daemon/cron-engine.js.map +1 -1
- package/dist/src/daemon/wolf-daemon.js +53 -0
- package/dist/src/daemon/wolf-daemon.js.map +1 -1
- package/dist/src/hooks/session-start.js +4 -1
- package/dist/src/hooks/session-start.js.map +1 -1
- package/dist/src/hooks/shared.js +103 -2
- package/dist/src/hooks/shared.js.map +1 -1
- package/dist/src/hooks/stop.js +5 -1
- package/dist/src/hooks/stop.js.map +1 -1
- package/dist/src/mcp/server.js +32 -0
- package/dist/src/mcp/server.js.map +1 -1
- package/dist/src/scanner/anatomy-scanner.js +29 -5
- package/dist/src/scanner/anatomy-scanner.js.map +1 -1
- package/dist/src/scanner/import-graph.js +206 -0
- package/dist/src/scanner/import-graph.js.map +1 -0
- package/dist/src/scanner/treesitter-extractor.js +226 -0
- package/dist/src/scanner/treesitter-extractor.js.map +1 -0
- package/dist/src/tracker/token-ledger.js +1 -0
- package/dist/src/tracker/token-ledger.js.map +1 -1
- package/dist/src/utils/agent-hooks.js +73 -9
- package/dist/src/utils/agent-hooks.js.map +1 -1
- package/dist/src/utils/link-graph.js +183 -0
- package/dist/src/utils/link-graph.js.map +1 -0
- package/dist/src/utils/maintenance.js +20 -0
- package/dist/src/utils/maintenance.js.map +1 -1
- package/dist/src/utils/marker-block.js +68 -0
- package/dist/src/utils/marker-block.js.map +1 -0
- package/package.json +4 -2
- package/src/templates/cron-manifest.json +32 -10
- package/dist/dashboard/assets/index-Cr3yWM5G.css +0 -2
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Import graph + PageRank importance (idea from cytostack/openwolf 2.1.0, §J2).
|
|
3
|
+
//
|
|
4
|
+
// What for: `openwolf find` has to decide which of several hits comes first. File size is no
|
|
5
|
+
// help — the biggest file is rarely the most important one. How often a file is imported, and
|
|
6
|
+
// from how important a file, is a much better signal.
|
|
7
|
+
//
|
|
8
|
+
// Deliberately PROJECT-INTERNAL relative imports only. Package imports ("react", "node:fs") say
|
|
9
|
+
// nothing about the structure of THIS project and would flood the graph with leaves.
|
|
10
|
+
//
|
|
11
|
+
// Self-contained (no relative imports) so tests can load the module directly.
|
|
12
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
const TS_JS_EXT = new Set([".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"]);
|
|
14
|
+
const PY_EXT = new Set([".py"]);
|
|
15
|
+
/** Languages whose imports we read. Everything else is treated as a leaf — honest, rather than guessed. */
|
|
16
|
+
export function importsSupported(ext) {
|
|
17
|
+
return TS_JS_EXT.has(ext.toLowerCase()) || PY_EXT.has(ext.toLowerCase());
|
|
18
|
+
}
|
|
19
|
+
const TS_PATTERNS = [
|
|
20
|
+
/\bimport\s+[^;'"]*?\bfrom\s*["']([^"']+)["']/g,
|
|
21
|
+
/\bexport\s+[^;'"]*?\bfrom\s*["']([^"']+)["']/g,
|
|
22
|
+
/\bimport\s*\(\s*["']([^"']+)["']\s*\)/g,
|
|
23
|
+
/\brequire\s*\(\s*["']([^"']+)["']\s*\)/g,
|
|
24
|
+
/\bimport\s+["']([^"']+)["']/g,
|
|
25
|
+
];
|
|
26
|
+
/**
|
|
27
|
+
* Raw import specifiers from source. Only relative ones are returned.
|
|
28
|
+
*
|
|
29
|
+
* Python: `from .x import y` and `from ..pkg.mod import y` are relative and get normalized into a
|
|
30
|
+
* path fragment with leading `./` or `../`, so `resolveImport` can treat both languages alike.
|
|
31
|
+
*/
|
|
32
|
+
export function extractImports(content, ext) {
|
|
33
|
+
const e = ext.toLowerCase();
|
|
34
|
+
const out = [];
|
|
35
|
+
if (TS_JS_EXT.has(e)) {
|
|
36
|
+
for (const re of TS_PATTERNS) {
|
|
37
|
+
re.lastIndex = 0;
|
|
38
|
+
for (let m = re.exec(content); m; m = re.exec(content)) {
|
|
39
|
+
if (m[1].startsWith("."))
|
|
40
|
+
out.push(m[1]);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
else if (PY_EXT.has(e)) {
|
|
45
|
+
const re = /^\s*from\s+(\.+)([\w.]*)\s+import\b/gm;
|
|
46
|
+
for (let m = re.exec(content); m; m = re.exec(content)) {
|
|
47
|
+
const up = m[1].length - 1; // a single dot = same package
|
|
48
|
+
const rest = m[2].replace(/\./g, "/");
|
|
49
|
+
const prefix = up === 0 ? "./" : "../".repeat(up);
|
|
50
|
+
out.push(prefix + rest);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return [...new Set(out)];
|
|
54
|
+
}
|
|
55
|
+
const CANDIDATE_SUFFIXES = ["", ".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts", ".py",
|
|
56
|
+
"/index.ts", "/index.tsx", "/index.js", "/index.jsx", "/__init__.py"];
|
|
57
|
+
/**
|
|
58
|
+
* Collapse `.` and `..` segments. Returns `null` when `..` walks out of the project root.
|
|
59
|
+
*
|
|
60
|
+
* [2026-08-20, review] This used to `parts.pop()` on an empty array and carry on, so
|
|
61
|
+
* `../../shared/util` from `src/a.ts` silently became `shared/util` — an import pointing OUTSIDE
|
|
62
|
+
* the project could then resolve onto an unrelated file inside it and add a phantom edge. That
|
|
63
|
+
* skews PageRank invisibly, which is exactly what this module's header says must not happen.
|
|
64
|
+
*/
|
|
65
|
+
function normalize(p) {
|
|
66
|
+
const parts = [];
|
|
67
|
+
for (const seg of p.split("/")) {
|
|
68
|
+
if (seg === "" || seg === ".")
|
|
69
|
+
continue;
|
|
70
|
+
if (seg === "..") {
|
|
71
|
+
if (parts.length === 0)
|
|
72
|
+
return null;
|
|
73
|
+
parts.pop();
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
parts.push(seg);
|
|
77
|
+
}
|
|
78
|
+
return parts.join("/");
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Resolve a relative specifier against the files that actually exist.
|
|
82
|
+
*
|
|
83
|
+
* Returns `null` when nothing matches — an unresolvable import must NOT create an edge. Invented
|
|
84
|
+
* edges would skew importance, and do it invisibly.
|
|
85
|
+
*
|
|
86
|
+
* `.js` in TypeScript sources means the `.ts` file (ESM convention), so a `.js` match also checks
|
|
87
|
+
* for — and prefers — the `.ts` variant.
|
|
88
|
+
*/
|
|
89
|
+
export function resolveImport(spec, fromRel, known) {
|
|
90
|
+
const baseDir = fromRel.includes("/") ? fromRel.slice(0, fromRel.lastIndexOf("/")) : "";
|
|
91
|
+
const joined = normalize(`${baseDir}/${spec}`);
|
|
92
|
+
if (joined === null)
|
|
93
|
+
return null; // escapes the project root — no edge
|
|
94
|
+
if (/\.(js|jsx|mjs|cjs)$/.test(joined)) {
|
|
95
|
+
const tsVariant = joined.replace(/\.(js|jsx|mjs|cjs)$/, (m) => m === ".js" ? ".ts" : m === ".jsx" ? ".tsx" : m === ".mjs" ? ".mts" : ".cts");
|
|
96
|
+
if (known.has(tsVariant))
|
|
97
|
+
return tsVariant;
|
|
98
|
+
}
|
|
99
|
+
for (const suffix of CANDIDATE_SUFFIXES) {
|
|
100
|
+
const cand = joined + suffix;
|
|
101
|
+
if (known.has(cand))
|
|
102
|
+
return cand;
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* PageRank over the import graph, normalized to 0..1 (largest value = 1).
|
|
108
|
+
*
|
|
109
|
+
* Dangling nodes (files with no resolvable imports) spread their mass evenly — without that,
|
|
110
|
+
* probability leaks on every iteration and the ranking tips over. An edge A->B means "A imports
|
|
111
|
+
* B", so importance flows toward the imported file.
|
|
112
|
+
*/
|
|
113
|
+
export function pageRank(graph, nodes, opts = {}) {
|
|
114
|
+
const d = opts.damping ?? 0.85;
|
|
115
|
+
const iters = opts.iterations ?? 30;
|
|
116
|
+
const n = nodes.length;
|
|
117
|
+
if (n === 0)
|
|
118
|
+
return {};
|
|
119
|
+
if (n === 1)
|
|
120
|
+
return { [nodes[0]]: 1 };
|
|
121
|
+
const idx = new Map(nodes.map((f, i) => [f, i]));
|
|
122
|
+
const out = nodes.map(() => []);
|
|
123
|
+
for (const [from, tos] of Object.entries(graph)) {
|
|
124
|
+
const fi = idx.get(from);
|
|
125
|
+
if (fi === undefined)
|
|
126
|
+
continue;
|
|
127
|
+
for (const to of tos) {
|
|
128
|
+
const ti = idx.get(to);
|
|
129
|
+
if (ti !== undefined && ti !== fi)
|
|
130
|
+
out[fi].push(ti);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
let rank = new Array(n).fill(1 / n);
|
|
134
|
+
for (let it = 0; it < iters; it++) {
|
|
135
|
+
const next = new Array(n).fill(0);
|
|
136
|
+
let dangling = 0;
|
|
137
|
+
for (let i = 0; i < n; i++) {
|
|
138
|
+
const targets = out[i];
|
|
139
|
+
if (targets.length === 0) {
|
|
140
|
+
dangling += rank[i];
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
const share = rank[i] / targets.length;
|
|
144
|
+
for (const t of targets)
|
|
145
|
+
next[t] += share;
|
|
146
|
+
}
|
|
147
|
+
const spread = dangling / n;
|
|
148
|
+
for (let i = 0; i < n; i++)
|
|
149
|
+
next[i] = (1 - d) / n + d * (next[i] + spread);
|
|
150
|
+
rank = next;
|
|
151
|
+
}
|
|
152
|
+
const max = Math.max(...rank);
|
|
153
|
+
const result = {};
|
|
154
|
+
for (let i = 0; i < n; i++)
|
|
155
|
+
result[nodes[i]] = max > 0 ? rank[i] / max : 0;
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
/** Turn per-file raw imports into a resolved graph. */
|
|
159
|
+
export function buildGraph(rawImports) {
|
|
160
|
+
const known = new Set(Object.keys(rawImports));
|
|
161
|
+
const graph = {};
|
|
162
|
+
for (const [file, specs] of Object.entries(rawImports)) {
|
|
163
|
+
const edges = [];
|
|
164
|
+
for (const spec of specs) {
|
|
165
|
+
const target = resolveImport(spec, file, known);
|
|
166
|
+
if (target && target !== file)
|
|
167
|
+
edges.push(target);
|
|
168
|
+
}
|
|
169
|
+
graph[file] = [...new Set(edges)];
|
|
170
|
+
}
|
|
171
|
+
return graph;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Convert PageRank scores into rank percentiles (0..1).
|
|
175
|
+
*
|
|
176
|
+
* Why not the raw, max-normalized value: on an import graph it is heavily right-skewed. Measured
|
|
177
|
+
* on this repo (158 files) the median was 0.058 against a maximum of 1.0 — which put 118 of 158
|
|
178
|
+
* files in the lowest bar. Useless as a display and too coarse as a tiebreak. The percentile keeps
|
|
179
|
+
* the ORDER exactly and spreads it evenly.
|
|
180
|
+
*
|
|
181
|
+
* Equal scores share a percentile (average rank) — otherwise the order of two equally important
|
|
182
|
+
* files would depend on the accident of the sort.
|
|
183
|
+
*/
|
|
184
|
+
export function toPercentile(scores) {
|
|
185
|
+
const items = Object.entries(scores);
|
|
186
|
+
const n = items.length;
|
|
187
|
+
if (n === 0)
|
|
188
|
+
return {};
|
|
189
|
+
if (n === 1)
|
|
190
|
+
return { [items[0][0]]: 1 };
|
|
191
|
+
items.sort((a, b) => a[1] - b[1]);
|
|
192
|
+
const out = {};
|
|
193
|
+
let i = 0;
|
|
194
|
+
while (i < n) {
|
|
195
|
+
let j = i;
|
|
196
|
+
while (j + 1 < n && items[j + 1][1] === items[i][1])
|
|
197
|
+
j++;
|
|
198
|
+
const avgRank = (i + j) / 2;
|
|
199
|
+
const pct = avgRank / (n - 1);
|
|
200
|
+
for (let k = i; k <= j; k++)
|
|
201
|
+
out[items[k][0]] = pct;
|
|
202
|
+
i = j + 1;
|
|
203
|
+
}
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=import-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-graph.js","sourceRoot":"","sources":["../../../src/scanner/import-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// tree-sitter symbol extraction (idea from cytostack/openwolf 2.1.0).
|
|
3
|
+
//
|
|
4
|
+
// Why OPTIONAL: `tree-sitter-wasms` unpacks to ~52 MB, more than everything else in this package
|
|
5
|
+
// combined. For a tool whose whole point is frugality, making that a hard dependency is the wrong
|
|
6
|
+
// trade. So it lives in `optionalDependencies` and this module falls back cleanly to the existing
|
|
7
|
+
// regex extractor when it is absent.
|
|
8
|
+
//
|
|
9
|
+
// Why bother at all: the regex version only knows line-anchored top-level declarations and guesses
|
|
10
|
+
// a symbol's end as "the line before the next one". tree-sitter gives the REAL end from the syntax
|
|
11
|
+
// tree and finds methods inside classes — both decide whether an offset/limit read hint lands on
|
|
12
|
+
// the right slice. Measured on this repo: 472 of 487 shared symbols (97 %) had an end line that
|
|
13
|
+
// was too far.
|
|
14
|
+
//
|
|
15
|
+
// Used only from `openwolf scan` (async). The hooks stay synchronous on the regex path; their
|
|
16
|
+
// symbols get replaced on the next scan.
|
|
17
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
const GRAMMARS = {
|
|
19
|
+
".ts": "typescript", ".mts": "typescript", ".cts": "typescript",
|
|
20
|
+
".tsx": "tsx",
|
|
21
|
+
".js": "javascript", ".mjs": "javascript", ".cjs": "javascript", ".jsx": "javascript",
|
|
22
|
+
".py": "python",
|
|
23
|
+
".go": "go",
|
|
24
|
+
".rs": "rust",
|
|
25
|
+
".java": "java",
|
|
26
|
+
".rb": "ruby",
|
|
27
|
+
".php": "php",
|
|
28
|
+
".c": "c", ".h": "c",
|
|
29
|
+
".cpp": "cpp", ".hpp": "cpp", ".cc": "cpp",
|
|
30
|
+
};
|
|
31
|
+
// Wrappers that hold declarations but are not symbols themselves. [2026-08-20, review] The first
|
|
32
|
+
// cut listed only export_statement/declaration_list/class_body, so `export const f = () => {}`
|
|
33
|
+
// (lexical_declaration -> variable_declarator -> arrow_function) and Python's decorated_definition
|
|
34
|
+
// were never reached — 9 real symbols vanished on this repo after a scan.
|
|
35
|
+
const WRAPPERS = new Set([
|
|
36
|
+
"export_statement", "declaration_list", "class_body", "statement_block",
|
|
37
|
+
"lexical_declaration", "variable_declaration", "variable_declarator",
|
|
38
|
+
"decorated_definition", "expression_statement",
|
|
39
|
+
]);
|
|
40
|
+
// Node types that count as a symbol, mapped onto our three categories.
|
|
41
|
+
const KIND_MAP = {
|
|
42
|
+
function_declaration: "fn", function_definition: "fn", method_definition: "fn",
|
|
43
|
+
method_declaration: "fn", arrow_function: "fn", generator_function_declaration: "fn",
|
|
44
|
+
function_item: "fn", func_literal: "fn",
|
|
45
|
+
class_declaration: "class", class_definition: "class", class_specifier: "class",
|
|
46
|
+
struct_item: "class", impl_item: "class", type_declaration: "class",
|
|
47
|
+
interface_declaration: "section", type_alias_declaration: "section",
|
|
48
|
+
enum_declaration: "section", enum_item: "section", trait_item: "section",
|
|
49
|
+
module: "section", mod_item: "section",
|
|
50
|
+
};
|
|
51
|
+
let loaded = null;
|
|
52
|
+
let unavailable = null;
|
|
53
|
+
/** true when tree-sitter could handle this extension (grammar known). */
|
|
54
|
+
export function treeSitterSupports(ext) {
|
|
55
|
+
return ext.toLowerCase() in GRAMMARS;
|
|
56
|
+
}
|
|
57
|
+
/** Why tree-sitter is not being used — so the scan report can say so instead of staying silent. */
|
|
58
|
+
export function treeSitterUnavailableReason() {
|
|
59
|
+
return unavailable;
|
|
60
|
+
}
|
|
61
|
+
async function load() {
|
|
62
|
+
if (loaded)
|
|
63
|
+
return loaded;
|
|
64
|
+
if (unavailable)
|
|
65
|
+
return null;
|
|
66
|
+
try {
|
|
67
|
+
const mod = await import("web-tree-sitter");
|
|
68
|
+
const Parser = mod.Parser ?? mod.default?.Parser ?? mod.default;
|
|
69
|
+
// [2026-08-20] Two versions, two shapes — and the order matters:
|
|
70
|
+
// 0.24.x: `Parser.Language`, but only available AFTER `Parser.init()`
|
|
71
|
+
// 0.26.x: `Language` as its own export
|
|
72
|
+
// So init() runs first and Language is resolved afterwards. The other way round, the tool
|
|
73
|
+
// wrongly reported "unexpected version".
|
|
74
|
+
//
|
|
75
|
+
// ⚠ Do NOT bump blindly: 0.26 is ABI-incompatible with the grammars in tree-sitter-wasms
|
|
76
|
+
// 0.1.13 — Language.load() fails there with an EMPTY error message. Upstream pins ^0.24.7
|
|
77
|
+
// for the same reason.
|
|
78
|
+
await Parser.init();
|
|
79
|
+
const Language = mod.Language ?? mod.default?.Language ?? Parser?.Language;
|
|
80
|
+
if (!Language?.load) {
|
|
81
|
+
unavailable = "web-tree-sitter without Language.load — unexpected version";
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
loaded = { Parser, Language, langs: new Map() };
|
|
85
|
+
return loaded;
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
unavailable = `web-tree-sitter failed to load (${e.message.split("\n")[0]})`;
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async function language(ctx, name) {
|
|
93
|
+
if (ctx.langs.has(name))
|
|
94
|
+
return ctx.langs.get(name);
|
|
95
|
+
try {
|
|
96
|
+
// The path comes from package resolution, not from a guessed node_modules path — otherwise it
|
|
97
|
+
// breaks under pnpm, where packages are not laid out flat.
|
|
98
|
+
const { createRequire } = await import("node:module");
|
|
99
|
+
const require = createRequire(import.meta.url);
|
|
100
|
+
const wasmPath = require.resolve(`tree-sitter-wasms/out/tree-sitter-${name}.wasm`);
|
|
101
|
+
const lang = await ctx.Language.load(wasmPath);
|
|
102
|
+
ctx.langs.set(name, lang);
|
|
103
|
+
return lang;
|
|
104
|
+
}
|
|
105
|
+
catch (e) {
|
|
106
|
+
// Record the reason instead of swallowing it — otherwise the scan report later says just "null".
|
|
107
|
+
unavailable = unavailable ?? `grammar ${name} failed to load (${e?.message || "no message"})`;
|
|
108
|
+
ctx.langs.set(name, null);
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function nameOf(node) {
|
|
113
|
+
const direct = node.childForFieldName?.("name");
|
|
114
|
+
if (direct?.text)
|
|
115
|
+
return direct.text;
|
|
116
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
117
|
+
const c = node.namedChild(i);
|
|
118
|
+
if (c && (c.type === "identifier" || c.type === "type_identifier" || c.type === "property_identifier")) {
|
|
119
|
+
return c.text;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Symbols from the syntax tree. Returns `null` when tree-sitter is unavailable — the caller then
|
|
126
|
+
* takes the regex path. `null` means "not measured", an empty list means "measured, found nothing".
|
|
127
|
+
* Conflating the two would be exactly the silent omission this codebase keeps trying to avoid.
|
|
128
|
+
*/
|
|
129
|
+
export async function extractSymbolsTS(content, ext, maxCount, ratio = 3.5) {
|
|
130
|
+
const grammar = GRAMMARS[ext.toLowerCase()];
|
|
131
|
+
if (!grammar)
|
|
132
|
+
return null;
|
|
133
|
+
const ctx = await load();
|
|
134
|
+
if (!ctx)
|
|
135
|
+
return null;
|
|
136
|
+
const lang = await language(ctx, grammar);
|
|
137
|
+
if (!lang)
|
|
138
|
+
return null;
|
|
139
|
+
let tree;
|
|
140
|
+
try {
|
|
141
|
+
const parser = new ctx.Parser();
|
|
142
|
+
parser.setLanguage(lang);
|
|
143
|
+
tree = parser.parse(content);
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
if (!tree?.rootNode)
|
|
149
|
+
return null;
|
|
150
|
+
const out = [];
|
|
151
|
+
const seen = new Set();
|
|
152
|
+
const visit = (node, depth) => {
|
|
153
|
+
if (out.length >= maxCount || depth > 3)
|
|
154
|
+
return;
|
|
155
|
+
for (let i = 0; i < node.namedChildCount; i++) {
|
|
156
|
+
const c = node.namedChild(i);
|
|
157
|
+
if (!c)
|
|
158
|
+
continue;
|
|
159
|
+
const kind = KIND_MAP[c.type];
|
|
160
|
+
if (kind) {
|
|
161
|
+
const name = nameOf(c);
|
|
162
|
+
const start = c.startPosition.row + 1;
|
|
163
|
+
const key = `${name}:${start}`;
|
|
164
|
+
if (name && !seen.has(key)) {
|
|
165
|
+
seen.add(key);
|
|
166
|
+
out.push({
|
|
167
|
+
name, kind, startLine: start, endLine: c.endPosition.row + 1,
|
|
168
|
+
tokens: Math.ceil((c.endIndex - c.startIndex) / ratio),
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
// Descend into class/impl bodies to catch methods — precisely what the regex version cannot do.
|
|
172
|
+
if (kind === "class")
|
|
173
|
+
visit(c, depth + 1);
|
|
174
|
+
}
|
|
175
|
+
else if (WRAPPERS.has(c.type)) {
|
|
176
|
+
visit(c, depth); // skip wrappers without spending depth
|
|
177
|
+
}
|
|
178
|
+
if (out.length >= maxCount)
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
visit(tree.rootNode, 0);
|
|
183
|
+
out.sort((a, b) => a.startLine - b.startLine);
|
|
184
|
+
return out;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Follow-up pass after the (synchronous) scan: replace the regex-guessed symbol ranges with the
|
|
188
|
+
* real ones from the syntax tree.
|
|
189
|
+
*
|
|
190
|
+
* Deliberately a separate, ASYNCHRONOUS pass. Scanner and hooks stay synchronous — tree-sitter is
|
|
191
|
+
* WASM and needs `await`, and turning the hook path async would be a far bigger change for a gain
|
|
192
|
+
* only the full scan needs.
|
|
193
|
+
*
|
|
194
|
+
* Returns how many files were refined — 0 plus a reason when tree-sitter is missing.
|
|
195
|
+
*/
|
|
196
|
+
export async function refineSymbols(symbols, readFile, maxCount) {
|
|
197
|
+
let refined = 0;
|
|
198
|
+
let skipped = 0;
|
|
199
|
+
for (const relPath of Object.keys(symbols)) {
|
|
200
|
+
const ext = relPath.includes(".") ? relPath.slice(relPath.lastIndexOf(".")) : "";
|
|
201
|
+
if (!treeSitterSupports(ext)) {
|
|
202
|
+
skipped++;
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const content = readFile(relPath);
|
|
206
|
+
if (content === null) {
|
|
207
|
+
skipped++;
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const better = await extractSymbolsTS(content, ext, maxCount);
|
|
211
|
+
// [2026-08-20, review] MERGE, do not replace. tree-sitter is more accurate where it looks,
|
|
212
|
+
// but it does not look everywhere — replacing wholesale deleted symbols the regex extractor
|
|
213
|
+
// had found, and an unfindable symbol defeats the entire point of `openwolf find`.
|
|
214
|
+
// tree-sitter wins on names it knows (its ranges are the real ones); regex-only names survive.
|
|
215
|
+
if (better && better.length > 0) {
|
|
216
|
+
const known = new Set(better.map((s) => s.name));
|
|
217
|
+
const kept = (symbols[relPath] ?? []).filter((s) => !known.has(s.name));
|
|
218
|
+
symbols[relPath] = [...better, ...kept].sort((a, b) => a.startLine - b.startLine);
|
|
219
|
+
refined++;
|
|
220
|
+
}
|
|
221
|
+
else
|
|
222
|
+
skipped++;
|
|
223
|
+
}
|
|
224
|
+
return { refined, skipped, reason: refined === 0 ? treeSitterUnavailableReason() : null };
|
|
225
|
+
}
|
|
226
|
+
//# sourceMappingURL=treesitter-extractor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"treesitter-extractor.js","sourceRoot":"","sources":["../../../src/scanner/treesitter-extractor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-ledger.js","sourceRoot":"","sources":["../../../src/tracker/token-ledger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAa,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"token-ledger.js","sourceRoot":"","sources":["../../../src/tracker/token-ledger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAa,MAAM,qBAAqB,CAAC;AAkE1D,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,QAAQ,CAAc,aAAa,CAAC,OAAO,CAAC,EAAE;QACnD,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,QAAQ,EAAE;YACR,sBAAsB,EAAE,CAAC;YACzB,WAAW,EAAE,CAAC;YACd,YAAY,EAAE,CAAC;YACf,cAAc,EAAE,CAAC;YACjB,YAAY,EAAE,CAAC;YACf,cAAc,EAAE,CAAC;YACjB,sBAAsB,EAAE,CAAC;YACzB,6BAA6B,EAAE,CAAC;YAChC,0BAA0B,EAAE,CAAC;SAC9B;QACD,QAAQ,EAAE,EAAE;QACZ,YAAY,EAAE,EAAE;QAChB,WAAW,EAAE,EAAE;QACf,mBAAmB,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;KAC5D,CAAC,CAAC;AACL,CAAC;AAED,8FAA8F;AAC9F,kGAAkG;AAClG,4FAA4F;AAC5F,yFAAyF"}
|
|
@@ -2,6 +2,7 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { readJSON, writeJSON, writeText } from "./fs-safe.js";
|
|
4
4
|
import { ensureDir } from "./paths.js";
|
|
5
|
+
import { upsertMarkerBlock, AGENTS_SNIPPET } from "./marker-block.js";
|
|
5
6
|
export const NON_CLAUDE_AGENTS = ["codex", "gemini", "opencode"];
|
|
6
7
|
const HOOKS = [
|
|
7
8
|
{ script: "session-start.js", claudeEvent: "SessionStart", matcher: "" },
|
|
@@ -43,19 +44,69 @@ function claudeSettings() {
|
|
|
43
44
|
// ---- Codex: same event names as Claude; edits arrive as `apply_patch`, shell as `Bash`.
|
|
44
45
|
// Env var for the project dir is unconfirmed upstream, so we bake in the absolute path (stable per
|
|
45
46
|
// machine → the trust-hash stays put until the next `openwolf update`). ----
|
|
47
|
+
// [2026-08-20] Codex used to get only 4 of the 8 hooks: session-start, post-write, post-bash,
|
|
48
|
+
// stop. Missing were pre-read, pre-write, post-read and precompact — exactly the ones carrying
|
|
49
|
+
// read avoidance, the do-not-repeat warning and the compaction snapshot. OpenWolf ran on Codex
|
|
50
|
+
// at half strength without anything ever failing.
|
|
51
|
+
//
|
|
52
|
+
// Matchers are a UNION of Claude and Codex tool names: which name Codex actually sends depends
|
|
53
|
+
// on its version, and a matcher that misses fails silently. The earlier `^apply_patch$` would
|
|
54
|
+
// never have seen a write reported as `Write`. `statusMessage` is Codex-specific and shows there
|
|
55
|
+
// what is currently running.
|
|
46
56
|
function codexSettings(projectRoot) {
|
|
47
|
-
const c = (script
|
|
57
|
+
const c = (script, statusMessage, timeout = 15) => ({
|
|
58
|
+
type: "command", _managedBy: "openwolf", statusMessage,
|
|
59
|
+
command: cmd(projectRoot, script, { literal: true, exportVar: true }), timeout,
|
|
60
|
+
});
|
|
61
|
+
const WRITE = "^(Edit|Write|MultiEdit|apply_patch)$";
|
|
62
|
+
const READ = "^(Read|read_file)$";
|
|
48
63
|
return {
|
|
49
64
|
hooks: {
|
|
50
|
-
|
|
65
|
+
// [2026-08-20, review] NO matcher here on purpose. `startup|resume|clear` omits `compact`,
|
|
66
|
+
// and session-start.ts has a dedicated branch for source === "compact" that re-injects the
|
|
67
|
+
// post-compaction digest — which this same change newly makes reachable by deploying
|
|
68
|
+
// PreCompact to Codex. Claude's entry matches every source too (matcher: "").
|
|
69
|
+
SessionStart: [{ hooks: [c("session-start.js", "OpenWolf session bootstrap")] }],
|
|
70
|
+
PreToolUse: [
|
|
71
|
+
{ matcher: READ, hooks: [c("pre-read.js", "OpenWolf read precheck")] },
|
|
72
|
+
{ matcher: WRITE, hooks: [c("pre-write.js", "OpenWolf write precheck")] },
|
|
73
|
+
],
|
|
51
74
|
PostToolUse: [
|
|
52
|
-
{ matcher:
|
|
53
|
-
{ matcher:
|
|
75
|
+
{ matcher: READ, hooks: [c("post-read.js", "OpenWolf read tracking")] },
|
|
76
|
+
{ matcher: WRITE, hooks: [c("post-write.js", "OpenWolf anatomy update", 20)] },
|
|
77
|
+
{ matcher: "^(Bash|shell|local_shell)$", hooks: [c("post-bash.js", "OpenWolf shell tracking")] },
|
|
54
78
|
],
|
|
55
|
-
|
|
79
|
+
PreCompact: [{ hooks: [c("precompact.js", "OpenWolf compaction snapshot")] }],
|
|
80
|
+
Stop: [{ hooks: [c("stop.js", "OpenWolf session wrap-up", 20)] }],
|
|
56
81
|
},
|
|
57
82
|
};
|
|
58
83
|
}
|
|
84
|
+
// Codex only reads hooks when `hooks = true` sits under `[features]`. Without that switch a
|
|
85
|
+
// perfectly fine-looking hooks.json is there and none of it fires — so we create the file when it
|
|
86
|
+
// is missing and WARN otherwise, rather than editing someone else's config.toml.
|
|
87
|
+
function ensureCodexFeatureFlag(codexDir) {
|
|
88
|
+
const p = path.join(codexDir, "config.toml");
|
|
89
|
+
if (!fs.existsSync(p)) {
|
|
90
|
+
writeText(p, "[features]\nhooks = true\n");
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
const existing = fs.readFileSync(p, "utf-8");
|
|
94
|
+
// Anchored AND table-scoped. [2026-08-20, review] Anchoring alone still accepted `hooks = true`
|
|
95
|
+
// under any other table (e.g. `[experimental]`), where Codex ignores it — the warning would be
|
|
96
|
+
// swallowed while the hooks stayed dead. So: find [features] and look only until the next table.
|
|
97
|
+
const lines = existing.split(/\r?\n/);
|
|
98
|
+
let inFeatures = false;
|
|
99
|
+
for (const line of lines) {
|
|
100
|
+
const table = line.match(/^\s*\[([^\]]+)\]\s*$/);
|
|
101
|
+
if (table) {
|
|
102
|
+
inFeatures = table[1].trim() === "features";
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (inFeatures && /^\s*hooks\s*=\s*true\s*$/.test(line))
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return 'set "hooks = true" under [features] in .codex/config.toml — otherwise Codex ignores the hooks';
|
|
109
|
+
}
|
|
59
110
|
// ---- Gemini: PostToolUse = AfterTool, Stop = SessionEnd; tools write_file/replace/run_shell_command.
|
|
60
111
|
// $GEMINI_PROJECT_DIR is documented. Timeouts are milliseconds here. ----
|
|
61
112
|
function geminiSettings() {
|
|
@@ -150,8 +201,18 @@ export function deployAgentHooks(projectRoot) {
|
|
|
150
201
|
for (const agent of detectAgents(projectRoot)) {
|
|
151
202
|
try {
|
|
152
203
|
if (agent === "codex") {
|
|
153
|
-
|
|
154
|
-
|
|
204
|
+
const codexDir = path.join(projectRoot, ".codex");
|
|
205
|
+
deployJsonAgent(codexDir, "hooks.json", codexSettings(projectRoot));
|
|
206
|
+
const warn = ensureCodexFeatureFlag(codexDir);
|
|
207
|
+
const ctx = upsertMarkerBlock(path.join(projectRoot, "AGENTS.md"), AGENTS_SNIPPET);
|
|
208
|
+
const bits = [".codex/hooks.json (re-approve trust in Codex)"];
|
|
209
|
+
if (ctx.changed)
|
|
210
|
+
bits.push("AGENTS.md block");
|
|
211
|
+
if (ctx.refused)
|
|
212
|
+
bits.push(`AGENTS.md skipped: ${ctx.refused}`);
|
|
213
|
+
if (warn)
|
|
214
|
+
bits.push(`⚠ ${warn}`);
|
|
215
|
+
results.push({ agent, deployed: true, detail: bits.join(" · ") });
|
|
155
216
|
}
|
|
156
217
|
else if (agent === "gemini") {
|
|
157
218
|
deployJsonAgent(path.join(projectRoot, ".gemini"), "settings.json", geminiSettings());
|
|
@@ -161,7 +222,10 @@ export function deployAgentHooks(projectRoot) {
|
|
|
161
222
|
const dir = path.join(projectRoot, ".opencode", "plugin");
|
|
162
223
|
ensureDir(dir);
|
|
163
224
|
writeText(path.join(dir, "openwolf.js"), opencodePlugin(projectRoot));
|
|
164
|
-
|
|
225
|
+
// OpenCode reads AGENTS.md as its context file — without the block it never sees the protocol.
|
|
226
|
+
const ctx = upsertMarkerBlock(path.join(projectRoot, "AGENTS.md"), AGENTS_SNIPPET);
|
|
227
|
+
results.push({ agent, deployed: true, detail: ".opencode/plugin/openwolf.js (compaction-only inject)"
|
|
228
|
+
+ (ctx.changed ? " · AGENTS.md block" : "") + (ctx.refused ? ` · AGENTS.md skipped: ${ctx.refused}` : "") });
|
|
165
229
|
}
|
|
166
230
|
}
|
|
167
231
|
catch (e) {
|
|
@@ -171,5 +235,5 @@ export function deployAgentHooks(projectRoot) {
|
|
|
171
235
|
return results;
|
|
172
236
|
}
|
|
173
237
|
// Exposed for tests.
|
|
174
|
-
export const _internal = { claudeSettings, codexSettings, geminiSettings, opencodePlugin, mergeManagedHooks };
|
|
238
|
+
export const _internal = { claudeSettings, codexSettings, geminiSettings, opencodePlugin, mergeManagedHooks, ensureCodexFeatureFlag };
|
|
175
239
|
//# sourceMappingURL=agent-hooks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-hooks.js","sourceRoot":"","sources":["../../../src/utils/agent-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"agent-hooks.js","sourceRoot":"","sources":["../../../src/utils/agent-hooks.ts"],"names":[],"mappings":"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"}
|