Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ DATA_GO_KR_API_KEY=
# KOSIS 국가통계포털 OpenAPI (https://kosis.kr/openapi)
KOSIS_API_KEY=

# 법제처 국가법령정보 공동활용 OC (https://open.law.go.kr) — 법령·행정규칙·조례 수집
LAW_OC=

# LLM providers (use whichever you have; open models via OpenAI-compatible endpoint)
OPENAI_API_KEY=
ANTHROPIC_API_KEY=
Expand Down
4 changes: 2 additions & 2 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# 코드 소유자: PR이 열리면 아래 사람에게 자동으로 리뷰 요청이 갑니다.
# 멘티 폴더(cases/<ID>-<주제>/)는 폴더를 만들 때 한 줄씩 추가합니다.
# 코드 소유자: PR이 열리면 아래 사람에게 자동으로 리뷰 요청이 갑니다 (필수 승인은 아님).
# 멘티 폴더(cases/<ID>-<주제>/)는 운영진이 첫 계획 PR을 합칠 때 한 줄씩 추가합니다.
# 예) /cases/gildong-*/ @gildong

* @jsshin2022
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ body:
id: where
attributes:
label: 위치
placeholder: core/estimators, app/streamlit_app.py, cases/gildong-local-currency/estimate.py
placeholder: core/estimators, app/streamlit_app.py, cases/gildong-local-currency/fetch.py
validations:
required: true
- type: textarea
Expand Down
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
- [ ] `plan.yaml`을 **결과를 보기 전에** 작성·커밋했습니다 (이후 변경 시 이유를 커밋 메시지에 기록)
- [ ] 데이터 출처와 **라이선스**(공공누리 유형 등)를 `plan.yaml > data_sources`에 명시했습니다
- [ ] API 키·`.env`·개인정보가 담긴 원자료·재배포 불가 데이터를 포함하지 않았습니다
- [ ] 그림/수치는 `fetch.py` → `estimate.py` 실행으로 **재현** 가능합니다
- [ ] 그림/수치는 `fetch.py` → `make flow` 실행으로 **재현** 가능합니다 (해석은 `discussion.md`)
- [ ] `make check` (ruff + pytest)가 통과합니다
- [ ] 다른 사람의 폴더나 `core/`를 (합의 없이) 수정하지 않았습니다
- [ ] 원자료·가공 데이터 파일을 커밋하지 않았습니다 (시뮬레이션·조례 목록 제외)
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Install
run: |
python -m pip install --upgrade pip
pip install -e ".[dev,agent]"
pip install -e ".[dev,agent,app]"
- name: Ruff
run: |
ruff check .
Expand Down
34 changes: 34 additions & 0 deletions .github/workflows/legal-watch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: legal-watch

# 매주 월요일, 주제와 관련된 법령·행정규칙이 지난 7일 사이 바뀌었는지 확인하고
# 바뀐 것이 있으면 이슈(라벨 law-change)를 엽니다. 구성원 누구나 확인해 topics.yaml events 에 반영합니다.
# 필요: Settings → Secrets → Actions 의 LAW_OC. 없으면 아무것도 하지 않습니다.
on:
schedule:
- cron: "7 0 * * 1" # 매주 월요일 09:07 KST
workflow_dispatch:
inputs:
days:
description: "며칠 전까지 볼까요"
default: "7"

permissions:
contents: read
issues: write

