@shield-agent/kya 0.33.2 → 0.33.3

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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shield-kya",
3
- "version": "0.33.2",
3
+ "version": "0.33.3",
4
4
  "description": "Audit trail and traceability for AI agents. See what every coding agent did and check each tool call against policy.",
5
5
  "author": {
6
6
  "name": "Shield Agent",
package/.mcp.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
package/README.md CHANGED
@@ -383,7 +383,7 @@ MCP Registry entry: `server.json` plus package `mcpName` `io.github.The-Pixel-Bo
383
383
  "mcpServers": {
384
384
  "shield-kya": {
385
385
  "command": "npx",
386
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
386
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
387
387
  "env": {
388
388
  "KYA_BASE_URL": "http://127.0.0.1:8090",
389
389
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -427,7 +427,7 @@ Framework recipes (each one tested with a scripted model and the published CLI):
427
427
 
428
428
  ```bash
429
429
  # Prefer a preinstalled package (no registry auto-install):
430
- npx --no-install @shield-agent/kya@0.33.2 serve-mcp --stdio
430
+ npx --no-install @shield-agent/kya@0.33.3 serve-mcp --stdio
431
431
  # Or after npm i -g / local install:
432
432
  kya serve-mcp --stdio
433
433
  ```
@@ -438,7 +438,7 @@ Copy `claude/claude_desktop_config.example.json` into Claude Desktop MCP setting
438
438
 
439
439
  ## OpenAI (Codex / Responses)
440
440
 
441
- **Codex CLI plugin (hooks):** see [Codex plugin](#codex-plugin). **Codex CLI / IDE (MCP):** copy `openai/codex.config.example.toml` into `~/.codex/config.toml`. Local stdio uses `npx --no-install @shield-agent/kya@0.33.2 serve-mcp --stdio`. Hosted Codex uses `url = "https://shield-agent.com/mcp"` with `bearer_token_env_var = "KYA_API_KEY"`.
441
+ **Codex CLI plugin (hooks):** see [Codex plugin](#codex-plugin). **Codex CLI / IDE (MCP):** copy `openai/codex.config.example.toml` into `~/.codex/config.toml`. Local stdio uses `npx --no-install @shield-agent/kya@0.33.3 serve-mcp --stdio`. Hosted Codex uses `url = "https://shield-agent.com/mcp"` with `bearer_token_env_var = "KYA_API_KEY"`.
442
442
 
443
443
  **Responses API:** see `openai/responses-mcp.example.json` (`server_url` + `Authorization: Bearer <KYA_API_KEY>`).
444
444
 
@@ -2,7 +2,7 @@
2
2
  "amp.mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -55,6 +55,9 @@ export declare function drawModel(graph: MapGraph): {
55
55
  lastTs: string;
56
56
  }[];
57
57
  };
58
+ /** Navigation-only commands. The summary list hides them; the graph, the heat views and the JSON keep them. */
59
+ export declare const NAV_CLASSES: ReadonlySet<string>;
60
+ export declare const NAV_LINE = "Navigation commands (cd, ls, pwd) are not listed.";
58
61
  /**
59
62
  * The page body: summary, graph container, side panel, both heat tables, and the data. Used inside the standalone
60
63
  * file and as the live report's Map fragment. The graph is drawn by MAP_SCRIPT from the data element.
@@ -68,14 +71,14 @@ export declare const MAP_CSP = "default-src 'none'; style-src 'unsafe-inline'; s
68
71
  * The browser part. Labels go to Cytoscape (canvas) or textContent. The live body is parsed with DOMParser (the body
69
72
  * has no executable script), so this file never assigns innerHTML.
70
73
  */
71
- export declare const MAP_SCRIPT = "(function () {\n 'use strict';\n var cy = null;\n var last = null;\n var live = !!document.querySelector('main[data-live-token]');\n function token() {\n var m = /(?:^|[?&])t=([^&]*)/.exec(location.search);\n if (!m) return '';\n try { return decodeURIComponent(m[1]); } catch (e) { return m[1]; }\n }\n function model() {\n var el = document.getElementById('kya-map-data');\n if (!el) return null;\n try { return JSON.parse(el.textContent || 'null'); } catch (e) { return null; }\n }\n function add(parent, tag, text) {\n var n = document.createElement(tag);\n n.textContent = String(text);\n parent.appendChild(n);\n return n;\n }\n function showNode(node) {\n var panel = document.getElementById('kya-map-panel');\n if (!panel) return;\n while (panel.firstChild) panel.removeChild(panel.firstChild);\n add(panel, 'h3', node.kind + ': ' + node.label);\n add(panel, 'p', 'Class: ' + node.detail);\n var list = document.createElement('dl');\n panel.appendChild(list);\n [['Events', node.count], ['Allow', node.verdicts.allow], ['Deny', node.verdicts.deny], ['Hold', node.verdicts.hold],\n ['Observed', node.verdicts.observed], ['First seen', node.firstTs || '-'], ['Last seen', node.lastTs || '-']]\n .forEach(function (r) { add(list, 'dt', r[0]); add(list, 'dd', r[1]); });\n }\n function style(d) {\n var out = [\n { selector: 'node', style: { 'label': 'data(label)', 'font-size': 10, 'text-wrap': 'ellipsis', 'text-max-width': 130, 'min-zoomed-font-size': 9,\n 'text-background-color': '#ffffff', 'text-background-opacity': 0.8, 'text-background-padding': 1,\n 'width': 18, 'height': 18, 'background-color': '#98a2b3', 'color': '#101828' } },\n { selector: 'node[kind = \"device\"]', style: { 'background-color': '#344054', 'shape': 'round-rectangle', 'width': 34, 'height': 34 } },\n { selector: 'node[kind = \"agent\"]', style: { 'background-color': '#1d4ed8' } },\n { selector: 'node[kind = \"tool\"]', style: { 'background-color': '#7a5af8', 'shape': 'round-rectangle' } },\n { selector: 'node[kind = \"target\"]', style: { 'background-color': '#0e9384' } },\n { selector: 'edge', style: { 'width': 'data(width)', 'line-color': 'data(colour)', 'target-arrow-color': 'data(colour)',\n 'target-arrow-shape': 'triangle', 'curve-style': 'bezier', 'opacity': 0.9 } }\n ];\n return out;\n }\n var MAX_DRAW_NODES = 400;\n function draw() {\n var host = document.getElementById('kya-map-graph');\n var d = model();\n if (cy) { cy.destroy(); cy = null; }\n if (!host || !d || !window.cytoscape || !d.nodes || !d.nodes.length) return;\n // A force layout on thousands of nodes hangs the tab. The JSON and both heat views still hold everything.\n if (d.nodes.length > MAX_DRAW_NODES) {\n host.textContent = 'Graph not drawn: ' + d.nodes.length + ' nodes is too many for the page. Use a shorter window (kya map --days 1) or kya map --json.';\n return;\n }\n cy = window.cytoscape({\n container: host,\n elements: {\n nodes: d.nodes.map(function (n) { return { data: n }; }),\n edges: d.edges.map(function (e) { return { data: e }; })\n },\n style: style(d),\n layout: { name: 'cose', animate: false, randomize: true, fit: true, padding: 24, numIter: 900, nodeRepulsion: function () { return 9000; }, idealEdgeLength: function () { return 80; }, nodeOverlap: 14, gravity: 0.35 }\n });\n cy.on('tap', 'node', function (evt) { showNode(evt.target.data()); });\n cy.fit();\n }\n function refresh() {\n if (!live) return;\n var host = document.getElementById('frag-map');\n if (!host) return;\n fetch('/fragments?t=' + encodeURIComponent(token()), {\n method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{\"map\":true}'\n })\n .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })\n .then(function (j) {\n if (!j || !j.ok || !j.fragments || typeof j.fragments.mapBody !== 'string') return;\n if (j.fragments.mapBody === last) return;\n last = j.fragments.mapBody;\n var doc = new DOMParser().parseFromString(j.fragments.mapBody, 'text/html');\n var nodes = Array.prototype.slice.call(doc.body.childNodes);\n while (host.firstChild) host.removeChild(host.firstChild);\n nodes.forEach(function (n) { host.appendChild(n); });\n draw();\n })\n .catch(function (err) { console.error('KYA map refresh failed', err); });\n }\n // Live only: fetch the vendored library with the token from this page's URL, then run it as a script element.\n function loadLibrary(next) {\n if (window.cytoscape) { next(); return; }\n fetch('/vendor/cytoscape.min.js?t=' + encodeURIComponent(token()))\n .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.text(); })\n .then(function (text) {\n var s = document.createElement('script');\n s.id = 'kya-cytoscape';\n s.textContent = text;\n document.head.appendChild(s);\n next();\n })\n .catch(function (err) { console.error('KYA map library failed', err); });\n }\n window.kyaMapRefresh = refresh;\n window.addEventListener('hashchange', function () {\n if (location.hash !== '#map') return;\n refresh();\n setTimeout(function () { if (cy) { cy.resize(); cy.fit(); } }, 0);\n });\n if (live) loadLibrary(refresh); else draw();\n})();";
74
+ export declare const MAP_SCRIPT = "(function () {\n 'use strict';\n var cy = null;\n var last = null;\n var live = !!document.querySelector('main[data-live-token]');\n function token() {\n var m = /(?:^|[?&])t=([^&]*)/.exec(location.search);\n if (!m) return '';\n try { return decodeURIComponent(m[1]); } catch (e) { return m[1]; }\n }\n function model() {\n var el = document.getElementById('kya-map-data');\n if (!el) return null;\n try { return JSON.parse(el.textContent || 'null'); } catch (e) { return null; }\n }\n function add(parent, tag, text) {\n var n = document.createElement(tag);\n n.textContent = String(text);\n parent.appendChild(n);\n return n;\n }\n function showNode(node) {\n var panel = document.getElementById('kya-map-panel');\n if (!panel) return;\n while (panel.firstChild) panel.removeChild(panel.firstChild);\n add(panel, 'h3', node.kind + ': ' + node.label);\n add(panel, 'p', node.more ? node.detail : 'Class: ' + node.detail);\n var list = document.createElement('dl');\n panel.appendChild(list);\n [['Events', node.count], ['Allow', node.verdicts.allow], ['Deny', node.verdicts.deny], ['Hold', node.verdicts.hold],\n ['Observed', node.verdicts.observed], ['First seen', node.firstTs || '-'], ['Last seen', node.lastTs || '-']]\n .forEach(function (r) { add(list, 'dt', r[0]); add(list, 'dd', r[1]); });\n }\n // kya-map-layout:begin\n // Layered layout: one column per node kind (device, agent, tool, target), left to right. Rows sort by count.\n // This block is pure (same input, same output) and is byte-identical in page.ts and kya-map.js (a test checks it).\n var KYA_LAYOUT = { kinds: ['device', 'agent', 'tool', 'target'], colGap: 220, rowGap: 28, maxRows: 20, maxLabel: 22,\n dupLabel: 28, labelRoom: 140, padBottom: 44, pad: 48, minZoom: 0.8 };\n // Cuts by code point, so an emoji is never split.\n function kyaCut(s, max) {\n var a = Array.from(String(s));\n return a.length > max ? a.slice(0, max - 1).join('') + '\u2026' : a.join('');\n }\n function kyaCmp(a, b) {\n return a < b ? -1 : a > b ? 1 : 0;\n }\n function kyaTone(v) {\n if (v.deny > 0) return 'deny';\n if (v.hold > 0) return 'hold';\n if (v.observed > 0) return 'observed';\n return 'allow';\n }\n function kyaVerdicts() {\n return { allow: 0, deny: 0, hold: 0, observed: 0 };\n }\n function kyaAddVerdicts(into, v) {\n ['allow', 'deny', 'hold', 'observed'].forEach(function (k) { into[k] += (v && v[k]) || 0; });\n }\n // Unique labels in one column. Each label is cut at maxLabel. When two nodes draw the same text (the same label, or\n // two long labels that look the same after the cut), they get the event count. A unique text gets no suffix.\n // Texts that are still equal get a number.\n function kyaLabels(col) {\n var L = KYA_LAYOUT;\n function bump(m, k) { m[k] = (m[k] || 0) + 1; }\n function fit(s, suffix) { return kyaCut(s, Math.max(4, L.dupLabel - suffix.length)) + suffix; }\n function events(i) { return ' \u00B7 ' + col[i].count + (col[i].count === 1 ? ' event' : ' events'); }\n var plain = col.map(function (n) {\n var s = n.label == null ? String(n.id) : String(n.label);\n return s === '' ? '(no label)' : s;\n });\n var suffix = plain.map(function () { return ''; });\n var text = plain.map(function (s) { return kyaCut(s, L.maxLabel); });\n var drawn = {};\n text.forEach(function (t) { bump(drawn, t); });\n text = text.map(function (t, i) {\n if (drawn[t] < 2) return t;\n suffix[i] = events(i);\n return fit(plain[i], suffix[i]);\n });\n var again = {};\n var used = {};\n text.forEach(function (t) { bump(again, t); });\n return text.map(function (t, i) {\n if (again[t] < 2) return t;\n bump(used, t);\n return fit(plain[i], suffix[i] + ' (' + used[t] + ')');\n });\n }\n // Zoom, minimum width and height of the graph box for a scroll box that is avail px wide (0 when hidden).\n // The zoom never goes below minZoom, so labels stay readable; a narrow box scrolls sideways instead.\n function kyaMapSize(avail, lay) {\n var L = KYA_LAYOUT;\n var zoom = avail > 0 ? Math.min(1, Math.max(L.minZoom, (avail - L.pad) / lay.width)) : 1;\n return { zoom: zoom, minWidth: Math.ceil(lay.width * L.minZoom + L.pad),\n height: Math.max(360, Math.ceil(lay.height * zoom + L.pad)) };\n }\n // nodes and edges: the draw data. colours: tone to colour. Returns Cytoscape elements with preset positions.\n function kyaMapLayout(nodes, edges, colours) {\n var L = KYA_LAYOUT;\n var cols = L.kinds.map(function () { return []; });\n nodes.forEach(function (n) {\n var c = L.kinds.indexOf(n.kind);\n if (c >= 0) cols[c].push(n);\n });\n var outNodes = [];\n var moved = {};\n var rows = 0;\n cols.forEach(function (col, c) {\n col.sort(function (a, b) {\n return (b.count - a.count) || kyaCmp(String(a.label), String(b.label)) || kyaCmp(a.id, b.id);\n });\n // Cap only when two or more nodes would hide: one \"+1 more\" node would take the row of the node it hides.\n var shown = col.length > L.maxRows + 1 ? col.slice(0, L.maxRows) : col.slice();\n var rest = col.slice(shown.length);\n var labels = kyaLabels(shown);\n shown.forEach(function (n, i) {\n var data = {};\n Object.keys(n).forEach(function (k) { data[k] = n[k]; });\n data.text = labels[i];\n data.col = c;\n outNodes.push({ data: data, position: { x: c * L.colGap, y: i * L.rowGap } });\n });\n if (rest.length) {\n var id = 'more:' + L.kinds[c];\n var v = kyaVerdicts();\n var count = 0;\n rest.forEach(function (n) { moved[n.id] = id; count += n.count || 0; kyaAddVerdicts(v, n.verdicts); });\n var text = '+' + rest.length + ' more';\n outNodes.push({ data: { id: id, kind: L.kinds[c], label: text, text: text, col: c, more: rest.length, count: count,\n verdicts: v, detail: rest.length + ' more ' + L.kinds[c] + ' nodes, not drawn (' + count + ' events)', firstTs: '', lastTs: '' },\n position: { x: c * L.colGap, y: shown.length * L.rowGap } });\n }\n rows = Math.max(rows, shown.length + (rest.length ? 1 : 0));\n });\n var outEdges = [];\n var merged = {};\n var m = 0;\n edges.forEach(function (e) {\n var s = moved[e.source] || e.source;\n var t = moved[e.target] || e.target;\n if (s === e.source && t === e.target) {\n var copy = {};\n Object.keys(e).forEach(function (k) { copy[k] = e[k]; });\n if (e.verdicts) copy.tone = kyaTone(e.verdicts);\n outEdges.push({ data: copy });\n return;\n }\n var key = s + ' ' + t;\n if (!merged[key]) {\n merged[key] = { id: 'm' + m, source: s, target: t, count: 0, verdicts: kyaVerdicts() };\n m += 1;\n outEdges.push({ data: merged[key] });\n }\n merged[key].count += e.count || 0;\n kyaAddVerdicts(merged[key].verdicts, e.verdicts);\n });\n Object.keys(merged).forEach(function (k) {\n var x = merged[k];\n x.tone = kyaTone(x.verdicts);\n x.colour = colours[x.tone];\n x.width = Math.round((1 + 2 * Math.log10(Math.max(1, x.count))) * 100) / 100;\n });\n return { nodes: outNodes, edges: outEdges, rows: rows,\n width: (L.kinds.length - 1) * L.colGap + 2 * L.labelRoom, height: Math.max(0, rows - 1) * L.rowGap + L.padBottom };\n }\n // Styles: labels beside the nodes (left of the device and agent columns, right of the tool and target columns).\n // Allow and observed edges are thin and quiet. Deny and hold edges stay strong. A tap on a node fades the rest\n // (class faded) and brightens its edges (class hl).\n function kyaMapStyle() {\n return [\n { selector: 'node', style: { 'label': 'data(text)', 'font-size': 11, 'text-valign': 'center',\n 'text-background-color': '#ffffff', 'text-background-opacity': 0.8, 'text-background-padding': 1,\n 'width': 16, 'height': 16, 'background-color': '#98a2b3', 'color': '#101828' } },\n { selector: 'node[col < 2]', style: { 'text-halign': 'left', 'text-margin-x': -6 } },\n { selector: 'node[col >= 2]', style: { 'text-halign': 'right', 'text-margin-x': 6 } },\n { selector: 'node[kind = \"device\"]', style: { 'background-color': '#344054', 'shape': 'round-rectangle', 'width': 26, 'height': 26 } },\n { selector: 'node[kind = \"agent\"]', style: { 'background-color': '#1d4ed8' } },\n { selector: 'node[kind = \"tool\"]', style: { 'background-color': '#7a5af8', 'shape': 'round-rectangle' } },\n { selector: 'node[kind = \"target\"]', style: { 'background-color': '#0e9384' } },\n { selector: 'node[more]', style: { 'background-color': '#d0d5dd', 'shape': 'round-rectangle', 'color': '#475467' } },\n { selector: 'edge', style: { 'width': 'mapData(width, 1, 8, 0.6, 3)', 'line-color': 'data(colour)', 'target-arrow-color': 'data(colour)',\n 'target-arrow-shape': 'triangle', 'arrow-scale': 0.6, 'curve-style': 'bezier', 'opacity': 0.18 } },\n { selector: 'edge[tone = \"deny\"], edge[tone = \"hold\"]', style: { 'opacity': 0.9, 'z-index': 2 } },\n { selector: 'edge.hl', style: { 'width': 'data(width)', 'opacity': 1 } },\n { selector: '.faded', style: { 'opacity': 0.1, 'text-opacity': 0.25 } }\n ];\n }\n // Draws the layout into host. Host height follows the row count; the scroll box around host scrolls.\n function kyaMapDraw(host, nodes, edges, colours) {\n var lay = kyaMapLayout(nodes, edges, colours);\n var size = kyaMapSize(host.parentNode ? host.parentNode.clientWidth : 0, lay);\n host.style.minWidth = size.minWidth + 'px';\n host.style.height = size.height + 'px';\n var g = window.cytoscape({\n container: host,\n elements: { nodes: lay.nodes, edges: lay.edges },\n style: kyaMapStyle(),\n layout: { name: 'preset', fit: true, padding: 24 },\n minZoom: KYA_LAYOUT.minZoom,\n maxZoom: 1,\n userZoomingEnabled: false,\n userPanningEnabled: false,\n boxSelectionEnabled: false,\n autoungrabify: true\n });\n // The fit zoom uses the real label widths. Set the height again for that zoom and put the first row at the top,\n // so the bottom pad (one row gap and the node radius) stays below the last row.\n var z = g.zoom();\n host.style.height = Math.max(360, Math.ceil(lay.height * z + KYA_LAYOUT.pad)) + 'px';\n g.resize();\n g.pan({ x: g.pan().x, y: KYA_LAYOUT.pad / 2 - g.elements().boundingBox().y1 * z });\n g.on('tap', 'node', function (evt) {\n g.elements().removeClass('hl').addClass('faded');\n var near = evt.target.closedNeighborhood();\n near.removeClass('faded');\n near.edges().addClass('hl');\n });\n g.on('tap', function (evt) {\n if (evt.target === g) g.elements().removeClass('faded').removeClass('hl');\n });\n return g;\n }\n // kya-map-layout:end\n var MAX_DRAW_NODES = 400;\n function draw() {\n var host = document.getElementById('kya-map-graph');\n var d = model();\n if (cy) { cy.destroy(); cy = null; }\n if (!host || !d || !window.cytoscape || !d.nodes || !d.nodes.length) return;\n // Thousands of nodes make the page too slow to use. The JSON and both heat views still hold everything.\n if (d.nodes.length > MAX_DRAW_NODES) {\n host.textContent = 'Graph not drawn: ' + d.nodes.length + ' nodes is too many for the page. Use a shorter window (kya map --days 1) or kya map --json.';\n return;\n }\n cy = kyaMapDraw(host, d.nodes, d.edges, d.colours);\n cy.on('tap', 'node', function (evt) { showNode(evt.target.data()); });\n }\n function refresh() {\n if (!live) return;\n var host = document.getElementById('frag-map');\n if (!host) return;\n fetch('/fragments?t=' + encodeURIComponent(token()), {\n method: 'POST', headers: { 'Content-Type': 'application/json' }, body: '{\"map\":true}'\n })\n .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.json(); })\n .then(function (j) {\n if (!j || !j.ok || !j.fragments || typeof j.fragments.mapBody !== 'string') return;\n if (j.fragments.mapBody === last) return;\n last = j.fragments.mapBody;\n var doc = new DOMParser().parseFromString(j.fragments.mapBody, 'text/html');\n var nodes = Array.prototype.slice.call(doc.body.childNodes);\n while (host.firstChild) host.removeChild(host.firstChild);\n nodes.forEach(function (n) { host.appendChild(n); });\n draw();\n })\n .catch(function (err) { console.error('KYA map refresh failed', err); });\n }\n // Live only: fetch the vendored library with the token from this page's URL, then run it as a script element.\n function loadLibrary(next) {\n if (window.cytoscape) { next(); return; }\n fetch('/vendor/cytoscape.min.js?t=' + encodeURIComponent(token()))\n .then(function (r) { if (!r.ok) throw new Error('HTTP ' + r.status); return r.text(); })\n .then(function (text) {\n var s = document.createElement('script');\n s.id = 'kya-cytoscape';\n s.textContent = text;\n document.head.appendChild(s);\n next();\n })\n .catch(function (err) { console.error('KYA map library failed', err); });\n }\n window.kyaMapRefresh = refresh;\n window.addEventListener('hashchange', function () {\n if (location.hash !== '#map') return;\n refresh();\n // Draw again now that the tab shows: a draw while the tab was hidden measured a width of 0.\n setTimeout(draw, 0);\n });\n if (live) loadLibrary(refresh); else draw();\n})();";
72
75
  /**
73
76
  * Live report: the draw script, in the page shell (not in the swapped fragment). The script reads the token from its
74
77
  * own URL and fetches the library from /vendor/cytoscape.min.js, so the token never appears in the HTML.
75
78
  */
76
79
  export declare function liveMapScripts(): string;
77
80
  /** Map components. Shared by the standalone file and the live report, so it uses the report's tokens (--line, --mute, --fg, --bg). */
78
- export declare const MAP_CSS = "\n .map-body .map-advisory { border-left: 3px solid var(--line, #d0d5dd); padding: 4px 10px; font-weight: 600; }\n .map-body .mute { color: var(--mute, #667085); }\n .map-stats p { margin: 4px 0; }\n .map-top { margin: 4px 0 12px 20px; padding: 0; }\n .map-canvas { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 12px; margin: 12px 0; }\n .map-graph { height: 60vh; min-height: 360px; border: 1px solid var(--line, #d0d5dd); border-radius: 6px; }\n .map-panel { border: 1px solid var(--line, #d0d5dd); border-radius: 6px; padding: 8px 12px; overflow: auto; }\n .map-panel dl { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; }\n .map-panel dt { color: var(--mute, #667085); }\n .map-panel dd { margin: 0; }\n .map-scroll { overflow-x: auto; }\n .map-heat { border-collapse: collapse; font-size: 12px; margin-bottom: 12px; }\n .map-heat caption { text-align: left; color: var(--mute, #667085); padding: 4px 0; }\n .map-heat th, .map-heat td { border: 1px solid var(--line, #d0d5dd); padding: 3px 5px; text-align: right; min-width: 22px; }\n .map-heat th { text-align: left; font-weight: 600; }\n .map-heat td.l0 { background: transparent; }\n .map-heat td.l1 { background: #d1fadf; color: #101828; }\n .map-heat td.l2 { background: #75e0a7; color: #101828; }\n .map-heat td.l3 { background: #12b76a; color: #fff; }\n .map-heat td.l4 { background: #027a48; color: #fff; }\n .map-heat td.deny { outline: 2px solid #b42318; outline-offset: -2px; }\n .map-empty { font-weight: 600; }\n @media (max-width: 760px) { .map-canvas { grid-template-columns: 1fr; } }\n";
81
+ export declare const MAP_CSS = "\n .map-body .map-advisory { border-left: 3px solid var(--line, #d0d5dd); padding: 4px 10px; font-weight: 600; }\n .map-body .mute { color: var(--mute, #667085); }\n .map-stats p { margin: 4px 0; }\n .map-top { margin: 4px 0 12px 20px; padding: 0; }\n .map-canvas { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 12px; margin: 12px 0; }\n .map-graph-scroll { max-height: 80vh; overflow: auto; border: 1px solid var(--line, #d0d5dd); border-radius: 6px; }\n .map-graph { min-height: 360px; }\n .map-panel { border: 1px solid var(--line, #d0d5dd); border-radius: 6px; padding: 8px 12px; overflow: auto; }\n .map-panel dl { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; }\n .map-panel dt { color: var(--mute, #667085); }\n .map-panel dd { margin: 0; }\n .map-scroll { overflow-x: auto; }\n .map-heat { border-collapse: collapse; font-size: 12px; margin-bottom: 12px; }\n .map-heat caption { text-align: left; color: var(--mute, #667085); padding: 4px 0; }\n .map-heat th, .map-heat td { border: 1px solid var(--line, #d0d5dd); padding: 3px 5px; text-align: right; min-width: 22px; }\n .map-heat th { text-align: left; font-weight: 600; }\n .map-heat td.l0 { background: transparent; }\n .map-heat td.l1 { background: #d1fadf; color: #101828; }\n .map-heat td.l2 { background: #75e0a7; color: #101828; }\n .map-heat td.l3 { background: #12b76a; color: #fff; }\n .map-heat td.l4 { background: #027a48; color: #fff; }\n .map-heat td.deny { outline: 2px solid #b42318; outline-offset: -2px; }\n .map-empty { font-weight: 600; }\n @media (max-width: 760px) { .map-canvas { grid-template-columns: 1fr; } }\n";
79
82
  /** Live report: the Map zone shows only on its tab (same :target rule as the other zones). */
80
83
  export declare const MAP_LIVE_ZONE_CSS = "\n @supports selector(body:has(*)) {\n #map { display: none; }\n #map:target { display: block; }\n body:has(#map:target) #overview { display: none; }\n body:has(#map:target) .nav-link[href=\"#map\"] { color: var(--fg); background: var(--bg); border-color: var(--line); }\n }\n";
81
84
  /** Standalone file only: its own tokens and page frame (the live report has its own). */
@@ -1 +1 @@
1
- {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/map/page.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,QAAQ,EAAW,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE9D,2EAA2E;AAC3E,eAAO,MAAM,aAAa,iHACsF,CAAC;AAEjH,uHAAuH;AACvH,eAAO,MAAM,WAAW;;;;;CAAuF,CAAC;AAChH,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,WAAW,CAAC;AAEhD,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAK9C;AAED,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAOD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED,sCAAsC;AACtC,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAErC;AAED,gIAAgI;AAChI,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BxC;AAuED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB/E;AAKD,wHAAwH;AACxH,wBAAgB,eAAe,IAAI,MAAM,CAKxC;AAED,qFAAqF;AACrF,eAAO,MAAM,OAAO,6FAA6F,CAAC;AAElH;;;GAGG;AACH,eAAO,MAAM,UAAU,y5KA+GjB,CAAC;AAEP;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,sIAAsI;AACtI,eAAO,MAAM,OAAO,ilDAwBnB,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,uSAO7B,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,YAAY,ifAMxB,CAAC;AAEF,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAyBzG"}
1
+ {"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../../src/map/page.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,EAAE,QAAQ,EAAW,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE9D,2EAA2E;AAC3E,eAAO,MAAM,aAAa,iHACsF,CAAC;AAEjH,uHAAuH;AACvH,eAAO,MAAM,WAAW;;;;;CAAuF,CAAC;AAChH,MAAM,MAAM,QAAQ,GAAG,MAAM,OAAO,WAAW,CAAC;AAEhD,4EAA4E;AAC5E,wBAAgB,QAAQ,CAAC,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAK9C;AAED,0FAA0F;AAC1F,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEpD;AAOD,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAEhD;AAED,sCAAsC;AACtC,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAErC;AAED,gIAAgI;AAChI,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BxC;AAWD,+GAA+G;AAC/G,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,MAAM,CAAwD,CAAC;AACrG,eAAO,MAAM,QAAQ,sDAAsD,CAAC;AA+D5E;;;GAGG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAsB/E;AAKD,wHAAwH;AACxH,wBAAgB,eAAe,IAAI,MAAM,CAKxC;AAED,qFAAqF;AACrF,eAAO,MAAM,OAAO,6FAA6F,CAAC;AAElH;;;GAGG;AACH,eAAO,MAAM,UAAU,+7aAuRjB,CAAC;AAEP;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,sIAAsI;AACtI,eAAO,MAAM,OAAO,8nDAyBnB,CAAC;AAEF,8FAA8F;AAC9F,eAAO,MAAM,iBAAiB,uSAO7B,CAAC;AAEF,yFAAyF;AACzF,eAAO,MAAM,YAAY,ifAMxB,CAAC;AAEF,qDAAqD;AACrD,wBAAgB,aAAa,CAAC,KAAK,EAAE;IAAE,KAAK,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAyBzG"}
package/dist/map/page.js CHANGED
@@ -86,6 +86,9 @@ function detailOf(n) {
86
86
  return n.id;
87
87
  }
88
88
  const SHOWN_TARGETS = 5;
89
+ /** Navigation-only commands. The summary list hides them; the graph, the heat views and the JSON keep them. */
90
+ export const NAV_CLASSES = new Set(["command:cd", "command:ls", "command:pwd"]);
91
+ export const NAV_LINE = "Navigation commands (cd, ls, pwd) are not listed.";
89
92
  function sum(nums) {
90
93
  return nums.reduce((a, b) => a + b, 0);
91
94
  }
@@ -100,7 +103,7 @@ function summaryHtml(graph) {
100
103
  const events = sum(devices.map((n) => n.count));
101
104
  const sessions = sum(graph.nodes.filter((n) => n.kind === "agent").map((n) => n.grouped ?? 1));
102
105
  const classes = graph.nodes
103
- .filter((n) => n.kind === "target" && n.grouped === undefined)
106
+ .filter((n) => n.kind === "target" && n.grouped === undefined && !NAV_CLASSES.has(n.class))
104
107
  .sort((a, b) => b.count - a.count || (a.class < b.class ? -1 : a.class > b.class ? 1 : 0))
105
108
  .slice(0, SHOWN_TARGETS);
106
109
  const top = classes.length
@@ -110,6 +113,7 @@ function summaryHtml(graph) {
110
113
  <p><strong>${events}</strong> events · <strong>${sessions}</strong> sessions · <strong>${devices.length}</strong> device${devices.length === 1 ? "" : "s"}</p>
111
114
  <p class="small">Top ${SHOWN_TARGETS} target classes:</p>
112
115
  ${top}
116
+ ${graph.nodes.some((n) => n.kind === "target" && NAV_CLASSES.has(n.class)) ? `<p class="small mute map-nav-note">${NAV_LINE}</p>` : ""}
113
117
  </div>`;
114
118
  }
