601 Commits

  • Merge pull request #466 from thejesh23/fix/understandignore-multi-language-test-patterns
    feat(core): broaden .understandignore starter for C#/Java/Go test patterns
  • fix(skills): prefer $PLUGIN_ROOT over relative path in generate-ignore.mjs
    Addresses codex review feedback (P2). `resolve(__dirname, '../..')` breaks
    when `skills/understand/` is copied to a runtime skills directory whose
    parent is not the plugin checkout — exactly the case SKILL.md Phase 0 warns
    about and resolves via its multi-candidate $PLUGIN_ROOT search.
    
    This script now prefers $PLUGIN_ROOT from the env (validated via
    package.json presence) and falls back to the existing relative resolution.
    SKILL.md Phase 0.5 passes the env var in the invocation.
    
    Same latent pattern exists in scan-project / compute-batches / extract-import-map
    / extract-structure / build-fingerprints; hardening those is a separate
    concern (no behaviour change today for installs that already work).
    
    Refs #76
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • refactor(skills): extract generate-ignore.mjs from SKILL.md inline one-liner
    Replaces the duplicated Node.js block in Phase 0.5 with a call into
    `generateStarterIgnoreFile` via a thin wrapper script, mirroring the
    scan-project.mjs pattern. Removes ~40 lines of duplicated logic; single
    source of truth in @understand-anything/core.
    
    Also tightens code review nits:
    - Add 3 tests: stable language-group ordering, all-commented invariant
      on empty dirs, suffix-glob rejects non-directory entries
    - Clarify comments on EXACT_DIR_NAMES (ecosystem mix, not Python) and
      SUFFIX_DIR_GLOBS (unanchored String.endsWith match)
    - Type detectDirectories' readdirSync result explicitly (Dirent[]) to
      pin the utf-8 encoding overload
    
    Refs #76
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • feat(core): broaden .understandignore starter — C#/Java/Go test patterns
    Detect C# project-suffix dirs (Foo.Tests/, Foo.UnitTests/) and PascalCase
    test dirs (Tests/, UnitTests/, IntegrationTests/) via case-insensitive
    match; group test-file suggestions by language (JS, C#, Java, Go).
    
    Keeps all suggestions commented-out — same opt-in model as today. Updates
    SKILL.md Phase 0.5 inline generator to stay in sync with the TS module.
    
    Refs #76
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • docs(readme): add Kiro platform support to translated READMEs
    Mirror the English README's Kiro additions across all 7 translations
    (es-ES, ja-JP, ko-KR, ru-RU, tr-TR, zh-CN, zh-TW): the one-line install
    heading, supported <platform> values, a dedicated Kiro CLI / IDE
    section, and the Platform Compatibility table row.
  • fix(install): address PR #364 review feedback for Kiro support
    Addresses the maintainer (@Lum1104) change requests and the Codex
    review on PR #364.
    
    install.sh
    - Build the Kiro agent's "resources" list dynamically by iterating over
      understand-anything-plugin/agents/*.md instead of hard-coding each path
      (review: "do not hard code the agents, instead use loop of the repo
      dir"). Deterministic order via LC_ALL=C sort; pure bash, no jq
      dependency. This also fixes pre-existing drift: the hard-coded list had
      7 entries and was missing article-analyzer.md and
      knowledge-graph-guide.md, while 9 agent files actually exist.
    - Drop the unsupported "Kiro IDE auto-discovers .kiro-plugin/plugin.json"
      install tip; keep the usage hint.
    
    install.ps1 (Windows)
    - Add the `kiro` platform entry (~/.kiro/skills, per-skill) so
      `install.ps1 kiro` no longer fails with "Unknown platform: kiro".
    - Generate ~/.kiro/agents/understand.json in Cmd-Install using the same
      dynamic agent discovery; emit forward-slashed file:// URIs and write
      UTF-8 without a BOM via [System.IO.File]::WriteAllText.
    - Remove the agent JSON in Cmd-Uninstall.
    
    README.md
    - Point the Kiro install command at the canonical Egonex-AI repo instead
      of Lum1104 (Codex P2: a lagging fork would error "Unknown platform:
      kiro" before cloning the canonical repo).
    - Replace the unverified ".kiro-plugin auto-discovery" claim with the
      actual behavior (skills symlinked into ~/.kiro/skills, agent written to
      ~/.kiro/agents/understand.json).
    
    Remove .kiro-plugin/plugin.json
    - Kiro's documented discovery locations are ~/.kiro/agents, .kiro/skills
      and .kiro/prompts only; .kiro-plugin/plugin.json is never read, so the
      file and the claims that referenced it are removed (maintainer: "use
      install.sh only is fine").
    
    Verification
    - install.sh: `bash -n` clean; executed the real agent-JSON generation
      block -> valid JSON with 9 resources; `kiro-cli agent validate` exit 0.
    - install.ps1: parsed with 0 syntax errors (PowerShell 7.6.2 AST parser);
      ConvertTo-FileUri yields file:///C:/... for Windows paths; the real
      Cmd-Install "kiro" path runs without error and produces JSON that
      passes `kiro-cli agent validate` (exit 0).
  • Merge pull request #435 from thejesh23/feat/dart-language-support
    feat(core): add Dart language support via workspace-vendored WASM
  • fix(core): DartExtractor — call graph coverage for codex P2 findings
    Two gaps in the call-graph walker, both flagged by codex on #435:
    
    1. `const Foo(...)` / `new Foo(...)` constructor calls were silently
       dropped. The grammar emits these as `const_object_expression` /
       `new_expression` containing `arguments` directly — they bypass the
       `selector > argument_part` shape the walker relied on. Added a
       dedicated branch that records the inner `type_identifier` as the
       callee. Critical for Flutter widget trees where
       `runApp(const MyApp())` would otherwise lose the MyApp construction
       edge.
    
    2. When a getter / setter / constructor / factory_constructor has a
       body, its `method_signature` wraps `getter_signature` /
       `setter_signature` / `constructor_signature` /
       `factory_constructor_signature` instead of `function_signature`. The
       walker only looked for `function_signature`, so `pendingName`
       stayed null and the sibling `function_body` was walked with an
       empty stack — calls inside ctor/factory/getter/setter bodies were
       silently dropped even though those members were already extracted
       as functions. Now dispatch across all five signature variants,
       using `constructorName` for the (factory) constructor pair to
       match what `collectClassBody` pushes.
    
    Tests: 41 → 47 dart cases (+6); full core 733 → 739; no regressions.
  • chore: sync root pnpm-lock.yaml with new workspace dep
    CI runs `pnpm install` from the repo root using the root lockfile with
    the default frozen-lockfile behaviour. The previous commits ran install
    only inside understand-anything-plugin/ so the new
    @understand-anything/tree-sitter-dart-wasm workspace dependency was
    recorded in understand-anything-plugin/pnpm-lock.yaml but missed at
    the repo root — CI would have stopped at install.
    
    Flagged by @chatgpt-codex-connector on #435.
  • feat(core): DartExtractor — broaden coverage per review (#436)
    Incorporates stronger pieces from the prior Dart attempts (#348, #415)
    that @Lum1104 called out:
    
    - `extractParams` now walks `optional_formal_parameters` (covers both
      optional positional `[...]` AND named `{...}` parameters — the Dart
      grammar uses one wrapper for both).
    - New `extractParamName` helper extracts the user-visible field name
      from `this.field` and `super.field` initializer parameters by
      unwrapping `constructor_param` / `super_formal_parameter`.
    - `collectClassBody` now routes `getter_signature` and `setter_signature`
      in both shapes:
        - concrete: `method_signature > getter_signature` + sibling function_body
        - abstract: `declaration > getter_signature`
      Setters use the same path. The previous limitation assertion
      (`methods).not.toContain("value")`) flipped to a positive
      `.toContain("value")`.
    - Added import/export edge-case tests: `dart:` SDK URIs, multi-import
      declaration-order preservation, and `export ... show` clauses.
    - Added a comma-list field test (`int a, b, c;`).
    
    Underscore-prefix visibility carries through naturally to all new code
    paths via the existing `isExported` gate inside `pushMethod`; explicit
    test added for an underscore-prefixed getter.
    
    Test counts: 28 → 41 dart cases; full core suite 720 → 733; no
    regressions.
  • chore: trim process docs from docs/superpowers/
    Per maintainer feedback on #436 — these are personal brainstorm/plan
    artifacts produced via the superpowers skill flow, not repo
    documentation. The BUILD.md provenance note in
    packages/tree-sitter-dart-wasm/ stays since that's repo-level docs
    about the vendored wasm.
  • feat(core): DartExtractor — call graph extraction
    Implements extractCallGraph with a sibling-aware walk that pairs each
    function_signature with its subsequent function_body sibling (Dart's
    AST differs from Kotlin's: signature and body are siblings, not
    parent/child). Detects call sites via selector nodes containing
    argument_part; uses startIndex for sibling lookup (web-tree-sitter
    returns new wrapper objects per child() call, making === unreliable).
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • feat(core): DartExtractor — enum declarations
    Adds enum_declaration handling to DartExtractor: enum constants are surfaced
    as properties[] so the structural graph captures Color.red / Color.green etc.
    Implements Task 9 of the Dart language support plan (TDD, 16/16 dart tests
    pass, full suite 708/708).
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • feat(core): DartExtractor — mixin declarations
    Add mixin_declaration handling to extractStructure, folding mixins into
    classes[] (same convention as class_definition). The `on` constraint
    sibling is intentionally ignored for graph purposes.
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • feat(core): DartExtractor — constructor naming (default/named/factory)
    Add constructorName() helper and extend collectClassBody() to surface
    unnamed constructors as "ClassName", named constructors as "Class.named",
    and factory named constructors as "Class.named" in methods[]/functions[].
    Probe confirmed plan's AST shapes match exactly; extractReturnType returns
    undefined for all constructor forms (factory keyword is an unnamed node).
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • feat(core): DartExtractor — top-level function extraction
    Add TDD tests and implement extractTopLevelFunction with helpers for
    extracting function name, params, and return type (including generics
    where the grammar emits type_identifier + type_arguments as siblings).
    
    Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
  • feat(core): scaffold DartExtractor + register in builtinExtractors
    Empty extractor that satisfies the LanguageExtractor interface so the
    plugin pipeline can load it. Real extraction logic lands in subsequent
    TDD commits.
  • feat(core): register dart LanguageConfig
    Adds the Dart language config and wires it into builtinLanguageConfigs
    so .dart files are recognized by the language registry. References the
    vendored @understand-anything/tree-sitter-dart-wasm package for grammar
    loading.
    
    No extractor yet — structural extraction lands in the next commit.
  • feat(tree-sitter-dart-wasm): vendor freshly-built dart WASM grammar
    The upstream tree-sitter-dart@1.0.0 ships a pre-`dylink.0` wasm that
    fails to load in web-tree-sitter@0.26.x. The grammar source itself is
    sound — rebuilding with the current tree-sitter-cli + wasi-sdk produces
    a working dylink.0 wasm. Vendor that artifact as a workspace-internal
    package so @understand-anything/core can depend on it via workspace:*.
    
    BUILD.md documents the provenance and rebuild instructions.
  • docs: implementation plan for Dart language support
    Thirteen-task TDD plan walking from vendoring the workspace wasm package
    through scaffolding the extractor and adding extraction logic in
    test-first slices: functions, classes, constructors, mixins, extensions,
    enums, imports, exports, visibility, and call graph.
    
    Every code block reflects AST shapes confirmed via a live probe against
    a freshly-built tree-sitter-dart wasm in the project's own
    web-tree-sitter at 0.26.x. No placeholder code, no "fill in later"
    references.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • docs: revise Dart spec for workspace-vendored wasm
    Live verification during planning surfaced two facts that change the
    shipping strategy:
    
    1. tree-sitter-dart@1.0.0's prebuilt wasm uses the pre-`dylink.0` format
       and fails to load in web-tree-sitter@0.26.x (the version this project
       uses). Verified by directly loading the upstream wasm and catching
       the failure in getDylinkMetadata.
    
    2. The grammar source itself is sound — rebuilding with the current
       tree-sitter-cli@0.26.x + wasi-sdk-29 toolchain produces a working
       dylink.0-format wasm that parses every construct the extractor needs.
    
    Revised packaging: ship the freshly-built wasm as a workspace-internal
    package (@understand-anything/tree-sitter-dart-wasm) rather than
    depending on the broken upstream npm artifact. No loader changes
    required; existing TreeSitterPlugin resolves it the same way it
    resolves other tree-sitter packages.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • docs: design spec for Dart language support
    Adds the brainstormed design for landing deep Dart support at parity with
    the recent Kotlin add (PR #347): LanguageConfig + tree-sitter WASM grammar
    (tree-sitter-dart@1.0.0, verified ships a prebuilt .wasm in its tarball) +
    DartExtractor + ~22 vitest cases. Six file changes, no edits to shared
    schemas/registries.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • Merge pull request #419 from chengyongru/feat/nanobot-support
    feat(install): add Nanobot platform support
  • Merge pull request #347 from tirth8205/feat/kotlin-extractor
    feat(core): add Kotlin structural analysis via tree-sitter
  • Merge pull request #359 from tirth8205/fix/import-resolver-nodenext-rewrite
    fix(extract-import-map): apply NodeNext .js→.ts rewrite (#294)
  • Merge pull request #387 from tirth8205/fix/phase7-cleanup-mv-trash
    fix(skill): use mv-to-trash + delayed purge for Phase 7 cleanup (#301)
  • Merge pull request #346 from tirth8205/perf/understand-pipeline
    perf(understand): parallelise file I/O in compute-batches + extract-import-map (#76)
  • fix(skill): use mv-to-trash + delayed purge for Phase 7 cleanup (#301)
    Phase 7's `rm -rf` of the just-created `intermediate/` and `tmp/` dirs
    trips destructive-action gates on hardened hosts (e.g. freshness-window
    checks that flag deleting paths created moments earlier). Move them into
    a timestamped `.trash-<epoch>/` instead; Phase 0 reclaims the space once
    the trash is older than 7 days, well past any freshness window. Behavior
    on normal hosts is unchanged — disk usage is identical after the next
    run's purge.
    
    Closes #301
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • fix(extract-import-map): preserve deterministic stderr order across concurrent loaders
    Addresses the regression flagged by ZebangCheng on #346: under the
    parallelised `buildResolutionContext`, `loadTsConfigs` /
    `loadGoModules` / `loadPhpAutoloads` ran concurrently but each wrote
    warnings to stderr inline as it iterated read results, so a fixture
    with both a malformed `tsconfig.json` and a malformed `composer.json`
    could emit `composer, tsconfig` instead of the pre-PR `tsconfig,
    composer` depending on I/O timing.
    
    Each loader now buffers its warnings into a returned array and the
    caller drains them in canonical order (tsconfig → go → php) after
    `Promise.all`, restoring byte-identical stderr output. Added a
    regression test that fixtures both malformed configs and asserts the
    tsconfig warning precedes the composer warning in stderr.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • Merge pull request #378 from BozhengLong/feat/understand-language-auto-detection
    feat(understand): auto-detect conversation language on first run
  • feat(understand): auto-detect conversation language on first run
    When /understand runs with no --language flag and no stored outputLanguage,
    step 3.6 now infers the conversation language and — only when it is non-English
    — confirms once before generating, then persists the choice to config.json.
    English conversations keep the exact same silent `en` path; --language flag and
    stored config still take priority. README documents the behavior; version
    bumped 2.7.5 -> 2.7.6 across all five manifests (user-visible behavior change).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
  • Merge pull request #350 from tirth8205/chore/repo-hygiene
    chore(repo): community templates, CoC, SECURITY, package metadata, CI on main (#248, #249, #251, #252).
  • feat: add Kiro CLI/IDE platform support
    - Add kiro to install.sh platforms_table (per-skill symlinks to ~/.kiro/skills/)
    - Generate ~/.kiro/agents/understand.json on install for full pipeline support
    - Clean up agent JSON on uninstall
    - Add .kiro-plugin/plugin.json for IDE auto-discovery
    - Update README with Kiro in platform table, one-line install list, and dedicated section
  • Merge pull request #332 from ZebangCheng/fix/phase7-preserve-scan-result
    fix(skill): preserve scan-result.json across Phase 7 cleanup for incremental runs (#293)
  • Merge branch 'main' into fix/import-resolver-nodenext-rewrite
    Resolve conflict in tests/skill/understand/test_extract_import_map.test.mjs
    by keeping both new test groups — they cover independent fixes that should
    coexist:
      - upstream #214: tsconfig path-alias targets with leading "./"
      - this PR  #294: NodeNext .js → .ts rewrite for ESM TypeScript imports
    
    The extract-import-map.mjs script auto-merged cleanly; both fixes are
    already present in the merged source.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
  • 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
  • chore(repo): add issue/PR templates, SECURITY.md, CoC, package metadata; widen CI triggers
    Closes a cluster of community-profile gaps (#248, #249, #251, #252) in one
    PR rather than four micro-PRs that all touch the same surface area.
    
    ### Templates (#251, #252)
    
    - .github/ISSUE_TEMPLATE/bug_report.yml — required fields for repro
      (plugin version, platform, OS, project language, file count); the four
      pieces of context that are missing from ~every current bug report.
    - .github/ISSUE_TEMPLATE/feature_request.yml — leads with the *problem*
      rather than the proposed solution, which keeps maintainer review focused
      on whether to solve, not just how.
    - .github/ISSUE_TEMPLATE/question.yml — separate from bug to keep the
      bug queue triagable.
    - .github/ISSUE_TEMPLATE/config.yml — disables blank issues and routes
      general discussion to README + Discussions.
    - .github/PULL_REQUEST_TEMPLATE.md — includes the version-bump checklist
      that CLAUDE.md says must stay in sync across 5 manifests; otherwise
      every contributor learns this rule by getting their PR bounced.
    
    ### Community files
    
    - CODE_OF_CONDUCT.md — short, project-specific document that names the
      expectations and reporting path. Not a verbatim Contributor Covenant
      to keep it readable.
    - SECURITY.md — describes the project's local-only threat model
      explicitly so reporters know what's in / out of scope before they
      spend time on a writeup. Points at GitHub private vulnerability
      reporting as the primary channel.
    
    ### CI (#249)
    
    - ci.yml now also runs on pushes to main, not only PRs. Without this,
      a direct push to main (which happens when maintainers merge a PR
      branch locally) doesn't trigger CI, so a regression can land green-
      looking and stay broken for days.
    - Added a concurrency group that cancels stale runs for the same ref.
      Saves runner minutes and keeps the per-ref status meaningful.
    - Used `github.ref` (a controlled value), not user-controlled input,
      so no script-injection surface.
    
    ### package.json (#248)
    
    - Added description, license, repository, bugs, homepage, keywords —
      the standard set for npm package discoverability and so GitHub's
      community-profile check shows the project at 100%.