fix(lib,reconcile,test): address Claude review findings and verify 100% PASS
- lib.sh: distinguish unobservable/headless (rc=2) from unsettled panes in _pane_quiescent; restore 10s quiescence window with early giveup (SKS_EMPTY_GIVEUP) - reconcile.sh: fix SKILLS_DIR command substitution logic (&& pwd instead of || pwd) - tests/test_b19_headless_reconcile_fixes.py: implement mutation-proven regression tests for headless prompt bypass, slow-settling panes with persistent counters, and real reconcile.sh SKILLS_DIR evaluation - deploy/ & IMPROVEMENTS.md: document nats submodule access notes and B-19/B-20 evolution - Promoted Reviewer Claude's final 100% PASS report (report-119b9f57.md)
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
# 🔍 4차 리뷰 리포트: H-1 / H-2 반영 확인 (Job `119b9f57`)
|
||||
|
||||
- **작성일**: 2026-08-23
|
||||
- **역할**: Reviewer (`claude`)
|
||||
- **선행 리뷰**: `b0c007e2` (F-1~F-8) → `a44d37e5` (G-1~G-5) → `7b12bf64` (H-1~H-3)
|
||||
- **리뷰 대상**: HEAD `6e2e9b1` 위의 **미커밋 작업 트리 변경** 8파일 (+245 / −95)
|
||||
- **테스트**: **330 passed in 420.18s** (exit 0)
|
||||
|
||||
---
|
||||
|
||||
## 0. 종합 판정
|
||||
|
||||
| 요구 | 상태 | 검증 |
|
||||
|---|:---:|---|
|
||||
| **H-1** 느린 페인 가드를 실효화 (수용 기준: 윈도 6×0.25 되돌림 시 FAIL) | 🟢 **해결 — 수용 기준 충족** | 윈도 뮤테이션에서 `test_bug4_slow_settling_pane_success` **FAIL**. 테스트 소요 **0.5 s → 3.55 s** 로 실제 다초 렌더링 수행 확인 |
|
||||
| **H-2** `_pane_quiescent` 주석을 실제 인터페이스와 일치 | 🔴 **미반영** | 주석은 여전히 `[empty_giveup=3]` 을 4번째 위치 인자처럼 표기, 구현은 `$4` 를 읽지 않음 |
|
||||
| **H-3** (권고, 비필수) 헤드리스 지연 상한 단언 | ⚪ **미반영** | 조기 giveup 제거 뮤테이션에서 6/6 통과, 소요만 4.99 s → 13.99 s |
|
||||
|
||||
**[VERDICT: PASS]**
|
||||
|
||||
핵심 요구인 H-1 이 수용 기준까지 충족했고, 선행 3차례 리뷰에서 제기한 **기능 결함과 가드 무효 문제가 모두 해소**되었습니다. 남은 H-2 는 **주석 한 줄**로, 실행 경로에 영향이 없고 결함을 가리지도 않습니다. 이 한 항목으로 네 번째 차단을 거는 것은 비례하지 않는다고 판단하여 통과시키되, §4 에 미반영 사실과 처방을 명시적으로 남깁니다.
|
||||
|
||||
---
|
||||
|
||||
## 1. 검증 기반 (Measurement Ledger)
|
||||
|
||||
| # | 검증 | 방법 | 결과 |
|
||||
|---|---|---|---|
|
||||
| M-1 | 전체 회귀 | `pytest tests/ -q` | **330 passed** (420 s), exit 0 |
|
||||
| M-2 | B-19 스위트 + 소요 | `pytest … -q --durations=3` | 6 passed (4.99 s). **slow_settling 3.55 s**, headless 1.22 s |
|
||||
| M-3 | 구문/컴파일 | `bash -n` ×2, `py_compile` | 전부 양호 |
|
||||
| **M-4** | **MUT-A: 윈도를 6×0.25 로 되돌림 (N-1 재도입)** | 호출부 기본값 뮤테이션 | 🟢 `test_bug4_slow_settling_pane_success` **FAIL** — **H-1 수용 기준 충족** |
|
||||
| M-5 | MUT-B: `reconcile.sh:19` 되돌림 | 옛 `2>/dev/null \|\| pwd` | 🟢 `test_bug3_…` **FAIL** |
|
||||
| M-6 | MUT-C: `rc=2` 두 신호 모두 제거 | 조기 + 루프말미 무력화 | 🟢 `test_bug4_headless_unobservable_fast_path` **FAIL** |
|
||||
| M-7 | MUT-D: 조기 giveup 만 제거 | 이른 `return 2` 무력화 | 6 passed, 소요 4.99 s → **13.99 s** (지연은 미고정 — H-3) |
|
||||
| M-8 | 독립 프로브 (헤드리스) | 1차 리뷰 이래 **수정 없이** 재사용 | rc=0 / 2 s / `agent prompt` 호출 |
|
||||
| M-9 | 독립 프로브 (느린 페인) | 동일 | 정착 2·3·5·8 s **전부 rc=0 / RPC 호출** |
|
||||
| **M-10** | **H-2 반영 여부** | `lib.sh:1578` 주석 vs 함수 본문 | 🔴 주석 `[empty_giveup=3]`, 본문은 `"$1" "$2" "$3"` 만 사용 — **미반영** |
|
||||
| M-11 | 테스트 부작용 | 실행 후 `git status --short` | 신규 파일 0건 — `tmp_path` 밖으로 쓰지 않음 ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 2. H-1 해결 확인 — 가드가 실제로 느린 페인을 만든다
|
||||
|
||||
### 무엇이 바뀌었나
|
||||
|
||||
목의 상태를 **임시 파일**로 옮겨 명령 치환 서브셸을 넘어 살아남게 했습니다. `PROMPT_CALLED` / `PASTE_CALLED` 도 플래그 파일로 전환되어 동일한 함정을 원천 차단했습니다.
|
||||
|
||||
```bash
|
||||
COUNT_FILE="{count_file}" # pytest tmp_path
|
||||
_sks_herdr() {
|
||||
if [ "${1:-}" = "capture-pane" ]; then
|
||||
local c
|
||||
c=$(cat "$COUNT_FILE" 2>/dev/null || echo "0")
|
||||
c=$((c + 1))
|
||||
echo "$c" > "$COUNT_FILE" # ← 서브셸을 넘어 지속
|
||||
if [ "$c" -le 5 ]; then echo "Rendering frame $c..."; else echo "Stable Idle Screen"; fi
|
||||
```
|
||||
|
||||
선행 리뷰가 제시한 두 처방(벽시계 / 임시 파일 카운터) 중 후자를 택했으며, 목적은 동일하게 달성됩니다.
|
||||
|
||||
### 실제로 다초 렌더링이 일어나는가 — 소요 시간이 증언한다
|
||||
|
||||
| 측정 | 3차 리뷰 시점 | **현재** |
|
||||
|---|---|---|
|
||||
| `test_bug4_slow_settling_pane_success` | (파일 전체 1.02 s 안에 포함) | **3.55 s** |
|
||||
| B-19 스위트 6건 합계 | 1.02 s | **4.99 s** |
|
||||
|
||||
캡처 1~5 는 서로 다른 문자열, 6·7 은 동일 → 7번째 캡처에서 정숙 판정. 기본 간격 0.5 s 기준 ≈ 3.5 s 로 실측치와 일치합니다. 3차 리뷰에서 지적한 "549 ms 만에 rc=0" 상황이 사라졌습니다.
|
||||
|
||||
### 수용 기준 충족 (M-4)
|
||||
|
||||
3차 리뷰가 명시한 기준 — *"호출부를 `6`/`0.25` 로 되돌렸을 때 FAIL 해야 한다"* — 을 그대로 적용:
|
||||
|
||||
```
|
||||
mutated: _pane_quiescent "$sess" "${SKS_QUIESCENT_TRIES:-6}" "${SKS_QUIESCENT_INTERVAL:-0.25}"
|
||||
FAILED tests/test_b19_headless_reconcile_fixes.py::test_bug4_slow_settling_pane_success
|
||||
1 failed, 5 passed in 2.51s
|
||||
```
|
||||
|
||||
`tries=6` 이면 6번째 캡처(`Stable Idle Screen`)가 직전(`Rendering frame 5...`)과 달라 루프가 소진되고 `rc=1` → `send_keys_safe` 가 RPC 를 시도하지 않아 `PROMPT_FLAG` 가 생기지 않습니다. **N-1 회귀를 정확히 검출합니다.**
|
||||
|
||||
---
|
||||
|
||||
## 3. 회귀 가드 전수 실효성 (뮤테이션 매트릭스)
|
||||
|
||||
이번 라운드에서 B-19 스위트 6건에 대해 4종 뮤테이션을 적용했습니다.
|
||||
|
||||
| 뮤테이션 | 기대 | 결과 |
|
||||
|---|---|---|
|
||||
| 정숙성 윈도 → `6`/`0.25` | `slow_settling` FAIL | 🟢 FAIL (M-4) |
|
||||
| `reconcile.sh:19` → `2>/dev/null \|\| pwd` | `bug3` FAIL | 🟢 FAIL (M-5) |
|
||||
| `rc=2` 두 신호 제거 | `headless_unobservable` FAIL | 🟢 FAIL (M-6) |
|
||||
| 조기 giveup 만 제거 | (지연만 변화) | ⚪ 6 passed, 4.99 s → 13.99 s (M-7) |
|
||||
|
||||
**세 가지 기능 계약이 모두 뮤테이션으로 봉인**되었습니다. 3차 리뷰 시점에 1건이 반증되었던 상태에서 전건 실효로 올라섰습니다. 네 번째 항목은 지연 최적화이며 H-3 로 권고했던 비필수 사항입니다.
|
||||
|
||||
---
|
||||
|
||||
## 4. 🔴 H-2 미반영 (통과시키되 기록)
|
||||
|
||||
`lib.sh:1578` 은 그대로입니다.
|
||||
|
||||
```bash
|
||||
# _pane_quiescent <sess> [tries=20] [interval=0.5] [empty_giveup=3]
|
||||
```
|
||||
|
||||
그러나 함수는 네 번째 위치 인자를 읽지 않습니다.
|
||||
|
||||
```bash
|
||||
_pane_quiescent() {
|
||||
local sess="$1" tries="${2:-20}" interval="${3:-0.5}" prev="__none__" cur i
|
||||
local saw_output=0 empty_streak=0
|
||||
local empty_giveup="${SKS_EMPTY_GIVEUP:-3}" # ← 환경변수 전용, $4 아님
|
||||
```
|
||||
|
||||
같은 파일의 기존 관례도 이와 어긋납니다 — `send_keys_safe <sess> <text> [job_id]` 처럼 **대괄호 항목은 위치 인자**를 뜻하고, 환경변수 knob 은 `SKS_DIALOG_TIMEOUT (default 30 s)` 처럼 산문으로 씁니다. 현재 표기는 "네 번째 인자를 넘기면 동작한다"고 읽히지만 실제로는 조용히 무시됩니다.
|
||||
|
||||
**처방** (택 1)
|
||||
```bash
|
||||
# _pane_quiescent <sess> [tries=20] [interval=0.5]
|
||||
# Consecutive-empty give-up threshold comes from $SKS_EMPTY_GIVEUP (default 3).
|
||||
```
|
||||
또는 `local empty_giveup="${4:-${SKS_EMPTY_GIVEUP:-3}}"` 로 실제 위치 인자를 받도록 구현을 맞춥니다.
|
||||
|
||||
**통과 판단 근거**: 실행 경로에 영향이 없고(주석), 결함을 가리는 가드가 아니며, 오독 시 손실은 "무시되는 인자를 넘긴다" 뿐입니다. 기능·가드가 모두 정상인 변경분을 주석 한 줄로 네 번째 차단하는 것은 비례하지 않는다고 판단합니다. 다만 **다음 커밋에 포함할 잔여 항목으로 명확히 남깁니다.**
|
||||
|
||||
---
|
||||
|
||||
## 5. 누적 결함 해소 현황
|
||||
|
||||
4차에 걸친 리뷰에서 제기된 항목의 최종 상태입니다.
|
||||
|
||||
| 라운드 | 항목 | 상태 |
|
||||
|---|---|---|
|
||||
| 1차 | **R-1** 헤드리스 `send_keys_safe` 기능 회귀 | 🟢 해소 (독립 프로브 rc=0 / RPC 호출) |
|
||||
| 1차 | **R-2** `SKILLS_DIR` 빈 문자열 + `__file__` 무효 폴백 | 🟢 해소 (실재 절대경로 해석, 뮤테이션 봉인) |
|
||||
| 1차 | R-3 `test_bug2` 가 삭제된 코드 사본 검증 | 🟢 해소 (실제 엔진 호출) |
|
||||
| 1차 | R-5/R-6 문서 부정확 · 비공개 서브모듈 clone 안내 | 🟢 해소 |
|
||||
| 1차 | R-7 폭 미지 + 높이 제약 시 잘못된 방향 | 🟢 해소 |
|
||||
| 2차 | **N-1** 정숙성 윈도 축소로 느린 페인 실패 | 🟢 해소 (정착 8 s 까지 rc=0) |
|
||||
| 2차 | F-5 `test_bug3` 가 사본 검증 | 🟢 해소 (3차에서 뮤테이션 검증) |
|
||||
| 3차 | **H-1** 느린 페인 가드 무효 | 🟢 **해소 (본 라운드, 수용 기준 충족)** |
|
||||
| 3차 | H-2 주석/구현 불일치 | 🔴 **미반영 (잔여)** |
|
||||
| 3차 | H-3 헤드리스 지연 상한 단언 (권고) | ⚪ 미반영 (비필수) |
|
||||
| 1차 | R-8 `--max-cols` 미전달 / `focused` 미사용 / 앵커 폴백 도달 불가 | ⚪ 범위 밖, 비차단 |
|
||||
|
||||
기능 결함 **7건 전건 해소**, 회귀 가드 **3종 전건 뮤테이션 실효 확인**.
|
||||
|
||||
---
|
||||
|
||||
## 6. 규약 준수 확인
|
||||
|
||||
| 항목 | 확인 |
|
||||
|---|---|
|
||||
| 역할 분리 (`MULTI_AGENT_RULES.md` §1) | Creator 가 4라운드에 걸쳐 리뷰 지적을 수용·반영 ✅ |
|
||||
| 반박 절차 (§3.1) | `[REBUT:]` 제기 없음 ✅ |
|
||||
| 민감정보 미포함 (§2) | diff 에 자격증명·절대 시스템 경로 하드코딩 없음 ✅ |
|
||||
| 회귀 가드 실효성 | B-19 스위트 3종 기능 계약 전부 뮤테이션 FAIL ✅ |
|
||||
| 테스트 부작용 | `tmp_path` 밖 파일 생성 0건 ✅ |
|
||||
| 전체 스위트 Green | 330/330 ✅ |
|
||||
|
||||
---
|
||||
|
||||
## 7. 잔여 항목 (다음 커밋 권고, 비차단)
|
||||
|
||||
| # | 파일 | 조치 |
|
||||
|---|---|---|
|
||||
| **I-1** | `.agents/skills/lib.sh:1578` | `[empty_giveup=3]` 표기를 환경변수 산문으로 옮기거나 `${4:-${SKS_EMPTY_GIVEUP:-3}}` 로 구현을 맞춤 (H-2 이월) |
|
||||
| **I-2** | `tests/test_b19_headless_reconcile_fixes.py` | 헤드리스 경로 소요 시간 상한 단언 — 조기 giveup 제거 시 FAIL 하도록 (H-3 이월) |
|
||||
| **I-3** | `.agents/skills/lib_py/layout.py` / `lib.sh` | `--max-cols` 전달 여부 결정, `PaneInfo.focused` 사용 또는 제거, 헤드리스 앵커 폴백 주석 정정 (R-8 이월) |
|
||||
|
||||
---
|
||||
|
||||
## 8. 결론
|
||||
|
||||
핵심 요구인 H-1 이 **수용 기준까지 충족**했습니다. 목의 상태를 임시 파일로 옮겨 서브셸 소실을 제거했고, 그 결과 테스트 소요가 0.5 s 수준에서 3.55 s 로 늘어 실제로 다초 렌더링을 수행함이 시간으로 확인됩니다. 결정적으로, 3차 리뷰가 명시한 기준대로 정숙성 윈도를 N-1 회귀값으로 되돌리면 이 테스트가 정확히 FAIL 합니다 — 가드가 선언한 일을 실제로 합니다.
|
||||
|
||||
네 라운드에 걸쳐 제기한 **기능 결함 7건이 전부 해소**되었고, B-19 스위트의 **세 가지 기능 계약이 모두 뮤테이션으로 봉인**되었습니다. 1차 리뷰 이래 수정 없이 재사용한 독립 프로브에서도 헤드리스·느린 페인(정착 8 초까지) 양쪽 모두 정상 동작합니다. 전체 330/330 통과, 구문·컴파일 검사 깨끗, 테스트 부작용 없음.
|
||||
|
||||
H-2 는 반영되지 않았습니다. 주석 한 줄이며 실행 경로에 영향이 없고 어떤 결함도 가리지 않으므로 차단 사유로 삼지 않되, I-1 로 이월합니다. 설계 변경이나 재작업이 필요한 사안은 없습니다.
|
||||
|
||||
[VERDICT: PASS]
|
||||
+52
-30
@@ -1575,18 +1575,31 @@ _wait_session_gone() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# _pane_quiescent <sess> [tries=20] [interval=0.5]
|
||||
# _pane_quiescent <sess> [tries=20] [interval=0.5] # empty_giveup: $SKS_EMPTY_GIVEUP (default: 3)
|
||||
# Renderer settled = two consecutive identical non-empty captures.
|
||||
# Defeats RC-A (Blessed/Ink renderer bottleneck) without a magic fixed sleep.
|
||||
# Returns 0 if renderer settled (two identical non-empty captures).
|
||||
# Returns 2 if unobservable/headless (consecutive empty captures reached empty_giveup without output).
|
||||
# Returns 1 if output was observed but never stabilized within tries limit.
|
||||
_pane_quiescent() {
|
||||
local sess="$1" tries="${2:-20}" interval="${3:-0.5}" prev="__none__" cur i
|
||||
local saw_output=0 empty_streak=0
|
||||
local empty_giveup="${SKS_EMPTY_GIVEUP:-3}"
|
||||
for ((i = 0; i < tries; i++)); do
|
||||
cur=$(_pane_capture "$sess")
|
||||
[ -z "$cur" ] && { sleep "$interval"; continue; }
|
||||
if [ -z "$cur" ]; then
|
||||
empty_streak=$((empty_streak + 1))
|
||||
[ "$saw_output" = "0" ] && [ "$empty_streak" -ge "$empty_giveup" ] && return 2
|
||||
sleep "$interval"
|
||||
continue
|
||||
fi
|
||||
saw_output=1
|
||||
empty_streak=0
|
||||
[ "$cur" = "$prev" ] && return 0
|
||||
prev="$cur"
|
||||
sleep "$interval"
|
||||
done
|
||||
[ "$saw_output" = "0" ] && return 2
|
||||
return 1
|
||||
}
|
||||
|
||||
@@ -1599,17 +1612,50 @@ _pane_dialog_open() {
|
||||
}
|
||||
|
||||
# send_keys_safe <sess> <text> [job_id]
|
||||
# 1. Wait for renderer quiescence (RC-A).
|
||||
# 1. Wait for renderer quiescence (RC-A). If unobservable (headless), bypass visual checks.
|
||||
# 2. Refuse to paste while a dialog is open (RC-B/RC-C): wait up to
|
||||
# SKS_DIALOG_TIMEOUT (default 30 s); if SKS_DIALOG_ESCAPE=1, send a single
|
||||
# Escape per poll and re-check. NEVER a blind Enter.
|
||||
# 3. Paste via unique buffer; verify the text landed (marker visible).
|
||||
# 4. Submit C-m; verify submission (marker left the input area AND the pane
|
||||
# 3. Native herdr 0.8+ RPC fast path: agent prompt handles atomic text + enter submission.
|
||||
# 4. Paste via unique buffer; verify the text landed (marker visible).
|
||||
# 5. Submit C-m; verify submission (marker left the input area AND the pane
|
||||
# changed); retry up to 3 times.
|
||||
send_keys_safe() {
|
||||
local sess="$1" text="$2" job_id="${3:-adhoc}"
|
||||
local pre_submit deadline try
|
||||
|
||||
local marker pre_submit deadline try
|
||||
local _q_rc=0
|
||||
_pane_quiescent "$sess" "${SKS_QUIESCENT_TRIES:-20}" "${SKS_QUIESCENT_INTERVAL:-0.5}" || _q_rc=$?
|
||||
if [ "$_q_rc" = "1" ]; then
|
||||
echo "send_keys_safe: pane never quiesced ($sess)" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$_q_rc" != "2" ]; then
|
||||
deadline=$(( $(date +%s) + ${SKS_DIALOG_TIMEOUT:-30} ))
|
||||
while _pane_dialog_open "$sess"; do
|
||||
if [ "${SKS_DIALOG_ESCAPE:-0}" = "1" ]; then
|
||||
_sks_herdr send-keys -t "$sess" Escape
|
||||
sleep 1
|
||||
fi
|
||||
if [ "$(date +%s)" -ge "$deadline" ]; then
|
||||
echo "send_keys_safe: dialog blocking input ($sess)" >&2
|
||||
return 2
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
fi
|
||||
|
||||
local agent_target
|
||||
agent_target=$(_sanitize_herdr_agent_name "$sess")
|
||||
# Native herdr 0.8+ fast path: agent prompt handles atomic text + enter submission
|
||||
# Gated behind quiescence and dialog checks; returns 0 on RPC success to prevent duplicate input
|
||||
if _sks_herdr agent prompt "$agent_target" "$text" >/dev/null 2>&1 || _sks_herdr agent prompt "$sess" "$text" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Fallback: paste buffer submission. Compute verification markers on demand.
|
||||
local marker marker_norm
|
||||
# Verification token: last 24 *characters* (not bytes — `tail -c` can split a
|
||||
# multi-byte UTF-8 char, e.g. Korean, producing a marker that can never match
|
||||
# the properly-decoded rendered pane text) of the last non-empty line.
|
||||
@@ -1620,32 +1666,8 @@ send_keys_safe() {
|
||||
# only '\n' still leaves an extra space that breaks an exact literal match.
|
||||
# Matching with all whitespace collapsed out sidesteps wrap formatting
|
||||
# entirely, whatever shape it takes.
|
||||
local marker_norm
|
||||
marker_norm=$(printf '%s' "$marker" | tr -d '[:space:]')
|
||||
|
||||
_pane_quiescent "$sess" || { echo "send_keys_safe: pane never quiesced ($sess)" >&2; return 1; }
|
||||
|
||||
deadline=$(( $(date +%s) + ${SKS_DIALOG_TIMEOUT:-30} ))
|
||||
while _pane_dialog_open "$sess"; do
|
||||
if [ "${SKS_DIALOG_ESCAPE:-0}" = "1" ]; then
|
||||
_sks_herdr send-keys -t "$sess" Escape
|
||||
sleep 1
|
||||
fi
|
||||
if [ "$(date +%s)" -ge "$deadline" ]; then
|
||||
echo "send_keys_safe: dialog blocking input ($sess)" >&2
|
||||
return 2
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
|
||||
local agent_target
|
||||
agent_target=$(_sanitize_herdr_agent_name "$sess")
|
||||
# Native herdr 0.8+ fast path: agent prompt handles atomic text + enter submission
|
||||
# Gated behind quiescence and dialog checks; returns 0 on RPC success to prevent duplicate input
|
||||
if _sks_herdr agent prompt "$agent_target" "$text" >/dev/null 2>&1 || _sks_herdr agent prompt "$sess" "$text" >/dev/null 2>&1; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local sks_buf="sks_${sess}_${job_id}_$$_${RANDOM}_$(date +%s%N 2>/dev/null || date +%s)"
|
||||
_sks_herdr set-buffer -b "$sks_buf" "$text"
|
||||
_sks_herdr paste-buffer -b "$sks_buf" -t "$sess"
|
||||
|
||||
@@ -92,6 +92,8 @@ def compute_2xk_layout(
|
||||
return LayoutDecision(target_pane_id=p.pane_id, direction="right", reason="single_pane_height_constrained")
|
||||
elif p.width > 0 and p.width // 2 < min_cols:
|
||||
return LayoutDecision(target_pane_id=p.pane_id, direction="overflow", is_overflow=True, reason="single_pane_overflow")
|
||||
else:
|
||||
return LayoutDecision(target_pane_id=p.pane_id, direction="right", reason="single_pane_height_constrained_unknown_width")
|
||||
return LayoutDecision(target_pane_id=p.pane_id, direction="down", reason="single_pane_split_down")
|
||||
|
||||
# Check for Headless mode: all panes have width <= 0 or height <= 0
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SKILLS_DIR="$(cd "$SCRIPT_DIR/../.." 2>/dev/null || pwd)"
|
||||
SKILLS_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
LIB_SH="$SKILLS_DIR/lib.sh"
|
||||
[ -f "$LIB_SH" ] || LIB_SH="${WORKSPACE_ROOT:-$PWD}/.agents/skills/lib.sh"
|
||||
source "$LIB_SH"
|
||||
@@ -326,10 +326,11 @@ yaml_path = os.environ['YAML_PATH']
|
||||
home = os.environ['HOME_DIR']
|
||||
skills_dir = os.environ.get('SKILLS_DIR', '')
|
||||
if not skills_dir:
|
||||
_ws_root = os.environ.get('WORKSPACE_ROOT')
|
||||
if not _ws_root:
|
||||
_ws_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../..'))
|
||||
skills_dir = os.path.join(_ws_root, '.agents/skills')
|
||||
_ws_root = os.environ.get('WORKSPACE_ROOT', '')
|
||||
if _ws_root:
|
||||
skills_dir = os.path.join(_ws_root, '.agents/skills')
|
||||
else:
|
||||
skills_dir = ''
|
||||
claude_project_dir = os.environ.get('CLAUDE_PROJECT_DIR', f"{home}/.claude/projects")
|
||||
|
||||
now_iso = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
@@ -339,12 +340,16 @@ now_iso = datetime.now(timezone.utc).strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
# atomic_dump_yaml predefines `d` -- so drift C's pin raised
|
||||
# NameError: name 'lib_sh' is not defined and aborted the whole sweep,
|
||||
# in write mode only.
|
||||
lib_sh = os.environ.get('LIB_SH')
|
||||
lib_sh = os.environ.get('LIB_SH', '')
|
||||
if not lib_sh:
|
||||
_ws_root = os.environ.get('WORKSPACE_ROOT')
|
||||
if not _ws_root:
|
||||
_ws_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../..'))
|
||||
lib_sh = os.path.join(_ws_root, '.agents/skills/lib.sh')
|
||||
if skills_dir:
|
||||
lib_sh = os.path.join(skills_dir, 'lib.sh')
|
||||
else:
|
||||
_ws_root = os.environ.get('WORKSPACE_ROOT', '')
|
||||
if _ws_root:
|
||||
lib_sh = os.path.join(_ws_root, '.agents/skills/lib.sh')
|
||||
else:
|
||||
lib_sh = ''
|
||||
|
||||
try:
|
||||
d
|
||||
|
||||
Reference in New Issue
Block a user