Skip to content

[bug] Linux supervisor HOME 불일치와 pr-review grep 대체 경로 결함을 고친다 - #554

Merged
m16khb merged 6 commits into
mainfrom
552-supervisor-home-and-pr-review-grep
Oct 8, 2026
Merged

m16khb merged 6 commits into
mainfrom
552-supervisor-home-and-pr-review-grep

Conversation

@m16khb

@m16khb m16khb commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

요약

#548·#550에서 미뤘던 결함 세 가지를 고칩니다.

  • HOME이 user systemd manager와 다른 Linux HTTP 설치는 이제 credential과 unit을 쓰기 전에 원인을 밝힌 오류로 멈춥니다. 이전에는 다 쓴 뒤 systemctl --user enable에서 실패했습니다.
  • pr-review defs.md의 source: 줄에 실제로 쓴 검색 도구가 표시됩니다.
  • rg가 없을 때 git 저장소에서는 .gitignore로 무시되는 파일을 검색하지 않습니다.

Closes #552

변경 내용

  • supervisor 사전 확인 (internal/adapter/mcpservice)
    • Prepare의 첫 단계에서 systemd 어댑터가 실행 중인 user manager의 HOME·XDG_CONFIG_HOME(systemctl --user show-environment)을 읽습니다. 쓰려는 unit 디렉터리가 manager의 기대 디렉터리와 다르면 systemctl --user show -p UnitPath --value 목록에서 한 번 더 찾습니다.
    • 둘 다 아니면 credential·log·unit을 쓰지 않고 멈춥니다. 오류에는 unit 디렉터리, manager HOME, 해결 방법(같은 HOME에서 설치하거나 --mcp-transport=stdio)이 들어갑니다.
    • manager를 조회할 수 없거나, HOME이 없거나, 값이 이스케이프돼 있으면 판정하지 않고 기존 흐름을 따릅니다. 외부 도구 상태를 설치 전제 조건으로 삼지 않기 위해서입니다.
    • issueops mcp service start는 이 거부를 이전과 같은 supervisor_failed로 보고합니다.
    • macOS launchd는 plist 경로를 직접 넘기므로 조회하지 않습니다.
  • CI 회귀 단계: GitHub runner에서 임시 HOME으로 HTTP 설치를 실행합니다. 실패해야 하고, 출력에 위 오류가 있어야 하며, 임시 HOME에 credential과 unit이 없어야 통과합니다. scripts/ci_workflow_test.py가 이 단계의 실패 전파를 고정합니다.
  • pr-review 검색 (skills/pr-review/scripts/mr_context.py)
    • 기호마다 실제로 쓴 도구(codegraph explore, rg, git grep, grep)를 기록하고, source: 줄에 쓰인 순서대로 나열합니다.
    • rg가 없고 git 작업 트리면 git grep --untracked로 찾습니다. 제외 패턴은 glob magic으로 써서 blocks/처럼 이름에 lock이 든 디렉터리를 지우지 않습니다. git grep이 실패하면 기존 grep을 씁니다.
  • 문서: install.md의 Linux HOME 설명을 고쳤고, 이번에 만난 함정을 새 주의사항으로 남겼습니다.

바뀌지 않는 것: Linux 기본 transport, mcpservice.Status와 error_code 집합, CLI·MCP JSON 출력, rg가 있을 때의 pr-review 검색, macOS 설치.

