S-CANVAS (Saman Corp.) — DXF + DEM + AI 기반 3D 조감도 생성 엔진. ~24k LOC Python (scanvas_maker.py 7072 LOC GUI + 구조물 파서/빌더 다수). 이 커밋은 7-iter cleanup이 적용된 상태로 import: - F821 8 + B023 6: 비동기 lambda + except/loop 변수 캡처 NameError (Py3.13에서 reproduce 확인된 진짜 버그) - RUF012 4 + RUF013 1: ClassVar / implicit Optional 명시화 - F811/B905/B904/F401/F841/W293/F541/UP/SIM/RUF/PLR 700+ cleanup/modernization 신규 파일: - ruff.toml: target=py313, Korean unicode/저자 스타일/도메인 복잡도 무력화 - requirements-py313.txt: pyproj>=3.7, scipy>=1.14, numpy>=2.0.2 (Py3.13 wheel) - .gitignore: gcp-key.json, 캐시, 백업, 생성 이미지 제외 검증: ruff 0 errors, py_compile 0 errors, import 33/33 OK on Py3.13.13. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
139 lines
5.5 KiB
Bash
139 lines
5.5 KiB
Bash
#!/bin/bash
|
|
# 4-pane tmux layout for AI agents
|
|
# ┌─────────────────────────┬─────────────────────────┐
|
|
# │ TL: 오케 + 메인구현 │ TR: 대시보드 │
|
|
# │ Claude Code │ │
|
|
# ├─────────────────────────┼─────────────────────────┤
|
|
# │ BL: 플래너 │ BR: 디자이너+검수자 │
|
|
# │ Codex (Plus) │ Claude Code │
|
|
# └─────────────────────────┴─────────────────────────┘
|
|
#
|
|
# 모든 AI 페인은 ~/work/agents/ 워크스페이스에서 시작.
|
|
# claude는 cwd의 CLAUDE.md를 자동 로드 → TL/BR은 매 turn 컨텍스트 자동.
|
|
# BL(codex)는 자동 로드 X → dispatch.sh의 self-contained 헤더로 보완.
|
|
|
|
SESSION=agents
|
|
WORKSPACE=$HOME/work/agents
|
|
|
|
mkdir -p "$WORKSPACE/outputs"
|
|
|
|
# 부트스트랩 마커 정리 (디버깅용)
|
|
rm -f "$WORKSPACE/outputs/.bootstrap_done" 2>/dev/null
|
|
|
|
# Project Root는 매 작업마다 TL이 사용자에게 묻고 TASK.md에 갱신함.
|
|
# (한 세션에서 여러 프로젝트를 번갈아 다룰 수 있으므로 시작 시 인자로 못 박지 않음)
|
|
|
|
# 항상 리셋: 기존 세션이 있으면 죽이고 새로 만든다
|
|
tmux kill-session -t "$SESSION" 2>/dev/null
|
|
|
|
# 1) 새 세션 - 첫 페인 ID 캡처 (좌상단)
|
|
TL=$(tmux new-session -d -s "$SESSION" -n main -c "$WORKSPACE" -P -F '#{pane_id}')
|
|
|
|
# 2) TL을 좌우 분할 → 우측이 TR
|
|
TR=$(tmux split-window -h -t "$TL" -c "$WORKSPACE" -P -F '#{pane_id}')
|
|
|
|
# 3) TL을 위아래 분할 → 아래가 BL
|
|
BL=$(tmux split-window -v -t "$TL" -c "$WORKSPACE" -P -F '#{pane_id}')
|
|
|
|
# 4) TR을 위아래 분할 → 아래가 BR
|
|
BR=$(tmux split-window -v -t "$TR" -c "$WORKSPACE" -P -F '#{pane_id}')
|
|
|
|
# 5) 진단: 실제 페인 위치를 /tmp/agents-layout.log 에 기록
|
|
{
|
|
echo "=== Pane Layout (실제 위치) ==="
|
|
tmux list-panes -t "$SESSION:main" \
|
|
-F 'pane=#{pane_id} pos=(left:#{pane_left}, top:#{pane_top}) size=#{pane_width}x#{pane_height} cwd=#{pane_current_path}'
|
|
echo "지정한 ID: TL=$TL TR=$TR BL=$BL BR=$BR"
|
|
echo "==============================="
|
|
} > /tmp/agents-layout.log
|
|
|
|
# 6) 각 페인에 명령 전송
|
|
# TL: 오케 + 메인구현 (Claude)
|
|
# TR: 라이브 대시보드 (Python rich)
|
|
# BL: 플래너 (Codex)
|
|
# BR: 디자이너+검수자 (Claude)
|
|
tmux send-keys -t "$TL" "claude" C-m
|
|
tmux send-keys -t "$TR" "python3 $WORKSPACE/dashboard.py" C-m
|
|
tmux send-keys -t "$BL" "codex" C-m
|
|
tmux send-keys -t "$BR" "claude" C-m
|
|
|
|
# 7) 시작 포커스는 좌상단 (오케)
|
|
tmux select-pane -t "$TL"
|
|
|
|
# 8) 백그라운드 부트스트랩
|
|
# claude/codex가 ready 되도록 12초 대기 후 페인별 역할 프롬프트 주입.
|
|
# multiline 메시지는 dispatch.sh와 동일한 방식 (-l literal paste + 3 Enter).
|
|
(
|
|
sleep 12
|
|
|
|
TODAY=$(date +'%Y-%m-%d %H:%M')
|
|
|
|
LAST_LOG=$(tail -n 5 "$WORKSPACE/outputs/iterations.log" 2>/dev/null)
|
|
[ -z "$LAST_LOG" ] && LAST_LOG="(없음 — 새 워크스페이스)"
|
|
|
|
LAST_TASK_HEAD=$(awk 'NR<=12' "$WORKSPACE/TASK.md" 2>/dev/null)
|
|
[ -z "$LAST_TASK_HEAD" ] && LAST_TASK_HEAD="(없음)"
|
|
|
|
TL_PROMPT="새 agents 세션 시작 ($TODAY).
|
|
|
|
너는 TL = 오케스트레이터 + 메인 구현자 + GAN 루프 드라이버.
|
|
|
|
[즉시 실행]
|
|
1. AGENTS.md, DESIGN.md, TASK.md, outputs/iterations.log 읽고 상태 파악.
|
|
2. iterations.log 마지막 줄 mtime이 24시간 이내면 \"이전 작업 이어가는 세션\"일 가능성 높음.
|
|
사용자 첫 메시지 받으면:
|
|
- 새 작업 같음 → Project Root 묻기 → TASK.md 갱신 → plan→design→review 흐름.
|
|
- 이어가는 거 같음 → \"어제 <TASK 제목> iter=N (마지막 점수 NN)에서 끊겼는데 이어갈까?\" 명시적 확인.
|
|
추측 금지.
|
|
3. dispatch.sh 호출 시 self-contained 헤더가 자동 prepend됨 — 본문엔 작업 내용만.
|
|
|
|
[직전 iterations.log (tail -5)]
|
|
$LAST_LOG
|
|
|
|
[직전 TASK.md 헤더 12줄]
|
|
$LAST_TASK_HEAD
|
|
|
|
사용자 메시지 받을 때까지 대기."
|
|
|
|
BL_PROMPT="새 agents 세션 시작 ($TODAY).
|
|
너는 BL = 플래너 + 보조 (Codex Plus). dispatch.sh planner 메시지 오면 발동.
|
|
매 메시지에 [ROLE: planner | iter=N | project=...] 헤더 + 필독 파일 목록 자동 포함됨.
|
|
헤더 따라 ~/work/agents/AGENTS.md, TASK.md 읽고 outputs/plan.md 작성.
|
|
요청 없을 때는 대기."
|
|
|
|
BR_PROMPT="새 agents 세션 시작 ($TODAY).
|
|
|
|
너는 BR = 디자이너 + 검수자 (점수 산출).
|
|
|
|
[즉시 실행]
|
|
1. AGENTS.md, DESIGN.md, TASK.md, outputs/iterations.log 읽기.
|
|
2. iter ≥ 1이면 outputs/review.md, outputs/design.md도 읽어서 직전 비평/디자인 맥락 파악.
|
|
3. dispatch.sh로 메시지 오면 헤더의 [ROLE: designer] 또는 [ROLE: reviewer]에 따라 모드 전환.
|
|
|
|
[직전 iterations.log (tail -5)]
|
|
$LAST_LOG
|
|
|
|
요청 올 때까지 대기."
|
|
|
|
send_bootstrap() {
|
|
local pane="$1"
|
|
local msg="$2"
|
|
tmux send-keys -t "$pane" -l "$msg"
|
|
sleep 1.2
|
|
tmux send-keys -t "$pane" Enter
|
|
sleep 0.6
|
|
tmux send-keys -t "$pane" Enter
|
|
sleep 0.6
|
|
tmux send-keys -t "$pane" Enter
|
|
}
|
|
|
|
send_bootstrap "$TL" "$TL_PROMPT"
|
|
send_bootstrap "$BL" "$BL_PROMPT"
|
|
send_bootstrap "$BR" "$BR_PROMPT"
|
|
|
|
# 부트스트랩 완료 마커 (디버깅용)
|
|
date +%s > "$WORKSPACE/outputs/.bootstrap_done"
|
|
) &
|
|
|
|
exec tmux attach -t "$SESSION"
|