Commit Graph
439 Commits
Author SHA1 Message Date
Yuxiang LinandGitHub c80cd5ee64 Merge pull request #111 from Lum1104/feature/graph-layout-scaling
feat(dashboard): replace dagre with ELK + folder/community containers + lazy two-stage layout
2026-05-03 18:12:21 +08:00
Lum1104andClaude Opus 4.7 2327cd74e4 fix(dashboard): address Codex review
P1: Anchor edges at the collapsed-side container atom when only one
side of an aggregated edge is expanded. The previous pass always
emitted file→file endpoints, but a collapsed container's children
aren't rendered as nodes — React Flow silently dropped those edges.
Now the collapsed endpoint stays as the container id, and the
expanded endpoint becomes the real file id; multiple files
collapsing onto the same (container → file) pair are deduped.

P2: Pending-fit ref + post-render trigger replaces the fixed 50ms
timer for layer-transition fitView. ELK takes ~125ms+ on medium
layers, so the timer was firing before positions arrived and the
viewport stayed on the old layer. Now we mark a pending fit on
navigation change and execute it once `nodes` populate, then
requestAnimationFrame so React Flow has placed the nodes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 17:49:32 +08:00
Lum1104andClaude Opus 4.7 a6612b17e1 fix(dashboard): render intra-container edges when container is expanded
Stage 1 stashes intra-folder file→file edges on `topo.intraContainer`
but `expandedEdges` only walked `topo.edges` (aggregated cross-
container only). When a user expanded a container the children
appeared but their internal wiring was invisible, even though the
NodeInfo sidebar listed the connections.

Now after the inflated cross-container pass, also push every
intra-container edge whose owning container is expanded.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 17:29:59 +08:00
Lum1104andClaude Opus 4.7 09308631bc fix(dashboard): clear container cache on focus, deprecate applyDagreLayout
setFocusNode was missed in the C1 cache-reset pass. Focus mode narrows
filteredGraphNodes to focus + 1-hop neighbors, so a container that
survives still has a subset of its children — the cache must drop
or it'll keep returning positions for filtered-out ids.

Mark applyDagreLayout @deprecated. The structural views all use ELK
now; the helper is retained for one release as a quick fallback path
and removed in the next.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 17:26:49 +08:00
Lum1104andClaude Opus 4.7 8d068549cb fix(dashboard): address final review C1 + C2
C1 (cache leak across topology changes):
Container ids derive from folder names (`container:auth`, etc.) and
collide across layers, personas, and node-type filters. Without a
reset, navigating from Layer A to Layer B left Stage 2's cache and
size memory keyed by Layer A children, so Stage 2 short-circuited
and Layer B's children silently disappeared.

Reset containerLayoutCache, containerSizeMemory, and
expandedContainers in:
- drillIntoLayer (most visible — layer drill)
- navigateToOverview (drilling out)
- toggleNodeTypeFilter (filter change shifts container.nodeIds)
- setPersona (persona filters node types)

setGraph already resets all three on full graph reload — unchanged.

C2 (bundle regression):
Add elkjs and graphology rules to vite manualChunks. The main index
chunk drops from 525KB gzipped back to 62KB, with ELK split into a
parallel-loadable 439KB chunk. Restores baseline first-paint cost.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 17:14:04 +08:00
Lum1104 1329c93dbd feat(dashboard): layout-issue banner + Computing layout overlay 2026-05-03 17:01:41 +08:00
Lum1104andClaude Opus 4.7 69a0cd13a9 chore(dashboard): address Task 14 + 15 review concerns
Task 14 stale TODO:
- Delete the TODO(Task 14) comment that this very task already
  resolved (selection→container neighbor highlighting now flows
  through isFocusedViaChild).

Task 15 visible container size:
- mergeElkPositions now propagates width/height from the ELK output
  back onto the React Flow node, not just position. After a
  stage1Tick-driven re-layout, the container atom resizes to match
  the actual Stage 2 footprint instead of staying clipped at the
  pre-expansion estimate. ELK echoes back the same width/height we
  pass in for non-container nodes, so this is a no-op for them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:53:58 +08:00
Lum1104 ccb52545ad feat(dashboard): Stage 2 size-deviation triggers Stage 1 re-layout 2026-05-03 16:51:47 +08:00
Lum1104 bbbd789603 test(dashboard): layout perf benchmark script 2026-05-03 16:50:01 +08:00
Lum1104andClaude Opus 4.7 cb71e989e8 chore(dashboard): address Task 12 + 13 review concerns
Task 13 onMove auto-expand:
- Skip when event === null so React Flow's programmatic moves
  (fitView at layer entry, zoomTo from search) don't cascade-expand
  every container the moment the layer paints.