115
119
  function whenTable(heat) {
@@ -151,10 +155,10 @@ export function renderMapBody(graph, heat, days) {
151
155
  const graphBlock = events === 0
152
156
  ? ""
153
157
  : `<div class="map-canvas">
154
- <div id="kya-map-graph" class="map-graph" aria-label="Map of agent actions"></div>
158
+ <div class="map-graph-scroll"><div id="kya-map-graph" class="map-graph" aria-label="Map of agent actions"></div></div>
155
159
  <aside id="kya-map-panel" class="map-panel" aria-live="polite"><p class="mute">Click a node to see its class, counts and first and last time.</p></aside>
156
160
  </div>
157
- <p class="map-legend small">Edges: red = deny, amber = hold, grey = observed (recorded, not enforced), green = allow. Width grows with the count.</p>`;
161
+ <p class="map-legend small">Edges: red = deny, amber = hold, grey = observed (recorded, not enforced), green = allow. Width grows with the count. Allow and observed edges are drawn light until you click a node.</p>`;
158
162
  return `<div class="map-body">
159
163
  <p class="map-advisory">${esc(ADVISORY_LINE)}</p>
160
164
  ${summaryHtml(graph)}
@@ -208,49 +212,216 @@ export const MAP_SCRIPT = `(function () {
208
212
  if (!panel) return;
209
213
  while (panel.firstChild) panel.removeChild(panel.firstChild);
210
214
  add(panel, 'h3', node.kind + ': ' + node.label);
211
- add(panel, 'p', 'Class: ' + node.detail);
215
+ add(panel, 'p', node.more ? node.detail : 'Class: ' + node.detail);
212
216
  var list = document.createElement('dl');
213
217
  panel.appendChild(list);
214
218
  [['Events', node.count], ['Allow', node.verdicts.allow], ['Deny', node.verdicts.deny], ['Hold', node.verdicts.hold],
215
219
  ['Observed', node.verdicts.observed], ['First seen', node.firstTs || '-'], ['Last seen', node.lastTs || '-']]
216
220
  .forEach(function (r) { add(list, 'dt', r[0]); add(list, 'dd', r[1]); });
217
221
  }
218
- function style(d) {
219
- var out = [
220
- { selector: 'node', style: { 'label': 'data(label)', 'font-size': 10, 'text-wrap': 'ellipsis', 'text-max-width': 130, 'min-zoomed-font-size': 9,
222
+ // kya-map-layout:begin
223
+ // Layered layout: one column per node kind (device, agent, tool, target), left to right. Rows sort by count.
224
+ // This block is pure (same input, same output) and is byte-identical in page.ts and kya-map.js (a test checks it).
225
+ var KYA_LAYOUT = { kinds: ['device', 'agent', 'tool', 'target'], colGap: 220, rowGap: 28, maxRows: 20, maxLabel: 22,
226
+ dupLabel: 28, labelRoom: 140, padBottom: 44, pad: 48, minZoom: 0.8 };
227
+ // Cuts by code point, so an emoji is never split.
228
+ function kyaCut(s, max) {
229
+ var a = Array.from(String(s));
230
+ return a.length > max ? a.slice(0, max - 1).join('') + '…' : a.join('');
231
+ }
232
+ function kyaCmp(a, b) {
233
+ return a < b ? -1 : a > b ? 1 : 0;
234
+ }
235
+ function kyaTone(v) {
236
+ if (v.deny > 0) return 'deny';
237
+ if (v.hold > 0) return 'hold';
238
+ if (v.observed > 0) return 'observed';
239
+ return 'allow';
240
+ }
241
+ function kyaVerdicts() {
242
+ return { allow: 0, deny: 0, hold: 0, observed: 0 };
243
+ }
244
+ function kyaAddVerdicts(into, v) {
245
+ ['allow', 'deny', 'hold', 'observed'].forEach(function (k) { into[k] += (v && v[k]) || 0; });
246
+ }
247
+ // Unique labels in one column. Each label is cut at maxLabel. When two nodes draw the same text (the same label, or
248
+ // two long labels that look the same after the cut), they get the event count. A unique text gets no suffix.
249
+ // Texts that are still equal get a number.
250
+ function kyaLabels(col) {
251
+ var L = KYA_LAYOUT;
252
+ function bump(m, k) { m[k] = (m[k] || 0) + 1; }
253
+ function fit(s, suffix) { return kyaCut(s, Math.max(4, L.dupLabel - suffix.length)) + suffix; }
254
+ function events(i) { return ' · ' + col[i].count + (col[i].count === 1 ? ' event' : ' events'); }
255
+ var plain = col.map(function (n) {
256
+ var s = n.label == null ? String(n.id) : String(n.label);
257
+ return s === '' ? '(no label)' : s;
258
+ });
259
+ var suffix = plain.map(function () { return ''; });
260
+ var text = plain.map(function (s) { return kyaCut(s, L.maxLabel); });
261
+ var drawn = {};
262
+ text.forEach(function (t) { bump(drawn, t); });
263
+ text = text.map(function (t, i) {
264
+ if (drawn[t] < 2) return t;
265
+ suffix[i] = events(i);
266
+ return fit(plain[i], suffix[i]);
267
+ });
268
+ var again = {};
269
+ var used = {};
270
+ text.forEach(function (t) { bump(again, t); });
271
+ return text.map(function (t, i) {
272
+ if (again[t] < 2) return t;
273
+ bump(used, t);
274
+ return fit(plain[i], suffix[i] + ' (' + used[t] + ')');
275
+ });
276
+ }
277
+ // Zoom, minimum width and height of the graph box for a scroll box that is avail px wide (0 when hidden).
278
+ // The zoom never goes below minZoom, so labels stay readable; a narrow box scrolls sideways instead.
279
+ function kyaMapSize(avail, lay) {
280
+ var L = KYA_LAYOUT;
281
+ var zoom = avail > 0 ? Math.min(1, Math.max(L.minZoom, (avail - L.pad) / lay.width)) : 1;
282
+ return { zoom: zoom, minWidth: Math.ceil(lay.width * L.minZoom + L.pad),
283
+ height: Math.max(360, Math.ceil(lay.height * zoom + L.pad)) };
284
+ }
285
+ // nodes and edges: the draw data. colours: tone to colour. Returns Cytoscape elements with preset positions.
286
+ function kyaMapLayout(nodes, edges, colours) {
287
+ var L = KYA_LAYOUT;
288
+ var cols = L.kinds.map(function () { return []; });
289
+ nodes.forEach(function (n) {
290
+ var c = L.kinds.indexOf(n.kind);
291
+ if (c >= 0) cols[c].push(n);
292
+ });
293
+ var outNodes = [];
294
+ var moved = {};
295
+ var rows = 0;
296
+ cols.forEach(function (col, c) {
297
+ col.sort(function (a, b) {
298
+ return (b.count - a.count) || kyaCmp(String(a.label), String(b.label)) || kyaCmp(a.id, b.id);
299
+ });
300
+ // Cap only when two or more nodes would hide: one "+1 more" node would take the row of the node it hides.
301
+ var shown = col.length > L.maxRows + 1 ? col.slice(0, L.maxRows) : col.slice();
302
+ var rest = col.slice(shown.length);
303
+ var labels = kyaLabels(shown);
304
+ shown.forEach(function (n, i) {
305
+ var data = {};
306
+ Object.keys(n).forEach(function (k) { data[k] = n[k]; });
307
+ data.text = labels[i];
308
+ data.col = c;
309
+ outNodes.push({ data: data, position: { x: c * L.colGap, y: i * L.rowGap } });
310
+ });
311
+ if (rest.length) {
312
+ var id = 'more:' + L.kinds[c];
313
+ var v = kyaVerdicts();
314
+ var count = 0;
315
+ rest.forEach(function (n) { moved[n.id] = id; count += n.count || 0; kyaAddVerdicts(v, n.verdicts); });
316
+ var text = '+' + rest.length + ' more';
317
+ outNodes.push({ data: { id: id, kind: L.kinds[c], label: text, text: text, col: c, more: rest.length, count: count,
318
+ verdicts: v, detail: rest.length + ' more ' + L.kinds[c] + ' nodes, not drawn (' + count + ' events)', firstTs: '', lastTs: '' },
319
+ position: { x: c * L.colGap, y: shown.length * L.rowGap } });
320
+ }
321
+ rows = Math.max(rows, shown.length + (rest.length ? 1 : 0));
322
+ });
323
+ var outEdges = [];
324
+ var merged = {};
325
+ var m = 0;
326
+ edges.forEach(function (e) {
327
+ var s = moved[e.source] || e.source;
328
+ var t = moved[e.target] || e.target;
329
+ if (s === e.source && t === e.target) {
330
+ var copy = {};
331
+ Object.keys(e).forEach(function (k) { copy[k] = e[k]; });
332
+ if (e.verdicts) copy.tone = kyaTone(e.verdicts);
333
+ outEdges.push({ data: copy });
334
+ return;
335
+ }
336
+ var key = s + ' ' + t;
337
+ if (!merged[key]) {
338
+ merged[key] = { id: 'm' + m, source: s, target: t, count: 0, verdicts: kyaVerdicts() };
339
+ m += 1;
340
+ outEdges.push({ data: merged[key] });
341
+ }
342
+ merged[key].count += e.count || 0;
343
+ kyaAddVerdicts(merged[key].verdicts, e.verdicts);
344
+ });
345
+ Object.keys(merged).forEach(function (k) {
346
+ var x = merged[k];
347
+ x.tone = kyaTone(x.verdicts);
348
+ x.colour = colours[x.tone];
349
+ x.width = Math.round((1 + 2 * Math.log10(Math.max(1, x.count))) * 100) / 100;
350
+ });
351
+ return { nodes: outNodes, edges: outEdges, rows: rows,
352
+ width: (L.kinds.length - 1) * L.colGap + 2 * L.labelRoom, height: Math.max(0, rows - 1) * L.rowGap + L.padBottom };
353
+ }
354
+ // Styles: labels beside the nodes (left of the device and agent columns, right of the tool and target columns).
355
+ // Allow and observed edges are thin and quiet. Deny and hold edges stay strong. A tap on a node fades the rest
356
+ // (class faded) and brightens its edges (class hl).
357
+ function kyaMapStyle() {
358
+ return [
359
+ { selector: 'node', style: { 'label': 'data(text)', 'font-size': 11, 'text-valign': 'center',
221
360
  'text-background-color': '#ffffff', 'text-background-opacity': 0.8, 'text-background-padding': 1,
222
- 'width': 18, 'height': 18, 'background-color': '#98a2b3', 'color': '#101828' } },
223
- { selector: 'node[kind = "device"]', style: { 'background-color': '#344054', 'shape': 'round-rectangle', 'width': 34, 'height': 34 } },
361
+ 'width': 16, 'height': 16, 'background-color': '#98a2b3', 'color': '#101828' } },
362
+ { selector: 'node[col < 2]', style: { 'text-halign': 'left', 'text-margin-x': -6 } },
363
+ { selector: 'node[col >= 2]', style: { 'text-halign': 'right', 'text-margin-x': 6 } },
364
+ { selector: 'node[kind = "device"]', style: { 'background-color': '#344054', 'shape': 'round-rectangle', 'width': 26, 'height': 26 } },
224
365
  { selector: 'node[kind = "agent"]', style: { 'background-color': '#1d4ed8' } },
225
366
  { selector: 'node[kind = "tool"]', style: { 'background-color': '#7a5af8', 'shape': 'round-rectangle' } },
226
367
  { selector: 'node[kind = "target"]', style: { 'background-color': '#0e9384' } },
227
- { selector: 'edge', style: { 'width': 'data(width)', 'line-color': 'data(colour)', 'target-arrow-color': 'data(colour)',
228
- 'target-arrow-shape': 'triangle', 'curve-style': 'bezier', 'opacity': 0.9 } }
368
+ { selector: 'node[more]', style: { 'background-color': '#d0d5dd', 'shape': 'round-rectangle', 'color': '#475467' } },
369
+ { selector: 'edge', style: { 'width': 'mapData(width, 1, 8, 0.6, 3)', 'line-color': 'data(colour)', 'target-arrow-color': 'data(colour)',
370
+ 'target-arrow-shape': 'triangle', 'arrow-scale': 0.6, 'curve-style': 'bezier', 'opacity': 0.18 } },
371
+ { selector: 'edge[tone = "deny"], edge[tone = "hold"]', style: { 'opacity': 0.9, 'z-index': 2 } },
372
+ { selector: 'edge.hl', style: { 'width': 'data(width)', 'opacity': 1 } },
373
+ { selector: '.faded', style: { 'opacity': 0.1, 'text-opacity': 0.25 } }
229
374
  ];
230
- return out;
231
375
  }
376
+ // Draws the layout into host. Host height follows the row count; the scroll box around host scrolls.
377
+ function kyaMapDraw(host, nodes, edges, colours) {
378
+ var lay = kyaMapLayout(nodes, edges, colours);
379
+ var size = kyaMapSize(host.parentNode ? host.parentNode.clientWidth : 0, lay);
380
+ host.style.minWidth = size.minWidth + 'px';
381
+ host.style.height = size.height + 'px';
382
+ var g = window.cytoscape({
383
+ container: host,
384
+ elements: { nodes: lay.nodes, edges: lay.edges },
385
+ style: kyaMapStyle(),
386
+ layout: { name: 'preset', fit: true, padding: 24 },
387
+ minZoom: KYA_LAYOUT.minZoom,
388
+ maxZoom: 1,
389
+ userZoomingEnabled: false,
390
+ userPanningEnabled: false,
391
+ boxSelectionEnabled: false,
392
+ autoungrabify: true
393
+ });
394
+ // The fit zoom uses the real label widths. Set the height again for that zoom and put the first row at the top,
395
+ // so the bottom pad (one row gap and the node radius) stays below the last row.
396
+ var z = g.zoom();
397
+ host.style.height = Math.max(360, Math.ceil(lay.height * z + KYA_LAYOUT.pad)) + 'px';
398
+ g.resize();
399
+ g.pan({ x: g.pan().x, y: KYA_LAYOUT.pad / 2 - g.elements().boundingBox().y1 * z });
400
+ g.on('tap', 'node', function (evt) {
401
+ g.elements().removeClass('hl').addClass('faded');
402
+ var near = evt.target.closedNeighborhood();
403
+ near.removeClass('faded');
404
+ near.edges().addClass('hl');
405
+ });
406
+ g.on('tap', function (evt) {
407
+ if (evt.target === g) g.elements().removeClass('faded').removeClass('hl');
408
+ });
409
+ return g;
410
+ }
411
+ // kya-map-layout:end
232
412
  var MAX_DRAW_NODES = 400;
233
413
  function draw() {
234
414
  var host = document.getElementById('kya-map-graph');
235
415
  var d = model();
236
416
  if (cy) { cy.destroy(); cy = null; }
237
417
  if (!host || !d || !window.cytoscape || !d.nodes || !d.nodes.length) return;
238
- // A force layout on thousands of nodes hangs the tab. The JSON and both heat views still hold everything.
418
+ // Thousands of nodes make the page too slow to use. The JSON and both heat views still hold everything.
239
419
  if (d.nodes.length > MAX_DRAW_NODES) {
240
420
  host.textContent = 'Graph not drawn: ' + d.nodes.length + ' nodes is too many for the page. Use a shorter window (kya map --days 1) or kya map --json.';
241
421
  return;
242
422
  }
243
- cy = window.cytoscape({
244
- container: host,
245
- elements: {
246
- nodes: d.nodes.map(function (n) { return { data: n }; }),
247
- edges: d.edges.map(function (e) { return { data: e }; })
248
- },
249
- style: style(d),
250
- layout: { name: 'cose', animate: false, randomize: true, fit: true, padding: 24, numIter: 900, nodeRepulsion: function () { return 9000; }, idealEdgeLength: function () { return 80; }, nodeOverlap: 14, gravity: 0.35 }
251
- });
423
+ cy = kyaMapDraw(host, d.nodes, d.edges, d.colours);
252
424
  cy.on('tap', 'node', function (evt) { showNode(evt.target.data()); });
253
- cy.fit();
254
425
  }
255
426
  function refresh() {
256
427
  if (!live) return;
@@ -290,7 +461,8 @@ export const MAP_SCRIPT = `(function () {
290
461
  window.addEventListener('hashchange', function () {
291
462
  if (location.hash !== '#map') return;
292
463
  refresh();
293
- setTimeout(function () { if (cy) { cy.resize(); cy.fit(); } }, 0);
464
+ // Draw again now that the tab shows: a draw while the tab was hidden measured a width of 0.
465
+ setTimeout(draw, 0);
294
466
  });
295
467
  if (live) loadLibrary(refresh); else draw();
296
468
  })();`;
@@ -308,7 +480,8 @@ export const MAP_CSS = `
308
480
  .map-stats p { margin: 4px 0; }
309
481
  .map-top { margin: 4px 0 12px 20px; padding: 0; }
310
482
  .map-canvas { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 12px; margin: 12px 0; }
311
- .map-graph { height: 60vh; min-height: 360px; border: 1px solid var(--line, #d0d5dd); border-radius: 6px; }
483
+ .map-graph-scroll { max-height: 80vh; overflow: auto; border: 1px solid var(--line, #d0d5dd); border-radius: 6px; }
484
+ .map-graph { min-height: 360px; }
312
485
  .map-panel { border: 1px solid var(--line, #d0d5dd); border-radius: 6px; padding: 8px 12px; overflow: auto; }
313
486
  .map-panel dl { display: grid; grid-template-columns: auto 1fr; gap: 2px 10px; }
314
487
  .map-panel dt { color: var(--mute, #667085); }
@@ -1 +1 @@
1
- {"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/map/page.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"page.js","sourceRoot":"","sources":["../../src/map/page.ts"],"names":[],"mappings":"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"}
package/droid/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Droid (Factory) + Shield KYA
2
2
 
3
- Preferred path is Droid's own CLI: `droid mcp add shield-kya "npx --no-install @shield-agent/kya@0.33.2 serve-mcp --stdio" --env KYA_BASE_URL=https://shield-agent.com --env KYA_API_KEY=$KYA_API_KEY --env KYA_HOST=ide`.
3
+ Preferred path is Droid's own CLI: `droid mcp add shield-kya "npx --no-install @shield-agent/kya@0.33.3 serve-mcp --stdio" --env KYA_BASE_URL=https://shield-agent.com --env KYA_API_KEY=$KYA_API_KEY --env KYA_HOST=ide`.
4
4
 
5
5
  `mcp.example.json` shows the expected on-disk shape (`~/.factory/mcp.json`) - **schema not yet verified against a live Droid install**; treat as a starting point and prefer `droid mcp add`.
6
6
 
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
package/grok/README.md CHANGED
@@ -40,7 +40,7 @@ chat = client.chat.create(
40
40
  There is no grok.com stdio path. For a local agent host use the same stdio launch as Claude:
41
41
 
42
42
  ```bash
43
- npx --no-install @shield-agent/kya@0.33.2 serve-mcp --stdio
43
+ npx --no-install @shield-agent/kya@0.33.3 serve-mcp --stdio
44
44
  ```
45
45
 
46
46
  Env: `KYA_BASE_URL`, `KYA_API_KEY`, `KYA_HOST`. Codex and Gemini example configs in this package show the full snippets.
@@ -2,7 +2,7 @@
2
2
  "mcp": {
3
3
  "shield-kya": {
4
4
  "type": "local",
5
- "command": ["npx", "--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "command": ["npx", "--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "enabled": true,
7
7
  "environment": {
8
8
  "KYA_BASE_URL": "https://shield-agent.com",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
package/manifest.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "manifest_version": "0.3",
3
3
  "name": "shield-kya",
4
4
  "display_name": "Shield KYA",
5
- "version": "0.33.2",
5
+ "version": "0.33.3",
6
6
  "description": "Audit trail and traceability for AI agents. MCP gate: evaluate, ingest, request approval.",
7
7
  "long_description": "Local Claude Desktop extension that runs the packaged `dist/cli.js serve-mcp --stdio` against your Shield control plane (local or https://shield-agent.com). Tools evaluate policy, ingest session risk, and open Hold tickets. They never execute irreversible side effects.",
8
8
  "author": {
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
package/mcp.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "shield-kya": {
4
4
  "description": "Know Your Agent local MCP gate: wrap-before-write, named-agent registry, Hold/Clear.",
5
5
  "command": "npx",
6
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
6
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
7
7
  "env": {
8
8
  "KYA_BASE_URL": "${KYA_BASE_URL}",
9
9
  "KYA_API_KEY": "${KYA_API_KEY}",
@@ -11,7 +11,7 @@
11
11
  # --- Local stdio (OSS) ---
12
12
  [mcp_servers.shield-kya]
13
13
  command = "npx"
14
- args = ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"]
14
+ args = ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"]
15
15
  startup_timeout_sec = 20
16
16
  env_vars = ["KYA_BASE_URL", "KYA_API_KEY", "KYA_HOST", "KYA_AGENT_ID"]
17
17
 
@@ -2,7 +2,7 @@
2
2
  "mcp": {
3
3
  "shield-kya": {
4
4
  "type": "local",
5
- "command": ["npx", "--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "command": ["npx", "--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "enabled": true,
7
7
  "environment": {
8
8
  "KYA_BASE_URL": "https://shield-agent.com",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shield-agent/kya",
3
- "version": "0.33.2",
3
+ "version": "0.33.3",
4
4
  "description": "Audit trail and traceability for AI agents. See what every coding agent did and check each tool call against policy.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "shield-kya": {
4
4
  "command": "npx",
5
- "args": ["--no-install", "@shield-agent/kya@0.33.2", "serve-mcp", "--stdio"],
5
+ "args": ["--no-install", "@shield-agent/kya@0.33.3", "serve-mcp", "--stdio"],
6
6
  "env": {
7
7
  "KYA_BASE_URL": "https://shield-agent.com",
8
8
  "KYA_API_KEY": "${KYA_API_KEY}",
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/The-Pixel-Boys/shield-kya",
8
8
  "source": "github"
9
9
  },
10
- "version": "0.33.2",
10
+ "version": "0.33.3",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "@shield-agent/kya",
15
- "version": "0.33.2",
15
+ "version": "0.33.3",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },