Commit Graph

540 Commits

  • fix(extract-import-map): apply NodeNext .js→.ts rewrite (#294)
    Fixes the silent near-edgeless-graph regression on any modern ESM
    TypeScript project. Reported in #294 with full repro + root-cause
    analysis.
    
    ### Why this matters
    
    Under `moduleResolution: NodeNext` (or `Node16` / `Bundler` with
    explicit extensions — the default for new TS-ESM projects since 2023),
    TypeScript does NOT rewrite import specifiers during compilation:
    
      // src/index.ts — real, idiomatic NodeNext source
      import { x } from './config.js';   // on disk: config.ts
    
    Before this fix, `probeWithExtensions` only tried APPENDING extensions
    to the import specifier:
    
      './config.js' → not in fileSet
      './config.js.ts', './config.js.tsx', './config.js.js', ... → all miss
      → returns null → edge dropped at merge as dangling
    
    Net result on the reporter's repro: a knowledge graph with hundreds of
    file nodes and almost no `imports` edges between them — silently
    removing exactly the dependency structure the graph is meant to show.
    
    ### Fix
    
    New `NODENEXT_REWRITES` table maps each compiled-output extension to
    the TypeScript source extensions that could have produced it:
    
      .js   → [.ts, .tsx, .js, .jsx]
      .jsx  → [.tsx, .jsx]
      .mjs  → [.mts, .mjs, .ts]
      .cjs  → [.cts, .cjs, .ts]
    
    `probeWithExtensions` now applies the rewrite when the import already
    ends with one of these extensions and no such file exists on disk. The
    rewrite runs BEFORE the legacy append-extensions loop — otherwise
    `./foo.js` would generate the nonsense candidate `foo.js.ts` and the
    append loop would never reach the actual `foo.ts`.
    
    ### Disambiguation
    
    If both `config.ts` and `config.js` exist on disk (rare, but possible
    during a partial migration), `import './config.js'` still resolves to
    the .js — that's an exact-disk match and what NodeNext compilation
    actually does. The rewrite only kicks in when the .js doesn't exist.
    
    ### Tests
    
    6 new tests in `test_extract_import_map.test.mjs`:
    - The main #294 case (`.js → .ts`)
    - `.jsx → .tsx` and `.mjs → .mts` rewrites
    - Disambiguation when both `.ts` and `.js` exist on disk
    - Pure-JS projects still work (real `.js → .js` imports)
    - Historical no-extension probes unaffected
    - Missing files still return null (rewrite can't invent targets)
    
    Total: 202 tests passing (was 196).
    
    Closes #294
  • Merge pull request #200 from AsimRaza10/fix/agent-model-omit-inherit
    fix(agents): omit `model: inherit` so non-Claude tools don't see a bad model id
  • docs(readme): note Cursor manual install fallback when auto-discovery fails (#199)
    Several users have reported that cloning the repo and opening it in Cursor
    doesn't always trigger auto-discovery of the .cursor-plugin manifest. Add
    the community-reported workaround (Cursor Settings → Plugins, paste repo
    URL) to the Cursor section so it isn't only discoverable from issue
    threads.
    
    Closes #172
  • Merge pull request #204 from Lum1104/feat/semantic-batching-and-output-chunking
    fix(#159): semantic batching + bundled importMap + Phase 1 speedup
  • fix(agents): omit model: inherit so non-Claude tools don't see a bad model id
    `model: inherit` is a Claude Code-specific keyword that means "use the
    parent session's model." Other tools that read the same agent frontmatter
    (opencode, codex, etc.) don't understand it and instead try to use
    `inherit` as a literal model id, which the configured provider rejects.
    
    Reproduction (from #167): opencode + deepseek runs `/understand`, the
    project-scanner subagent dispatches with `model: inherit`, deepseek
    returns `ProviderModelNotFoundError`, and the pipeline halts on every
    subagent dispatch.
    
    With the field omitted, each platform falls back to its own configured
    default:
    - Claude Code: user's default subagent model
    - opencode / codex / etc.: globally configured model
    
    Note for Claude Code Opus users: subagents will no longer auto-inherit
    the Opus session model. If you want the previous behavior, set your
    default subagent model globally — that single setting now controls all
    nine agents.
    
    Closes #167
  • docs(readme): note Cursor manual install fallback when auto-discovery fails
    Several users have reported that cloning the repo and opening it in Cursor
    doesn't always trigger auto-discovery of the .cursor-plugin manifest. Add
    the community-reported workaround (Cursor Settings → Plugins, paste repo
    URL) to the Cursor section so it isn't only discoverable from issue
    threads.
    
    Closes #172
  • Merge pull request #186 from AsimRaza10/fix/tailwind-source-detection
    fix(dashboard): explicit @source for Tailwind v4 (fixes #179)
  • Merge pull request #187 from devangpratap/fix/progress-reporting
    fix(ux): add progress reporting to /understand pipeline
  • docs(readme): document incremental updates, subdir scoping, and tree-sitter+LLM split
    Add to all 8 READMEs (English + 7 translations):
    - "Keep learning" section gets inline commands for incremental re-runs, the --auto-update post-commit hook, and scoping /understand to a subdirectory for huge monorepos
    - "Under the Hood" gets a new "Tree-sitter + LLM hybrid" subsection explaining the deterministic-vs-semantic split that powers the pipeline
  • fix(ux): add progress reporting to /understand pipeline
    Adds phase status lines, batch progress with total count, and phase
    completion confirmations to the skill definition. Users now see
    [Phase N/7] headers and Batch X/N during analysis instead of
    unnumbered batch lines with no context.
    
    Fixes #182
  • fix(dashboard): add explicit @source for Tailwind v4 detection
    Tailwind v4's default source detection walks the nearest .git and
    collects tracked files via git ls-files. When the dashboard sources
    sit inside a gitignored subtree of an ancestor repo (e.g. the default
    marketplace install path ~/.claude/plugins/cache/, which is ignored by
    ~/.claude/.gitignore), detection returns 0 files and the Oxide engine
    skips all utility generation — the dashboard renders unstyled.
    
    Adding explicit @source directives is the supported Tailwind v4 escape
    hatch and is a no-op for installs where automatic detection works.
    
    Verified: built CSS bundle jumps from ~9 KB to ~55 KB and utility
    classes (.flex, .grid, .absolute, .w-full, .h-full) are present.
    
    Fixes #179
  • Merge pull request #171 from Derrick-xn/docs/update-skill-graph-reference
    docs(skills): update graph structure references
  • Merge pull request #177 from vedrao/fix/security-astro-vite-cve-bumps
    chore(deps): bump astro to 6.3.7 and dashboard vite to 6.4.2 for security fixes
  • chore(dependencies): update astro and vite versions in package.json and pnpm-lock.yaml
    Bumps astro to version 6.3.7 and vite to version 6.4.2 across relevant package files to ensure compatibility and access to the latest features.
  • 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)