- Track previous zoom; only fire when zoom actually increased. Pans
  and zoom-outs are now no-ops, so a user who manually collapses a
  container while zoomed in can keep it that way.

Task 12 inflated edge ids:
- Append index suffix so parallel edges with identical
  (source, target, type) — which the schema doesn't disallow — don't
  collide in React Flow's edge map.

Other Task 12 concerns (per-container Stage 2 cancellation, O(K·E)
edge bucket pre-pass, extent:"parent" clipping pre-Task-15) are
known trade-offs documented in the plan; deferring to follow-ups.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:46:43 +08:00
Lum1104 202c9e0481 feat(dashboard): container overlays — search/diff/focus 2026-05-03 16:42:39 +08:00
Lum1104 1e0849b528 feat(dashboard): auto-expand on zoom, focus, and tour 2026-05-03 16:38:53 +08:00
Lum1104andClaude Opus 4.7 7dd1c41906 chore(dashboard): address Task 11 review minors
- Stable handleContainerToggle via useCallback so ContainerNode's
  memo() actually short-circuits. Reading toggleContainer through
  getState() keeps Stage 1 from accidentally subscribing to
  expandedContainers.
- Cap pre-expansion container size at 800x600 so layers with many
  files don't render as huge empty boxes during Stage 1. Stage 2
  measurement and Task 15's reflow handle the real size.
- Update stale "dagre relayout" comment now that ELK is the layout
  engine; flag the Task 14 follow-up for selection→container
  neighbor highlighting via inline TODO.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:35:39 +08:00
Lum1104 b19d93efc2 feat(dashboard): layer-detail Stage 2 — lazy children layout + edge expansion 2026-05-03 16:32:38 +08:00
Lum1104 4efeccc702 feat(dashboard): layer-detail Stage 1 — containers + ELK 2026-05-03 16:26:17 +08:00
Lum1104andClaude Opus 4.7 ff4ac3c265 chore(dashboard): address Task 9 + 10 review concerns
Cross-cutting fixes for the dagre→ELK migration pattern:

- nodesToElkInput accepts an optional layoutOptionsOverride so views
  can override defaults (e.g. direction) without forking the helper.
- DomainGraphView restores its original LR layout by passing
  { "elk.direction": "RIGHT" } — the previous commit silently shifted
  it to TB because the helper hardcoded DOWN.
- Both overview and DomainGraphView now .catch the ELK promise so
  strict-mode (DEV) failures don't surface as unhandled rejections.
- Both also console.warn returned issues until Task 16 wires the
  WarningBanner funnel; auto-corrected/dropped issues no longer
  silently disappear in production.
- Minor: DRY the duplicate `as unknown as Node[]` cast in GraphView.

Ranksep label-aware spacing in DomainGraphView is intentionally
deferred — see Task 14 polish or follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:19:50 +08:00
Lum1104 8d20efec94 feat(dashboard): DomainGraphView uses ELK 2026-05-03 16:17:26 +08:00
Lum1104andClaude Opus 4.7 47a80912c9 chore(dashboard): address Task 6 + 8 review minors
ContainerNode (Task 8 quality review):
- Add accessibility: role="button", tabIndex, aria-expanded,
  aria-label with item count + state, focus-ring on focus, Enter/Space
  keyboard activation. Containers are the primary lazy-load
  interaction so keyboard support shouldn't be a regression.
- Use var(--color-diff-changed) and the font-serif Tailwind class
  instead of literals so theme switching still works.
- Replace the 🔍 emoji with a typographic "N hits" pill matching the
  badge pattern used by LayerClusterNode.
- Add a displayName so React DevTools shows "ContainerNode" rather
  than "Memo(Anonymous)".

elk-layout.test.ts (Task 6 quality review):
- Drop the (c as { x?: number }).x casts now that ElkChild declares
  x?/y? directly. Tests now exercise the typed contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:14:10 +08:00
Lum1104 0b18a84014 feat(dashboard): overview view uses ELK 2026-05-03 16:12:17 +08:00
Lum1104andClaude Opus 4.7 a9b614ae2d fix(dashboard): complete the GraphEdge test fixture
Earlier review fix-up dropped the `as GraphEdge` cast but didn't add
the `direction` and `weight` fields, breaking `tsc -b`. Tests still
passed because vitest doesn't typecheck. Add the missing fields so
the dashboard build is green again.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:08:52 +08:00
Lum1104andClaude Opus 4.7 00a75c27db chore(dashboard): address Task 5 review minors
- Re-export NODE_WIDTH/NODE_HEIGHT from utils/layout.ts as the
  fallback dimensions in elk-layout.ts. Coupling them with the dagre/
  force defaults prevents silent drift during the migration.
