저장 절차가 예전 버튼 이름을 못 찾을 때 이름을 고치는 일은 필요할 수 있다. 하지만 성공 조건까지 쉬운 것으로 바꿔 버리면 같은 업무를 고친 것이 아니다. 북극성의 과거 의미 대상 수리는 실패 단계의 target만 바꾸고 입력·행동·결과의 약속은 유지하도록 제한했다.

수정할 수 있는 것은 target 한 자리다

assertTargetRepair는 candidate의 target을 원래 target으로 되돌려 놓은 나머지가 original과 정확히 같은지 비교한다. 동작 종류·입력값·매개변수·expect를 함께 고치는 후보는 거절한다. patchTarget도 단계 전체를 새로 만드는 대신 원래 단계에 target만 얹는다. 작은 함수로 변경의 경계를 표현한 것이다.

기존 role이 정해져 있으면 바꾸지 못하고 inViewport 제한이 있으면 없애지 못한다. role이 없던 옛 정의는 새 실제 대상에서 확인한 역할을 배울 수 있다. 모르는 값을 채우는 것과 이미 아는 제약을 느슨하게 만드는 것은 다르다. 같은 target이라는 말 안에서도 어떤 조건이 반드시 유지돼야 하는지 남겼다.

새 이름 문자열보다 실제 최신 ref를 먼저 본다

수리 후보는 모델이 상상한 selector 문자열을 그대로 저장하는 방식이 아니다. programTarget은 현재 관찰에서 모든 ref 필드가 맞는 요소를 찾고 실제 드라이버 validate를 거친다. 원래 작업 범위와 민감 여부, 관찰 이름과 검증 이름도 확인한다. 이미 사라진 참조를 동등한 버튼이라고 받아들이지 않으려는 경계다.

수리 요청의 stepIndex와 tabId도 실패한 단계와 맞아야 한다. 다른 단계의 버튼을 편하게 가져오는 것을 막는다. 이 검사로 모든 업무 의미가 자동 입증되는 것은 아니다. 같은 역할과 이름처럼 관찰 가능한 조건으로 동등한 대상을 좁히고, 최종 업무 결과는 원래 expect로 다시 확인하는 구조다.

대기 시간을 늘리는 수리로 모호함을 숨기지 않는다

같은 대상이 늦게 나타난 경우에는 제한된 lookupWaitMs를 학습할 수 있다. 하지만 원래 오류가 중복 대상이나 잘린 목록의 모호함인데 이름·링크·표시 조건이 그대로라면 대기만 바꿔 통과시키지 않는다. PROGRAM_REPAIR_TARGET_UNCHANGED로 멈추는 반례가 있다.

같은 화면의 후보가 두 개인 문제는 오래 기다린다고 한 개의 의미가 되지 않는다. source 시험은 이런 요청에서 다음 모델 대역을 한 번만 부르고 끝내는지 본다. 대기 재시도와 대상 구분이 해결하는 문제가 다르기 때문이다. 실제 site 변경이 전혀 다른 절차를 요구하면 이 좁은 수리 범위 밖으로 남겨야 한다.

실행 중과 저장할 때 같은 제약을 확인한다

engine은 수리 콜백이 돌려준 단계도 다시 assertTargetRepair로 검사한다. 이미 전달된 행동에는 새 step을 적용하지 않는다. 원래 expect를 약한 문자열로 바꾼 후보를 돌려주는 시험은 범위 거절을 기대한다. 수리 함수 한 곳의 선의만 믿지 않고 실행 경계에서도 같은 약속을 확인한다.

역할 변경 거절은 영구 프로그램 저장 시험에도 있다. 전체 작업이 원래 조건으로 검증된 뒤 버전과 이전 정의를 남긴다는 것은 과거 플러그인 문서의 별도 계약이다. 모든 변경이 디스크 장애에도 한 번에 확정되는 트랜잭션이라는 보장은 아니다. 실행 승인과 장기 보관의 성공을 서로 빌려 쓰지 않는다.

남은 코드와 현재 자동 연결을 구별한다

이 설계와 실제 CLI 연계 기록은 0.1.58 등 과거 버전에 있다. 현재 내부 gateway는 제거 상태이고 helper와 시험이 남았다는 사실만으로 모든 현재 외부 실행이 자동으로 고쳐진다고 소개하지 않는다. 이번에는 관련 함수·시험·역사 문서를 읽었으며 실제 사이트의 버튼을 새로 고치지 않았다.

연결한 합성 대상 모듈도 현재 관찰에서 유일한 대상을 고르는 실험이며 자동 수리 모델이 아니다. 독자가 재사용할 것은 바꾸려는 자리와 유지할 약속을 먼저 정하는 방식이다. 나는 성공 조건을 낮춰 녹색 결과를 만드는 대신 같은 업무의 남은 단계를 정확하게 이어 갈 수 있는 수정만 허용하려 했다.