@event4u/agent-config 17.1.0 → 17.2.1

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 (73) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +92 -0
  5. package/README.md +2 -2
  6. package/dist/agent-src/commands/project/analyze.md +9 -6
  7. package/dist/agent-src/commands/project/map.md +58 -0
  8. package/dist/agent-src/commands/project.md +5 -3
  9. package/dist/agent-src/skills/code-intelligence/SKILL.md +6 -0
  10. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  11. package/dist/cli/registry.js +1 -1
  12. package/dist/cli-delegate/cmd_conformance.js +23 -39
  13. package/dist/discovery/deprecation-report.md +1 -1
  14. package/dist/discovery/discovery-manifest.json +39 -13
  15. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  16. package/dist/discovery/discovery-manifest.summary.md +3 -3
  17. package/dist/discovery/dormancy-report.md +1 -1
  18. package/dist/discovery/orphan-report.md +1 -1
  19. package/dist/discovery/packs.json +6 -5
  20. package/dist/discovery/trust-report.md +2 -2
  21. package/dist/discovery/workspaces.json +5 -4
  22. package/dist/hooks/dispatch.js +65 -74
  23. package/dist/hooks/dispatch.sha256 +1 -1
  24. package/dist/hooks/instructions_observer.chunk.cjs +301 -0
  25. package/dist/hooks/instructions_observer.chunk.cjs.sha256 +1 -0
  26. package/dist/mcp/registry-manifest.json +2 -2
  27. package/dist/mcp/server.json +2 -2
  28. package/dist/mcp/server.mjs +33058 -22930
  29. package/package.json +4 -1
  30. package/src/config/continuity-surface.json +7 -0
  31. package/src/config/evaluator-budgets.json +4 -4
  32. package/src/config/gate-violation-baselines.json +3 -3
  33. package/src/config/gitignore-block.txt +6 -0
  34. package/src/config/hook-bundle-budget.json +17 -2
  35. package/src/config/hook-token-budget.json +1 -1
  36. package/src/config/packed-binary-manifest.json +27 -0
  37. package/src/config/skill-body-budget.json +7 -1
  38. package/src/scripts/_lib/bench_ab_complexity.ts +14 -2
  39. package/src/scripts/_lib/collector_record.ts +1 -0
  40. package/src/scripts/_lib/runtime_journal.ts +7 -7
  41. package/src/scripts/code_graph/build.ts +210 -10
  42. package/src/scripts/code_graph/cli.ts +168 -46
  43. package/src/scripts/code_graph/detect.ts +5 -4
  44. package/src/scripts/code_graph/docs_layer.ts +57 -0
  45. package/src/scripts/code_graph/extract.ts +58 -13
  46. package/src/scripts/code_graph/extract_more.ts +314 -0
  47. package/src/scripts/code_graph/laravel_overlay.ts +454 -0
  48. package/src/scripts/code_graph/map.ts +846 -0
  49. package/src/scripts/code_graph/map_model.ts +977 -0
  50. package/src/scripts/code_graph/map_verify.ts +140 -0
  51. package/src/scripts/code_graph/map_viewer/viewer.css +278 -0
  52. package/src/scripts/code_graph/map_viewer/viewer.js +756 -0
  53. package/src/scripts/code_graph/scip_reader.ts +201 -0
  54. package/src/scripts/code_graph/sqlite_store.ts +8 -1
  55. package/src/scripts/code_graph/types.ts +81 -15
  56. package/src/scripts/code_graph/validate.ts +16 -26
  57. package/src/scripts/code_graph/verbs.ts +7 -0
  58. package/src/scripts/hook_chunks.mjs +7 -0
  59. package/src/scripts/hook_manifest.json +1 -1
  60. package/src/scripts/hook_manifest.yaml +20 -0
  61. package/src/scripts/hooks/dispatch_hook.ts +2 -2
  62. package/src/scripts/hooks/instructions_observer_hook.ts +25 -6
  63. package/src/scripts/hooks/lazy_concern.ts +4 -0
  64. package/src/scripts/install-hooks.sh +5 -0
  65. package/src/scripts/lint_agents_layout.ts +2 -0
  66. package/src/scripts/lint_hook_manifest.ts +1 -0
  67. package/src/scripts/mcp_server/consumer_tool_catalog.json +53 -6
  68. package/src/scripts/mcp_server/graph_tools.ts +73 -1
  69. package/src/scripts/mcp_server/tools.ts +19 -36
  70. package/src/vendor/grammars/README.md +10 -5
  71. package/src/vendor/grammars/tree-sitter-go.wasm +0 -0
  72. package/src/vendor/grammars/tree-sitter-java.wasm +0 -0
  73. package/src/vendor/grammars/tree-sitter-python.wasm +0 -0