- Declare optional x/y on ElkChild so downstream consumers (Tasks 9-12)
  see the position contract in the type. Comment notes ELK sets them
  on output but they're absent on input.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:07:57 +08:00
Lum1104 e459e924ff feat(dashboard): ContainerNode component (visual + click toggle) 2026-05-03 16:07:26 +08:00
Lum1104 43fd232df7 test(dashboard): applyElkLayout integration cases 2026-05-03 16:06:49 +08:00
Lum1104andClaude Opus 4.7 9da085018e chore(dashboard): address Task 4 review minors
- Length-prefix the inter-container bucket key to eliminate collision
  risk when container ids contain the separator (e.g. folder names with
  spaces). Adds a regression test.
- Rename AggregatedContainerEdge.types -> edgeTypes for symmetry with
  the existing LayerEdgeAggregation.edgeTypes field.
- Drop the as-cast in the test helper by giving it the real EdgeType
  literal type and a complete object shape.
- Reword the JSDoc to match what the function actually does (silently
  drop unmapped endpoints; callers needing strict can pre-filter).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:04:57 +08:00
Lum1104 3ba65e67a0 feat(dashboard): store fields for expanded containers + layout cache 2026-05-03 16:04:34 +08:00
Lum1104andClaude Opus 4.7 a2b8f27810 chore(dashboard): address Task 2 + 3 review minors
- louvain.ts: rewrite the misleading "disconnected nodes get -1" comment
  (the library actually assigns unique ids; the reassignment loop is a
  defensive net for future API drift).
- containers.test.ts: add tags:[] to the test node helper for shape
  fidelity; replace the vacuously-true "every is community" assertion
  with one that actually fails if the community fallback regresses.
- containers.ts: collapse the two-pass groupByFolder into a single
  branching loop; guard Cluster A-Z naming so it doesn't wrap into
  punctuation past 26 communities.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 16:02:20 +08:00
Lum1104 8f3a6bf2c4 feat(dashboard): elk-layout repair pipeline + applyElkLayout 2026-05-03 16:00:49 +08:00
Lum1104 46dc0485b9 feat(dashboard): aggregateContainerEdges (directional, types-set) 2026-05-03 15:57:28 +08:00
Lum1104 74342da070 feat(dashboard): deriveContainers community fallback via Louvain 2026-05-03 15:54:24 +08:00
Lum1104andClaude Opus 4.7 5d11a6bfdc docs(spec+plan): fix-up — rename KnowledgeGraph* types, correct §2 thresholds
Task 2 implementation surfaced inconsistencies between the spec/plan
and the actual codebase:
- The real type exports are GraphNode / GraphEdge, not KnowledgeGraph*
- Folder grouping uses bucket count (folders + rooted) not just folder
  count, with threshold < 2 instead of < 3
- Concentration threshold is > 70% (was > 60%) so 2/3 distributions
  stay in folder mode
- Single-child suppression is gated by layer total ≥ 3 to avoid
  emptying tiny layers
- Removed the "layer < 8 → flat" rule; the algorithm is now uniform
  and small layers fall through naturally via single-child suppression

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 15:51:28 +08:00
Lum1104 30cd640b1e feat(dashboard): deriveContainers folder strategy 2026-05-03 10:53:46 +08:00
Lum1104andClaude Opus 4.7 a11c692c99 chore(dashboard): add graphology-types as direct dep
Code review flagged that without it as a direct dep, TypeScript would
fail to resolve types like Attributes/NodeKey from transitive
graphology-types when later tasks import them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:46:53 +08:00
Lum1104 28362dbfe0 chore(dashboard): add elkjs, graphology, vitest 2026-05-03 10:42:34 +08:00
Lum1104andClaude Opus 4.7 fec05f6278 docs(plan): graph layout scaling — implementation tasks
17-task plan for the dashboard layout migration: dependencies + vitest,
container derivation (folder + Louvain), edge aggregation, ELK repair
pipeline, store extensions, ContainerNode component, per-view migration,
Stage 2 lazy expansion, auto-expand triggers, visual overlays, size
deviation re-layout, banner integration, and perf benchmarks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:37:18 +08:00
Lum1104andClaude Opus 4.7 d965df7859 docs(spec): graph layout scaling — ELK + lazy containers
Design doc for replacing dagre with ELK across structural views, plus
folder/community-based containers and lazy two-stage layout for the
layer-detail view to fix horizontal sprawl at 50+ nodes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 10:27:26 +08:00
Yuxiang LinandGitHub ab96806c08 Merge pull request #110 from LukasWana/main
fix: change file permissions for extract-domain-context.py
2026-05-01 18:31:22 +08:00
OpenClaw Ad Radar d0f77aa736 fix: change file permissions for extract-domain-context.py 2026-05-01 12:24:43 +02:00
Yuxiang LinandGitHub 32875a486e Merge pull request #108 from arkaigrowth/codex/code-viewer-sidepane
feat(dashboard): add read-only source viewer
2026-05-01 18:01:29 +08:00
Lum1104andClaude Opus 4.7 87e3150c4b chore: bump version to 2.4.0
PR #108 ships a new user-visible feature (in-dashboard source code viewer
with Files tab + double-click navigation), so it warrants a minor bump
across all 5 version-tracked files.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:57:43 +08:00
Lum1104andClaude Opus 4.7 7e58e97b5a feat(dashboard): file double-click also navigates the graph
Double-clicking a file in the Files tab previously only opened the source
viewer; the graph stayed wherever it was. Now also calls navigateToNode
first (drills into the layer + selects the node), then re-opens the code
viewer so the source panel stays visible.

