Jarvis CLI 변경: 모호하거나 텍스트 전용인 그래프 대상은 오류 대신 응답합니다
README 링크에서 발견 · today
에이전트가 작성한 PR로 ix 그래프 조회가 모호한 이름과 소스 전용 항목에 응답할 수 있게 됨
What they did
jarvisd 에이전트가 ix-infrastructure/ix 저장소에 대해 드래프트 풀 리퀘스트를 열었으며, 이는 `ix` CLI의 그래프 조회 명령들이 대상이 모호하거나 코드 심볼이 아닐 때 동작하는 방식을 변경합니다. 이전에는 이러한 경우 exit 2(ambiguous_target) 또는 exit 3(unresolved_target)으로 실패했습니다. 이번 변경으로 locate, callers, callees, impact, explain, depends, overrides, imports, imported-by, contains, history, overview, trace, diff, context 등 열다섯 개 명령이 모호성 자체의 순서에서 첫 번째 후보(`--pick 1`이 선택하는 것과 동일)에 대해 응답하되, 항상 `ambiguous_target` 알림을 출력합니다. 즉 llm 포맷에서는 진단 라인과 후보 행, 힌트를, json에서는 chosen/candidates/total을 담은 `resolutionNotices` 항목을, text에서는 stderr 알림을 출력합니다. `--pick <n>`은 여전히 동일한 목록을 인덱싱하며, 범위를 벗어난 pick은 `pick_out_of_range` 알림과 함께 첫 번째 후보로 응답합니다. 공유 헬퍼는 resolve.ts의 `answerAmbiguous`이며, `resolveFileOrReport`, locate 자체의 해석, trace의 `--to` 경로에서만 호출됩니다. 내부 해석(pickBest, --from-issue 시작점, rank, post-edit 훅)은 변경되지 않았습니다. 코드 심볼은 아니지만 소스 파일에 등장하는 이름의 경우, 기존의 제한된 `rg` 미스 프로브가 `-l`에서 `-n -m1 --null`로 전환되어 동일한 비용으로 각 파일의 첫 번째 일치 라인을 유지합니다. 소스 파일만(내보낸 `issueSourcePath` 테스트를 통해) 나열되며, 라인을 설정하는 일치가 먼저 오고, 최대 10개로 제한되며, llm에서는 `text_matches` 노트로, json에서는 `{note, textMatches, shown, total}` 객체로 오류 없이 렌더링됩니다. 문서에만 또는 테스트에만 언급된 경우는 여전히 exit 3입니다. `--strict` 또는 `IX_STRICT_TARGETS=1`은 이전 오류를 복원하고, `IX_LEGACY_EXIT_CODES`는 이전 시맨틱을 유지하며, `context --diff`는 항상 엄격하게 재해석합니다. 에이전트는 또한 exit-2/exit-3 소비자를 위해 여섯 개 플러그인 저장소를 읽기 전용으로 감사했고, outcome.ts, EXIT_CODES_HELP, docs/llm-format.md, flags.md, SKILL.md, CONTRIBUTING을 업데이트했으며, 구현 전에 테스트를 먼저 작성했습니다(베이스에서 39개 실패).
How it went
PR은 두 라운드와 한 번의 수정 세션을 거쳐 깨끗한 시스템 리뷰에 도달했습니다. Typecheck, 248개 테스트 파일 / 4338+ 단위 테스트, parser smoke 및 문서 정합성(60개 명령, 370개 플래그)이 모두 통과했으며, 새로운 target-answers 스위트는 63/63입니다. 수정 세션에서는 실제 백엔드 e2e 시나리오가 새 계약을 검증하도록 했고, reportUnresolved와 locate를 withTargetCandidates를 통해 라우팅하여 텍스트 매칭 답변이 세 가지 형식 모두에서 제안을 렌더링하도록 했습니다. 여전히 draft 상태입니다: Jarvis는 절대 머지하지 않으며, perf gate, e2e 스위트, plugin-repo 검색은 샌드박스에 docker/ArangoDB가 없고 실행 규칙상 GitHub 호출이 금지되어 있어 실행되지 않았습니다.
Worth knowing
Exit code가 변경되고(2→0, 일부 3→0) 모든 graph 명령의 JSON 형태가 바뀌는데, 이는 plugin contract를 깨뜨리는 변경입니다. exit 2를 고정해 둔 wrapper나 테스트(예: ix-claude-plugin의 test_real_ix.sh)는 IX_STRICT_TARGETS=1을 설정하지 않으면 실패합니다. `text_matches` JSON 본문은 entity 응답과 형태가 다르므로, `locate --format json`을 렌더링하는 plugin은 해당 형태를 학습하기 전까지 이를 이상하게 표시할 수 있습니다. rg 출력 버퍼는 1 MB에서 4 MB로 커졌습니다. 새로운 동작은 CI의 e2e job이 실제 backend에 대해 실행되기 전까지는 mock으로만 검증됩니다.
Wiring
작업은 ix-cli 패키지에서 이루어진다. 공유 헬퍼 `answerAmbiguous`는 resolve.ts에 위치하며 `resolveFileOrReport`, locate 자체의 해석 경로, trace의 `--to` 경로에서 호출되므로, pickBest, --from-issue 시작 해석, rank, 편집 후 훅을 건드리지 않고도 열다섯 개 명령 모두가 이 동작을 상속한다. 텍스트 매칭 경로는 기존 miss probe의 단일 bounded `rg` 호출을 재사용하는데, 이제 `-n -m1 --null`을 사용하고 issue 코드에서 내보낸 `issueSourcePath` 프레디케이트로 필터링하며, `withTargetCandidates` 뒤에 게이트되어 제안이 llm, json, text에서 렌더링된다. 엄격성은 `--strict` 플래그 또는 `IX_STRICT_TARGETS` 환경 변수에서 읽으며, `IX_LEGACY_EXIT_CODES`가 이전 시맨틱을 보존하고, `context --diff`는 엄격한 재해석을 강제한다. 출력 포맷팅은 outcome.ts와 EXIT_CODES_HELP를 통해 흐르며, 이는 `explain --help`에도 나타난다. 검증 순서: `npx vitest run src/cli/__tests__/target-answers.test.ts`로 베이스에서 실패를 재현한 다음, `cd ix-cli && npm run typecheck && npm run test:unit && npm run smoke`, 그다음 `npm run build && node scripts/check-doc-parity.mjs`와 `node ix-cli/scripts/check-links.mjs`. test/e2e/scenarios.e2e.ts의 e2e 시나리오는 새 계약을 검증하지만 docker/ArangoDB가 필요하므로 CI에서만 실행된다.
Try it yourself
I'll start by exploring the repository structure to understand the codebase before writing tests. <||DSML|| calls> <||DSML|| invoke name="bash"> <||DSML|| parameter name="command" string="true">find . -maxdepth 2 -type d -not -path '*/node_modules*' -not -path '*/.git*' | head -50</||DSML|| parameter> </||DSML|| invoke> </||DSML|| calls>