@@ -0,0 +1,314 @@
1
+ /**
2
+ * Python, Go and Java extraction — the same shape `extract.ts` emits for
3
+ * PHP / TS / JS, so the build pass resolves them with no language branch
4
+ * beyond module lookup.
5
+ *
6
+ * definitions classes / interfaces / structs, functions, methods
7
+ * imports with the module as written, for `build.ts` to map to a file
8
+ * inherits superclasses, implemented interfaces
9
+ * calls free calls, `self.` / `this.` calls on the enclosing class,
10
+ * `X.m()` scoped calls, `new X()`, and dynamic member calls
11
+ */
12
+ import { type FileExtract, loc, namedChildren, nameField, uniq } from './extract.js';
13
+ import type { TsNode } from './loader.js';
14
+
15
+ function text(n: TsNode | null | undefined): string {
16
+ return n ? n.text : '';
17
+ }
18
+
19
+ /** Every descendant of `type`, document order. */
20
+ function descendants(n: TsNode, type: string): TsNode[] {
21
+ const out: TsNode[] = [];
22
+ const visit = (x: TsNode): void => {
23
+ for (const c of namedChildren(x)) {
24
+ if (c.type === type) out.push(c);
25
+ visit(c);
26
+ }
27
+ };
28
+ visit(n);
29
+ return out;
30
+ }
31
+
32
+ /** Node identity: the runtime hands out a fresh wrapper per access. */
33
+ function same(a: TsNode | null, b: TsNode | null): boolean {
34
+ return (
35
+ a !== null &&
36
+ b !== null &&
37
+ a.type === b.type &&
38
+ a.startPosition.row === b.startPosition.row &&
39
+ a.startPosition.column === b.startPosition.column
40
+ );
41
+ }
42
+
43
+ function lastSegment(dotted: string): string {
44
+ const parts = dotted.split(/[./]/);
45
+ return parts[parts.length - 1] ?? dotted;
46
+ }
47
+
48
+ export function extractPython(root: TsNode, file: string, out: FileExtract): void {
49
+ out.nodes.push({ id: file, label: file, kind: 'file', source_file: file, source_location: [] });
50
+ const walk = (n: TsNode, classId: string | null, scopeId: string): void => {
51
+ switch (n.type) {
52
+ case 'import_statement': {
53
+ for (const c of namedChildren(n)) {
54
+ const dotted = c.type === 'aliased_import' ? c.childForFieldName('name') : c;
55
+ const alias = c.type === 'aliased_import' ? text(c.childForFieldName('alias')) : '';
56
+ const spec = text(dotted);
57
+ if (!spec) continue;
58
+ out.rawEdges.push({
59
+ sourceId: file,
60
+ relation: 'imports',
61
+ targetName: lastSegment(spec),
62
+ confidenceHint: 'EXTRACTED',
63
+ moduleSpecifier: spec,
64
+ importKind: 'namespace',
65
+ localName: alias || (spec.split('.')[0] as string),
66
+ });
67
+ }
68
+ return;
69
+ }
70
+ case 'import_from_statement': {
71
+ const mod = text(n.childForFieldName('module_name'));
72
+ for (const c of namedChildren(n)) {
73
+ if (same(c, n.childForFieldName('module_name'))) continue;
74
+ if (c.type !== 'dotted_name' && c.type !== 'aliased_import') continue;
75
+ const name = c.type === 'aliased_import' ? text(c.childForFieldName('name')) : text(c);
76
+ const alias = c.type === 'aliased_import' ? text(c.childForFieldName('alias')) : '';
77
+ out.rawEdges.push({
78
+ sourceId: file,
79
+ relation: 'imports',
80
+ targetName: name,
81
+ confidenceHint: 'EXTRACTED',
82
+ moduleSpecifier: mod,
83
+ importKind: 'named',
84
+ ...(alias ? { localName: alias } : {}),
85
+ });
86
+ }
87
+ return;
88
+ }
89
+ case 'class_definition': {
90
+ const nm = nameField(n) ?? '<anon>';
91
+ const id = uniq(out, `${file}#${nm}`);
92
+ out.nodes.push({ id, label: nm, kind: 'class', source_file: file, source_location: loc(n) });
93
+ out.rawEdges.push({ sourceId: file, relation: 'member', targetName: nm, confidenceHint: 'EXTRACTED' });
94
+ const supers = n.childForFieldName('superclasses');
95
+ if (supers)
96
+ for (const s of namedChildren(supers))
97
+ if (s.type === 'identifier' || s.type === 'attribute') out.inherits.push({ classId: id, parentName: lastSegment(s.text) });
98
+ const body = n.childForFieldName('body');
99
+ if (body) for (const c of namedChildren(body)) walk(c, id, id);
100
+ return;
101
+ }
102
+ case 'function_definition': {
103
+ const nm = nameField(n) ?? '<anon>';
104
+ const id = uniq(out, classId ? `${classId}::${nm}` : `${file}#${nm}`);
105
+ out.nodes.push({ id, label: nm, kind: classId ? 'method' : 'function', source_file: file, source_location: loc(n) });
106
+ out.rawEdges.push({ sourceId: classId ?? file, relation: 'member', targetName: nm, confidenceHint: 'EXTRACTED' });
107
+ const body = n.childForFieldName('body');
108
+ // A nested def is a local helper: its calls belong to it, and it
109
+ // no longer sees the class as `self`.
110
+ if (body) for (const c of namedChildren(body)) walk(c, null, id);
111
+ return;
112
+ }
113
+ case 'call': {
114
+ const fn = n.childForFieldName('function');
115
+ if (fn?.type === 'identifier') {
116
+ out.rawEdges.push({ sourceId: scopeId, relation: 'calls', targetName: fn.text, confidenceHint: 'EXTRACTED', callStyle: 'free' });
117
+ } else if (fn?.type === 'attribute') {
118
+ const obj = fn.childForFieldName('object');
119
+ const attr = text(fn.childForFieldName('attribute'));
120
+ const isSelf = obj?.type === 'identifier' && (obj.text === 'self' || obj.text === 'cls');
121
+ out.rawEdges.push({
122
+ sourceId: scopeId,
123
+ relation: 'calls',
124
+ targetName: attr,
125
+ confidenceHint: isSelf && classId ? 'INFERRED' : 'AMBIGUOUS',
126
+ callStyle: isSelf ? 'this' : 'dynamic',
127
+ ...(classId ? { enclosingClassId: classId } : {}),
128
+ });
129
+ }
130
+ break;
131
+ }
132
+ default:
133
+ break;
134
+ }
135
+ for (const c of namedChildren(n)) walk(c, classId, scopeId);
136
+ };
137
+ walk(root, null, file);
138
+ }
139
+
140
+ export function extractJava(root: TsNode, file: string, out: FileExtract): void {
141
+ out.nodes.push({ id: file, label: file, kind: 'file', source_file: file, source_location: [] });
142
+ const TYPES: Record<string, 'class' | 'interface' | 'enum'> = {
143
+ class_declaration: 'class',
144
+ record_declaration: 'class',
145
+ interface_declaration: 'interface',
146
+ enum_declaration: 'enum',
147
+ };
148
+ const walk = (n: TsNode, classId: string | null, scopeId: string): void => {
149
+ const kind = TYPES[n.type];
150
+ if (kind) {
151
+ const nm = nameField(n) ?? '<anon>';
152
+ const id = uniq(out, classId ? `${classId}::${nm}` : `${file}#${nm}`);
153
+ out.nodes.push({ id, label: nm, kind, source_file: file, source_location: loc(n) });
154
+ out.rawEdges.push({ sourceId: classId ?? file, relation: 'member', targetName: nm, confidenceHint: 'EXTRACTED' });
155
+ for (const c of namedChildren(n)) {
156
+ if (c.type === 'superclass' || c.type === 'super_interfaces' || c.type === 'extends_interfaces') {
157
+ for (const t of descendants(c, 'type_identifier')) out.inherits.push({ classId: id, parentName: t.text });
158
+ }
159
+ }
160
+ const body = n.childForFieldName('body');
161
+ if (body) for (const c of namedChildren(body)) walk(c, id, id);
162
+ return;
163
+ }
164
+ switch (n.type) {
165
+ case 'import_declaration': {
166
+ const spec = namedChildren(n).find((c) => c.type === 'scoped_identifier' || c.type === 'identifier');
167
+ if (spec && !n.text.includes('*')) {
168
+ out.rawEdges.push({
169
+ sourceId: file,
170
+ relation: 'imports',
171
+ targetName: lastSegment(spec.text),
172
+ confidenceHint: 'EXTRACTED',
173
+ moduleSpecifier: spec.text,
174
+ importKind: 'named',
175
+ });
176
+ }
177
+ return;
178
+ }
179
+ case 'method_declaration':
180
+ case 'constructor_declaration': {
181
+ const nm = nameField(n) ?? '<anon>';
182
+ const id = uniq(out, classId ? `${classId}::${nm}` : `${file}#${nm}`);
183
+ out.nodes.push({ id, label: nm, kind: 'method', source_file: file, source_location: loc(n) });
184
+ out.rawEdges.push({ sourceId: classId ?? file, relation: 'member', targetName: nm, confidenceHint: 'EXTRACTED' });
185
+ const body = n.childForFieldName('body');
186
+ if (body) for (const c of namedChildren(body)) walk(c, classId, id);
187
+ return;
188
+ }
189
+ case 'method_invocation': {
190
+ const obj = n.childForFieldName('object');
191
+ const nm = text(n.childForFieldName('name'));
192
+ if (!obj || obj.type === 'this') {
193
+ out.rawEdges.push({
194
+ sourceId: scopeId,
195
+ relation: 'calls',
196
+ targetName: nm,
197
+ confidenceHint: classId ? 'INFERRED' : 'AMBIGUOUS',
198
+ callStyle: 'this',
199
+ ...(classId ? { enclosingClassId: classId } : {}),
200
+ });
201
+ } else if (obj.type === 'identifier' && /^[A-Z]/.test(obj.text)) {
202
+ out.rawEdges.push({
203
+ sourceId: scopeId,
204
+ relation: 'calls',
205
+ targetName: nm,
206
+ confidenceHint: 'AMBIGUOUS',
207
+ callStyle: 'scoped',
208
+ scopeName: obj.text,
209
+ ...(classId ? { enclosingClassId: classId } : {}),
210
+ });
211
+ } else {
212
+ out.rawEdges.push({
213
+ sourceId: scopeId,
214
+ relation: 'calls',
215
+ targetName: nm,
216
+ confidenceHint: 'AMBIGUOUS',
217
+ callStyle: 'dynamic',
218
+ ...(classId ? { enclosingClassId: classId } : {}),
219
+ });
220
+ }
221
+ break;
222
+ }
223
+ case 'object_creation_expression': {
224
+ const t = n.childForFieldName('type');
225
+ if (t) out.rawEdges.push({ sourceId: scopeId, relation: 'calls', targetName: lastSegment(t.text.replace(/<.*$/, '')), confidenceHint: 'EXTRACTED', callStyle: 'new' });
226
+ break;
227
+ }
228
+ default:
229
+ break;
230
+ }
231
+ for (const c of namedChildren(n)) walk(c, classId, scopeId);
232
+ };
233
+ walk(root, null, file);
234
+ }
235
+
236
+ export function extractGo(root: TsNode, file: string, out: FileExtract): void {
237
+ out.nodes.push({ id: file, label: file, kind: 'file', source_file: file, source_location: [] });
238
+ const walk = (n: TsNode, scopeId: string): void => {
239
+ switch (n.type) {
240
+ case 'import_spec': {
241
+ const spec = text(n.childForFieldName('path')).replace(/^["`]|["`]$/g, '');
242
+ const alias = text(n.childForFieldName('name'));
243
+ if (spec && alias !== '_') {
244
+ out.rawEdges.push({
245
+ sourceId: file,
246
+ relation: 'imports',
247
+ targetName: lastSegment(spec),
248
+ confidenceHint: 'EXTRACTED',
249
+ moduleSpecifier: spec,
250
+ importKind: 'namespace',
251
+ ...(alias && alias !== '.' ? { localName: alias } : {}),
252
+ });
253
+ }
254
+ return;
255
+ }
256
+ case 'type_spec': {
257
+ const nm = text(n.childForFieldName('name'));
258
+ const t = n.childForFieldName('type');
259
+ const kind = t?.type === 'interface_type' ? 'interface' : t?.type === 'struct_type' ? 'class' : 'type';
260
+ const id = uniq(out, `${file}#${nm}`);
261
+ out.nodes.push({ id, label: nm, kind, source_file: file, source_location: loc(n) });
262
+ out.rawEdges.push({ sourceId: file, relation: 'member', targetName: nm, confidenceHint: 'EXTRACTED' });
263
+ return;
264
+ }
265
+ case 'function_declaration': {
266
+ const nm = nameField(n) ?? '<anon>';
267
+ const id = uniq(out, `${file}#${nm}`);
268
+ out.nodes.push({ id, label: nm, kind: 'function', source_file: file, source_location: loc(n) });
269
+ out.rawEdges.push({ sourceId: file, relation: 'member', targetName: nm, confidenceHint: 'EXTRACTED' });
270
+ const body = n.childForFieldName('body');
271
+ if (body) walk(body, id);
272
+ return;
273
+ }
274
+ case 'method_declaration': {
275
+ const nm = nameField(n) ?? '<anon>';
276
+ const recv = n.childForFieldName('receiver');
277
+ const typeName = recv ? (descendants(recv, 'type_identifier')[0]?.text ?? '') : '';
278
+ const id = uniq(out, typeName ? `${file}#${typeName}::${nm}` : `${file}#${nm}`);
279
+ out.nodes.push({ id, label: nm, kind: 'method', source_file: file, source_location: loc(n) });
280
+ // The receiver type may be declared in another file of the
281
+ // package, so the member link hangs off the file, named so the
282
+ // build pass derives this method's own id from it.
283
+ out.rawEdges.push({
284
+ sourceId: file,
285
+ relation: 'member',
286
+ targetName: id.slice(file.length + 1),
287
+ confidenceHint: 'EXTRACTED',
288
+ });
289
+ const body = n.childForFieldName('body');
290
+ if (body) walk(body, id);
291
+ return;
292
+ }
293
+ case 'call_expression': {
294
+ const fn = n.childForFieldName('function');
295
+ if (fn?.type === 'identifier') {
296
+ out.rawEdges.push({ sourceId: scopeId, relation: 'calls', targetName: fn.text, confidenceHint: 'EXTRACTED', callStyle: 'free' });
297
+ } else if (fn?.type === 'selector_expression') {
298
+ out.rawEdges.push({
299
+ sourceId: scopeId,
300
+ relation: 'calls',
301
+ targetName: text(fn.childForFieldName('field')),
302
+ confidenceHint: 'AMBIGUOUS',
303
+ callStyle: 'dynamic',
304
+ });
305
+ }
306
+ break;
307
+ }
308
+ default:
309
+ break;
310
+ }
311
+ for (const c of namedChildren(n)) walk(c, scopeId);
312
+ };
313
+ walk(root, file);
314
+ }