polydeukes-sdk (Python)
pdks covenant check와 pdks memory를 호출하는 Python 3.12+ 동기 클라이언트입니다.
설치와 세 동사
예시를
참고하세요.
동사는 keyword-only frozen dataclass spec 하나를 받아 동결된 결과 값을 반환합니다. 경로는
str | os.PathLike[str]를 받습니다. 생성된 TypedDict 입력은 CLI의 camelCase 전송 필드를
유지합니다. py.typed를 포함하며 런타임 의존성은 없습니다.
| 동사 | 필수 spec 필드 | 결과 |
|---|---|---|
check_covenant(CheckCovenantSpec(...)) |
repo_root, input: CovenantInput |
Upheld(advisories), Blocked(reason), Unjudged(reason) |
check_change_set(CheckChangeSetSpec(...)) |
repo_root, diff: str |
같은 CheckCovenantVerdict 합집합 |
memory_search(MemorySearchSpec(...)) |
root, query: str |
Found(hits), Empty(), Unavailable(reason) |
모든 spec은 executable=None, timeout=None, spawn=None을 갖습니다. 약속(covenant) spec은
enforce='block', config_layer=None, telemetry_path=None도 갖습니다. 검색은 limit=None을
더하며, 지정한 limit은 양의 정수여야 합니다. enforce는 'advise' 또는 'block'입니다. 모든 결과
변종을 처리했는지 검사하려면 완전한 class pattern 분기 뒤에 typing.assert_never를 사용합니다.
동결은 얕으며 중첩 입력 사전은 호출자가 소유합니다.
실행 파일과 프로세스
섹션 제목: “실행 파일과 프로세스”세 동사는 해석기와 실행기 하나를 사용합니다. 지정한 executable은 단순한 이름이어도 호출자 cwd 기준
파일 경로이며 symlink 표기를 보존합니다. 없으면 절대 PATH 디렉터리에서 처음 발견한 실행 가능한
일반 파일 pdks를 실행합니다. 비거나 상대적인 항목은 건너뜁니다. 선택한 실행 파일이 실패하면 실패
결과를 반환합니다.
자식 cwd는 호출자 cwd 기준으로 절대화한 repo_root 또는 root입니다. 설정과 텔레메트리 경로는
그대로 전달하며, 자식이 상대 값을 그 root 기준으로 해석합니다. SDK는 호출자의 IR을 UTF-8
JSON(allow_nan=False)으로, diff를 줄바꿈이 보존된 UTF-8 바이트로 보냅니다. SDK가 자체 증거를
더하지 않습니다. query는 argv 한 항목입니다. 표준 스트림을 파이프로 연결하고 파일 디스크립터를
닫으며 셸이 명령을 평가하지 않습니다.
| 동사 | 실행 파일 뒤 인자 | stdin |
|---|---|---|
check_covenant |
covenant check --enforce <level> --unattended |
JSON |
check_change_set |
covenant check --diff --enforce <level> |
통합 diff |
memory_search |
memory search <query> --json [--limit <n>] |
빈 바이트 |
check_covenant은 covenant check --enforce <level> --unattended를 실행하고, 지정한
--config-layer와 --telemetry-path를 뒤에 덧붙입니다. --unattended를 끄는 옵션은 없습니다.
session.userMessages의 토큰은 증인 밸브(witness valve)를 열지 않으며, 선언 본체에서 userTexts를
읽는 규율(discipline)은 범위 안의 호출마다 사유 no-observation과 함께 skipped를 기록합니다.
SDK는 같은 릴리스 또는 이후 릴리스의 pdks가 필요하며, 이전 pdks는 사용법 줄과 종료 코드 2로
--unattended를 거부하고 SDK는 이를 차단된 판정 결과(verdict)로 반환합니다.
두 약속 동사는 지정한 --config-layer와 --telemetry-path를 덧붙입니다. diff는
git diff --no-color --no-ext-diff --src-prefix=a/ --dst-prefix=b/ HEAD로 만듭니다. 추적하지 않는
파일은 먼저 git add -N이 필요합니다. SDK가 git을 실행하지 않습니다.
timeout은 유한한 0 이상의 초입니다. 0은 즉시 기한이며 None은 기다립니다. 프로세스 생성 뒤 통신
중에 시작합니다. 기한을 넘기면 직접 자식을 죽이고 회수합니다. 후손은 계속 실행되며 Linux x64와 macOS
arm64에서 상속한 파이프가 기한 반환을 늦추지 않습니다. 직렬화와 실행 파일 해석은 기한 앞입니다.
비동기 호출자는 await asyncio.to_thread(check_covenant, spec)를 사용합니다.
약속 종료 0은 Upheld, 2는 Blocked이며 다른 status, 시그널, 해석·직렬화·실행·기한 실패는
Unjudged입니다. 자식 stderr를 advisories 또는 reason에 보존합니다. CLI 설정 실패도 종료 2에
포함됩니다. 결과 계약은 status를 따르며 실제 판정한 규율(discipline)은 텔레메트리로 식별합니다.
Unjudged는 실행 허가가 아닙니다.
기억 검색은 pdks memory ...를 통해 SDK 프로세스의 PATH에 있는 pdks-memory를 실행합니다.
설치 안내에 따라 확장을 설치하고, 로컬 npm 설치라면 SDK를 실행하기
전에 프로젝트의 node_modules/.bin 절대 경로를 PATH에 추가하세요. 실행 파일이 없으면 pdks가
출력한 이유와 함께 Unavailable을 반환합니다.
검색 출력은 저장소 schema/의 memory-search-output.schema.json을 따르며 형태는
{"results": [...]}입니다. 기억(memory)의 0 아닌 종료, 시그널, 실행 실패, 기한 초과는
Unavailable입니다. 검색은 results 배열이 있는 유효한 UTF-8 JSON을 요구합니다. 각 hit의 필수
필드·타입과 trust/matchPath enum을 검사하고 추가 필드는 허용합니다. 유효한 빈 배열만
Empty입니다. Found.hits는 CLI 순서를 유지하는 비지 않은 tuple이며 hit 필드는 camelCase입니다.
잘못된 응답은 Unavailable입니다. 검색은 절을 찾으며 의무 조회는 별도 CLI 명령입니다.
Spawn 주입
섹션 제목: “Spawn 주입”선택적인 동기 함수는
SpawnSpec(command: str, args: tuple[str, ...], cwd: str, stdin: bytes, timeout: float | None)을
받아 SpawnOutcome(status: int | None, stdout: bytes, stderr: bytes)를 반환합니다. None status는
시그널입니다. 주입 함수는 전달받은 기한을 직접 집행합니다. 일반 예외는 동사의 실패 결과로 바뀌며
KeyboardInterrupt와 SystemExit는 전파됩니다.
개발과 릴리스
섹션 제목: “개발과 릴리스”저장소 루트에서 실행합니다.
uv sync --project packages/sdk-python --lockeduv run --project packages/sdk-python --locked python -m unittest discover -s packages/sdk-python/testsuv run --project packages/sdk-python --locked python packages/sdk-python/scripts/generate_types.py --checkuv run --project packages/sdk-python --locked pyright --project packages/sdk-python/pyproject.tomluv run --project packages/sdk-python --locked ruff check packages/sdk-pythonuv build --project packages/sdk-python타입은 저장소의 JSON 스키마 두 개와 고정한 개발 생성기로 결정적으로 생성합니다. wheel과 sdist는
런타임 의존성 없이 설치됩니다. 릴리스 자동화는 저장소와 함께 project.version을 올리고 태그·패키지
버전을 확인하며 Linux 실행 파일 artifact를 검사합니다. 실행 파일 빌드가 통과한 뒤 OIDC로 PyPI에
출판합니다. 재실행은 이미 출판된 버전을 건너뜁니다.
첫 릴리스 전에 소유자가 PyPI pending trusted publisher에 프로젝트 polydeukes-sdk, 소유자
huskyhoochu, 저장소 polydeukes, 워크플로 publish.yml, 환경 pypi를 등록하고 일치하는 GitHub
환경을 확인해야 합니다. 첫 릴리스의 선행 조건이며 저장소 배선만으로 외부 설정의 존재가 확인되지는
않습니다.
기존 릴리스 버전으로 Python만 출판할 때는 SDK가 들어 있는 커밋에 annotated sdk-python-v<version>
태그를 만들고, 그 태그의 publish.yml을 python_only=true로 실행합니다. 다른 패키지의 소스와
manifest가 v<version>과 같은지 확인하고, 해당 릴리스의 Linux 실행 파일을 받아 digest를 대조한 뒤
같은 Python 배포물 검사와 PyPI 업로드를 수행합니다. npm/crate와 실행 파일 릴리스 작업은 건너뜁니다.
일반 통합 릴리스는 v<version>과 python_only=false를 사용합니다.
세 언어의 공통 계약
섹션 제목: “세 언어의 공통 계약”TS·Rust·Python SDK는 명시 실행 파일 → 절대 PATH의 pdks, 세 동사와 닫힌 결과, 기한의 같은 의미를 사용합니다. TS는 Promise와 밀리초, Rust는 동기 함수와 Duration, Python은 동기 함수와 초를 사용합니다. 두 저장소 스키마가 전송 타입의 원본이며 언어별 생성 타입과 검색 응답 검증을 구분합니다.
저장소에서 node scripts/verify-sdk-contract.mjs --executable <absolute-pdks>를 실행하면 세 SDK가
같은 fixture를 관측한 결과·실제 판정·telemetry·검색 순서를 비교합니다. TS 계약과
Rust 계약을 참고하세요.