@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,140 @@
1
+ /**
2
+ * Render check for `agents/map/index.html`.
3
+ *
4
+ * The map draws its labels on a canvas, so a DOM overflow check passes while a
5
+ * label is cut off or sits on top of another. This opens the page in a real
6
+ * browser at the three widths `ui:render` uses and asks the viewer itself for
7
+ * the boxes it placed (`window.__mapLabelBoxes`), in the overview and inside
8
+ * the largest area. It also fails on a page error, on any request that is not
9
+ * the file itself, and on horizontal scroll.
10
+ *
11
+ * Playwright is a devDependency: a consumer usually has no browser, and then
12
+ * the result is `unverified` with the reason — never a pass.
13
+ */
14
+ import { pathToFileURL } from 'node:url';
15
+
16
+ /**
17
+ * The slice of Playwright this check drives, declared here rather than
18
+ * imported: the package is a devDependency, and even a type-only import of it
19
+ * makes this module look like it needs one at runtime.
20
+ */
21
+ interface PwLocator {
22
+ first(): PwLocator;
23
+ count(): Promise<number>;
24
+ click(): Promise<void>;
25
+ }
26
+ interface PwPage {
27
+ on(event: 'pageerror', fn: () => void): void;
28
+ on(event: 'request', fn: (r: { url(): string }) => void): void;
29
+ goto(url: string): Promise<unknown>;
30
+ waitForFunction(fn: () => boolean): Promise<unknown>;
31
+ evaluate<T>(fn: () => T): Promise<T>;
32
+ locator(selector: string): PwLocator;
33
+ close(): Promise<void>;
34
+ }
35
+ interface PwBrowser {
36
+ newPage(opts: { viewport: { width: number; height: number } }): Promise<PwPage>;
37
+ close(): Promise<void>;
38
+ }
39
+ interface PwChromium {
40
+ launch(): Promise<PwBrowser>;
41
+ }
42
+
43
+ export const MAP_VIEWPORTS = [
44
+ { name: 'desktop', width: 1440, height: 900 },
45
+ { name: 'mobile-375', width: 375, height: 812 },
46
+ { name: 'mobile-320', width: 320, height: 640 },
47
+ ] as const;
48
+
49
+ export interface MapRenderCheck {
50
+ verification: 'verified' | 'failed' | 'unverified';
51
+ reason?: string;
52
+ viewports: Array<{
53
+ name: string;
54
+ pageErrors: number;
55
+ externalRequests: number;
56
+ horizontalScroll: boolean;
57
+ views: Array<{ view: string; labels: number; outside: number; overlapping: number }>;
58
+ }>;
59
+ }
60
+
61
+ interface Box {
62
+ x: number;
63
+ y: number;
64
+ w: number;
65
+ h: number;
66
+ }
67
+
68
+ /** Labels outside the canvas and label pairs that overlap — pure, so it is testable without a browser. */
69
+ export function labelProblems(boxes: readonly Box[], width: number, height: number): { outside: number; overlapping: number } {
70
+ let outside = 0;
71
+ let overlapping = 0;
72
+ for (const b of boxes) if (b.x < 0 || b.y < 0 || b.x + b.w > width || b.y + b.h > height) outside += 1;
73
+ for (let i = 0; i < boxes.length; i++) {
74
+ for (let j = i + 1; j < boxes.length; j++) {
75
+ const a = boxes[i] as Box;
76
+ const c = boxes[j] as Box;
77
+ if (a.x < c.x + c.w && c.x < a.x + a.w && a.y < c.y + c.h && c.y < a.y + a.h) overlapping += 1;
78
+ }
79
+ }
80
+ return { outside, overlapping };
81
+ }
82
+
83
+ export async function verifyMap(htmlPath: string): Promise<MapRenderCheck> {
84
+ let chromium: PwChromium;
85
+ try {
86
+ // Through a variable: a literal specifier lets every bundle that reaches
87
+ // this module (the MCP server does, via cli.ts) try to inline a
88
+ // devDependency it does not ship.
89
+ const specifier = '@playwright/test';
90
+ ({ chromium } = (await import(specifier)) as { chromium: PwChromium });
91
+ } catch {
92
+ return { verification: 'unverified', reason: '@playwright/test is not installed (a devDependency)', viewports: [] };
93
+ }
94
+ let browser: PwBrowser;
95
+ try {
96
+ browser = await chromium.launch();
97
+ } catch (e) {
98
+ return { verification: 'unverified', reason: `no browser could start: ${(e as Error).message.split('\n')[0]}`, viewports: [] };
99
+ }
100
+ const url = pathToFileURL(htmlPath).href;
101
+ const out: MapRenderCheck = { verification: 'verified', viewports: [] };
102
+ try {
103
+ for (const vp of MAP_VIEWPORTS) {
104
+ const page = await browser.newPage({ viewport: { width: vp.width, height: vp.height } });
105
+ let pageErrors = 0;
106
+ let externalRequests = 0;
107
+ page.on('pageerror', () => {
108
+ pageErrors += 1;
109
+ });
110
+ page.on('request', (r) => {
111
+ if (r.url() !== url) externalRequests += 1;
112
+ });
113
+ await page.goto(url);
114
+ await page.waitForFunction(() => (window as unknown as { __mapLabelBoxes?: unknown }).__mapLabelBoxes !== undefined);
115
+ const read = async (view: string): Promise<{ view: string; labels: number; outside: number; overlapping: number }> => {
116
+ const r = (await page.evaluate(() => (window as unknown as { __mapLabelBoxes: { boxes: Box[]; width: number; height: number } }).__mapLabelBoxes)) as {
117
+ boxes: Box[];
118
+ width: number;
119
+ height: number;
120
+ };
121
+ return { view, labels: r.boxes.length, ...labelProblems(r.boxes, r.width, r.height) };
122
+ };
123
+ const views = [await read('overview')];
124
+ const firstArea = page.locator('#panel .plist button').first();
125
+ if ((await firstArea.count()) > 0) {
126
+ await firstArea.click();
127
+ views.push(await read('largest-area'));
128
+ }
129
+ const horizontalScroll = await page.evaluate(() => document.documentElement.scrollWidth > window.innerWidth);
130
+ out.viewports.push({ name: vp.name, pageErrors, externalRequests, horizontalScroll, views });
131
+ if (pageErrors || externalRequests || horizontalScroll || views.some((v) => v.outside || v.overlapping)) {
132
+ out.verification = 'failed';
133
+ }
134
+ await page.close();
135
+ }
136
+ } finally {
137
+ await browser.close();
138
+ }
139
+ return out;
140
+ }
@@ -0,0 +1,278 @@
1
+ :root {
2
+ --bg: #f7f7f5;
3
+ --panel: #ffffff;
4
+ --text: #1d1f23;
5
+ --muted: #5d636e;
6
+ --line: #d9dbe0;
7
+ --edge: rgba(40, 48, 64, 0.32);
8
+ --edge-strong: rgba(40, 48, 64, 0.62);
9
+ --grey-node: #b4b8c1;
10
+ --accent: #2f5bd3;
11
+ --focus: #2f5bd3;
12
+ --change: #d1495b;
13
+ --good: #2e8b57;
14
+ --contested: #d98b1d;
15
+ }
16
+ @media (prefers-color-scheme: dark) {
17
+ :root:not([data-theme='light']) {
18
+ --bg: #14161a;
19
+ --panel: #1c1f25;
20
+ --text: #e7e9ee;
21
+ --muted: #9aa1ad;
22
+ --line: #2e333c;
23
+ --edge: rgba(200, 208, 224, 0.22);
24
+ --edge-strong: rgba(220, 228, 244, 0.55);
25
+ --grey-node: #555b66;
26
+ --accent: #8aa8ff;
27
+ --focus: #8aa8ff;
28
+ --change: #ff7a8a;
29
+ --good: #5fd39a;
30
+ --contested: #ffb347;
31
+ }
32
+ }
33
+ :root[data-theme='dark'] {
34
+ --bg: #14161a;
35
+ --panel: #1c1f25;
36
+ --text: #e7e9ee;
37
+ --muted: #9aa1ad;
38
+ --line: #2e333c;
39
+ --edge: rgba(200, 208, 224, 0.22);
40
+ --edge-strong: rgba(220, 228, 244, 0.55);
41
+ --grey-node: #555b66;
42
+ --accent: #8aa8ff;
43
+ --focus: #8aa8ff;
44
+ --change: #ff7a8a;
45
+ --good: #5fd39a;
46
+ --contested: #ffb347;
47
+ }
48
+ * {
49
+ box-sizing: border-box;
50
+ }
51
+ html,
52
+ body {
53
+ margin: 0;
54
+ height: 100%;
55
+ background: var(--bg);
56
+ color: var(--text);
57
+ font: 14px/1.4 system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
58
+ }
59
+ body {
60
+ display: grid;
61
+ grid-template-rows: auto 1fr;
62
+ overflow: hidden;
63
+ }
64
+ header {
65
+ display: flex;
66
+ flex-wrap: wrap;
67
+ align-items: center;
68
+ gap: 8px;
69
+ padding: 8px 16px;
70
+ border-bottom: 1px solid var(--line);
71
+ background: var(--panel);
72
+ }
73
+ header h1 {
74
+ font-size: 15px;
75
+ margin: 0 8px 0 0;
76
+ white-space: nowrap;
77
+ }
78
+ .crumbs {
79
+ display: flex;
80
+ gap: 4px;
81
+ align-items: center;
82
+ min-width: 0;
83
+ flex: 1 1 200px;
84
+ overflow: hidden;
85
+ }
86
+ .crumbs button {
87
+ max-width: 220px;
88
+ overflow: hidden;
89
+ text-overflow: ellipsis;
90
+ white-space: nowrap;
91
+ }
92
+ .crumbs span {
93
+ color: var(--muted);
94
+ }
95
+ button,
96
+ input,
97
+ select {
98
+ font: inherit;
99
+ color: var(--text);
100
+ background: var(--bg);
101
+ border: 1px solid var(--line);
102
+ border-radius: 6px;
103
+ padding: 4px 8px;
104
+ }
105
+ button {
106
+ cursor: pointer;
107
+ }
108
+ button[aria-pressed='true'] {
109
+ border-color: var(--accent);
110
+ color: var(--accent);
111
+ }
112
+ :focus-visible {
113
+ outline: 2px solid var(--focus);
114
+ outline-offset: 1px;
115
+ }
116
+ .search {
117
+ position: relative;
118
+ flex: 0 1 260px;
119
+ min-width: 140px;
120
+ }
121
+ .search input {
122
+ width: 100%;
123
+ }
124
+ .results {
125
+ position: absolute;
126
+ top: 100%;
127
+ left: 0;
128
+ right: 0;
129
+ z-index: 5;
130
+ margin: 2px 0 0;
131
+ padding: 0;
132
+ list-style: none;
133
+ background: var(--panel);
134
+ border: 1px solid var(--line);
135
+ border-radius: 6px;
136
+ max-height: 50vh;
137
+ overflow: auto;
138
+ }
139
+ .results li button {
140
+ width: 100%;
141
+ text-align: left;
142
+ border: 0;
143
+ border-radius: 0;
144
+ background: transparent;
145
+ }
146
+ .toolbar {
147
+ display: flex;
148
+ flex-wrap: wrap;
149
+ gap: 4px;
150
+ }
151
+ main {
152
+ display: grid;
153
+ grid-template-columns: 1fr 340px;
154
+ min-height: 0;
155
+ }
156
+ .stage {
157
+ position: relative;
158
+ min-width: 0;
159
+ min-height: 0;
160
+ }
161
+ canvas {
162
+ display: block;
163
+ width: 100%;
164
+ height: 100%;
165
+ touch-action: none;
166
+ }
167
+ aside {
168
+ border-left: 1px solid var(--line);
169
+ background: var(--panel);
170
+ overflow: auto;
171
+ padding: 12px 16px;
172
+ min-width: 0;
173
+ }
174
+ aside h2 {
175
+ font-size: 15px;
176
+ margin: 0 0 4px;
177
+ overflow-wrap: anywhere;
178
+ }
179
+ aside h3 {
180
+ font-size: 12px;
181
+ text-transform: uppercase;
182
+ letter-spacing: 0.04em;
183
+ color: var(--muted);
184
+ margin: 14px 0 4px;
185
+ }
186
+ .meta {
187
+ color: var(--muted);
188
+ font-size: 12px;
189
+ }
190
+ .plist {
191
+ list-style: none;
192
+ margin: 0;
193
+ padding: 0;
194
+ }
195
+ .plist li {
196
+ margin: 0 0 2px;
197
+ }
198
+ .plist button {
199
+ display: block;
200
+ width: 100%;
201
+ text-align: left;
202
+ border: 0;
203
+ background: transparent;
204
+ padding: 2px 4px;
205
+ }
206
+ .plist button:hover {
207
+ background: var(--bg);
208
+ }
209
+ .fname {
210
+ display: block;
211
+ white-space: nowrap;
212
+ overflow: hidden;
213
+ text-overflow: ellipsis;
214
+ }
215
+ .fdir {
216
+ display: block;
217
+ color: var(--muted);
218
+ font-size: 12px;
219
+ white-space: nowrap;
220
+ overflow: hidden;
221
+ text-overflow: ellipsis;
222
+ }
223
+ .swatch {
224
+ display: inline-block;
225
+ width: 10px;
226
+ height: 10px;
227
+ border-radius: 50%;
228
+ margin-right: 6px;
229
+ vertical-align: baseline;
230
+ }
231
+ .kv {
232
+ display: grid;
233
+ grid-template-columns: auto 1fr;
234
+ gap: 2px 10px;
235
+ font-size: 13px;
236
+ }
237
+ .kv dt {
238
+ color: var(--muted);
239
+ }
240
+ .kv dd {
241
+ margin: 0;
242
+ overflow-wrap: anywhere;
243
+ }
244
+ code {
245
+ font: 12px ui-monospace, SFMono-Regular, Menlo, monospace;
246
+ }
247
+ .more {
248
+ color: var(--muted);
249
+ font-size: 12px;
250
+ padding: 2px 4px;
251
+ }
252
+ @media (max-width: 760px) {
253
+ main {
254
+ grid-template-columns: 1fr;
255
+ grid-template-rows: 1fr minmax(160px, 40vh);
256
+ }
257
+ aside {
258
+ border-left: 0;
259
+ border-top: 1px solid var(--line);
260
+ }
261
+ header h1 {
262
+ display: none;
263
+ }
264
+ }
265
+ @media (prefers-reduced-motion: reduce) {
266
+ * {
267
+ transition: none !important;
268
+ animation: none !important;
269
+ }
270
+ }
271
+ details summary {
272
+ cursor: pointer;
273
+ padding: 2px 0;
274
+ overflow-wrap: anywhere;
275
+ }
276
+ details summary .swatch {
277
+ margin: 0 0 0 4px;
278
+ }