Skip to content

multi-language: --in and --from consult every language graph before refusing - #1627

Merged
swapnilpaliwal-sd merged 1 commit into
0.1.4from
loop/to-p0-multilang-scope
Sep 28, 2026
Merged

swapnilpaliwal-sd merged 1 commit into
0.1.4from
loop/to-p0-multilang-scope

Conversation

@swapnilpaliwal-sd

Copy link
Copy Markdown
Contributor

Symptom

In a repository with several language graphs:

  • context/impact/path … <repo> --in <dir> refused with "no indexed file has '' in its path" when <dir> held only a non-main language (e.g. Python scripts in a TypeScript repo). The CLI and the MCP in_path both did this.
  • context … --from main started a flow in every language, main graph first, so the first flow a reader saw was often in a language the task wasn't about. It also refused outright ("--in required", "none of these words") when the task's words missed that graph, even though --from already says where to start.

Cause and fix

  • Dispatcher: the repository was taken to be "the last argument that is a directory", so an --in value that is a real directory became the repository. That repository had no .axiomcode/lang, so only the main graph was asked. Flag values are now skipped, and the MCP server's timeout path does the same.
  • ax_langs: when no graph answers, refusals from graphs that don't hold the --in path at all give way to the graph that does hold it.
  • context --from:
    • A graph that declares the name answers even if the task's words don't land in it.
    • Under fan-out, a graph that doesn't declare the name refuses.
    • A common name is narrowed to the declarations whose flow reaches the files the task's words land in. The language where most words land comes first; languages reaching half as many or fewer are left out and named.

Tests

tests/multi_language.py adds 3 scope cases and 4 --from cases, each with a control. The controls cover:

  • --in on the main graph's own directory still answers from the main graph alone, with no header;
  • a directory no graph holds is still refused;
  • a scope one graph holds but where nothing matches is refused by that graph alone;
  • a task about TypeScript still starts in TypeScript;
  • a name declared once isn't narrowed.

The refresh checks no longer inherit AXIOMCODE_NO_REFRESH from the machine. The upgrade check now uses --fresh, because under the answer-at-once contract only --fresh waits when the answer lies in no edited file.

  • Before, on unchanged code: 21 ok / 9 FAIL.
  • After: 30 / 30.
  • tests/run.py: 329/331, 2 pending (unchanged).
  • tests/mcp.py: ok.
  • tests/surfaces.py: ok.

Real repository (this one: TypeScript main graph + Python/Java/C#/JS)

  • context "…" . --in plugins/axiomcode/skills/axiomcode/scripts
    • Before: refused.
    • After: answers from the python graph in 0.75 s.
  • context "how does the mcp server start and run a verb" . --from main
    • Before: flows in 5 languages, typescript first, python last.
    • After: python first (3 of 107 mains); csharp and java left out and named.
  • Control: a TypeScript task with --from main answers from the typescript graph alone.

Graph edges are unchanged; no engine code is touched.

…efusing

- The dispatcher took a flag's value for the repository: `--in <dir>` with a real
  directory after the repository argument made that directory "the repository",
  found no .axiomcode/lang there, and asked the main graph alone, so a scope only
  another language's graph holds was refused as absent. Flag values are skipped
  now (the MCP server's timeout path does the same).
- When no graph answers, a graph that does not hold the --in path at all gives
  way to the one that does, so the refusal shown is the relevant one.
- context --from: a graph that declares the name answers from it even when the
  task's words land nowhere there (no scope refusal); under fan-out a graph that
  does not declare it refuses. A common name picks the declarations whose flow
  reaches the files the task's words land in, and the language where most land
  comes first; languages with half as many or fewer are left out and named.
- tests/multi_language.py: scope and --from cases with controls; the refresh
  checks no longer inherit AXIOMCODE_NO_REFRESH from the machine.

Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant