Commit Graph

525 Commits

  • Merge pull request #161 from okwn/contrib/understand-anything/eslint-tooling
    chore: add ESLint tooling with TypeScript support
  • chore(lint): switch to recommended baseline, fix errors, wire into CI
    - typescript-eslint preset: strict -> recommended for a usable first-pass
      baseline (per PR discussion); ratchet up in a follow-up.
    - Drop the projectService/parserOptions block. Neither `recommended` nor
      `strict` is type-aware, so it was unused; removing it also avoids the
      pnpm-workspace tsconfig-resolution failure mode flagged in review.
    - Add Node + browser globals via the `globals` package so .mjs scripts and
      the dashboard stop hitting `no-undef`.
    - Expand ignores: built bundles (**/public/**), Astro generated (.astro/),
      and .private/ (eval scratch). Cuts 2400+ errors in vendored output.
    - Allow `_`-prefixed unused vars/args/caught errors; skip irregular
      whitespace inside comments (json-parser intentionally embeds ZWSP-escaped
      block-comment examples in JSDoc).
    - Fix the residual 13 genuine errors: drop dead imports/vars, replace
      two `as any[]` in schema.ts with `Array<Record<string, unknown>>`,
      drop unused destructure in change-classifier, drop unused catch binding
      in extract-structure.mjs.
    - Add EOF newline to eslint.config.mjs.
    - Refresh pnpm-lock.yaml.
    - Add `pnpm lint` step to .github/workflows/ci.yml so the tooling
      actually enforces something.
    
    pnpm lint now exits 0 locally; 33+13 test files / 1445 tests still pass.
  • Merge pull request #175 from zichen0116/fix/wrong-github-url-in-footer
    fix: correct GitHub URL in onboarding guide footer
  • fix: correct GitHub URL in onboarding guide footer
    The generated onboarding markdown linked to a nonexistent repository
    (anthropics/understand-anything) instead of the actual project URL
    (Lum1104/Understand-Anything).
  • Merge pull request #170 from Lum1104/feat/trendshift-badge
    feat(readme,homepage): add Trendshift trending badge
  • feat(readme,homepage): add Trendshift badge
    Adds the Trendshift trending-repository badge just below the tagline on the
    English README and all 7 localized variants, and to the homepage hero between
    the action row and the Enterprise pill.
  • Merge pull request #164 from Lum1104/feat/community-video
    feat(readme,homepage): add Community section with Better Stack walkthrough video
  • feat(readme,homepage): add Community section featuring Better Stack walkthrough video
    Adds a Community section near the end of README (English + 7 localized
    variants) and a CommunityVideo component on the homepage embedding the
    YouTube walkthrough by Better Stack. Section invites future video / blog /
    tutorial contributions to be featured here.
  • Merge pull request #163 from Lum1104/fix/extract-structure-symlink-isCli
    fix(skills/understand): extract-structure isCli silently no-ops via symlinked SKILL_DIR
  • fix(skills/understand): canonicalize isCli paths so symlinked SKILL_DIR runs main()
    import.meta.url resolves through symlinks but pathToFileURL(process.argv[1])
    preserves them, so extract-structure.mjs silently exited 0 without writing
    output when invoked via the plugin's symlinked install path — the documented
    Claude Code / Copilot CLI layout. Compare both sides via realpathSync and add
    a post-write existence assertion plus caller-side guidance in the agent.
    
    Closes #162
  • chore: add ESLint tooling with TypeScript support
    The repository has a pnpm lint script running 'eslint .' but ESLint
    and typescript-eslint were not listed in devDependencies.
    
    Added:
    - eslint (^9.0.0)
    - @eslint/js (^9.0.0)
    - typescript-eslint (^8.0.0)
    
    Added eslint.config.mjs with flat config (ESLint 9+) using
    typescript-eslint strict rules. Ignores node_modules, dist, build,
    and framework-specific output directories.
  • Merge pull request #155 from nieao/feat/onboarding-overlay
    feat(dashboard): first-visit onboarding overlay
  • refactor(onboarding): theme tokens, lifted state, a11y
    - Replace hardcoded hex with var(--color-*) and CJK font stacks with
      var(--font-sans) / var(--font-heading) so the overlay tracks the theme
      picker and uses the project's typography (DM Serif Display).
    - Lift dismiss/visibility state to Dashboard (shouldShowOnboarding +
      showOnboarding useState + dismissOnboarding callback). Gate the
      Suspense mount with a boolean so the lazy chunk is only fetched on
      first visit, matching the PathFinderModal / KeyboardShortcutsHelp
      mount pattern.
    - Add capture-phase Escape handler (stopPropagation prevents the global
      shortcut chain from also firing) and role="dialog" / aria-modal /
      aria-labelledby on the card for screen readers.
  • fix(onboarding): include class/function in node-type description
    Schema (packages/core/src/schema.ts) defines node types: file, function,
    class, module, concept, config, document, ... The welcome step body only
    listed "file, concept, entity, claim", missing the most common code-side
    types. Updated all 6 locales (en / zh / zh-TW / ja / ko / ru) to mention
    file / class / function from code plus concept / entity / claim from the
    knowledge wiki.
  • fix(onboarding): wire to i18n + add missing ua-fade-in keyframes
    - Replace hardcoded Chinese strings with t.onboarding.* via useI18n
    - Add `onboarding` namespace to en / zh / zh-TW / ja / ko / ru locales
    - Inject @keyframes ua-fade-in (was referenced in inline style but
      never defined, so the overlay popped in instead of fading)
  • chore(release): bump version to 2.7.3
    Ships the fingerprints baseline fix (e7af9ae): every install since
    2.7.0 had a broken Phase 7 step 2.5 that threw TypeError on the first
    /understand run and left fingerprints.json empty/missing, which made
    every subsequent auto-update escalate to FULL_UPDATE. This release
    replaces the LLM-written script with a bundled build-fingerprints.mjs
    and reorders Phase 7 to write fingerprints before meta.json.
    
    Anyone upgrading from 2.7.0–2.7.2 should re-run /understand --full
    to regenerate a valid baseline.
  • fix(skills/understand): bundle build-fingerprints.mjs and reorder Phase 7
    The Phase 7 step 2.5 code example in SKILL.md called
    buildFingerprintStore() with 2 arguments, but the real signature
    requires 4 (projectDir, filePaths, registry: PluginRegistry,
    gitCommitHash: string). It also omitted the required
    `await TreeSitterPlugin.init()`. Any LLM following the example
    threw TypeError on `registry.analyzeFile()` and never produced a
    baseline — which is why fingerprints.json never existed in a usable
    form after a fresh /understand, and is the root cause behind
    issue #152's "every auto-update escalates to FULL_UPDATE" cascade.
    
    Replace the LLM-written script with a bundled `build-fingerprints.mjs`
    that mirrors `extract-structure.mjs`: resolves @understand-anything/core
    via createRequire, initializes TreeSitterPlugin + PluginRegistry
    correctly, calls buildFingerprintStore with all four arguments, and
    persists via saveFingerprints. Smoke-tested on this repo (3 files,
    correct functions/classes/imports extracted).
    
    Reorder Phase 7 so fingerprints are written BEFORE meta.json. If
    fingerprint generation fails, the new step explicitly says to abort
    Phase 7 — meta.json must not advance without a valid baseline, or
    the next auto-update sees a fresh commit hash with no fingerprints
    and classifies every file as STRUCTURAL.
    
    Affects every install since 2.7.0 (when the broken example was
    introduced). Users running /understand --full on 2.7.3+ will get
    a usable fingerprints.json on the first try.
  • chore(release): bump version to 2.7.2
    Ships two auto-update fixes:
    - #153 (5304ff0): apply .understandignore in Phase 0 so user-excluded
      paths don't inflate the structural-change count.
    - #152 (dd8b724): LOAD-PATCH-SAVE template for Phase 3d fingerprints
      merge, with guard against silent load failure.
  • fix(hooks/auto-update): make fingerprints merge unambiguous in Phase 3d
    Fixes #152. Phase 3d step 3 instructed the LLM to "merge with existing
    fingerprints (keep unchanged files as-is)" but the prose was vague
    enough that the LLM-written script frequently wrote only the freshly
    re-analyzed batch entries to fingerprints.json, discarding every other
    file's fingerprint. The next auto-update saw N-batch_size files with
    no stored fingerprint → classified as STRUCTURAL → exceeded the 30-file
    threshold → FULL_UPDATE permanently, burning hundreds of thousands of
    tokens on every subsequent commit.
    
    Replace the four-bullet description with an explicit LOAD-PATCH-SAVE
    script template:
    
      1. LOAD ALL existing entries from fingerprints.json (never skip).
      2. PATCH or REMOVE each path in filesToReanalyze (inline deletion
         handling so the spec doesn't need a separate deletedFiles list).
      3. GUARD: if the file existed and was non-empty but loaded as {},
         abort the write — silent load failure would otherwise clobber
         every fingerprint.
      4. SAVE the full dict back.
    
    The reporter's dry-run showed this restores 81/97 files to COSMETIC
    classification on their project (zero LLM tokens) instead of all 97
    incorrectly forced into STRUCTURAL.
    
    Note: a related ordering bug exists in skills/understand/SKILL.md
    Phase 7 (meta.json written before fingerprints.json — silent failure
    in step 2.5 leaves stale fingerprints). That's a separate fix in a
    different file and is intentionally not bundled here.
  • fix(hooks/auto-update): apply .understandignore exclusions in Phase 0
    Fixes #153. Phase 0 step 7 filters changed files to source extensions
    only and never reads `.understandignore`, so files in user-excluded
    paths (migrations, vendored code, tests) count as structural changes
    and can spuriously escalate the action to FULL_UPDATE. The reporter
    saw 50 → 38 structural files after applying their ignore patterns
    (below the 30-file FULL_UPDATE threshold, ARCHITECTURE_UPDATE would
    have sufficed).
    
    Add step 9 that delegates to `createIgnoreFilter` from
    `@understand-anything/core` via $CLAUDE_PLUGIN_ROOT. Same code path
    as /understand's project-scanner Step 2.5, so the auto-update honors
    the exact same patterns (hardcoded defaults + user .understandignore
    files at both standard locations + `!` negation semantics).
    
    If $CLAUDE_PLUGIN_ROOT can't be resolved, fail loud rather than
    silently skipping — a silent skip reproduces the original bug.
  • chore(release): bump version to 2.7.1
    Ships the fixes that landed on main after the 2.7.0 cut:
    
    - #139 (f3ea1a3): understand-knowledge — Windows path separators in
      wikilink resolution + omit empty `category` so KnowledgeMetaSchema's
      `z.string().optional()` no longer drops every article node. Closes #151.
    - #147 (fafb888): understand-domain — resolve $PLUGIN_ROOT at runtime
      for symlink installs.
    - f71bad5: understand — persist canonical edge direction during merge,
      fixing the 153k auto-correction cascade. Closes #140.
  • fix(skills/understand): persist canonical edge direction during merge
    Fixes #140. merge-batch-graphs.py already defaulted missing `direction`
    to "forward" when building the dedup key, but the value was never written
    back onto the edge — so the generated knowledge-graph.json shipped without
    the field and the dashboard validator emitted one auto-correction per
    edge (153k on the reporter's Go codebase).
    
    Mirror the dashboard schema validator at packages/core/src/schema.ts:
    lowercase the value, map "both"/"mutual" → "bidirectional", fall back to
    "forward" for missing or invalid values, and persist the result onto the
    edge before it enters edges_by_key. This also closes a latent dedup leak
    where "Forward" and "forward" (or "both" and "bidirectional") would have
    produced separate dedup keys.
  • Merge pull request #139 from nieao/fix/windows-compat
    fix(understand-knowledge): Windows path + zod schema null compatibility
  • Merge pull request #147 from rustanacexd/fix/understand-domain-plugin-root
    fix(skills/understand-domain): resolve plugin root for agent prompt loading (#146)
  • fix(skills/understand-domain): resolve plugin root at runtime for symlink installs
    Fixes #146. Ports the $PLUGIN_ROOT resolution pattern from understand/SKILL.md
    to understand-domain/SKILL.md, including:
    - Symlink resolution for ~/.agents/skills/understand-domain
    - Copilot fallback for ~/.copilot/skills/understand-domain
    - Detailed error diagnostics listing all checked paths
    - Phase 4 agent prompt path now uses $PLUGIN_ROOT/agents/domain-analyzer.md
  • docs(homepage): add author homepage link below enterprise contact
    A second pill mirroring the Enterprise one, linking to https://lum.is-a.dev/.
    Same gold/amber styling, 0.6rem gap below the Enterprise pill so the two read
    as one "contact" group, anim-5 so both pills enter together. Full mobile
    breakpoint mirror.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • chore(release): bump version to 2.7.0
    Includes since 2.6.3: Hermes (#91), Cline (#116), KIMI CLI (#134)
    platform support; dashboard ACCESS_TOKEN env override; README cleanup
    (slogan rewrite, drop outdated overview gifs, move thanks to footer).
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • Merge pull request #145 from zhushen12580/fix/code-review-feedback
    docs: Add --language parameter documentation to all READMEs
  • Merge pull request #142 from zhushen12580/feature/language-parameter
    feat: Add --language parameter for localized content generation
  • fix: Address code review feedback for PR #142
    - Remove invalid allowBuilds from pnpm-workspace.yaml (use onlyBuiltDependencies in root package.json)
    - Use data-testid for search input selector (fixes / keyboard shortcut for non-English locales)
  • feat(install): add KIMI CLI platform support (#134)
    KIMI CLI scans ~/.kimi/skills/ (its brand path) for SKILL.md per the
    official skill discovery spec, so distribution follows the same
    folder-symlink pattern as Hermes / Cline / OpenClaw. install.sh and
    install.ps1 register the `kimi` platform; README × 7 updated for the
    one-line install title, <platform> values, and compatibility table.
    
    Closes #134
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • feat(install): add Cline platform support (#116)
    Cline natively scans ~/.cline/skills/ for SKILL.md, so distribution
    follows the same folder-symlink pattern as Hermes / OpenClaw /
    Antigravity. install.sh and install.ps1 register the `cline` platform;
    README × 7 (English + 6 locales) updated for the one-line install
    title, <platform> values, and the compatibility table.
    
    Closes #116
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • feat(dashboard): allow ACCESS_TOKEN override via env var
    Honor UNDERSTAND_ACCESS_TOKEN if set, falling back to the random 16-byte
    hex token. Lets the dev token survive across server restarts so shared
    dashboard URLs don't rot, and makes the auth path easier to script in
    tests.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • fix: Wrap MobileLayout with I18nProvider; use outputLanguage key in config
    P1: MobileLayout was missing I18nProvider wrapper, causing useI18n
        to throw error on mobile devices. Now both desktop and mobile
        layouts are wrapped with I18nProvider.
    
    P2: SKILL.md used 'language' key but Dashboard reads 'outputLanguage'.
        Fixed config.json key name to match ProjectConfig type definition.
    
    All tests passed:
    - Core: 670 tests
    - Dashboard: 42 tests
  • feat(dashboard): Add i18n support for localized UI text
    - Add outputLanguage field to ProjectConfig type
    - Create /config.json endpoint in vite.config.ts
    - Build locale files for 5 languages (en, zh, zh-TW, ja, ko)
    - Add I18nProvider context and useI18n hook
    - Update 5 components (ProjectOverview, NodeInfo, FileExplorer, FilterPanel, PersonaSelector)
    - Dashboard reads language from config.json and displays localized UI
    
    All tests passed:
    - Core: 670 tests
    - Dashboard: 42 tests
  • feat: Add --language parameter for localized content generation
    Adds --language parameter to /understand command to generate knowledge
    graph content in user-specified language.
    
    Changes:
    - Update argument-hint and Options documentation in SKILL.md
    - Add language parsing logic in Phase 0 (language normalization,
      config persistence, LANGUAGE_DIRECTIVE template)
    - Inject language directive into agent dispatch prompts for all
      content-generating phases (Phase 1-5)
    - Add language directive handling instructions in agent definitions
    - Create locales/ directory with template files for:
      - English (en.md) - default
      - Chinese Simplified (zh.md)
      - Chinese Traditional (zh-TW.md)
      - Japanese (ja.md)
      - Korean (ko.md)
    
    Locale files provide language-specific guidance for:
    - Tag naming conventions
    - Summary writing style
    - Technical term handling
    - Layer name translations
    
    Closes #141
  • feat(install): add Hermes platform; refresh README (#91)
    - install.sh / install.ps1: register `hermes` platform (folder-style
      symlink to ~/.hermes/skills/understand-anything/). No new directories
      or plugin manifests needed — Hermes scans skills via os.walk(...,
      followlinks=True) and reads SKILL.md frontmatter directly.
    - README × 7 (English + 6 locales): one-line install title, `<platform>`
      values, and compatibility table updated for both Hermes and Vibe CLI
      (locale READMEs were missing Vibe).
    - README × 7: drop top-of-page Star History Rank badge and the TIP-style
      thanks blockquote; rewrite the slogan into a longer line about quietly
      teaching how the pieces fit; move a single italic thanks line between
      Star History and the MIT footer.
    - README × 7: remove the two outdated overview-*.gif blocks. The
      Features section already opens with a NOTE callout linking to the live
      demo, which serves as the visual entry instead.
    - Delete assets/overview-{structural,domain}.gif (8.1 MB of orphaned
      binaries) from the working tree.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • Merge pull request #138 from voidborne-d/fix/worktree-paths
    fix(skills): redirect PROJECT_ROOT out of git worktrees (closes #133)
  • Merge pull request #132 from Xingkai98/feat/dashboard-file-class-views
    feat(dashboard): add file/class dual-view toggle to reduce graph clutter
  • fix(dashboard): reset fn toggle on view switch; hide detail toolbar in domain view
    - Issue 1: setDetailLevel now resets showFunctionsInClassView so the fn
      toggle doesn't resurrect when re-entering class view after a file-view
      round-trip.
    - Issue 2: detail-level toolbar (Files/+Classes/fn) now gated on
      viewMode !== "domain" so it doesn't render in domain view where it has
      no effect.
  • Merge pull request #124 from tipich/fix/windows-pnpm10-compat
    fix(skill): make /understand work on Windows + pnpm 10
  • feat(dashboard): first-visit onboarding overlay
    Add a 5-step modal that walks new users through the dashboard's core operations
    on first visit. Auto-hides via localStorage after dismiss; can be force-shown
    with `?onboard=force` for screenshots and demos.
    
    ## What it teaches
    
    1. What the graph represents (entities/relations from code or wiki)
    2. Three view buttons (Overview / Learn / Deep Dive) — each answers a different
       question
    3. Search + node click — find by name, click for details panel
    4. Layer switch + Project Tour — drill into a category, or follow a guided
       walkthrough
    5. Hidden features (Filter / Export / Path / Theme) and Shift+? for keyboard
       shortcuts
    
    ## Design
    
    - Inline styles, no extra CSS file — easier to land in the existing structure
    - Lazy-loaded via Suspense like the other modals (KeyboardShortcutsHelp,
      PathFinderModal) so it ships in a separate chunk
    - Architectural-minimalism dark palette consistent with the existing dashboard:
      off-black surface, warm accent (#c8a882), Noto Serif SC headings, generous
      whitespace
    - localStorage key `ua-onboarding-dismissed-v1` — versioned so future content
      changes can re-trigger
    - Accessible: keyboard-navigable buttons, click-outside to close (without
      remembering dismiss), explicit "不再显示" / "Skip" affordance
    
    ## Tested
    
    - Windows 11 + Chrome via Playwright: 5 steps render, progress bar tracks,
      prev/next/dismiss/finish all work, localStorage persists dismiss across
      reloads, `?onboard=force` re-shows for testing
    - No new dependencies (uses React 19 hooks already present)
    - No changes to data flow, store, or other components — strictly additive
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • fix(understand-knowledge): Windows path + zod schema null compatibility
    Four single-line fixes that make `/understand-knowledge` work end-to-end on Windows.
    
    ## Root causes
    
    1. Path separator mismatch (3 occurrences in parse-knowledge-base.py)
       - `str(rel.with_suffix(""))` returns backslash-separated stems on Windows
         (e.g. `entities\foo`), while wikilinks always use forward slashes
         (`[[entities/foo]]`).
       - Result: name_map keys and article_ids hold `entities\foo`, while
         `resolve_wikilink()` looks up `entities/foo` -> 100% miss.
       - Tested on Windows 11 + Python 3.14: 151/151 wikilinks unresolved,
         0 edges built from wikilinks.
    
       Fix: use `rel.with_suffix("").as_posix()` in all three places
       (lines 235, 316, 330 on main).
    
    2. Null vs missing field (1 occurrence)
       - `"category": category or None` writes `null` when category is empty.
       - `KnowledgeMetaSchema.category` in packages/core/src/schema.ts is
         `z.string().optional()`, which accepts `undefined`/missing but
         rejects `null`.
       - Result: every article node fails GraphNodeSchema validation in the
         dashboard (`Invalid input: expected string, received null`),
         all nodes get dropped, dashboard renders empty.
    
       Fix: omit the field when empty using dict spread.
    
    ## After
    
    Tested with a 27-article Karpathy wiki on Windows:
    - before: 151 unresolved wikilinks, 0 edges, 0 nodes rendered in dashboard
    - after:  0 unresolved, 110 wikilink edges + 23 LLM-implicit edges,
              all 53 nodes (article/topic/entity/claim) render correctly
    
    No behavior change on macOS/Linux: `as_posix()` is a no-op when the OS
    already uses `/`, and dict spread produces the same key as the previous
    truthy branch.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>