Order matters: navigateToNodeInLayer resets codeViewerOpen, so the
openCodeViewer call has to come after.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:55:56 +08:00
Lum1104andClaude Opus 4.7 c6f5409111 fix(dashboard): preserve sidebar composition + restore slide-up code viewer
Two issues from review of #108:

1. Sidebar exclusivity regression — replacing the entire sidebar with the
   CodeViewer when codeViewerOpen hid NodeInfo / LearnPanel / ProjectOverview
   while reading source. Same pattern that was rejected in #50. Restore the
   slide-up bottom overlay (per CLAUDE.md), keep sidebar tabs always visible,
   and revert the <aside> overflow-hidden change so long content can scroll.

2. Cross-graph mismatch (Codex P1) — FileExplorer always builds its tree from
   the structural graph and emits structural node IDs, but CodeViewer resolved
   IDs against the domain graph in domain mode, yielding "No file selected".
   Fall back to the structural graph when the active graph misses, so the
   Files tab works regardless of viewMode.

Also update CLAUDE.md to describe the Files tab + modal expand behavior so
future Claude sessions don't re-introduce the slide-up regression.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 17:28:08 +08:00
arkaigrowth 13327b7945 feat(dashboard): add source code viewer 2026-04-27 17:02:34 -05:00
Lum1104andClaude Opus 4.7 d3c2c65b86 docs: add Discord join badge to all README locales
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 16:58:14 +08:00
1e07cbac94 fix(hooks): use \${CLAUDE_PLUGIN_ROOT} so plugin path expands at runtime
Hook echo commands referenced \${PLUGIN_DIR}, which Claude Code does not
inject into hook commands. The documented variable is \${CLAUDE_PLUGIN_ROOT}
(used elsewhere in skills/understand/SKILL.md and friends). Also switched
the surrounding single quotes to double quotes so the variable actually
expands at runtime instead of being passed literally.

Without this fix, the auto-update hook silently sent Claude a non-existent
file path, so the knowledge graph never incrementally updated even when
autoUpdate: true was configured.

Builds on the direction identified in #96; closes #96.

Co-Authored-By: xiaolai <lixiaolai@gmail.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 21:00:55 +08:00
Yuxiang LinandGitHub 6afa1bdfc5 Merge pull request #97 from xiaolai/fix/nlpm-echo-tool-input-printf
fix: use printf instead of echo to pipe TOOL_INPUT into grep
2026-04-25 20:58:20 +08:00
Yuxiang LinandGitHub 1f61d9d03b Merge pull request #98 from xiaolai/fix/nlpm-gitignore-stderr-warnings
fix: log skipped invalid gitignore patterns to stderr
2026-04-25 20:55:47 +08:00
Lum1104andClaude Opus 4.7 ed584b1de2 compress hero image
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 20:49:48 +08:00
Yuxiang LinandGitHub f6dbaabbd2 Merge pull request #105 from gustn99/docs/update-claude-code-link
docs: update claude code link to claude code plugin in README
2026-04-25 11:49:42 +08:00
gustn99 e68f651fb0 docs: update claude code link to claude code plugin in README 2026-04-25 12:15:56 +09:00
Yuxiang LinandGitHub 2eb109d0f3 Merge pull request #103 from ZebangCheng/fix/image-404-paths
fix: correct hero image extension from .png to .jpg in Hero.astro
2026-04-24 19:29:29 +08:00