확인한 것

  • HOME 불일치 거부: fake runner 테스트 8종으로 확인했습니다. HOME이 다르면 credential·log·unit이 생기지 않고 오류가 원인을 밝힙니다. 같은 HOME의 첫 설치, XDG_CONFIG_HOME, UnitPath 일치, 조회 실패, HOME 부재, 이스케이프 값, launchd에서는 기존 동작을 유지합니다. 수정 전 코드에서는 거부 케이스가 실패했습니다.
  • mcp service start의 error_code: Start 경로 테스트로 supervisor_failed와 credential 미생성을 확인했습니다. 이 결함(credential_failed로 보고)은 구현 리뷰 1라운드에서 나왔습니다.
  • Linux 배선 테스트: 구현 리뷰 2라운드에서, 이 테스트가 CI runner의 실제 user manager에 닿아 새 거부에 걸린다는 결함이 나왔습니다. Linux 컨테이너에서 runner와 같은 응답을 내는 가짜 systemctl로 실패를 재현했고, 테스트를 실제 manager와 분리해 통과를 확인했습니다.
  • pr-review: rg가 없는 경우를 mock으로 고정했습니다. 임시 git 저장소에서 무시 파일이 빠지는지, lock 이름 디렉터리의 정의를 찾는지, git grep이 실패하면 grep으로 넘어가는지 확인했습니다. 스위트 102개가 skip 없이 통과합니다.
  • 로컬 전체 검증(macOS): 마지막 수정 뒤 gofmt, go vet, golangci-lint(darwin·linux 0건), race 전체, self-verify, CI workflow 테스트를 모두 다시 실행해 통과했습니다.
  • PR CI: push 뒤 CI run의 모든 단계가 통과했습니다. 새 HTTP 회귀 단계의 로그에서 runner의 user manager가 HOME=/home/runner를 돌려주었고, 설치가 쓰기 전에 위 오류로 멈춘 것을 확인했습니다. 계획 단계에서 남긴 가정(manager 환경에 HOME이 있다)이 실제 runner에서 맞았습니다.
  • 구현 리뷰는 3라운드 만에 통과했습니다. 3라운드는 effort를 한 단계 올렸습니다.

리뷰 포인트

  • 판정할 수 없을 때 막지 않는 기준(조회 실패, HOME 부재, $'...' 이스케이프)이 적절한지 봐 주세요. 막지 않으면 기존처럼 enable 단계에서 명령과 출력을 담아 실패합니다.
  • 설치 HOME과 manager HOME이 symlink로만 다른 경우에는 거부합니다. 일반 로그인 세션에서는 두 값이 같은 출처라 문제가 없다고 보았는데, 다른 환경을 알고 계시면 알려 주세요.

남은 일

  • launchd는 임시 HOME 설치도 실제 gui 도메인에 서비스를 올립니다. 이번 범위에서 바꾸지 않았습니다.
  • docs checker가 보고하는 .issueops/adr/roadmap.md 줄 수 초과는 이번 변경 전부터 있던 문제입니다.

