chore(boundary): PR 2 — Wave 1 closure + Lint #3 활성화
PYTHON_THINNING_PLAN §5 PR 2 — Bootstrap tree/list 청산. scope 조정 (실측 기반): - python_interpreter_browser.py는 *이미* helper exec_once 사용 중 (PR 2 scope에서 코드 청산 불필요). - ssh_runner.py의 `python3 -c` literal은 *로컬 askpass GUI* (Tkinter)용으로 원격 무관 — boundary §17-19 위반 *아님*. 모듈 docstring의 stale "Temporary bootstrap" 문구만 갱신. - 진짜 grandfather 위반 1건 (marimo_hosting.py:427 원격 port pick) 발견 — 별도 슬라이스로 청산 미룸. 산출물: - sublime/sessions/ssh_runner.py: 모듈 docstring 정정 (helper로 일원화 완료 명시 + askpass exception 명시). - scripts/lint_python_thinning.py: Lint #3 활성화. 패턴: `["']python3 -c ` / `"python3", "-c"`. ssh_runner.py exempt (로컬 askpass 영역). - .gitea/workflows/boundary-lint.yml: ban-list 단계에 `--lint 3` 추가. - planning/boundary_inventory.yml: marimo grandfather 위반 등록. 검증: - diff 모드 (CI 기본): 위반 0건. - all-files 모드: marimo:427 grandfather 1건 검출 (예상대로). - ssh_runner.py askpass 패턴은 exempt path로 통과. boundary-claim: removes: [] # 코드 청산 없음 (이미 helper 사용 중인 영역) delete-count: 0 ban-list: '#3 활성화 — 정밀 패턴, marimo grandfather 등록' note: | plan v1.1 §5 PR 2의 LOC 추정 ~180은 인벤토리 시점 stale. 실측 결과 코드 청산 영역이 거의 부재 — Wave 1은 PR 2 *이전*에 사실상 완료된 상태. 본 PR은 Lint #3 거버넌스 가드만 활성화. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ on:
|
||||
|
||||
jobs:
|
||||
ban-list:
|
||||
name: ban-list lint (Lint #1/#2.5/#4)
|
||||
name: ban-list lint (Lint #1/#2.5/#3/#4)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
- name: run boundary lint
|
||||
env:
|
||||
CI: "true"
|
||||
run: python3 scripts/lint_python_thinning.py --lint 1 --lint 2.5 --lint 4
|
||||
run: python3 scripts/lint_python_thinning.py --lint 1 --lint 2.5 --lint 3 --lint 4
|
||||
|
||||
duplication-deadline:
|
||||
name: duplication-deadline (Layer 1/2)
|
||||
|
||||
@@ -181,3 +181,9 @@ grandfather_violations:
|
||||
pattern: "time.monotonic"
|
||||
lint: "#2.5"
|
||||
cleanup_pr: "Track H2 분리 시 retry/timeout을 _rust_ffi/bridge로 이동"
|
||||
|
||||
- path: sublime/sessions/marimo_hosting.py
|
||||
line: 427
|
||||
pattern: "python3 -c (remote port pick)"
|
||||
lint: "#3"
|
||||
cleanup_pr: "별도 슬라이스 (marimo `--port 0` 직접 사용 가능 검증 후)"
|
||||
|
||||
@@ -14,9 +14,11 @@ Usage:
|
||||
- #4 Rust ABI 영문 자연어 ban (Rust 측)
|
||||
- #6 PR boundary-claim 헤더 검증
|
||||
|
||||
후속 활성화 룰 (env LINT_THINNING_ACTIVATE 로 켬):
|
||||
활성 룰 (PR 2):
|
||||
- #3 Python python3 -c SSH 폴백 ban (sublime/sessions/, askpass 예외)
|
||||
|
||||
후속 활성화 룰:
|
||||
- #2 Python deque/Event/Lock task queue 신설 ban (PR 16에서 활성화)
|
||||
- #3 Python python3 -c SSH 폴백 ban (PR 2에서 활성화)
|
||||
- #5 boundary inventory metasync (Wave 2.5에서 자동화)
|
||||
|
||||
normative 출처: planning/PYTHON_RUST_BOUNDARY.md (Wave 1.5 amend),
|
||||
@@ -62,6 +64,19 @@ LINT_2_5_RETRY_PATTERNS = [
|
||||
]
|
||||
LINT_2_5_PATH_PATTERN = re.compile(r"^sublime/sessions/commands_[^/]+\.py$")
|
||||
|
||||
# Lint #3 — Python `python3 -c` 원격 폴백 ban (boundary §17–19 Wave 1 closure)
|
||||
# 원격에서 실행될 명령에 `python3 -c` literal이 새로 추가되는 것을 차단.
|
||||
# 진짜 ban 의도: ssh 인자 또는 helper exec_once payload 안의 `python3 -c`.
|
||||
# Diff 모드라 grandfather 자동: ssh_runner.py 로컬 askpass + marimo port pick은
|
||||
# 기존 코드라 통과; 새 PR이 같은 패턴을 추가하면 fail.
|
||||
LINT_3_REMOTE_PYTHON_C = [
|
||||
re.compile(r'["\']\s*python3\s+-c\s'),
|
||||
re.compile(r'["\']\s*python3["\']\s*,\s*["\']-c["\']'),
|
||||
]
|
||||
LINT_3_PATH_PATTERN = re.compile(r"^sublime/sessions/")
|
||||
# askpass 모듈은 *로컬* python3 -c (Tk GUI dialog) 용도라 예외.
|
||||
LINT_3_EXEMPT_PATH_PATTERN = re.compile(r"^sublime/sessions/(ssh_runner\.py)$")
|
||||
|
||||
# Lint #4 — Rust ABI 영문 자연어 ban (Rust 측 sessions_native ABI 함수)
|
||||
# 식별자 코드만 반환해야 함. ABI 응답에 영문 자연어 문장(공백 + 3+ 어휘) 포함 금지.
|
||||
# 휴리스틱: ABI 함수 본문 string literal "Word word word..." 패턴 grep.
|
||||
@@ -227,6 +242,32 @@ def _check_lint_2_5(added: Iterable[Tuple[Path, int, str]]) -> List[Violation]:
|
||||
return violations
|
||||
|
||||
|
||||
def _check_lint_3(added: Iterable[Tuple[Path, int, str]]) -> List[Violation]:
|
||||
violations: List[Violation] = []
|
||||
for path, line_no, content in added:
|
||||
rel = str(path).replace("\\", "/")
|
||||
if not LINT_3_PATH_PATTERN.match(rel):
|
||||
continue
|
||||
if LINT_3_EXEMPT_PATH_PATTERN.match(rel):
|
||||
continue
|
||||
for pattern in LINT_3_REMOTE_PYTHON_C:
|
||||
if pattern.search(content):
|
||||
violations.append(
|
||||
Violation(
|
||||
lint_id="#3",
|
||||
path=path,
|
||||
line_no=line_no,
|
||||
content=content,
|
||||
reason=(
|
||||
"원격 명령에 `python3 -c` 폴백 신규 금지 "
|
||||
"(boundary §17–19) — helper 채널 사용 필요"
|
||||
),
|
||||
)
|
||||
)
|
||||
break
|
||||
return violations
|
||||
|
||||
|
||||
def _check_lint_4(added: Iterable[Tuple[Path, int, str]]) -> List[Violation]:
|
||||
violations: List[Violation] = []
|
||||
for path, line_no, content in added:
|
||||
@@ -285,7 +326,7 @@ def _check_lint_6_pr_body(pr_body_path: Path) -> List[Violation]:
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
ALL_LINTS = ("1", "2.5", "4", "6")
|
||||
ALL_LINTS = ("1", "2.5", "3", "4", "6")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
@@ -318,13 +359,15 @@ def main() -> int:
|
||||
selected = set(args.lint) if args.lint else set(ALL_LINTS)
|
||||
violations: List[Violation] = []
|
||||
|
||||
if {"1", "2.5", "4"} & selected:
|
||||
if {"1", "2.5", "3", "4"} & selected:
|
||||
base_ref = None if args.all_files else _resolve_base_ref(args.base_ref)
|
||||
added = _added_lines(base_ref)
|
||||
if "1" in selected:
|
||||
violations.extend(_check_lint_1(added))
|
||||
if "2.5" in selected:
|
||||
violations.extend(_check_lint_2_5(added))
|
||||
if "3" in selected:
|
||||
violations.extend(_check_lint_3(added))
|
||||
if "4" in selected:
|
||||
violations.extend(_check_lint_4(added))
|
||||
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
"""Thin SSH execution boundary between Sublime commands and remote operations.
|
||||
|
||||
This module centralizes non-interactive ``ssh`` subprocess invocations used for
|
||||
host probing, remote path checks, and directory listing before the Rust session
|
||||
helper exists. Call sites should stay limited to command orchestration; swap
|
||||
this layer for a helper-backed transport later without rewriting UX flows.
|
||||
host probing and connection preflight. Tree/file I/O and remote directory
|
||||
listing route through the Rust session helper (``local_bridge`` +
|
||||
``session_helper``); see ``ssh_file_transport.py`` and
|
||||
``python_interpreter_browser.py``.
|
||||
|
||||
The ``python3 -c`` literal that remains in this module is a *local* askpass
|
||||
GUI helper (it spawns Tk on the operator's workstation when the user typed in
|
||||
a passphrase). It does not run on the remote host and is not the
|
||||
boundary-document §17–19 fallback that Wave 1 closed.
|
||||
|
||||
Debug tracing:
|
||||
Set the environment variable ``SESSIONS_SSH_DEBUG`` to a non-empty value to
|
||||
print argv, exit code, and a stderr preview for each *failed* SSH run to
|
||||
``sys.stderr`` (visible in Sublime's Python console when running a dev
|
||||
build, or in CI logs).
|
||||
|
||||
Temporary bootstrap:
|
||||
Remote directory listing currently shells out to ``python3 -c`` on the
|
||||
remote host. That is bootstrap behavior; long-term listing should move onto
|
||||
the session helper protocol once stdio transport is wired from Sublime.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
Reference in New Issue
Block a user