jobs:
watch:
runs-on: ubuntu-latest
env:
LAW_OC: ${{ secrets.LAW_OC }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: pip
- run: pip install -e .
- name: Watch law/policy changes
if: ${{ env.LAW_OC != '' }}
run: python scripts/watch_legal.py --days "${{ github.event.inputs.days || '7' }}" --open-issue
8 changes: 5 additions & 3 deletions .github/workflows/pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: pages
# main 에 반영되면 정적 대시보드(_site/)를 만들어 GitHub Pages 로 배포한다.
# 최초 1회: Settings → Pages → Build and deployment → Source: "GitHub Actions"
# 선택: Settings → Secrets → Actions 에 넣으면 켜지는 것 (값은 절대 레포에 적지 않는다)
# LAW_OC 법제처 조례 목록 자동 수집
# LAW_OC 법제처 법령·행정규칙·조례 자동 수집 (주제별 법령 온톨로지)
# NAVER_CLIENT_ID, NAVER_CLIENT_SECRET '요즘 궁금해하는 주제' 순위에 검색 관심도 추가
on:
push:
Expand Down Expand Up @@ -36,9 +36,11 @@ jobs:
python-version: "3.11"
cache: pip
- run: pip install -e .
- name: Refresh ordinance snapshots (법제처, optional)
- name: Refresh law/policy ontology (법제처, optional)
if: ${{ env.LAW_OC != '' }}
run: python scripts/refresh_law_snapshots.py
run: |
python scripts/refresh_law_snapshots.py # 조례형 주제: 검색어로 지역별 조례 시행 연도(막대그래프). refresh_legal 은 근거 법률 기준 전체 온톨로지
python scripts/refresh_legal.py || echo "::warning::법제처 수집 일부 실패 — 커밋된 스냅샷으로 빌드합니다"
- name: Refresh topic ranking (site questions + optional Naver DataLab)
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ data/cache/
*.xlsx~
~$*

# Case data: 원자료·가공 데이터는 올리지 않고 fetch.py 로 각자 받는다 (시뮬레이션 예시만 예외)
cases/*/data/*
!cases/*/data/README.md
!cases/_example_night_clinic/data/*
!cases/t3-land-permit-2025/data/*

# Practice runs (make demo)
_demo/

# Generated at build time (GitHub Actions)
catalog/snapshots/trends.json

Expand Down
12 changes: 10 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ GitHub가 처음이라면 [GitHub 따라 하기](docs/ops/github-onboarding.md)

- **`plan.yaml`을 결과보다 먼저 커밋합니다.** 나중에 바꾸면 커밋 메시지에 이유를 적습니다.
- 데이터 출처와 이용 조건(공공누리 유형 등)을 `plan.yaml`의 `data_sources`에 적습니다.
- 그림과 숫자는 `fetch.py` → `make flow` 실행으로 다시 만들 수 있어야 합니다.
- 그림과 숫자는 `fetch.py` → `make flow` 실행으로 다시 만들 수 있어야 합니다. `make flow`는 plan.yaml이 커밋되어 있지 않으면 계산하지 않습니다(연습은 `make demo`).
- `report.md`·`figures/`는 자동으로 만들어집니다. 해석과 한계는 `discussion.md`에 쓰면 리포트 끝에 붙습니다.
- 가정이 깨지면 판정을 "판단 불가"로 두는 것도 좋은 결과입니다.

## 6. 올리면 안 되는 것
Expand All @@ -62,7 +63,14 @@ make flow CASE=cases/<내ID>-<주제>
python site/build.py && python -m http.server -d _site # 사이트 미리보기
```

## 9. 질문과 제안
## 9. 질문과 제안 (구성원 모두가 봅니다)

담당자를 따로 두지 않습니다. 모임 전에 각자 아래 두 목록을 훑고, 할 수 있는 것에 댓글을 달거나 PR로 반영합니다.

- [사이트 질문 (`from-site`)](https://github.com/CausalInferenceLab/policy-effect-analytics-agent/issues?q=is%3Aopen+label%3Afrom-site): 새 주제·데이터면 `catalog/`에 PR, 내 주제와 관련 있으면 내 분석에 반영
- [법령 변경 (`law-change`)](https://github.com/CausalInferenceLab/policy-effect-analytics-agent/issues?q=is%3Aopen+label%3Alaw-change): 매주 월요일 자동으로 열립니다. 시작일·대상이 바뀐 정책이면 `topics.yaml`의 `events`에 출처와 함께 추가
- 처리한 사람이 이슈를 닫습니다.


- 사이트 대화창에서 정리한 질문은 "이 대화를 제안으로 올리기" 버튼으로 이슈가 됩니다.
- 버그는 "버그 리포트", 새 분석 주제는 "케이스 제안" 이슈로 올립니다.
Expand Down
34 changes: 24 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
.PHONY: install check lint test format app activity flow
.PHONY: install check lint test format app activity flow demo site

PY ?= python

# .env 가 있으면 키를 환경변수로 불러온다 (.env 는 커밋 금지)
-include .env
export

install:
@command -v uv >/dev/null 2>&1 && uv pip install -e ".[dev]" || $(PY) -m pip install -e ".[dev]"
$(PY) -m pip install -e ".[dev]"

check: lint test

lint:
ruff check .
$(PY) -m ruff check .

test:
pytest -q
$(PY) -m pytest -q

format:
ruff format . && ruff check --fix .
$(PY) -m ruff format . && $(PY) -m ruff check --fix .

app:
streamlit run app/streamlit_app.py

# Run the 6-step agent flow on a case (demo: skips the plan pre-registration gate).
# 내 케이스를 여섯 단계로 실행. plan.yaml 이 커밋되어 있어야 계산한다(사전 등록).
CASE ?= cases/_example_night_clinic
flow:
$(PY) -m core.agent $(CASE) --allow-uncommitted
$(PY) -m core.agent $(CASE)

# 연습: 토지거래허가구역 예시를 _demo/ 에 복사해 돌린다. 레포 파일은 바뀌지 않는다.
demo:
rm -rf _demo && mkdir -p _demo && cp -r cases/t3-land-permit-2025 _demo/
$(PY) -m core.agent _demo/t3-land-permit-2025 --allow-uncommitted

# 사이트 미리보기: http://localhost:8000
site:
$(PY) site/build.py && $(PY) -m http.server -d _site

# (선택) 개발용 Streamlit 화면: pip install -e ".[app]"
app:
streamlit run app/streamlit_app.py

activity:
$(PY) scripts/weekly_activity.py --days 7
34 changes: 24 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@
| **요즘 궁금해하는 주제** | 대화창 아래 순위입니다. 최근 30일 사이트 질문 수 → 네이버 검색 관심도(키가 있을 때) → 최근 시행·발표일 순이고, 어떤 기준을 썼는지 화면에 적습니다. |
| **지금 이슈** | 토지거래허가구역, 6·27 대출 한도, 민생회복 소비쿠폰, 고유가 피해지원금, K-패스 '모두의 카드' 등 6개 정책의 분석 가이드입니다. |
| **데이터 지도** | 공공데이터 35개를 역할(누가 언제 받았나 / 무엇이 변했나 / 다른 요인), 단위, 받는 법, 이용 조건으로 정리했습니다. |
| **주제 8개** | 주제마다 정책 타임라인, 세 가지 확인 상태, 데이터, 분석 예시가 있습니다. |
| **주제 8개** | 주제마다 정책 타임라인, 세 가지 확인 상태, **관련 법령·행정규칙**(법제처 자동 수집), 데이터, 분석 예시가 있습니다. |

## 데이터는 어디서 오나

| 무엇 | 어디서 | 어떻게 |
|---|---|---|
| **정책이 언제, 누구에게** (법령·행정규칙·조례) | 법제처 국가법령정보 공동활용 API | 주제마다 근거 법률만 적으면 연혁·하위 규정·조례·지정/해제 공고를 모두 모읍니다. 매주 바뀐 것은 `law-change` 이슈로 알립니다. [자세히](catalog/README.md#법령정책-온톨로지-법제처-자동-수집) |
| **정책 발표** (지자체 공고, 대출 규제 같은 행정지도) | 정부 보도자료(korea.kr) 등 | 법령 DB에 없어 `topics.yaml`의 `events`에 출처와 함께 사람이 적습니다 |
| **무엇이 달라졌나** (결과) · **다른 요인** (통제) | 공공데이터포털, KOSIS, 서울 열린데이터광장 등 35개 | [데이터 지도](catalog/datasets.yaml)에 역할·단위·받는 법·이용 조건을 적고, 각 케이스의 `fetch.py`가 받습니다 |
| **사람들이 궁금해하는 것** | 사이트 질문(GitHub 이슈), 네이버 검색어트렌드(선택) | 주제를 고르는 데만 씁니다 |

## 대화가 오픈소스가 되는 길

Expand Down Expand Up @@ -52,10 +61,10 @@
git clone https://github.com/CausalInferenceLab/policy-effect-analytics-agent.git
cd policy-effect-analytics-agent
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
pip install -e ".[dev]" # Python 3.11 이상

make flow CASE=cases/t3-land-permit-2025 # 토지거래허가구역 예시를 6단계로 실행
python site/build.py && python -m http.server -d _site # 사이트를 http://localhost:8000 에서 보기
make demo # 토지거래허가구역 예시를 연습용 폴더(_demo/)에서 6단계로 실행. 레포 파일은 바뀌지 않음
make site # 사이트를 http://localhost:8000 에서 보기
```

API 키 없이 돌아갑니다. 실제 데이터를 받으려면 `.env.example`을 `.env`로 복사해 키를 넣으세요. `.env`는 커밋되지 않습니다.
Expand All @@ -66,7 +75,9 @@ API 키 없이 돌아갑니다. 실제 데이터를 받으려면 `.env.example`

1. **주제 고르기**: 사이트 대화창·순위·지금 이슈에서 고르고 "케이스 제안" 이슈를 엽니다.
2. **계획 올리기**: `cp -r cases/_template cases/<내ID>-<주제>`로 내 폴더를 만들고 `plan.yaml`을 써서 PR을 올립니다. 대화창의 "분석 계획 초안"을 출발점으로 써도 됩니다. 쓰는 법: [계획 작성 가이드](docs/strategy/plan-guide.md)
3. **실행하고 공개**: `make flow CASE=cases/<내ID>-<주제>`로 돌리고 결과를 PR로 올립니다. 합쳐지면 사이트에 자동으로 올라옵니다.
3. **실행하고 공개**: `fetch.py`로 `data/panel.csv`를 만들고 `make flow CASE=cases/<내ID>-<주제>`로 돌립니다. 해석은 `discussion.md`에 씁니다. 합쳐지면 사이트에 자동으로 올라옵니다.

`make flow`는 plan.yaml이 커밋되어 있지 않으면 계산하지 않습니다(사전 등록). 사이트 질문과 법령 변경 이슈는 담당자 없이 구성원 모두가 봅니다.

규칙은 세 가지입니다. 브랜치는 `<내ID>/<작업>`, 수정은 내 폴더만, 합치기는 리뷰 1명과 자동 검사 통과 뒤. 자세한 내용: [멘티 참여 가이드](docs/ops/mentee-guide.md) · [CONTRIBUTING](CONTRIBUTING.md) · [GitHub가 처음이라면](docs/ops/github-onboarding.md)

Expand All @@ -77,15 +88,16 @@ API 키 없이 돌아갑니다. 실제 데이터를 받으려면 `.env.example`
| [`cases/`](cases/) | 멘티별 분석 폴더 (`<내ID>-<주제>`, `_template`에서 시작) | 폴더 주인 |
| [`catalog/`](catalog/) | 주제 · 이슈 · 데이터셋 목록 (데이터 지도) | 누구나 (PR) |
| [`site/`](site/) | 공개 사이트와 대화창(`ask.js`) | 메인테이너 |
| [`scripts/`](scripts/) | 조례 목록 · 순위 갱신, 라이선스 확인, 활동 확인 | 메인테이너 |
| [`core/`](core/) | 주제 찾기(`discovery`) · 수집기(`adapters`) · 계산(`estimators`) · 6단계 실행(`agent`) | 메인테이너 |
| [`scripts/`](scripts/) | 법령 · 조례 · 순위 갱신, 법령 변경 감지, 라이선스 · 활동 확인 | 메인테이너 |
| [`core/`](core/) | 주제 찾기(`discovery`) · 수집기(`adapters`, 법령 온톨로지 포함) · 계산(`estimators`) · 6단계 실행(`agent`) | 메인테이너 |
| `app/` | (선택) 개발용 Streamlit 화면. `pip install -e ".[app]"` 후 `make app` | 메인테이너 |
| [`docs/`](docs/) | 국내 사례, 주제 고르기, 계획 작성법, 운영 가이드 | 운영진 |

## 지금 상태와 필요한 것

- **완성**: 대화창(가이드 · 내 AI 키) · 대화 → 이슈 · 주제 순위 · 데이터 지도 · 6단계 실행 · 계획 커밋 확인 · 이중차분/단절 시계열 · 정책 지역이 적을 때의 무작위화 추론 · 과장 표현 차단 · 사이트 자동 공개(매일)
- **키 대기**: 국토부 실거래가(실제 데이터 전환) · 법제처 조례 자동 수집(`LAW_OC`) · 순위의 검색 관심도(`NAVER_CLIENT_ID/SECRET`, 선택). 모두 레포 Settings → Secrets에만 넣습니다.
- **결정 필요**: 키 없는 사람도 AI 대화를 쓰게 할지(사용량 제한이 있는 작은 중계 서버와 비용 부담 주체가 필요)
- **완성**: 대화창(가이드 · 내 AI 키) · 대화 → 이슈 · 주제 순위 · 데이터 지도 · 법령 온톨로지(7개 주제 3,500여 건, 매주 변경 알림) · 6단계 실행 · 계획 커밋 확인 · 이중차분/단절 시계열 · 정책 지역이 적을 때의 무작위화 추론 · 과장 표현 차단 · 사이트 자동 공개(매일)
- **키 대기**: 국토부 실거래가(실제 데이터 전환) · 법제처 매일 갱신(`LAW_OC`) · 순위의 검색 관심도(`NAVER_CLIENT_ID/SECRET`, 선택). 모두 레포 Settings → Secrets에만 넣습니다.
- **결정 필요**: 키 없는 사람의 AI 대화 (권장: 구성원은 이슈에서 `@claude`로 답 받기, 공개 방문자용 중계 서버는 필요할 때만)
- **다음**: 시차 도입 이중차분(4주차) · 합성통제(5주차) · 공공데이터포털 검색을 공식 API로 전환 · 검색량으로 "미리 반응했나" 점검

## 관련 프로젝트
Expand All @@ -95,6 +107,7 @@ API 키 없이 돌아갑니다. 실제 데이터를 받으려면 `.env.example`
| 프로젝트 | 무엇을 | 우리와의 관계 |
|---|---|---|
| [CAIS (causal-agent)](https://github.com/causalNLP/causal-agent), [Causal-Copilot](https://github.com/Lancelot39/Causal-Copilot) | LLM 인과 분석 에이전트 (MIT) | 범용 도구. 우리는 한국 공공데이터 · 정책 시작일 · 사전 등록에 집중 |
| [korean-law-mcp](https://github.com/chrisryugj/korean-law-mcp) | 법제처 API를 AI 도구(MCP)로 묶은 서버 (MIT) | 법령 조회가 겹침. Claude로 법령을 탐색할 때 함께 쓰면 좋음. 우리는 재현용 스냅샷·변경 감지·효과 추정 연결에 집중 |
| [PublicDataReader](https://github.com/WooilJeong/PublicDataReader), [kpubdata](https://github.com/yeongseon/kpubdata), [data-go-mcp-servers](https://github.com/Koomook/data-go-mcp-servers) | 공공데이터 수집 라이브러리 · MCP 서버 (MIT · Apache-2.0) | 수집 층을 보완. 필요하면 가져다 씀 |
| [PolicyEngine](https://github.com/PolicyEngine/policyengine-core), [OpenFisca](https://github.com/openfisca/openfisca-core) | 세금·복지 제도 사전 시뮬레이션 (AGPL-3.0) | 목적이 다름. AGPL이라 코드를 가져오지 않음 |
| 국회예산정책처 · 기획재정부 재정사업 평가 | 공식 평가 | 우리 결과는 공식 평가가 아니며 그렇게 보이지 않게 표시 |
Expand All @@ -103,6 +116,7 @@ API 키 없이 돌아갑니다. 실제 데이터를 받으려면 `.env.example`

코드는 [MIT](LICENSE)입니다. GPL·AGPL 패키지는 필수 의존성으로 넣지 않고 CI가 확인합니다(`scripts/check_licenses.py`).
데이터는 출처마다 이용 조건이 다르며 데이터 지도와 각 케이스의 `plan.yaml`에 적습니다. 원자료와 가공 데이터 파일은 레포에 올리지 않고 `fetch.py`로 각자 받습니다.
법령 목록(`catalog/snapshots/legal_*.csv`)은 이름·날짜 같은 메타데이터만 담으며, 출처는 법제처 국가법령정보센터입니다. 법률 자문이 아닙니다.

---

Expand Down
2 changes: 1 addition & 1 deletion cases/_example_night_clinic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
## 실행
```bash
python cases/_example_night_clinic/fetch.py # data/panel.csv (+ panel.source.json)
python cases/_example_night_clinic/estimate.py # figures/*.png, report.md, results.json
python cases/_example_night_clinic/estimate.py # 이 예시만의 옛 방식. 새 케이스는 make flow 하나로 실행합니다
```

## 파일
Expand Down
Loading
Loading