m16khb added 6 commits October 8, 2026 11:53
Lore:
- Intent: Stop a Linux HTTP install whose HOME differs from the running user systemd manager before it writes anything.
- Why: The installer writes the unit under its own HOME, but the running user manager resolves the unit search path from its own HOME, so `systemctl --user enable` failed after the credential and unit were already written (#550 diagnosis, #552).
- Changes:
  - Add `checkUnitPath` to the supervisor interface; launchd passes, systemd reads `systemctl --user show-environment` (HOME, XDG_CONFIG_HOME) and confirms a mismatch against `systemctl --user show -p UnitPath --value`.
  - Call it first in `Service.Prepare`, before EnsureBearer, the log file, and the unit.
  - Stay silent when the manager cannot be queried, has no HOME, or prints `$'...'`-escaped values, so it adds no readiness gate.
  - Wrap the refusal in `errUnitPathNotSearched`; `Start` reports it as `supervisor_failed`, as before this change.
  - Isolate the Linux wiring test from the runner's real user manager with a systemctl stand-in on PATH.
  - Record the two new methods in the DDD responsibility inventory.
- Verify: go test -race -count=1 -v ./internal/adapter/mcpservice/... (8 Prepare subtests + Start test, RED first); Linux arm64 container run of TestSupervisorUnitRunsAbsoluteBinaryWithExplicitRootAndState with a runner-like systemctl stand-in (RED then GREEN); go test -race ./... -count=1; golangci-lint v2.12.2 darwin and linux 0 issues.
- Risk: A HOME that reaches the manager's directory only through a symlink is refused; the error names the fix (same HOME or --mcp-transport=stdio).
Lore:
- Intent: Exercise the new unit search path check against a real user systemd manager on the GitHub runner.
- Why: Fake-runner unit tests cannot prove that the runner's manager environment carries HOME; this step does, and it pins the #550 failure mode (#552).
- Changes:
  - Add a CI step that runs install-native.sh --mcp-transport=http in a temporary HOME and requires a failure, the "is not searched by the running systemd user manager" text, and no bearer or unit under that HOME.
  - Pin the step in scripts/ci_workflow_test.py: refusal passes; success, another error, a written unit, or a written credential fail; the temporary HOME is removed and the ambient HOME untouched.
- Verify: python3 -m unittest -v scripts/ci_workflow_test.py; disabling the grep check or the written-file check in the step makes the matching subtests fail.
- Risk: If the runner's manager environment lacks HOME, the check stays silent and the step fails on the missing text; that would show the assumption is wrong rather than pass silently.
Lore:
- Intent: Make the defs.md source line say which search actually ran.
- Why: render_defs printed "rg" whenever codegraph was off, even when rg was missing and grep found the rows, and printed only "codegraph explore" when codegraph came back empty and rg filled in (#552).
- Changes:
  - _rg_symbol returns its rows together with the tool that produced them (rg or grep); the output trimming moves to _hits.
  - collect_defs records a source per symbol; render_defs lists the tools in first-use order without repeats ("none" when no symbol was searched) and drops its unused codegraph argument.
  - Tests: grep fallback asserts "source: grep", a codegraph-plus-rg case asserts both tools, and a direct source-line test without rg.
- Verify: python3 -m unittest discover -s skills/pr-review/tests (RED: the new assertions saw "source: rg"); no consumer parses the source line.
- Risk: Low; the source line wording in defs.md changes.
Lore:
- Intent: Keep ignored build output out of definition search when rg is unavailable.
- Why: The grep fallback walks every file with a fixed exclude list, so .gitignore'd artifacts could appear in defs.md on runners without ripgrep (#552).
- Changes:
  - When rg is missing and the checkout is a git work tree, search with `git grep --untracked -n -w -F -I --max-count 3`, which skips ignored files.
  - Express rg's exclusions as `:(exclude,glob)` pathspecs; a magic-less `*` also matches `/` and would drop directories such as blocks/.
  - Fall back to grep when git is missing, the checkout is not a work tree, or git grep exits above 1 (for example git older than 2.38 without --max-count).
  - Tests: ignored files absent from a temp git repo, a definition under a lock-named directory found while lock/min/node_modules files stay out, a failing git grep falls back to grep.
- Verify: python3 -m unittest discover -s skills/pr-review/tests (RED: the ignored-file test saw build/ hits and "source: rg"); 5-run median in this repo, git grep 0.349s vs grep 0.669s.
- Risk: Low; only runs when rg is absent.
Lore:
- Intent: Keep the operations and caution docs in line with the new Linux HTTP install behaviour.
- Why: install.md still said a temporary-HOME HTTP install fails with supervisor_failed after writing; it now refuses before writing, and the cycle hit pitfalls worth not repeating (#552).
- Changes:
  - install.md: describe the pre-write unit search path check, when it stays silent, and the new CI step.
  - New caution 2026-10-08: systemd-analyze does not ask the manager, UnitPath omits missing directories, show-environment escapes values, a HEAD-CI gate passes falsely on the base commit, a stderr "skipped" grep misfires, and darwin-only gates miss Linux-only test paths.
  - CAUTIONS.md: index row for the new caution.
- Verify: go test ./cmd/issueops/issueopsapp -run TestResponseContractsGolden -update -count=1 (no golden change); project-docs-optimize check reports only the pre-existing adr/roadmap.md line budget.
- Risk: Low; documentation only.
…eport

Lore:
- Intent: Commit the cycle materials that back the #552 changes.
- Why: The plan, intent, plan-review summary, gate ledger, and verified-execution report are the inspectable evidence for this cycle (#552).
- Changes:
  - .issueops/issues/552/: plan, intent, plan-review summary, and the G1-G10 gate ledger (G8/G9 abandoned until the PR CI run).
  - .issueops/verified-execution/552-supervisor-home-and-pr-review-grep.md: acceptance results, ai-slop-clean, performance, docs, three implementation review rounds, and the verification log.
- Verify: issueops gates check re-ran G1-G7 and G10 fresh after the last code change (all met).
- Risk: Low; documentation only.
@m16khb m16khb added the bug Something isn't working label Oct 8, 2026
@m16khb m16khb self-assigned this Oct 8, 2026
@m16khb
m16khb marked this pull request as ready for review October 8, 2026 03:13
@m16khb
m16khb merged commit b8acdf1 into main Oct 8, 2026
2 checks passed
@m16khb
m16khb deleted the 552-supervisor-home-and-pr-review-grep branch October 8, 2026 03:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] Linux supervisor HOME 불일치와 pr-review grep 대체 경로 결함을 고친다

1 participant