yield-audit 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- yield_audit-0.3.2/.github/workflows/ci.yml +26 -0
- yield_audit-0.3.2/.github/workflows/pypi.yml +46 -0
- yield_audit-0.3.2/.gitignore +23 -0
- yield_audit-0.3.2/AGENTS.md +80 -0
- yield_audit-0.3.2/CHANGELOG.md +237 -0
- yield_audit-0.3.2/HANDOFF.md +86 -0
- yield_audit-0.3.2/LICENSE +202 -0
- yield_audit-0.3.2/PKG-INFO +197 -0
- yield_audit-0.3.2/README.ko.md +88 -0
- yield_audit-0.3.2/README.md +169 -0
- yield_audit-0.3.2/pyproject.toml +55 -0
- yield_audit-0.3.2/src/yield_audit/__init__.py +3 -0
- yield_audit-0.3.2/src/yield_audit/__main__.py +8 -0
- yield_audit-0.3.2/src/yield_audit/attribute.py +117 -0
- yield_audit-0.3.2/src/yield_audit/audit.py +453 -0
- yield_audit-0.3.2/src/yield_audit/cli.py +230 -0
- yield_audit-0.3.2/src/yield_audit/cohorts.py +70 -0
- yield_audit-0.3.2/src/yield_audit/costs.py +52 -0
- yield_audit-0.3.2/src/yield_audit/events.py +107 -0
- yield_audit-0.3.2/src/yield_audit/gitdata.py +335 -0
- yield_audit-0.3.2/src/yield_audit/lenses/AGENTS.md +35 -0
- yield_audit-0.3.2/src/yield_audit/lenses/__init__.py +1 -0
- yield_audit-0.3.2/src/yield_audit/lenses/accepted.py +79 -0
- yield_audit-0.3.2/src/yield_audit/lenses/cache_locality.py +112 -0
- yield_audit-0.3.2/src/yield_audit/lenses/retry.py +82 -0
- yield_audit-0.3.2/src/yield_audit/lenses/rework.py +152 -0
- yield_audit-0.3.2/src/yield_audit/lenses/survival.py +239 -0
- yield_audit-0.3.2/src/yield_audit/lenses/verify_gap.py +101 -0
- yield_audit-0.3.2/src/yield_audit/lenses/waste.py +102 -0
- yield_audit-0.3.2/src/yield_audit/pricing.py +124 -0
- yield_audit-0.3.2/src/yield_audit/redact.py +117 -0
- yield_audit-0.3.2/src/yield_audit/report.py +239 -0
- yield_audit-0.3.2/src/yield_audit/transcripts/__init__.py +130 -0
- yield_audit-0.3.2/src/yield_audit/transcripts/base.py +208 -0
- yield_audit-0.3.2/src/yield_audit/transcripts/claude.py +160 -0
- yield_audit-0.3.2/src/yield_audit/transcripts/codex.py +195 -0
- yield_audit-0.3.2/tests/AGENTS.md +33 -0
- yield_audit-0.3.2/tests/conftest.py +367 -0
- yield_audit-0.3.2/tests/test_attribute.py +133 -0
- yield_audit-0.3.2/tests/test_e2e.py +320 -0
- yield_audit-0.3.2/tests/test_lenses.py +246 -0
- yield_audit-0.3.2/tests/test_prefilter.py +147 -0
- yield_audit-0.3.2/tests/test_pricing_costs.py +136 -0
- yield_audit-0.3.2/tests/test_redact.py +96 -0
- yield_audit-0.3.2/tests/test_rework.py +112 -0
- yield_audit-0.3.2/tests/test_transcripts.py +214 -0
- yield_audit-0.3.2/tests/test_transcripts_codex.py +168 -0
- yield_audit-0.3.2//352/270/260/355/232/215/354/204/234-AIDD-/354/240/204/355/231/230/352/263/204/353/237/211.md +89 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ${{ matrix.os }}
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
15
|
+
python: ["3.10", "3.12", "3.14"]
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: ${{ matrix.python }}
|
|
21
|
+
- name: Install
|
|
22
|
+
run: python -m pip install -e '.[dev]'
|
|
23
|
+
- name: Lint
|
|
24
|
+
run: ruff check .
|
|
25
|
+
- name: Test
|
|
26
|
+
run: pytest -v
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
# PyPI trusted publishing (OIDC): the project's pending publisher on
|
|
4
|
+
# pypi.org is configured for this exact workflow filename — no API tokens
|
|
5
|
+
# anywhere. First successful run claims the `yield-audit` project name.
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags: ["v*"]
|
|
10
|
+
workflow_dispatch:
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
# required for the OIDC minting the publish action performs
|
|
14
|
+
id-token: write
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
build:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- uses: actions/setup-python@v5
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
- name: Build sdist and wheel
|
|
25
|
+
run: |
|
|
26
|
+
python -m pip install --upgrade build
|
|
27
|
+
python -m build
|
|
28
|
+
- name: Check metadata
|
|
29
|
+
run: |
|
|
30
|
+
python -m pip install --upgrade twine
|
|
31
|
+
twine check dist/*
|
|
32
|
+
- uses: actions/upload-artifact@v4
|
|
33
|
+
with:
|
|
34
|
+
name: dist
|
|
35
|
+
path: dist/
|
|
36
|
+
|
|
37
|
+
publish:
|
|
38
|
+
needs: build
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
steps:
|
|
41
|
+
- uses: actions/download-artifact@v4
|
|
42
|
+
with:
|
|
43
|
+
name: dist
|
|
44
|
+
path: dist/
|
|
45
|
+
- name: Publish to PyPI
|
|
46
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# macOS
|
|
2
|
+
.DS_Store
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*.egg-info/
|
|
8
|
+
.eggs/
|
|
9
|
+
build/
|
|
10
|
+
dist/
|
|
11
|
+
.venv/
|
|
12
|
+
venv/
|
|
13
|
+
|
|
14
|
+
# Tooling
|
|
15
|
+
.pytest_cache/
|
|
16
|
+
.ruff_cache/
|
|
17
|
+
.coverage
|
|
18
|
+
htmlcov/
|
|
19
|
+
# library: lockfile stays local (CI installs via pip)
|
|
20
|
+
uv.lock
|
|
21
|
+
|
|
22
|
+
# yield-audit local cache
|
|
23
|
+
.yield/
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# AGENTS.md — yield-audit
|
|
2
|
+
|
|
3
|
+
AI 코딩 에이전트(ZCode, Claude Code 등)가 이 저장소에서 작업할 때의 규약입니다.
|
|
4
|
+
사람 기여자는 먼저 [README.md](README.md)를 읽으세요. 내용이 겹치면 이 문서가 우선합니다.
|
|
5
|
+
렌즈 패키지와 테스트에는 하위 규약이 있습니다: [src/yield_audit/lenses/AGENTS.md](src/yield_audit/lenses/AGENTS.md), [tests/AGENTS.md](tests/AGENTS.md).
|
|
6
|
+
|
|
7
|
+
## 이 프로젝트가 하는 일
|
|
8
|
+
|
|
9
|
+
AI 코딩 에이전트(Claude Code)의 로컬 세션 트랜스크립트와 git 이력을 대조해 **성과를 회계**합니다:
|
|
10
|
+
무엇이 살아남았는지(M1 생존율), 무엇이 낭비였는지(M2), 재시도 세금(M3), 채택 작업당 비용(M4),
|
|
11
|
+
캐시 지역성(M5), 검증 공백(M8), AI 리워크율(M11, 코호트 certain/probable/human). 원칙: **완전 로컬, 읽기 전용, 결정적, 런타임 의존성 0**
|
|
12
|
+
(Python ≥3.10 표준라이브러리 + git CLI), **절감 주장 금지 — 측정만**.
|
|
13
|
+
|
|
14
|
+
## 명령어
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
python3 -m pip install -e '.[dev]' # 또는 uv pip install -e '.[dev]'
|
|
18
|
+
pytest # ~3초, 커밋 전 반드시 통과
|
|
19
|
+
ruff check . # 반드시 클린
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
스모크 실행은 **픽스처/tmp 저장소에만**:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
yield-audit audit --repo <tmp fixture repo> --transcripts-dir <tmp fixtures> --now 2026-08-20T00:00:00Z --format json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
⚠️ **절대 금지**: 실제 데이터 감사 — `--repo`/`--transcripts-dir`를 `/Users/*/.claude`·`~/.codex`나
|
|
29
|
+
사용자의 실제 프로젝트로 향하면 1.3GB+ 전체 스캔으로 수십 초~수 분이 걸리고 사생활을 침범합니다.
|
|
30
|
+
에이전트가 실데이터 스모크가 필요하면 사용자에게 먼저 물으세요.
|
|
31
|
+
|
|
32
|
+
## 구조 (데이터 흐름)
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
cli.py argparse, 종료코드 0/2, stdout 로케일 방어
|
|
36
|
+
└─ audit.py 파이프라인 오케스트레이터 — 리포트 dict 조립, 마지막에 deep_sanitize
|
|
37
|
+
├─ transcripts/ 벤더 어댑터 패키지: base(공통 계약·레지스트리) + claude + codex
|
|
38
|
+
│ → events.Session (키 기반 방어적 파싱, 세션 id는 "vendor:<raw>" 네임스페이스)
|
|
39
|
+
├─ gitdata.py 읽기 전용 git 래퍼 (스트리밍, blame=SHA 카운터, GIT_* env 제거)
|
|
40
|
+
├─ attribute.py 세션↔커밋 매칭 (high/medium 등급, 1/n 분할, 모호 플래그)
|
|
41
|
+
├─ cohorts.py 커밋 코호트 라벨 (certain=푸터/probable=세션 조인/human — 근거 등급, 판정 아님)
|
|
42
|
+
├─ pricing/costs 공시 요금표(USD/MTok)와 관측 usage 기반 비용
|
|
43
|
+
├─ lenses/ M1–M11 측정 렌즈 (순수 함수 — 하위 AGENTS.md 참고)
|
|
44
|
+
├─ redact.py 출력 경계: 살균·레닥션·deep_sanitize
|
|
45
|
+
└─ report.py console/json/markdown 렌더러
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 필수 규약 (어기다면 버그)
|
|
49
|
+
|
|
50
|
+
1. **렌즈는 순수 함수** — I/O·시계·난수 금지. `now`와 horizon은 인자로 받는다.
|
|
51
|
+
2. **정직성 라벨** — 모든 리포트 블록에 `measurement`가 있어야 한다:
|
|
52
|
+
`observed`(기록에서 직접) / `estimate`(관측 × 공시요금) / `proxy`(명시된 대체량).
|
|
53
|
+
라벨 없는 새 메트릭은 버그로 취급.
|
|
54
|
+
3. **출력 경계** — 트랜스크립트에서 온 모든 문자열은 `redact.py`를 거친다.
|
|
55
|
+
`run_audit`의 deep_sanitize는 안전망이지 레닥션의 대체품이 아니다
|
|
56
|
+
(안전망은 이스케이프 제거만 하고, 경로 치환은 필드 단계에서 한다).
|
|
57
|
+
4. **결정성** — 출력에 흐르는 모든 순회는 `sorted()` 먼저. 메트릭에 벽시계 금지
|
|
58
|
+
(재현은 `--now`). 스키마는 `yieldaudit.report.v1`, 변경은 하위호환(additive)만.
|
|
59
|
+
5. **런타임 의존성 0** — 표준라이브러리 + `git` CLI만. pytest/ruff는 dev에서만.
|
|
60
|
+
6. **서브프로세스 규율** — list argv(셸 금지), `gitdata._clean_env`로 GIT_* 제거,
|
|
61
|
+
스트림은 stderr=DEVNULL + stdout EOF 후 wait, 프로세스 수는 집계 단위로 캐싱
|
|
62
|
+
(유닛당 무캐시 호출 금지).
|
|
63
|
+
7. **측정 전용** — 절감 개입은 로드맵(v1.x) 게이트 뒤에. 리포트·문서에 절감 수치 주장 금지.
|
|
64
|
+
|
|
65
|
+
## 테스트
|
|
66
|
+
|
|
67
|
+
- `tests/conftest.py`가 고정 날짜의 픽스처 git 저장소와 실제 스키마를 모사한 합성
|
|
68
|
+
트랜스크립트를 만든다. 타임라인은 conftest 모듈 docstring이 유일한 진실원천.
|
|
69
|
+
- 새 렌즈/메트릭 = 렌즈 단위 테스트 + `test_e2e.py` 골든 단언 추가.
|
|
70
|
+
골든 수치(13/24 생존율, $0.00643 등)는 픽스처 타임라인에서 유도된 값이므로
|
|
71
|
+
픽스처 변경 시 docstring과 골든 전부를 함께 갱신.
|
|
72
|
+
- 악성 입력 픽스처( malformed JSONL, Infinity usage, 이스케이프 문자열)는
|
|
73
|
+
`test_transcripts.py`와 `test_redact.py`에. "리포트에 이스케이프 바이트 0" 보증은
|
|
74
|
+
`test_e2e.py::test_report_has_no_escape_bytes_anywhere`가 지킨다.
|
|
75
|
+
|
|
76
|
+
## 릴리스
|
|
77
|
+
|
|
78
|
+
- 버전은 두 곳을 함께: `src/yield_audit/__init__.py` + `pyproject.toml`.
|
|
79
|
+
- Keep-a-Changelog 형식의 CHANGELOG.md 항목 추가. CI 매트릭스: 3.10–3.14 × 3 OS.
|
|
80
|
+
- PyPI는 미게시 상태 — README 설치 안내는 소스 설치 기준으로 유지.
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to yield-audit are documented here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versioning is
|
|
5
|
+
SemVer.
|
|
6
|
+
|
|
7
|
+
## [0.3.2] - 2026-09-06
|
|
8
|
+
|
|
9
|
+
Distribution release: published to PyPI via trusted publishing (OIDC —
|
|
10
|
+
the pending publisher registered on pypi.org for `.github/workflows/
|
|
11
|
+
pypi.yml` claims the name on first run; no API tokens anywhere).
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- README is now fully English (the PyPI landing page) with the M11
|
|
15
|
+
rework-rate one-liner as the headline and a sample console report;
|
|
16
|
+
the Korean README moved to `README.ko.md`. Install docs switched from
|
|
17
|
+
source-install to `pip install yield-audit` / `uvx yield-audit`.
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- `.github/workflows/pypi.yml` — build + `twine check` + publish on
|
|
21
|
+
`v*` tag push (and manual dispatch).
|
|
22
|
+
|
|
23
|
+
## [0.3.1] - 2026-09-06
|
|
24
|
+
|
|
25
|
+
Trust, first-run, and performance fixes from the v0.3.0 review.
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- OpenAI models priced from the table instead of the conservative
|
|
29
|
+
claude-opus fallback: gpt-5.1 / gpt-5.1-codex (1.25/10/0.125),
|
|
30
|
+
gpt-5.3-codex (1.75/14/0.175), gpt-5-mini, o3, o4-mini (standard tier,
|
|
31
|
+
published list prices 2026-09; codex variants share the gpt-5.1 base —
|
|
32
|
+
no separate listing). Codex sessions' USD figures are no longer
|
|
33
|
+
inflated ~4x.
|
|
34
|
+
- Empty-state UX: a missing `--transcripts-dir` or absent vendor roots
|
|
35
|
+
now fail (exit 2) with a `doctor` hint instead of producing a silent
|
|
36
|
+
empty report; zero matching sessions print a prominent warning line in
|
|
37
|
+
console/markdown while staying a valid exit-0 measurement.
|
|
38
|
+
|
|
39
|
+
### Changed — performance
|
|
40
|
+
- Blame prefilter: one `git log --name-only` pass builds a per-path
|
|
41
|
+
touch map (committer dates, matching snapshot selection). Paths no
|
|
42
|
+
commit touched inside a measurement window are decided without a
|
|
43
|
+
single `git blame` process — same values, provably. A merge commit
|
|
44
|
+
inside a window forces blaming (merge resolutions rewrite lines
|
|
45
|
+
invisibly to the pass). Shared by M1 and M11 via the blame cache;
|
|
46
|
+
smoke: 102-commit full-history M11 audit in 0.12s.
|
|
47
|
+
|
|
48
|
+
## [0.3.0] - 2026-09-05
|
|
49
|
+
|
|
50
|
+
M11 AI rework rate — the first ADD-transition lens (기획서-AIDD-전환계량.md
|
|
51
|
+
v0.3.0 scope): compares how quickly AI-marked commits get reworked against
|
|
52
|
+
human ones, measured locally from git history alone.
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- `cohorts.py`: every commit lands in one evidence-graded cohort —
|
|
56
|
+
`certain` (AI footer in the commit message: `Co-Authored-By: …`,
|
|
57
|
+
`Generated with …`, 🤖), `probable` (no footer but claimed by a
|
|
58
|
+
transcript session via the usual attribution join), or `human`.
|
|
59
|
+
Labels state matching evidence, never authorship verdicts; every
|
|
60
|
+
cohort percentage ships with the evidence distribution.
|
|
61
|
+
- `lenses/rework.py` (M11): rework = lines a commit added that are no
|
|
62
|
+
longer present verbatim at the snapshot `--rework-days` (default 14)
|
|
63
|
+
later — the complement of M1's blame survival, applied to every commit
|
|
64
|
+
and aggregated by cohort plus an `ai_combined` view. Pending horizons
|
|
65
|
+
are excluded from rates and counted honestly; `--rework-days 0`
|
|
66
|
+
disables the lens.
|
|
67
|
+
- Report block `m11_rework` and `parameters.rework_horizon_days`
|
|
68
|
+
(schema v1, additive); console/markdown renderers gained an M11
|
|
69
|
+
section; `gitdata.commit_messages` streams full commit messages for
|
|
70
|
+
footer evidence.
|
|
71
|
+
|
|
72
|
+
### Changed
|
|
73
|
+
- Fixture repo grew commits C3 (AI-footered, new file) and C4 (human
|
|
74
|
+
rework of it); M1/attribution goldens are unchanged, window counts
|
|
75
|
+
updated (commits_in_window 4, unclaimed 3).
|
|
76
|
+
|
|
77
|
+
## [0.2.0] - 2026-09-05
|
|
78
|
+
|
|
79
|
+
Vendor-agnostic transcripts: the Claude-only ingest module became an
|
|
80
|
+
adapter registry, and the Codex CLI is scanned alongside Claude Code by
|
|
81
|
+
default. Claude-only audits keep identical measured values (regression:
|
|
82
|
+
all v0.1.2 golden numbers unchanged).
|
|
83
|
+
|
|
84
|
+
### Added
|
|
85
|
+
- `transcripts/` package with a `TranscriptAdapter` base class (find
|
|
86
|
+
files + parse one JSON record into `events.Session`) and a registry;
|
|
87
|
+
adding a vendor is one subclass plus one registry entry.
|
|
88
|
+
- Codex CLI adapter (`~/.codex/sessions` rollout JSONL): session meta /
|
|
89
|
+
turn context / function calls / token counts, with vendor tool names
|
|
90
|
+
normalized to the canonical set (shell execution becomes `Bash`,
|
|
91
|
+
`apply_patch` headers become edited files, exit_code becomes tool
|
|
92
|
+
errors). Compaction boundaries are not present in this format and stay
|
|
93
|
+
empty.
|
|
94
|
+
- `--agent {auto,claude,codex}` on `audit` and `doctor` (default `auto`:
|
|
95
|
+
every registered vendor; missing roots are skipped). An explicit
|
|
96
|
+
`--transcripts-dir` applies to all selected vendors — adapters skip
|
|
97
|
+
records that are not their schema, so mixed directories are safe.
|
|
98
|
+
- Session ids are namespaced per vendor (`"claude:<id>"`,
|
|
99
|
+
`"codex:<id>"`); report keys keep the prefix. Report `parameters` adds
|
|
100
|
+
`agents_scanned` and `transcripts_roots` (schema v1, additive).
|
|
101
|
+
|
|
102
|
+
### Changed
|
|
103
|
+
- `run_audit`'s `transcripts_root` accepts `None` (each agent's own
|
|
104
|
+
default root) and takes a new `agents` argument; `load_sessions`
|
|
105
|
+
likewise. Ingest internals moved from `transcripts.py` into
|
|
106
|
+
`transcripts/{base,claude,codex}.py` — the public helpers are
|
|
107
|
+
re-exported unchanged.
|
|
108
|
+
|
|
109
|
+
## [0.1.2] - 2026-09-05
|
|
110
|
+
|
|
111
|
+
Second review round: close the sanitizer bypasses found in v0.1.1's new
|
|
112
|
+
output boundary and harden ingest against hostile transcript values.
|
|
113
|
+
Measured values are unchanged (regression-checked against 0.1.1).
|
|
114
|
+
|
|
115
|
+
### Fixed — security
|
|
116
|
+
- Session ids are transcript-controlled and reached report keys/cells raw;
|
|
117
|
+
`_sid` now sanitizes, and `run_audit` deep-sanitizes the finished report
|
|
118
|
+
(strings and dict keys) so no future field can bypass the boundary.
|
|
119
|
+
- Path redaction's lookbehind is ASCII-only: a Unicode word (e.g. Hangul)
|
|
120
|
+
before an absolute path no longer suppresses redaction.
|
|
121
|
+
- `~/`-relative paths in commands are redacted to `<path>` like absolute
|
|
122
|
+
ones; Windows UNC free-text paths are a documented gap.
|
|
123
|
+
- Sanitization now also strips C1 control characters (U+0080-U+009F) and
|
|
124
|
+
CSI sequences with intermediate bytes.
|
|
125
|
+
|
|
126
|
+
### Fixed — robustness
|
|
127
|
+
- Bare `Infinity` token counts (accepted by Python's json parser) crashed
|
|
128
|
+
the run with OverflowError; non-finite values now read as 0.
|
|
129
|
+
- The Windows munged-directory name is separator/colon free, so the
|
|
130
|
+
prefilter can no longer resolve to an absolute path and scan the
|
|
131
|
+
repository itself instead of the transcripts.
|
|
132
|
+
- Transcript discovery prunes symlink cycles by (device, inode) instead of
|
|
133
|
+
looping forever.
|
|
134
|
+
- Blame porcelain parsing ignores tab-prefixed content lines whose first
|
|
135
|
+
token looks like a SHA.
|
|
136
|
+
|
|
137
|
+
### Changed
|
|
138
|
+
- Discovery notes (prefilter vs full walk) are surfaced in report notes
|
|
139
|
+
instead of being invisible.
|
|
140
|
+
- Hygiene: pending count dedupes contested units by (commit, path);
|
|
141
|
+
survival result annotations reflect share-weighted floats; waste
|
|
142
|
+
classifies each unit once; dead attribution overlap field removed;
|
|
143
|
+
version strings aligned to 0.1.2.
|
|
144
|
+
|
|
145
|
+
## [0.1.1] - 2026-09-05
|
|
146
|
+
|
|
147
|
+
Post-release review hardening: correctness, performance, and output-boundary
|
|
148
|
+
security. Measured values are unchanged (regression-checked against 0.1.0 on
|
|
149
|
+
a real corpus).
|
|
150
|
+
|
|
151
|
+
### Fixed — correctness
|
|
152
|
+
- Attribution: contested commits now split across ALL same-grade claimants
|
|
153
|
+
(previously only exact-overlap ties split; other claimants were silently
|
|
154
|
+
dropped, and a high-grade tie picked one winner unflagged). Every
|
|
155
|
+
ambiguity is flagged.
|
|
156
|
+
- Attribution: `shared_files` no longer leaks the last-iterated session's
|
|
157
|
+
file set into other pairs (regression test added).
|
|
158
|
+
- Waste bounds: the share denominator is now computed from units classified
|
|
159
|
+
at the *same* horizon, so bounds can never exceed the session cost when
|
|
160
|
+
horizon differs from the headline.
|
|
161
|
+
- Verification gap: reports both `gap_rate` (never verified) and
|
|
162
|
+
`gap_rate_strict` (not verified before the last commit).
|
|
163
|
+
- Cache locality: a compaction boundary stamped exactly at the previous
|
|
164
|
+
call's timestamp now counts as compaction (tie rule).
|
|
165
|
+
- Accepted: sessions with commits but no cost record land in a status
|
|
166
|
+
instead of vanishing from totals.
|
|
167
|
+
|
|
168
|
+
### Fixed — performance
|
|
169
|
+
- Survival: file existence is checked via one `git ls-tree -r` per snapshot
|
|
170
|
+
instead of one `cat-file` per unit×horizon (~10x fewer git processes on
|
|
171
|
+
commit-heavy repos).
|
|
172
|
+
- Transcripts: sessions are loaded from the repo's munged project directory
|
|
173
|
+
when present (full-walk fallback preserved) — real-corpus audit went from
|
|
174
|
+
14.1s to 3.8s on a 1.3GB transcript root.
|
|
175
|
+
- `git log --numstat` and `git blame` stream line-by-line; blame collapses
|
|
176
|
+
to per-SHA counts instead of retaining full porcelain output.
|
|
177
|
+
- Failure chains capped at 200 in the JSON report with a truncation flag.
|
|
178
|
+
- Cache locality boundary matching is a two-pointer scan, not O(calls×boundaries).
|
|
179
|
+
|
|
180
|
+
### Fixed — security
|
|
181
|
+
- Output boundary: every transcript-derived string is stripped of ANSI
|
|
182
|
+
escape and control sequences before rendering (terminal injection).
|
|
183
|
+
- Markdown: chain commands are escaped for table cells/code spans, so a
|
|
184
|
+
pasted report cannot be broken out of or turned into remote image loads.
|
|
185
|
+
- Chain commands have absolute paths redacted to `<path>` by default
|
|
186
|
+
(`--show-paths` restores them), matching the README's redaction promise.
|
|
187
|
+
- `parameters.transcripts_root` is home-abbreviated; path redaction handles
|
|
188
|
+
Windows separators.
|
|
189
|
+
- Git subprocesses run with `GIT_*` environment variables stripped so a
|
|
190
|
+
stray `GIT_DIR` cannot redirect the audit.
|
|
191
|
+
|
|
192
|
+
### Fixed — robustness
|
|
193
|
+
- Unparseable commit dates skip the commit with a warning note instead of
|
|
194
|
+
crashing the run.
|
|
195
|
+
- Float token counts in transcripts (e.g. `4096.0`) truncate instead of
|
|
196
|
+
reading as zero.
|
|
197
|
+
- `--days` rejects negative values; stdout/stderr are reconfigured to
|
|
198
|
+
survive non-UTF-8 locales.
|
|
199
|
+
- `core.quotePath=false` keeps non-ASCII file paths intact in numstat.
|
|
200
|
+
|
|
201
|
+
### Changed
|
|
202
|
+
- Packaging: `license = "Apache-2.0"` (PEP 639) with `license-files`.
|
|
203
|
+
- Transcript discovery follows symlinked directories via `os.walk`.
|
|
204
|
+
|
|
205
|
+
## [0.1.0] - 2026-09-05
|
|
206
|
+
|
|
207
|
+
Initial release: outcome accounting for AI coding agents, fully local,
|
|
208
|
+
measurement-only.
|
|
209
|
+
|
|
210
|
+
### Added
|
|
211
|
+
- Claude Code transcript adapter (JSONL, schema-defensive; sidechains and
|
|
212
|
+
malformed records skipped).
|
|
213
|
+
- M1 output survival rate with git-blame snapshots at configurable horizons
|
|
214
|
+
(default 7d headline, 7/30 measured), split by output kind
|
|
215
|
+
(source/test/docs/config); pending-horizon units reported separately;
|
|
216
|
+
aggregates weighted by attribution share so contested commits count once.
|
|
217
|
+
- M2 waste cost bounds (removed = lower+upper, >=50% lost = upper only);
|
|
218
|
+
attribution-share-weighted line-share proxy labeled as such.
|
|
219
|
+
- M3 retry tax: failure chains from repeated normalized Bash commands with
|
|
220
|
+
errors; interval-based token attribution.
|
|
221
|
+
- M4 accepted-task accounting: cost/tokens per accepted session
|
|
222
|
+
(survival >= 0.5); accepted/rejected/pending/no_output classes.
|
|
223
|
+
- M5 cache locality: ttl_expiry / prefix_break / compaction classification
|
|
224
|
+
of cold calls; wasted-vs-cached estimate; compaction excluded by design.
|
|
225
|
+
- M8 verification gap rate plus survival correlation table.
|
|
226
|
+
- Session-commit attribution with high/medium confidence grades, contested
|
|
227
|
+
commit splitting, and ambiguity flags.
|
|
228
|
+
- Pricing table (2026-09 list prices, prefix matching, conservative
|
|
229
|
+
fallback for unknown models) with JSON override file.
|
|
230
|
+
- Report formats: console, JSON (`yieldaudit.report.v1`, every block
|
|
231
|
+
labeled observed/estimate/proxy), markdown; path redaction by default.
|
|
232
|
+
- Graceful degradation on repositories with no commits yet (empty report,
|
|
233
|
+
no crash).
|
|
234
|
+
- CLI: `yield-audit audit`, `yield-audit doctor`; `--now` for reproducible
|
|
235
|
+
runs.
|
|
236
|
+
- Tests: deterministic fixture git repository (pinned dates) + synthetic
|
|
237
|
+
transcripts; unit and end-to-end golden assertions.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# HANDOFF — 다음 세션 작업 지시서
|
|
2
|
+
|
|
3
|
+
- **작성 시점**: 2026-09-05, v0.1.2 (커밋 `2fd3ebc` 기준)
|
|
4
|
+
- **업데이트 2026-09-05**: v0.2.0+v0.3.0 출시(커밋 `43054b5` + Windows 테스트 수정). **P0 완료 — 원격 [ictechgy/yield-audit](https://github.com/ictechgy/yield-audit) public 생성, 첫 CI 3 OS × py3.10/3.12/3.14 전부 그린, 태그 v0.1.2·v0.3.0 push.** 첫 CI에서 기존 테스트의 Windows 경로 버그(munged 이름 치환) 발견·수정됨
|
|
5
|
+
- **전제 상태**: 67 tests 통과 · ruff 클린 · 실데이터 회귀 확인(측정값 불변) · PyPI 미게시
|
|
6
|
+
- **에이전트 규약**: 작업 시작 전 [AGENTS.md](AGENTS.md) 읽기. **절대 실데이터(`/Users/*/.claude`, 실제 프로젝트) 감사 금지** — 픽스처/tmp만.
|
|
7
|
+
|
|
8
|
+
## 0. 현재 상태 빠른 확인 (5초)
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pytest -q && ruff check . && git log --oneline | head -5
|
|
12
|
+
# 예상: 67 passed, All checks passed, 최신 커밋 = docs 커밋
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
문서 지도: README(사용자용) → AGENTS.md(에이전트 규약, 루트+lenses+tests) →
|
|
16
|
+
CHANGELOG(변경 이력) → 기획서-AIDD-전환계량.md(v0.3+ 근거, M11 출시됨) →
|
|
17
|
+
../AI비용-빈영역-오픈소스-기획서.md(v0.2+ 근거) →
|
|
18
|
+
../context-guard-개선-보고서.md(별개 프로젝트 참고용).
|
|
19
|
+
|
|
20
|
+
## 1. 최우선: 원격 저장소 + 첫 CI 실행 (미해결 P0급)
|
|
21
|
+
|
|
22
|
+
CI가 CI워크플로 파일만 있고 **한 번도 돌아본 적이 없다**. 로컬은 macOS+py3.14 하나뿐이므로
|
|
23
|
+
3 OS × py 3.10/3.12/3.14 매트릭스에서 처음으로 검증되는 것과 같다.
|
|
24
|
+
|
|
25
|
+
- [ ] GitHub 원격 생성 후 push (`gh repo create yield-audit --public --source .` 또는 사용자 선호 방식 — 원격 생성은 사용자 승인 필요할 수 있음)
|
|
26
|
+
- [ ] CI 결과 확인. **예상 실패 후보와 대응**:
|
|
27
|
+
- py3.10 문법 → 전 모듈에 `from __future__ import annotations` 있음(확인됨), 그래도 실패 시 해당 시그니처 수정
|
|
28
|
+
- Windows: `tests/conftest.py` 픽스처 경로, `munged_project_dir_name`(v0.1.2에서 백슬래시·콜론 처리 완료), blame/ls-tree 동작 차이
|
|
29
|
+
- actions 태그 핀(@v4/@v5) → 공식 SHA 확인 후 핀 (아직 미적용 — 기억으로 SHA 쓰지 말 것)
|
|
30
|
+
- [ ] 그린이면 `git tag v0.1.2 && git push --tags`
|
|
31
|
+
- [ ] README의 홈페이지/원격 URL이 실제 원격과 일치하는지 갱신 (현재 placeholder)
|
|
32
|
+
|
|
33
|
+
## 2. 다음 기능 사이클
|
|
34
|
+
|
|
35
|
+
**v0.2 어댑터 인터페이스 + v0.3.0 M11 리워크율 완료됨**(기획서-AIDD-전환계량.md v0.3.0 스코프:
|
|
36
|
+
cohorts.py 코호트 라벨 + lenses/rework.py + `--rework-days` + 리포트 `m11_rework` 블록).
|
|
37
|
+
남은 v0.3 항목: M12 정착률(blame 스냅샷, `--snapshot` 서브커맨드), v0.4 `aidd` 서브커맨드 통합 리포트.
|
|
38
|
+
|
|
39
|
+
### 원래 v0.2 항목 (M7/M9/M10은 미착수)
|
|
40
|
+
|
|
41
|
+
**시작 전 아키텍처 과제가 먼저** — 2차 리뷰의 구조 지적:
|
|
42
|
+
|
|
43
|
+
- [x] **어댑터 인터페이스 추출** (v0.2.0 완료): `transcripts/` 패키지(base+claude+codex, 레지스트리),
|
|
44
|
+
`--agent {auto,claude,codex}`, 세션 id `"vendor:<raw>"` 네임스페이스. Gemini 어댑터는
|
|
45
|
+
스키마 그라운딩 확보 후 같은 방식으로 추가하면 됨(서브클래스 1개 + 레지스트리 등록).
|
|
46
|
+
- [ ] **M7 컨텍스트 사망율**: 읽어들인 파일 내용이 이후 생성물에 미등장하면 "사망"의 결정적 근사.
|
|
47
|
+
문자열 매칭 기반(정규화 후 포함 검사)으로 시작. 렌즈 계약 준수(순수 함수, measurement 라벨).
|
|
48
|
+
- [ ] **M9 세션 간 반복 지식 비용**: 콘텐츠 해시 기반 크로스세션 중복 과금 측정.
|
|
49
|
+
전략적 의미: 메모리·벡터 DB 투자 ROI 역산 — 제작자의 별도 벡터 DB 프로젝트와 상호 판매 구조.
|
|
50
|
+
- [ ] **M10 핸드오프 세금**: 서브에이전트 페이로드 측정. 트랜스크립트에 기록된
|
|
51
|
+
Agent/Task 도구 호출의 부모↔자식 구조 파싱.
|
|
52
|
+
|
|
53
|
+
각 항목: 단위 테스트 + E2E 골든 + conftest docstring 갱신까지가 완료 정의(tests/AGENTS.md §6).
|
|
54
|
+
|
|
55
|
+
## 3. 백로그 (우선순위 낮음, 근거 있음)
|
|
56
|
+
|
|
57
|
+
- [x] PyPI 게시 (v0.3.2) — 신뢰 퍼블리셔(OIDC) `pypi.yml`, 태그 푸시로 게시. README 영어화 + 한국어 README.ko.md 분리, 퀵스타트 `uvx yield-audit` 복원
|
|
58
|
+
- [ ] UNC 경로(`\\host\share`) 자유 텍스트 레닥션 — 현재 README에 문서화된 한계
|
|
59
|
+
- [x] 터치 프리필터(v0.3.1) — path_touch_log 원패스로 무터치 파일 blame 스킵(머지 가드 포함).
|
|
60
|
+
스냅샷 캐시 일(day) 버킷팅 옵션은 여전히 백로그 — rev-list/ls-tree 절감용
|
|
61
|
+
- [ ] `doctor`에 트랜스크립트 루트 용량·파일수 리포트 추가(사용자가 사전 감사 가능하도록)
|
|
62
|
+
- [ ] v0.3 잔여: M12 정착률(blame 스냅샷, `--snapshot` 서브커맨드), M5 기반 배치 스케줄 조언, M6 개인 라우팅 힌트(옵트인 리플레이) — M11은 0.3.0으로 출시됨(기획서-AIDD의 M11 인간 수정 시간과는 별개 표기 정리 필요 없음, 해당 항목은 M13/M14로 통합 검토)
|
|
63
|
+
|
|
64
|
+
## 4. 절대 어기지 말 것 (회귀 방지)
|
|
65
|
+
|
|
66
|
+
1. **절감 수치 주장 금지** — 측정만. 개입 기능은 v1.x 게이트 뒤.
|
|
67
|
+
2. **런타임 의존성 0** 유지 (stdlib + git CLI). dev 의존성은 런타임 import 금지.
|
|
68
|
+
3. **모든 리포트 블록에 `measurement` 라벨** (observed/estimate/proxy).
|
|
69
|
+
4. **트랜스크립트 파생 문자열은 redact.py 경유** — deep_sanitize는 안전망이지 대체품 아님.
|
|
70
|
+
5. **렌즈 순수성** — I/O·시계·난수 금지, 집계는 `attributed_added`(share 가중).
|
|
71
|
+
6. **커밋 전**: `pytest && ruff check .` 통과 + CHANGELOG 항목 + 버전 2곳 동시 bump.
|
|
72
|
+
7. **실데이터 감사 금지** (상단 경고 재확인 — 리뷰 에이전트 2회 타임아웃의 원인이었음).
|
|
73
|
+
|
|
74
|
+
## 5. 검증된 참고 수치 (회귀 비교용, macOS arm64 / speed 저장소 / --days 90)
|
|
75
|
+
|
|
76
|
+
| 항목 | 값 |
|
|
77
|
+
|---|---|
|
|
78
|
+
| 실행 시간 | ~3.5s (v0.1.0 대비 14.1s → 개선) |
|
|
79
|
+
| M1 생존율 | 95.4272% (17,276줄) |
|
|
80
|
+
| M2 낭비 구간 | $4.334524 – $19.773222 |
|
|
81
|
+
| M4 채택당 비용 | $841.384684 (채택 1 / no_output 2) |
|
|
82
|
+
| M5 히트율 | 74.9%, cold 0 |
|
|
83
|
+
|
|
84
|
+
새 버전 배포 전 이 값을 재현해 수치가 변했다면 그 이유를 설명할 수 있어야 한다.
|
|
85
|
+
(단, speed 저장소 자체가 변하면 당연히 달라진다 — 그 경우 raw 값 비교가 아니라
|
|
86
|
+
"같은 커밋 범위에서 재실행"으로 비교.)
|