diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index cbb1ced3..07ae2ff1 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -9,7 +9,7 @@ "name": "claude-code", "source": "./plugins/claude-code", "description": "Reference implementation of the Ironclad standard — multi-agent dev harness for Claude Code.", - "version": "0.9.3", + "version": "0.9.4", "author": { "name": "qwerfunch" }, diff --git a/.claude/settings.json b/.claude/settings.json index 6ea9c5d8..66a39a9e 100644 --- a/.claude/settings.json +++ b/.claude/settings.json @@ -1,5 +1,14 @@ { "enabledPlugins": { "claude-code@cladding": true + }, + "extraKnownMarketplaces": { + "cladding": { + "source": { + "source": "directory", + "path": "." + }, + "autoUpdate": true + } } } diff --git a/.gitignore b/.gitignore index 20a1f519..6dca7bfd 100644 --- a/.gitignore +++ b/.gitignore @@ -60,8 +60,9 @@ test-results/ playwright-report/ *.snap.png -# Cladding runtime state — audit log, events log, etc. -.cladding/ +# Cladding runtime state — audit log, events log, etc. (config.yaml stays committable) +.cladding/* +!.cladding/config.yaml # A/B-extended generated React demo projects. # These are regeneratable on demand via `UPDATE_AB_REPORTS=1 npx vitest run` diff --git a/.refactor/PLAN.md b/.refactor/PLAN.md new file mode 100644 index 00000000..5aeb377d --- /dev/null +++ b/.refactor/PLAN.md @@ -0,0 +1,517 @@ +# cladding 0.10.0 — 작업 큐 (Codex 루프용) + +**상태:** 설계 완료 · 구현 착수 전 · `develop` @ `23ea6be`, 트리 클린. +**이 문서는 루프가 매 바퀴 읽는 문서다.** 왜 이렇게 결정했는지는 **부록 A**에 있다. 결정을 의심할 때만 부록을 열어라 — 매 바퀴 읽지 마라. + +--- + +## 0. 오리엔테이션 — 이만큼만 읽고 시작한다 + +| 순서 | 읽을 것 | 답을 얻는 질문 | +|---|---|---| +| 1 | 이 문서 §1~§7 | 루프를 어떻게 도는가 | +| 2 | `.refactor/ledger.md` | 무엇이 끝났고 다음은 무엇인가 | +| 3 | (진행 중이면) `.refactor/units/<현재항목>.yaml` | 나는 항목 중간인가, 경계인가 | + +그리고 트리 상태 세 줄: + +```bash +git status --porcelain # 비어 있어야 한다. 아니면 §5의 "중간 복구"로. +git rev-parse --abbrev-ref HEAD # develop +node bin/clad --version # 0.9.3 +``` + +**부록 B**(리팩토링 49 유닛 전체 명세)는 `RF-*` 항목을 집을 때만 연다. + +--- + +## 1. 루프 한 바퀴 + +``` +1. 원장을 읽는다 (.refactor/ledger.md). +2. 마지막 줄이 IN_PROGRESS이면 → §5 "중간 복구". 아니면 계속. +3. 다음 항목을 고른다: + depends_on이 전부 DONE이고 status가 비어 있는 항목 중, + §3 표에서 가장 위에 있는 것. (동률은 없다 — 표 순서가 결정적이다.) +4. 그 항목이 [사람] 표시면 → 무엇이 필요한지 보고하고 멈춘다. 시작하지 않는다. +5. preconditions를 실행한다. 하나라도 어긋나면 → 멈추고 보고한다. 고치지 않는다. +6. 원장에 IN_PROGRESS 한 줄을 쓰고 커밋한다. (이게 있어야 컨텍스트를 잃어도 복구된다.) +7. actions를 수행한다. +8. done_conditions를 전부 실행한다. 하나라도 기대와 다르면 → §4로. +9. 스펙 항목을 만드는 항목이면(◆ 표시) 여기서 내부 루프: + clad verdict --json 을 폴링한다. + ITERATE → next_action이 가리키는 것을 고치고 다시 폴링 + ESCALATE → 멈추고 보고한다 (동일 발견 2회 = 진전 없음. 무시하지 마라) + BLOCKED / BOOTSTRAP → 멈추고 보고한다 + 초록이면 clad done . +10. §6의 자기 점검을 돌린다. +11. 원장 줄을 DONE으로 갱신하고 커밋한다. +12. 멈춘다. (한 바퀴 = 한 항목. 다음 바퀴는 goal을 다시 부른다.) +``` + +**왜 한 바퀴에 한 항목인가** — 항목 경계가 커밋 경계이고 롤백 단위다. 여러 개를 묶으면 실패했을 때 무엇을 되돌려야 하는지 알 수 없다. + +--- + +## 2. 원장 + +**위치: `.refactor/` (커밋된다).** `.cladding/`은 `.gitignore:64`에 있어서 거기 두면 클론 시 사라지고 리뷰도 안 된다 — 루프의 기억이 커밋되지 않으면 컨텍스트를 잃는 순간 복구 근거가 없다. + +`.refactor/ledger.md` — 항목당 한 줄, 추가만 한다: + +``` +| id | status | commit | 언제 | 한 줄 결과 | +|---|---|---|---|---| +| S1 | DONE | a1b2c3d | 2026-08-10 | refs/replay/ 아래 295개 고정 | +| S2 | DONE | e4f5g6h | 2026-08-10 | M5 VERDICT: 거부 메커니즘 필요 — 6b 범위 확대 | +| S3 | IN_PROGRESS | — | 2026-08-11 | jest 파서 탐침 중 | +``` + +`.refactor/units/.yaml` — 항목을 시작할 때 쓰고 끝날 때 채운다. 다음 바퀴가 **아무것도 다시 유도하지 않도록** 하는 게 목적이다: + +```yaml +id: S3 +started: 2026-08-11 +inherits: # 직전 항목의 exit에서 복사 + head: e4f5g6h + tree_clean: true +touch_allowed: [".refactor/sim/M7.md"] # 전수. 이 밖의 diff는 범위 위반이다. +done_conditions: # 각각 명령 + 리터럴 기대 + - {cmd: "test -f .refactor/sim/M7.md", expect: "exit 0"} + - {cmd: "grep -c '^VERDICT: ' .refactor/sim/M7.md", expect: "1"} +exit: + commit: + verdict: PASS | FAIL | KILLED + residue: "일부러 안 한 것과 그 이유" +``` + +`residue`가 **완료와 중단을 가른다**(§4). + +--- + +## 3. 작업 큐 + +표기: **◆** = 스펙 항목을 만들고 `clad done`으로 끝난다 · **[사람]** = 루프가 완료할 수 없다, 승인을 받아야 한다 · **☠** = 이 항목이 기각하면 뒤따르는 항목이 큐에서 빠진다. + +| id | 항목 | 의존 | | +|---|---|---|---| +| **S1** | **리플레이 코퍼스 고정 — 마감 지남** | — | | +| S2 | M5 · `clad sign-off` 출처 검증 | — | ☠ | +| S3 | M7 · jest 공허 가드 탐침 | — | ☠ | +| S4 | 5b 백테스트 · `repairModules` 정확도 | — | ☠ | +| P1 | 훅 배선 복구 (캐시가 0.4.0에 멈춘 원인) | S1 | | +| P1P | Claude 2.1.224 표준 hook 자동발견과 충돌하는 manifest 핀 재협상 | S1 | | +| P1B | **KILLED:** root bundle을 정답으로 둔 Claude engine mirror 동기화 | S1 | | +| P1G | standalone `build:plugin`이 source에서 engine을 먼저 재생성하도록 provenance 복구 | S1 | | +| P1R | 훅 배선 복구 재개 · current checkout cache + 실제 hook 발화 | P1G | | +| P2 | `clad doctor` 훅 상태 + `HOST_CLAIM_DRIFT` 신선도 ◆ | P1R | | +| P3 | 계수기: `stop_blocked` 확장 · `stop_exit_recorded` · `done_attempted.blockers` ◆ | P1R | | +| P4 | CI 버전 고정 + `doctor` 미고정 경고 ◆ | — | | +| P5 | attestation 정책 도장 + `clad init`이 `.gitattributes` 쓰기 ◆ | — | | +| P6 | **0.9.4 릴리즈** [사람] | P2·P3·P4·P5 | | +| RF0 | 리팩토링 기준선 동결 (U-00~U-07) | P6 | | +| RF1 | 패리티 하네스 + 킬 크라이테리언 (U-10~U-17) | RF0 | ☠ | +| A1 | Stop 거부권 좁히기 ◆ | RF1, P3 | | +| A2 | 게이트 페이로드 경제 ◆ | RF1 | | +| A3 | `gateFooter` 프로파일 — **스펙 개정 먼저** ◆ | RF1 | | +| A4 | 게이트 설정을 `spec.yaml`로 ◆ | RF1 | | +| A5 | 검증 능력 공시 ◆ | RF1, S3 | | +| A6 | jest·Go·Dart 러너 도달 ◆ | A5, S3 | | +| A7 | CI `--tier=all --strict` + `blind-author`에서 `Bash` 제거 ◆ | A5 | | +| A8 | `depends_on` writer ◆ | RF1 | | +| A9 | `repairModules` ◆ | A8, S4 | | +| A12 | 활성화 문장 18개 삭제 ◆ | RF1 | | +| A13 | `POLICY_LINE` 삭제 · `feature-cycle.md` 재작성 ◆ | A12 | | +| A14 | `CONTEXT_LINE` → 밀어주는 슬라이스 (Tier-A 스펙 편집) ◆ | A13, P3 | | +| RF2 | 리팩토링 2~7단계 (U-20~U-81) | RF1 | | +| A15 | **0.10.0 릴리즈** [사람] | A1~A9, A12~A14, RF2 | | + +**항목별 상세**(preconditions / actions / done_conditions / rollback)는 `RF*`는 **부록 B**, 나머지는 **부록 A**의 해당 Phase 절에 있다. 항목을 집을 때 그 절만 연다. + +**S2 KILL 반영:** 로컬 CLI는 같은 OS 사용자·git 설정·PTY를 쓰는 호스트 에이전트와 사람을 구분할 신뢰 경계가 없다. 따라서 A10·A11은 큐에서 빠졌다. `independence_policy: require`는 CLI-only 환경에서 만족 불가하며, 기존 실증은 `docs/dogfood/e2e-role-contract-2026-07-24.md:82-94`와 `docs/refinement-backlog.md:29-30`에 남아 있다. 재개 조건은 호스트가 서명한 실제 사용자 응답이나 사용자 현존을 강제하는 하드웨어 서명처럼 CLI 프로세스 밖의 검증 가능한 출처가 생기는 것이다. + +**P1 핀 발화:** 끊긴 훅의 1차 원인은 `.claude/settings.json`이 plugin만 enable하고 marketplace source를 선언하지 않아, 삭제된 pre-0.9.0 directory source와 0.4.0 cache가 남은 것이다. source를 복구하자 Claude Code 2.1.224가 표준 `hooks/hooks.json`과 manifest의 동일 파일 선언을 중복 로드해 실패했다. `tests/scripts/hooks-config.test.ts`가 그 manifest 필드를 고정하므로 P1 안에서 바꾸지 않는다. P1P가 핀을 독립적으로 재협상한 뒤 P1R에서 실제 cache와 hook 발화를 검증한다. 근거: `.refactor/sim/P1.md`. + +**P1P 범위 발화와 P1B 기각:** manifest 중복 선언 제거 후 actual inline loader는 0.9.3을 정상 load했다. 필수 `build:plugin`이 60-byte bundle delta를 만들었지만, 추가 조사에서 root `dist/`는 gitignored이고 그 60 bytes는 현재 source에 존재하지 않았다. 따라서 root bundle을 정답으로 plugin mirror에 복사하는 P1B는 provenance가 반대라 KILL했다. P1G가 standalone `build:plugin` 앞에서 source bundle을 재생성하도록 고친 뒤 P1R에서 실제 cache와 hook 발화를 검증한다. 근거: `.refactor/sim/P1P.md`. + +### S1 — 리플레이 코퍼스 고정 (첫 항목, 마감이 지났다) + +`stop_blocked` 헤드 48개 중 **29개**, `gate_run` 헤드 247개 중 **129개**가 `develop`의 조상이 아니다(feature 브랜치 스쿼시 머지의 결과). reflog에만 존재하고 가장 오래된 이벤트는 41일 전 — git 기본 `reflogExpireUnreachable`(30일)을 이미 넘겼다. 아직 살아 있는 유일한 이유는 `gc`가 안 돌았기 때문이고, 느슨한 객체가 4,824/6,700이다. **임계에 닿는 순간 부록 A의 모든 리플레이 근거가 영구히 감사 불가능해진다.** + +```bash +python3 - <<'PY' +import json, subprocess +ev=[json.loads(l) for l in open('.cladding/events.log.jsonl')] +heads={e['payload']['head'] for e in ev + if e.get('payload',{}).get('head') and e['type'] in ('stop_blocked','gate_run')} +n=0 +for h in sorted(heads): + if subprocess.run(['git','cat-file','-e',h+'^{commit}'],capture_output=True).returncode==0: + subprocess.run(['git','update-ref',f'refs/replay/{h[:12]}',h],check=True); n+=1 +print(f'pinned {n} of {len(heads)}') +PY +``` + +**done_condition:** `git for-each-ref refs/replay/ | wc -l` 이 위 스크립트가 출력한 `pinned N` 의 N과 같을 것. +**rollback:** `git for-each-ref --format='%(refname)' refs/replay/ | xargs -n1 git update-ref -d` +커밋 이력을 바꾸지 않는다(참조만 추가). 이후 `git gc`가 돌아도 안전하다. + +### 사전 검증 4건의 완료 조건 + +이 넷은 조사이므로 산출물로 판정한다. 각각 `.refactor/sim/.md`를 쓰고, 첫 줄이 `VERDICT: PASS|KILL|INCONCLUSIVE`, 그 아래에 근거를 `file:line`으로 적는다. + +```bash +test -f .refactor/sim/M7.md && head -1 .refactor/sim/M7.md | grep -qE '^VERDICT: (PASS|KILL|INCONCLUSIVE)' +``` + +- **S1** 만 다르다 — 명령의 결과가 곧 판정이다: `git for-each-ref refs/replay/ | wc -l` 이 이벤트 로그의 고유 head 수와 같아야 한다. +- **S2 KILL** → A10의 `sign-off`가 출처를 검증할 방법이 없다는 뜻. A10·A11을 큐에서 빼고 `independence_policy: require`를 "CLI에서 만족 불가"로 문서화한다. +- **S3 KILL** → jest 갭이 없다는 뜻. A6에서 jest 부분을 뺀다. +- **S4 KILL** → `repairModules`의 정확도가 부족하다는 뜻. A9를 빼고 리팩토링에서 파일 이동을 하지 않는다는 제약이 확정된다. + +--- + +## 4. 멈춰야 할 때 + +실패는 판단이 아니라 **무엇이 어긋났는가**로 대응이 정해진다. + +| 상황 | 대응 | 재시도 | +|---|---|---| +| **범위 위반** — `git diff --name-only`가 `touch_allowed` 밖 | 즉시 되돌린다. 항목 범위 선언이 틀린 것이므로 diff를 고치지 말고 항목을 다시 계획한다 | 안 함 | +| **자기 버그** — `touch_allowed` 안의 파일을 덮는 테스트가 실패 | 제자리에서 1회 재시도 | 1회 | +| **핀 테스트 발화** — 산문·개수·바이트를 고정하는 테스트가 빨감 | **멈춘다. 그 테스트를 건드리지 마라.** 별도 항목으로 핀을 재협상하고, 그걸 먼저 끝낸 뒤 이 항목을 다시 돈다. 깨뜨린 항목 안에서 핀을 고치는 건 자기인증이다 | 안 함 | +| **패리티 델타** — 관측 계약이 바뀜 | 되돌린다. 허용 항목 추가는 별도 커밋에 이유와 함께 | 안 함 | +| **오라클 실명** — 패리티 셀프테스트가 심어둔 변경을 못 잡음 | **마지막 정상 셀프테스트 이후 전부 되돌리고 프로그램을 멈춘다.** 눈먼 오라클로 검증한 것은 미검증이다 | 안 함 | +| **주석만 바꿨는데 번들 SHA가 움직임** | 되돌린다. 안 건드렸다고 믿은 코드를 건드린 것 — 프로그램에서 가장 값진 신호다 | 안 함 | +| `clad verdict` → **ESCALATE** | 멈추고 보고한다. 동일 발견 2회는 스스로 못 고친다는 뜻이다 | 안 함 | +| **attestation만 빨감** (`STALE_ATTESTATION` 단독) | 실패 아님. strict pre-push로 재도장하고 `spec/attestation.yaml`을 코드와 같은 커밋에 넣는다 | — | +| **`STALE_TESTS`** — 안 건드린 파일에서 | 실패 아님. 작업 사본 mtime 아티팩트다. **테스트를 만져서 고치지 마라** | — | +| 같은 항목에서 **2회 연속 되돌림** | 항목이 잘못 잘린 것이다. 쪼개고 다시 계획한다. 3번째 시도 금지 | — | + +**멈출 때는 항상** 원장에 이유를 남기고 커밋한다. 말 없이 멈추면 다음 바퀴가 무엇을 만났는지 모른다. + +--- + +## 5. 중간 복구 (컨텍스트를 잃었을 때) + +원장 마지막 줄이 `IN_PROGRESS`이면: + +```bash +git status --porcelain # 변경이 있나? +cat .refactor/units/.yaml # touch_allowed와 done_conditions +``` + +- **트리가 깨끗** → 항목이 시작만 되고 아무것도 안 했다. `IN_PROGRESS` 줄을 지우고 다시 시작한다. +- **변경이 `touch_allowed` 안에만** → 이어서 한다. `done_conditions`를 돌려 어디까지 왔는지 확인한다. +- **변경이 `touch_allowed` 밖에** → 되돌린다(`git checkout -- <해당 경로>`). 범위 위반이다. +- **내가 만들지 않은 변경** → 멈추고 사람에게 묻는다. 남의 작업 위에 쌓지 마라. + +--- + +## 6. 훅 없는 호스트에서의 자기 규율 + +Codex에는 훅이 없다. Claude Code에서 **기계가 막아주던 것**이 여기서는 전부 스스로 지켜야 하는 것이 된다. + +| 기계가 하던 것 | 이제 | 사후 점검 (§1의 10단계) | +|---|---|---| +| `status: done` 손으로 쓰기 차단 | 규율 | `git diff HEAD~1 -- spec/ \| grep -c '^+.*status: done'` → `clad done`을 안 돌린 커밋이면 **0**이어야 한다 | +| `F-NNN` 파일명 차단 | 규율 | `git diff --name-only HEAD~1 \| grep -cE 'spec/features/F-[0-9]+\.yaml'` → **0** | +| 편집 직후 드리프트 알림 | 없음 | 항목 끝에서 `clad check --tier=pre-commit` | +| 턴 종료 시 차단 | 없음 | 항목 끝에서 `clad check --tier=pre-push --strict` | + +**그리고 정직하지 않게 초록에 도달하는 여섯 가지 — 전부 금지:** +핀 테스트 약화 · 패리티 허용 항목 추가 · 커버리지 임계 하향 · 사후 `touch_allowed` 축소 · 사실 대신 그 사실을 비교하는 문구 수정 · 뮤턴트 삭제. + +기계적 점검 한 줄로: **커밋 diff에 테스트·임계값·허용목록의 완화가 들어 있는데 그게 이 항목의 선언된 목적이 아니면, 그 항목은 실패다.** + +--- + +## 7. goal 문장 + +**기본 — 한 바퀴에 한 항목** (매번 이걸 그대로 붙여넣는다): + +``` +/goal .refactor/ledger.md 의 다음 준비된 항목 하나를 완주한다. + +시작 전: 이 문서(.refactor/PLAN.md)의 §0~§7을 읽고, git status --porcelain 이 비어 있는지 확인한다. +비어 있지 않으면 §5 중간 복구를 따른다. + +항목 선택은 §1의 3단계 규칙을 따른다. [사람] 표시 항목은 시작하지 말고 무엇이 필요한지 보고하고 멈춘다. + +완료 판정은 그 항목의 done_conditions 를 전부 실행해서 한다. 하나라도 기대와 다르면 §4의 해당 행을 따른다. +스펙 항목을 만드는 항목(◆)은 clad verdict --json 으로 초록을 확인한 뒤 clad done 로 끝낸다. +status: done 을 손으로 쓰거나 F-NNN 파일을 손으로 만들지 마라 — 이 호스트에는 그걸 막는 훅이 없다. + +끝나면 §6의 자기 점검을 돌리고 원장에 결과를 기록하고 커밋한 뒤 멈춘다. 다음 항목으로 넘어가지 마라. +``` + +**묶음 — 위험이 낮은 구간에서만** (사전 검증 4건, 리팩토링 주석 유닛처럼 되돌리기 쉬운 것들): + +``` +/goal 위와 같되, 항목을 하나씩 완주하고 원장에 기록하기를 개 또는 첫 실패까지 반복한다. +◆ 표시 항목이나 [사람] 표시 항목을 만나면 그 앞에서 멈춘다. +``` + +**묶음을 쓰지 말아야 할 곳:** ◆ 항목(스펙을 만든다), `RF1`(패리티 하네스 — 킬 크라이테리언이 걸려 있다), 릴리즈. + +--- +--- + +# 부록 A — 결정과 그 근거 + +> 큐의 항목을 집을 때 해당 절만 연다. 결정을 의심할 때만 처음부터 읽는다. + +## A1. 판정 기준 + +> **없애면 벌지 않은 `done`이 서 버리거나 번 `done`을 설명할 수 없게 되는 것은 남긴다. 그 외는 알릴 수 있어도 가로막아서는 안 된다. 그리고 가로막는 것은, 그게 없었으면 기록이 놓쳤을 무언가를 실제로 잡았다는 계수기를 반드시 내놔야 한다.** + +1절은 **존재**를 정한다 — Stop 거부권·게이트·임플-블라인드 채점자·세션 카드가 남는 이유이고, "하네스라서" 잘리는 것은 하나도 없다. +2절은 **형태**를 정한다 — 스타일·시계·케이던스·중복 산문은 알릴 수 있으나 턴을 가로막는 순간 1절이 주지 않은 권한을 주장한 것이다. +3절은 **자기 자신에게 적용한 cladding의 기준**이다. 증거 없는 `done`을 거부하는 도구가 자기 차단만 신뢰로 돌릴 수는 없다. + +## A2. 확정된 발견 + +| # | 발견 | 근거 | 함의 | +|---|---|---|---| +| 1 | **훅 층이 3주간 죽어 있었고 제품이 그걸 못 본다.** 캐시된 플러그인은 0.4.0 하나뿐이고 `hooks/`도 `dist/`도 없다. 훅 이벤트는 07-12/16에 전부 멈췄고 게이트·done 이벤트는 오늘까지 정상 | `~/.claude/plugins/cache/cladding/claude-code/0.4.0/`, `events.log.jsonl` | Phase 0 | +| 2 | **거부권이 계수기 없는 주장이다.** `stop_blocked`는 `{count, fingerprint, head, identity}`만 남긴다 — 탐지기 이름도 귀속도 후속도 없어, 89회의 차단이 무엇을 잡았는지 오늘 아무도 답할 수 없다 | `hook.ts:431` | Phase 0 | +| 3 | **README:86의 "logged as a known-failing exit"에 코드가 없다.** demote 분기는 `return ''` 하고 아무것도 기록하지 않는다 | `hook.ts:417` · 3,694 이벤트 중 0건 | Phase 1 | +| 4 | **"한 번만 차단"이 19/89회 깨졌다.** 차단 파일이 가장 최근 지문 하나만 저장해 상태가 진동하면 다시 무장한다 | `hook.ts:412-424` · 고유 지문 70 / 차단 89 | Phase 1 | +| 5 | **"Stop once more to snooze" 문구가 거짓이다.** *한 번 더* 하라면서 코드는 **바이트 동일한 발견 집합**을 요구한다 | `softShell.ts:227` | Phase 1 | +| 6 | **거부권의 배타 영역은 하나뿐인데 그보다 훨씬 넓게 막는다.** `runStopGate`(drift+arch+secret)와 `pre-commit` tier `[1.3,1.5,1.6]`은 같은 세 검사다. 커밋하면 다시, 푸시하면 CI가 잡는다 → 배타 영역은 README:46이 이름 붙인 **"커밋 안 한 실패를 두고 가는 일"** 하나 | `hook.ts:361-397` · `clad.ts:469-473` | Phase 1 | +| 7 | **게이트 응답이 신호가 아니라 덤프다.** info 미필터 + 이중 pretty-print. **GREEN 실행에서 실패하지 않은 것들의 목록을 돌려주는 것**은 README:104를 뒤집는다 | `server.ts:1114-1118` | Phase 2 | +| 8 | **`gateFooter`가 full 프로파일로 돈다** → 뮤테이션 MCP 도구 호출마다 `secretlint '**/*'` + `madge --circular .` 스폰. 모든 호스트가 받는 유일한 채널에서 Stop보다 큰 비용 | `server.ts:297` | Phase 2 | +| 9 | **판정을 바꾸는 게이트 설정이 gitignore 안에 있다.** `gate.scope`·`gate.coverage`·`gate.commands`가 `.cladding/config.yaml`인데 `clad init`이 그 디렉터리를 무시 목록에 넣는다 → **노트북과 CI가 다른 게이트를 돈다** | `init.ts:475` · `gate-config.ts:70` | Phase 3 | +| 10 | **TS+vitest 밖에서 코드↔테스트 검증 절반이 침묵하는데 GREEN은 똑같다.** 진짜 `LanguageConfig`는 3개, 공허 가드는 vitest 전용, 어디에도 "이 스택에선 못 돌렸다"는 고지가 없다 | `language-config.ts:118-122` · `unit.ts:40-42` | Phase 4 | +| 11 | **임플-블라인드 채점자가 정책 없이는 SKIP이고, `blind-author`는 `Bash`를 갖는다.** `Read`/`Grep`/`Glob`은 막았지만 `cat`은 안 막았다. README:221 자신의 기준(*"what that agent could open, not what anyone promised"*)에 코드가 못 미친다 | `blind-author.md:4` · `spec-conformance.ts` | Phase 4 | +| 12 | **CI가 미고정 `npx --yes cladding`을 쓰고 3스테이지만 돈다** (README:173은 "all 15 in CI") | `init.ts:296` · `ci.yml:59` | Phase 0·4 | +| 13 | **`depends_on` 생산자가 없다.** 그래프·임팩트·워킹셋 전체의 입력인데 `clad_create_feature` 스키마에 필드가 없고 `infer-deps`는 출력만 한다 → `breaks_if_changed`가 구조적으로 빈다 | `server.ts:1515-1571` · `infer-depends-on.ts:5-8` | Phase 5 | +| 14 | **소스 경로 수리기가 없다.** `repairTestRefs`는 있는데 `modules[]` 대응물이 없어, 파일을 옮기면 `MISSING_IMPLEMENTATION`+`UNMAPPED_ARTIFACT`가 동시에 터진다 | `test-ref-repair.ts:61` · grep 0건 | Phase 5 | +| 15 | **증거 원장이 사실상 비어 있다.** `appendEvidence` 호출부 3곳이 전부 일반 사용자가 안 밟는 차선이고 **`clad done`은 증거를 한 줄도 안 쓴다.** `human` 증거 생산자는 0 → 모든 피처가 구조적으로 `self-certified`이고 `independence_policy: require`는 통과 불가. 게다가 원장 위치도 gitignore 안 | `oracle/record.ts:106` · `drive/*` · `hitl/audit.ts:21` | Phase 6 | +| 16 | **활성화 문장이 18번 중복된다** (12 스킬 + 6 페르소나, 2,700B). 코드가 이미 세 곳에서 `existsSync(spec.yaml)`로 강제하는 조건 | `SKILL.md:2` · `agents/*.md:3` · `hook.ts:127,367,1017` | Phase 7 | +| 17 | **`docs/feature-cycle.md`가 8개 에이전트 컨텍스트를 지시한다.** README:211은 *"cladding is not a multi-agent framework and doesn't arrange them"*, 수명주기는 `Define → Sync → Implement → Earn` 네 단계 | README:203,211 | Phase 7 | +| 18 | **`AC_DRIFT`에 status 가드가 없다** (`missing-tests.ts:42`와 대조) → cladding이 요구하는 "스펙 먼저"를 따르면 코드 한 줄 전에 EARS 문구로 error 차단 | `ac-drift.ts` | Phase 1 | + +**건드리지 않는 것:** `clad done`의 flip→gate→revert · `MISSING_TESTS`/`UNTESTED_AC`/`MISSING_IMPLEMENTATION` · PostToolUse 거버너(스킵률 97.4%) · `PreToolUse` deny 2개 · MCP 게이트 푸터 · 초기화 전 도구 스테이징과 뮤테이션 경계 · 세션 카드. + +## A3. 사전 검증 게이트 — 코드를 쓰기 전에 판정한다 + +Part A의 32개 변경 중 **21개는 코드 한 줄 쓰기 전에 go/no-go가 나온다**(그중 10개는 이 세션에서 읽기 전용으로 이미 결정됐다). 5개는 **버리는 구현**이 있어야 판정된다(사전 검증이 아니라 조기 검증 — 정직하게 구분한다). 3개는 **출하 후에만** 알 수 있다. 나머지 3개(1b·1c·1e)는 불편한 경우다 — 제품 코드가 필요 없어 사전 검증 가능해 **보이지만, 검증할 계측기 자체가 데이터에 의해 반증됐다.** + +### 이미 발화한 것 (6/8 실행, 총 4시간 미만) + +| # | 검사 | 결과 | 계획 변경 | +|---|---|---|---| +| **P0** | **리플레이 코퍼스 보존 — 마감 있음** | `stop_blocked` 헤드 48개 중 **29개**, `gate_run` 헤드 247개 중 **129개**가 `develop`의 조상이 아니다(스쿼시 머지의 결과). reflog에만 존재하고, 느슨한 객체 4,824/6,700, `reflogExpireUnreachable` 기본 30일, 이벤트는 25~38일 전 | **자동 `git gc` 한 번이면 모든 리플레이 질문이 영구 불가능해진다.** 번들로 뜨거나 `refs/replay/*`에 고정 — 쓰기이므로 **승인 후 첫 작업** | +| **M1** | 같은 커밋에서 GREEN이 났는가 | 블록 헤드 **40/48(블록 77/89)** 이 같은 커밋에서 strict GREEN `gate_run`을 갖는다. 즉 커밋된 트리를 리플레이하면 차단이 아니라 통과가 재현된다 — **차단을 만든 발견은 작업 트리에 있었고 git에는 없다.** EXACT 상한 56.2% | **48-헤드 리플레이 드라이버를 짓지 않는다**(1일 + 아암당 20~40분 절약). 1b·1c·1e는 Phase 0의 계수기 뒤로 | +| **M2** | LRU 지문 집합의 실측 이득 | 설계가 명시한 *"실패 0이면 비움"* 을 모델에 넣으면 **상한 5부터 89까지 결과가 동일**하고 현재 대비 개선은 **11일간 +2회**. 게다가 16회 중 14회가 **커밋을 넘나드는 해제**(간격 최대 3.9일) | **LRU를 짓지 않는다.** `stop_exit_recorded`만 먼저 내보내고 실제 해제 데이터로 재결정 | +| **M3** | `gateFooter` 프로파일 전환이 가능한가 | `tests/stages/interactive-profile-partition.test.ts`가 **출하된 피처의 AC**로 "`profile:'interactive'`를 쓰는 `src/` 파일 집합 == `['src/cli/hook.ts']`"와 "`server.ts`는 매치되면 안 된다"를 단언한다. 헤더는 gateFooter를 **의도적** full-suite 소비자로 명시 | 2b는 튜닝 노브가 아니라 **스펙 개정**이다. 개정을 구현 앞에 두거나 드롭 | +| **M4** | 증거 생산자가 라벨을 뒤집는가 | `computeIndependence`는 `author==='human'` **또는** `blind===true`일 때만 `independent`. **`'tool'`은 어느 쪽에도 없다.** `human` 생산자는 트리에 0개, `blind` 생산자는 호스트가 넘긴 값을 그대로 전달하는 한 곳뿐 | **6a는 감사 흔적일 뿐 `require`를 만족시키지 못한다.** M5가 검증 가능한 6b 출처를 기각했으므로 6b와 단독으로 낼 수 없는 7d를 함께 큐에서 제거한다 | +| **M6** | 죽은 코드 3종의 스펙 결합 | `preamble.ts`는 F-041의 선언 모듈이자 F-063의 `test_ref` 대상이고 attestation에 해시돼 있다. `PERSONA_PROMPT_ALIASES`는 `server.ts:2019`에서 살아 있고 테스트가 고정한다. `token_budget_per_session`은 types·schema·`update.ts`와 자기 spec.yaml에 살아 있다 | **삭제가 아니라 스펙 아카이브**(`modules: []` + `superseded_by`) + 와이어 노출 1건은 별도 폐기 절차 | +| **M7** | jest 공허 가드가 실제 갭인가 | **PASS** — Jest 30.2.0의 all-skipped suite는 exit 0 / `1 skipped, 1 total`이고 현재 strict Unit stage도 `{pass:true, exitCode:0}`으로 놓친다. native Jest JSON은 기존 pass-count 파서가 0으로 해석했다. 근거: `.refactor/sim/M7.md` | A6의 Jest 범위를 유지한다. 새 파서가 아니라 Jest JSON reporter 배선이 본체이며, macOS `/tmp` canonical path 정규화 E2E를 포함한다 | +| **M5** | `clad sign-off`의 비대화형 거부 | **KILL** — 호스트 에이전트가 PTY를 할당하고 대화형 확인에 직접 답할 수 있으며, git/OS identity도 같은 프로세스가 상속한다. 근거: `.refactor/sim/M5.md` | 로컬 CLI 안의 TTY·확인 문구·git author로는 사람 출처를 검증할 수 없다. A10·A11 제거; CLI-only `independence_policy: require`는 만족 불가로 유지 | + +### 출하 후에만 알 수 있는 것 (대리 지표를 만들지 않는다) + +- **0c 계수기의 값어치** — 훅 레인이 현재 0을 내므로, 복구 후 **4~6주**의 트래픽이 있어야 분모가 안정된다. **순서 제약: Phase 1이 설계상 차단율을 줄이므로 0c는 Phase 1 이전에 깨끗한 창을 가져야 한다.** 기록된 89회로 대체하면 안 된다 — demote 분기가 아무것도 기록하지 않아 그건 **비(非)해제만 모인 표본**이다. +- **7b(밀어주는 슬라이스)** — 에이전트가 바이트로 무엇을 하는지에 대한 주장이라 로그에 관측 근거가 없다. 다만 **필요조건은 오프라인 판정 가능**하다: 최근 200 커밋에서 푸시할 슬라이스가 그 커밋이 만진 파일을 포함하는가를 **세 개의 귀무 모델**(선언된 `modules[]`만 / 최근 수정 N개 / 직전 커밋이 만진 파일) 대비 lift로. 재현율이 최선의 귀무 이하이거나 정밀도 0.3 미만이면 기각. **사전 확률이 낮으므로**(직전-커밋 귀무 모델이 단일 저자 리포에서 매우 강하다) 이 필요조건에서 떨어지면 7b 자체를 접는다. +- **7e(PreCompact)** — 7b의 관측 불가능성을 물려받는다. 빈도만으로 결정: 긴 세션의 5% 미만이 압축되거나 압축 후 중앙 작업량이 3 툴콜 미만이면 기각. + +### 시뮬레이션하지 않기로 한 것 + +**0d(CI 버전 고정)** — 노출 대상이 가상의 채택자이고 그 모집단이 존재하지 않는다(커밋 580개 중 566개가 한 저자). 게다가 **순효과의 부호가 제안된 방법으로 계산 불가능하다** — `` 상한은 오탐 차단 수정으로부터도 채택자를 얼린다. **정책으로 결정하거나, 채택자가 생길 때까지 보류한다.** + +**1b·1c·1e의 리플레이 드라이버** — M1이 계측기를 반증했다. 커밋된 트리는 차단을 만든 트리가 아니고, `UNVERIFIED_AC`는 `.cladding/`이 gitignore라 모든 과거 시점에서 구조적으로 침묵하는데 그 편향은 **보수적이 아니라 관대한** 방향으로 작동한다. + +### 추가 사전 검증 결과 + +**5b(`repairModules`) — PASS, 자동수리 범위 축소.** 과거의 실제 module claim 수리 14건을 독립 정답으로 삼았을 때 같은 diff의 Git rename 기록은 **14/14 정답, 오탐 0**이었다. 반면 unique-basename은 현재 corpus leave-one-out에서 587/587을 맞혔지만, 과거 실제 이동 정답은 0건이라 자동 적용을 뒷받침하지 못했다. 따라서 Git rename 일치만 자동수리하고 basename은 명시적 선택이 필요한 제안으로 낮춘다. 근거: `.refactor/sim/5b.md`. + +## A4. 단계별 작업 + +cladding 규약 준수: 한 번에 한 기능 엔드투엔드, 해시 id, 코드보다 스펙 항목 먼저, `clad done`은 strict pre-push GREEN일 때만. 탐지기·페르소나·매니페스트 변경 후 `npm run build:plugin` 필수. + +### Phase 0 — 하네스를 보이게 한다 · **0.9.4 단독 출하** +판정을 바꾸지 않고, 이것 없이는 아래 어느 것도 판정할 수 없다. + +- **훅 배선 복구 — P1R PASS.** dogfood project가 current-checkout marketplace source를 선언하지 않아 삭제된 pre-0.9.0 directory와 0.4.0 cache를 계속 참조했고, Claude Code 2.1.224에서는 표준 hook 자동발견과 manifest 중복 선언도 충돌했다. source-first plugin build, 중복 선언 제거, project 0.9.3 cache 재설치 후 실제 cached `SessionStart`가 context card와 telemetry를 냈다. 근거: `.refactor/sim/P1.md`, `.refactor/sim/P1P.md`, `.refactor/sim/P1G.md`, `.refactor/sim/P1R.md`. +- **가시화 — P2 PASS.** bounded sidecar로 실제 훅 설치 상태와 다섯 이벤트별 마지막 발화를 `clad doctor` text/JSON에 노출했고, package-less Claude cache의 plugin manifest에서도 현재 버전을 판독한다. `HOST_CLAIM_DRIFT`는 30일 초과·구버전 matrix를 비차단 `info`로 보고한다. 실제 출하 bundle 다섯 이벤트와 cache 형태를 재현했고 기본 병렬 스위트 2828/2828 및 strict pre-push가 통과했다. 근거: `.refactor/sim/P2.md`. +- **계수기 — P3 PASS.** `stop_blocked` → `{count, fingerprint, head, detectors[], introduced, preexisting, dirty_hit}`; demote 분기에 **`stop_exit_recorded`**; `done_attempted`에 `blockers[]`. 읽기 시점 파생 질문 하나: **차단된 지문이 이후 어느 게이트에서든 관측된 적이 있는가.** 실제 출하 bundle에서 차단→동일 지문 종료→후속 gate 관측→doctor 집계와 정상 done 경로를 순차 검증했다. 근거: `.refactor/sim/P3.md`. +- **CI 버전 고정 — P4 PASS.** 생성 workflow는 실행 binary의 `cladding@`를 쓰고 version을 판독할 수 없으면 미고정 형태를 만들지 않는다. `clad doctor` text/JSON은 기존 GitHub Actions의 unversioned·floating `npx cladding` 호출을 정확한 상대 경로로 비차단 경고한다. 실제 출하 bundle의 pinned 생성→quiet doctor→unpinned 경고를 순차 검증했다. 근거: `.refactor/sim/P4.md`. +- **파생 파일 정책 도장 — P5 PASS.** attestation에 `{cladding, blocking, detectors sha}`를 기록하고 `clad init`이 기존 내용을 보존하며 `.gitattributes`에 `spec/index.yaml merge=union`을 정확히 한 번 쓴다. legacy policy-less 파일은 그대로 읽고 attestation에는 merge driver를 주지 않는다. 실제 출하 bundle init·strict gate와 2845/2845 테스트로 검증했다. 근거: `.refactor/sim/P5.md`. +- **git 훅 fail-open은 유지** — exit 1로 바꾸면서 기본 on으로 뒤집으면 바이너리 없는 머신에서 모든 커밋이 막힌다. + +**검증:** 스위트 GREEN · 정책 섹션 왕복/구버전 리더 관용 테스트 · `clad doctor`가 훅 침묵을 실제로 보고하는 픽스처. + +--- +*아래 Phase 1~7은 0.10.0 한 번에 나간다.* + +### Phase 1 — Stop 거부권: 광고대로 좁히고 정직하게 +- **죽은 `strict: true` 제거**(`hook.ts:377`). 어떤 탐지기도 `opts.strict`를 읽지 않고 Stop 경로는 `report.pass`를 안 본다. +- **`TURN_BLOCKING` 허용목록** — 기본값은 "아무것도 막지 않음"(README:215). v1은 **이미 `done`인 게 done이 아님을 말하는 넷**: `STATUS_DRIFT`, `UNVERIFIED_AC`, `MISSING_IMPLEMENTATION`, `DELIVERABLE_INTEGRITY` + 경로 무관하게 항상 막는 **arch·secret 스테이지**. `STALE_ATTESTATION`은 제외(strict pre-push가 이미 EXEMPT를 준다). +- **커밋 안 된 경로와의 교집합.** 이미 있는 `.cladding/hook-tree-state.json`을 쓴다(새 상태 파일 없음). **반드시 fail-closed로** — 스냅샷이 없거나 비면 교집합이 모든 것을 억제해 **거부권이 조용히 꺼지고, 첫 Bash 호출 전 새 세션의 기본 상태가 바로 그 빈 상태다**(200개 상한, 읽기 전용 Bash에서는 갱신 안 함). 스냅샷 부재 = 신호 없음이 아니라 **평소 규칙 적용**. 그리고 교집합 가능한 표면은 `path`를 내는 `MISSING_IMPLEMENTATION`·`DELIVERABLE_INTEGRITY` 둘뿐이므로(`STATUS_DRIFT`·`AC_DRIFT`는 `path`가 없다), 1시간짜리 측정이 1c를 아예 기각할 수도 있다. +- **`stop_exit_recorded`만 먼저.** demote 분기가 오늘 아무것도 기록하지 않아 README:86에 코드가 없다 — 그걸 채운다. **LRU 지문 집합은 짓지 않는다**(M2: 설계가 명시한 clear 의미론을 넣으면 상한 5~89가 동일하고 실측 개선이 11일간 +2회, 그나마 16회 중 14회가 커밋을 넘나드는 해제). 실제 해제 데이터가 쌓인 뒤 재결정. +- **문구 교정**: *"cladding paused before finishing: 2 thing(s) you're leaving uncommitted don't hold up — …. Fix them, or stop again on the same findings to record a known-failing exit. (14 other findings unchanged — the commit gate has them.)"* +- **대량 발화 캡을 `runDrift`에** — 한 패스 N(~20)회 초과 발화는 롤업 요약. `check`·`done`·CI·`gateFooter`·Stop을 한꺼번에 고친다. +- **`AC_DRIFT` status 인지 심각도** — 빈 껍데기 AC는 done에서 계속 error, EARS 문법 지적은 non-done에서 warn/info. + +**검증:** `tests/cli/hook.test.ts:257-340` 재작성 + 신규 5케이스(허용목록 밖 error→차단 없음 / 커밋된 경로→차단 없음 / 커밋 안 된 경로→차단 / 같은 지문 재차단 없음 + `stop_exit_recorded` / secret→항상 차단). `AC-973837`이 차단 결정을 의무화하므로 **스펙 개정 선행**. +**되돌릴 조건:** 계수기 50회 시점에 세션 유발 차단이 거의 0이고 차단 지문이 이후 게이트를 빠져나간 적이 없으면 → 보고 카드로 강등하고 README:46을 고친다. + +### Phase 2 — 페이로드 경제 +- `server.ts:1114-1118`: `severity !== 'info'` 필터(+`info_omitted: N`) · compact JSON · 스테이지당 발견 상한 30(+`truncated`) · **`worst`·`anyFailed`·스테이지 목록은 자르지 않음**. 이후 `clad_verdict`의 "run_gate 대신 이걸" 절 삭제. +- `gateFooter` 프로파일 전환은 **스펙 개정이 선행되어야 한다** — 출하된 AC가 `profile:'interactive'` 사용처를 `['src/cli/hook.ts']`로 못박고 `server.ts`를 명시적으로 배제한다(M3). 개정하거나 드롭. +- MCP `instructions`의 온보딩 텍스트를 `clad_prepare_init`으로 이동. `description-budget.test.ts`에 **합계 상한 + 스키마 상한** 추가. +- 죽은 것 정리 — **삭제가 아니라 스펙 아카이브**(M6): `preamble.ts`(F-041 선언 모듈 · F-063 `test_ref` 대상 · attestation 해시됨) → `modules: []` + `superseded_by`; `PERSONA_PROMPT_ALIASES`(`server.ts:2019`에서 살아 있고 `listPrompts()` 7→5로 바뀌는 **와이어 변경**) → 별도 폐기 절차; `token_budget_per_session`(types·schema·`update.ts`·자기 spec.yaml) → 스키마 변경 절차. + +### Phase 3 — 게이트 설정을 커밋되는 파일로 +`gate.scope`·`gate.coverage`·`gate.commands`를 `.cladding/config.yaml`에서 **`spec.yaml`의 `independence_policy` 옆으로**. `.cladding/config.yaml`은 노트북 로컬 오버라이드로만 유지. +*(스키마가 모든 층에서 `additionalProperties: false`이고 18개 피처가 `schema.json`을 claim하므로 키 추가는 채택자 가시 변경 — 자기 게이트 사이클을 갖는다.)* + +### Phase 4 — 실제로 검증한 것을 말한다 +**가장 큰 제품 격차이고, 방향은 "하네스가 너무 적은" 쪽이다.** +- 신규 `src/stages/verification-capability.ts` — **모든 게이트 실행(초록 포함)** 에 "이 스택에서 실제로 돌린 검사" 블록 + `--json` + MCP 푸터 + attestation 기록. +- 공허 가드를 jest까지(이미 그 형태를 파싱) · Go/Dart 러너 요약 · 인식 못 한 요약은 info. +- `unmapped-artifact.ts`: 파생 패턴이 0개 파일에 매치되면 공허함을 명시하는 info. +- **CI에 `--tier=all --strict` 스텝 추가** — README:173을 고치는 것보다 싸다. +- `blind-author.md`에서 **`Bash` 제거** → README:67이 쓰인 그대로 참이 된다. `oracle_policy`를 cladding 자기 스펙에 위험 가중 도입(`unwanted` EARS 부류부터). + +### Phase 5 — 그래프에 생산자를 붙인다 +- **`depends_on` 1급 writer**: `clad_create_feature` 스키마에 선택 필드 + 별도 `depends_on_inferred:` 키를 쓰는 writer(`test-ref-repair.ts` 방식 텍스트 스플라이스) + `reverse-index.ts`에서만 합집합. **어떤 탐지기도 추론 엣지를 읽지 않는다.** 스키마가 `additionalProperties: false`이므로 **키와 `schema:` 범프가 writer보다 먼저**. +- **`repairModules`** 를 `repairTestRefs` 옆에 — 같은 diff의 리네임 레코드(`git diff -M`)와 정확히 대응할 때만 자동수리. 유일 basename은 dry-run 제안으로만 노출하고 명시적 선택 전에는 쓰지 않으며, 모호하거나 rename 증거와 충돌하면 추측 금지. (5b에서 rename-backed 수리 14/14, 오탐 0; basename 실제 이동 정답 0건. 리팩토링 프로그램의 선행 조건이기도 함.) +- `ac.notes` 근거 탐지기는 **연기**. 대신 README:31 문구를 강제되는 절반으로 좁힌다. + +### Phase 6 — KILLED: 검증 가능한 사람 출처가 없다 +M5는 로컬 CLI가 사람과 같은 OS 사용자·git 설정·PTY를 쓰는 호스트 에이전트를 구분하지 못함을 확인했다. TTY 검사, 대화형 확인 문구, git author 어느 것도 `identity.author: human`의 출처를 증명하지 않는다. 따라서 `clad sign-off`, 그것을 전제로 한 증거 생산자/커밋 원장(A10), 그리고 함께 출하해야 했던 `claimed_blind`(A11)는 0.10.0 큐에서 제거한다. `independence_policy: require`는 CLI-only 환경에서 만족 불가로 유지한다. + +재개하려면 CLI 프로세스가 스스로 만들 수 없는 증명이 필요하다. 허용 후보는 인증된 호스트가 서명한 실제 사용자 응답 또는 사용자 현존을 요구하는 하드웨어 서명이며, 단순 환경 변수·TTY·일회용 문구·git/OS 계정은 포함하지 않는다. + +### Phase 7 — 규칙은 한 번만, 도달하는 곳에서만 +- **활성화 문장 18개 전부 삭제.** 호스트 조건부 파이프라인은 짓지 않는다. 선행 조건: 기존 호스트별 활성화 픽스처를 스펙 없는 프로젝트에 한 번 돌려 자가 활성화가 없는지 확인. +- **`POLICY_LINE` 삭제.** **`CONTEXT_LINE`은 삭제하지 않고 밀어주는 슬라이스로 교체** — README는 주입을 팔지 당김을 종용하지 않는다. Tier-A 스펙 편집이라 planner를 거치고 Phase 0 이후에. +- **MCP 검색 지시 4곳은 유지** — 값싸고 헤지돼 있으며 결함은 데이터 쪽(Phase 5)이었다. +- `docs/feature-cycle.md`를 5조건 **결과 계약**으로 재작성해 관리 블록에 넣는다(`docs/`는 npm으로 셔츠되지 않는다). +- `recordOracle`의 LLM 자기 신고 `blind` 강등은 M5 KILL로 큐에서 제거됐다. 검증 가능한 대체 출처 없이 단독 출하하면 `independent` 생산자가 0이 되므로 시행하지 않는다. +- **`PreCompact` 훅 추가**로 ~400B 상태 카드 재방출. + +### Phase 8 — 보류, 계수기로 개폐 +`clad done`의 드리프트를 피처 범위로 좁히기. Phase 0 텔레메트리가 `done_attempted` 차단자를 무관 경로가 지배함을 보일 때만. + +## A5. 하지 않기로 한 것 + +| 기각 | 이유 | +|---|---| +| **Stop 훅 보고 전환 / 완전 삭제** | 광고된 비교표 한 행(README:46)이고 뒷받침 증거가 없다. 모델이 실제로 보는 건 문장 하나 + 예시 2건(약 40토큰)이고, 차단의 4분의 1은 이미 5건 이하였다. 좁히고 계수기를 단다 | +| **Stop을 "error만 차단"으로** | 심각도는 양방향으로 잘못된 축이다. warn 전용 14개에 `STALE_ATTESTATION`·`SMOKE_PROBE_DEMAND`·`HOLLOW_GOVERNANCE`가 있고, error와 warn을 함께 내는 탐지기가 8개 더 있어 그 분기도 같이 침묵한다. 게다가 `UNMAPPED_ARTIFACT`가 미claim 파일마다 error라 채택 초기 리포는 상시 차단이 그대로다 | +| **세션 시작 기준선 래칫** | 제품에서 가장 신뢰도 낮은 표면이 소유하는 새 상태 subsystem이고, 세션 시작 시 이미 깨진 것을 세션 내내 면제한다. `hook-tree-state.json`이 새 생명주기 없이 같은 일을 한다 | +| **탐지기 심각도 다이얼(새 필드)** | **`severity`가 이미 다이얼이고**, 탐지기마다 근거를 적어가며 저작돼 있다(`planned-backlog.ts:20-27`). 호출자 하나가 무시했을 뿐이고 Phase 1이 그걸 고친다. `spec.yaml`에 다이얼을 두면 막힌 에이전트가 한 줄로 자기를 풀어주는 경로가 생긴다 | +| **탐지기 강등·삭제** | `UNVERIFIED_AC`의 `:81`·`:88`은 error로 "실패 중인 테스트"·"skip만 돌았다"를 잡는 유일한 프레임워크 무관 장치다. `--strict`를 `{error}`로 평탄화하면 커버리지 하한과 `SMOKE_PROBE_DEMAND`가 CI·pre-push·`done`에서 조용히 꺼진다 | +| **검색 지시 삭제 · AGENTS.md 작성용 분할** | 전자는 값싸고 헤지돼 있으며 결함은 데이터 쪽이었다. 후자는 산술이 본전인데 downside가 비대칭이다(EARS 실수는 한 턴에 자가 교정, 스펙 언어 실수는 조용하고 세션을 넘어간다) | +| **git 훅 fail-open을 exit 1로 (기본 on과 동시에)** | 바이너리 없는 머신에서 모든 커밋이 막힌다 — 사용자가 cladding을 지울 가능성이 가장 높은 조합 | +| **폴리글롯 언어 테이블 통합** | 두 지도가 오늘 서로 다르다. 한쪽으로 합치면 Rust 채택자의 `UNMAPPED_ARTIFACT`가 전멸(공허 초록)하고, 반대로 합치면 `.rs`에 `CONVENTION_DRIFT`가 붙는다(업그레이드 시 빨간 게이트). 이 리포는 100% TS라 **양방향 모두 여기서 보이지 않는다** | + +## A6. 바꿔야 할 README 문구 + +| 위치 | 지금 | 바뀔 것 | +|---|---|---| +| :48 · :67 | "an implementation-blind grader" | "**oracle policy를 선언한 프로젝트에서**" 단서 추가. `blind-author.md`에서 `Bash`를 빼면 :67은 쓰인 그대로 참이 된다 | +| :44 | "auto-detected **right after the edit**" | "surfaced as you work — the affected feature, its blast radius, and the tests to run" (발화율 2.6%, 20초 디바운스) | +| :31 | "the **why** lives in the spec" | "the **intent of each feature** lives in the spec" (AC 단위 근거는 파싱되지 않고 273개 중 111개에만 있다) | +| :178 | "Audit (**every** acceptance criterion has evidence)" | "every acceptance criterion **in the audit log**" | +| :126 | "median 4× less" | `medianStructuralRatio`를 싣거나 "기본 3,000토큰 예산 기준" 병기 | +| :173 | "all 15 in CI" | *문구 유지 — CI에 `--tier=all --strict`를 추가한다* | +| :46 · :86 | — | **그대로 유지. 코드가 그쪽으로 움직인다** | + +## A7. 릴리즈 + +- **0.9.4 (패치):** Phase 0 단독. 판정을 바꾸지 않으므로 채택자가 깨지지 않는다. +- **0.10.0 (마이너):** Phase 1~7을 한 브랜치에 순서대로. 체인지로그 `BREAKING GATE` 섹션 + 업그레이드 후 첫 N회 게이트 출력 1회성 배너 + `clad doctor`의 미고정 CI 넛지. +- 더 쪼개지 않는 이유: CI 버전 고정은 *새로* 스캐폴딩하는 워크플로에만 적용되므로 분할이 안전을 사주지 않고, 릴리즈 의례(11개 사이트 + PR + 태그 + 백머지 + npm + gh release + README 4종)를 반복할 이득이 없다. +- 의례는 CLAUDE.md 절차를 따른다(범프 → PR `develop → main` **머지 커밋**, 스쿼시·리베이스 금지 → 태그 → 백머지 → `npm publish` → `gh release`). 푸시·태그·publish·release는 각각 별도 승인. + +--- + +# 부록 B — 코드 리팩토링 프로그램 + +> **전체 설계서(738줄 · 49 유닛 · 유닛별 검증 명령·롤백·체크포인트):** +> `.refactor/REFACTOR.md` +> 아래는 결정 기록과 실행 골격이다. 유닛을 집을 때 위 문서를 연다. + +## B1. 접근 + +**제자리 압축.** 파일 내용을 줄이고 죽은 코드를 지우고 중복을 헬퍼로 모으고 주석을 기계 검사 가능한 표준 아래 둔다. 관측 계약(CLI·MCP·훅·기록 파일·이벤트·게이트 disposition)은 **바이트 동일**해야 한다. + +**하지 않는 것:** 파일 이름 변경·이동 금지(422개 모듈 경로가 275개 스펙 항목에 리터럴로 박혀 있다) · 동작 변경 금지(전부 Part A 소관) · 탐지기 테이블 재작성 금지(상한이 455줄=1.3%인데 파일 수가 세 곳에서 load-bearing) · `src/graph/viewer/` 제외 · **주석 class 4(자유 서술 삭제) 제외**(좋은 삭제와 결정 기록 삭제를 구분할 오라클이 없다). + +## B2. 검증을 가능하게 하는 두 오라클 + +**① 번들 동일성.** `scripts/build.mjs:32,38`이 `legalComments:'none'` + `minify:true`이고 `src/`에 `@__PURE__`/`@license`/`@preserve`가 **0건** → **주석만 바꾼 유닛은 `dist/clad.js` SHA-256을 반드시 유지해야 한다.** 가장 크고 주관적인 작업이 해시 비교로 판정된다. + +**② 패리티 하네스 + 킬 크라이테리언.** CLI·MCP·훅·기록물·이벤트·번들 6개 레인의 골든을 캡처·비교. 결정성은 마스킹이 아니라 **고정**으로. **하네스가 심어둔 변경을 못 잡으면 프로그램 중단** — 그 오라클로 검증한 모든 유닛은 미검증이므로 마지막 정상 셀프테스트 이후 전부 되돌린다. + +## B3. 리팩토링 설계 중 발견된 코드 결함 + +| 결함 | 근거 | 유닛 | +|---|---|---| +| **`tsconfig.json`의 `include` 12개 중 9개가 0개 파일에 매칭**(전부 `src/` 도입 이전 경로) → 지금 `tsc --noEmit`은 테스트가 임포트하는 소스만 간접 검사하고, 어떤 테스트도 안 건드리는 소스는 **타입 검사가 안 된다** | 직접 확인 | U-01 | +| **매니페스트 정직성이 공허 초록** — 탐지기 `.ts` 44개 − 헬퍼 3개 = 41. 검사기와 빌드가 **같은 파일 수**에서 파생돼 서로 어긋날 수 없고 둘 다 `allDetectors`와 비교하지 않는다. 헬퍼를 하나 더 넣으면 42를 광고하며 41이 도는 상태가 완전 초록 | 44 vs 41 | U-03 | +| **커버리지 임계값 미선언** → `stage_2.2`는 커버리지가 얼마든 통과 | `vitest.config.ts` | U-02 | +| **탐지기 발화 순서가 고정돼 있지 않다** — 순서는 `--json`·패널·`stop-block.json`·사용자에게 보이는 상위 2건에 드러나는데 검사하는 테스트가 0개. ESLint import-sort `--fix` 한 번이면 뒤바뀐다 | 8개 테스트 모두 length/uniqueness만 | U-04 | +| **Windows 엔트리 가드가 절대 매칭되지 않는다** → 13개 `stage:*` 스크립트와 `benchmark.ts`가 그 플랫폼에서 조용한 no-op | `import.meta.url === 'file://'+argv[1]` | U-50(동결) | +| **테스트 없는 불변식 5건** — 특히 `arch.ts`/`secret.ts`가 "이 탐지기는 절대 warn을 내지 않는다"에 기대어 `filter(severity==='error')` 한다 | 주석만 존재 | U-05 | + +## B4. 7단계 · 49 유닛 + +| 단계 | 유닛 | 내용 | +|---|---|---| +| 0. 기준선과 그물 | U-00~07 | 기준선 동결 · tsconfig 수리 · 커버리지 래칫 · 매니페스트 정직성 테스트 · 탐지기 순서 골든 · **불변식 5건을 주석→단언으로 승격** · 주석 표준 문서 | +| 1. 패리티 하네스 | U-10~17 | 정규화+픽스처+CLI 레인 → **뮤턴트/셀프테스트** → MCP·훅·기록물·번들 레인 → `census`/`comments`/`checkpoint` 도구 | +| 2. 린트 정합 | U-20 | ESLint 스코프 수리 — 단독, 포맷팅만 | +| 3. 죽은 코드 | U-30~31 | `preamble.ts`·`tail.ts` 삭제(의례 리허설) · 죽은 심볼 | +| 4. 주석 | U-40~44 | 참조 무결성 → 낡은 사실 → 헤더 상한 3배치. **전부 번들 SHA 불변이어야 함** | +| 5. 제자리 중복 제거 | U-50~59 | `isCliEntry` 추출+테이블 테스트 → 15개 러너 → 스테이지 어댑터·JSON 리더·훅 사이드카·서버 핸들러 | +| 6. 가산적 추출 | U-60~67 | `core/paths.ts`(`.cladding` 리터럴 39개) · `core/read.ts` · 서버 도구 분할 · `drive↔ui` 순환 제거. **원본은 경로에 남아 얇은 조립 루트가 된다**(스펙 수리 0건) | +| 7. 테스트 | U-70~81 | 교차 결합 해제 → `tests/_support/` → 4배치 마이그레이션 → 테스트 헤더 표준 | + +**단위 규칙:** 1 유닛 = 1 커밋 = 1 변경 이유, **≤400줄 · ≤12파일**, **완료 조건의 모든 항목이 "명령 + 리터럴 기대 출력"**. 산문으로만 쓸 수 있는 완료 조건이 하나라도 있으면 **착수 불가** — 쪼개거나, 계측기를 먼저 짓거나, 버린다. + +**19개 불변식**이 매 유닛 전후로, 싼 것·진단력 높은 것 순으로 검사된다 → **실패한 검사 번호가 곧 실패 분류**다. + +## B5. 체크포인트와 실패 규칙 + +유닛마다 `.refactor/units/.yaml` 하나 — **입장 브리핑**(조사를 다시 하지 않게)이자 **퇴장 영수증**(다음 유닛이 측정된 상태에서 시작하게). 필드: `inherits` · `preconditions` · `touch_allowed`/`touch_forbidden`(전수) · `pins_that_can_fire`(**사전 계산**) · `done_conditions`(명령+리터럴) · `expected_deltas` · `exit.carry` · `residue`. + +실패 대응은 판단이 아니라 **어떤 불변식이 깨졌는가**로 결정된다: A 범위 위반→되돌림·재계획 · B 자기 버그→1회 재시도 · **C 핀 발화→중단, 테스트를 건드리지 말 것**(깨뜨린 유닛 안에서 핀을 고치는 건 자기인증) · D 패리티 델타→되돌림 · **E 오라클 실명→마지막 정상 셀프테스트 이후 전부 되돌림, 프로그램 중단** · F 주석 유닛인데 번들이 움직임→되돌림 · G attestation만 빨감→재도장 · I `STALE_TESTS`→mtime 아티팩트, 고치지 말 것. + +**반합리화 조항:** 핀 테스트 약화 · 패리티 허용 항목 추가 · 커버리지 임계 하향 · 사후 `touch_allowed` 축소 · 사실 대신 주장 문구 수정 · 뮤턴트 삭제로 GREEN에 도달하는 것은 전부 금지. + +## B6. Part A와의 맞물림 + +- **규칙 0: 동작 변경과 리팩토링 유닛을 같은 커밋에 두지 않는다.** 의도된 델타와 사고 델타가 한 패리티 실행에 섞이면 사고 쪽이 숨는다. +- **규칙 1: Part A의 Phase 0이 리팩토링 U-00보다 먼저다.** U-00 기준선에는 "훅이 실제로 돈다"가 전제로 들어가야 하는데 오늘은 거짓이다. 죽은 채로 잰 기준선으로 시작하면 **훅 표면 전체가 패리티 그물 밖에 놓인다.** +- **규칙 2: 리팩토링 0·1단계 이후에야 Part A Phase 1~7이 나간다.** 패리티 하네스 없이는 모든 동작 변경의 검증이 "테스트가 통과했다"뿐인데, 그 테스트는 번들·MCP 응답 본문·훅 사이드카 순서·기록물 트리에 닿지 않는다. +- **규칙 3: 페르소나/산문 편집은 코드와 같은 커밋에 두지 않는다.** `choreography-guard`가 99개 산문 단언을 6개 README·6개 페르소나·3개 빌드 미러·4개 SVG에 걸고 있고, 미러 단언은 빌드 산출물을 읽는다. +- **Stop 좁히기(A Phase 1)는 U-13·U-55 이후.** `stop-block.json` 스키마가 단일 지문 → LRU 집합으로 바뀌므로 **지문 계산 방식 변경과 같은 창에 넣지 않는다.** +- **U-05의 "arch/secret은 절대 warn을 내지 않는다" 승격은 필수** — `TURN_BLOCKING`이 그 불변식의 새 소비자다. + +## B7. 결정된 사항 + +| 질문 | 결정 | +|---|---| +| 헤더 상한 | **균일 18, 예외 등록부 없음.** 예외 등록부는 파일마다 판단을 요구하는데, 무인 에이전트가 하면 안 되는 게 판단이다 | +| 6단계(가산적 추출) | **채택.** 2,030/1,364/1,209줄 신 파일이 이해도 문제의 본체다. 원본이 경로에 조립 루트로 남으므로 스펙 수리 0건 | +| U-30이 done 피처 2개 AC 편집 | **삭제 진행.** 168줄 죽은 코드를 영구히 남겨 "기존 항목 0건 편집" 보증을 지키는 건 잘못된 교환 | +| 페르소나 alias 제거 | **Part A로.** `listPrompts()`가 7→5로 바뀌는 와이어 계약 변경이다. 대신 허용목록 기계장치를 처음부터 끝까지 시험하는 첫 유닛으로 이상적 | +| 패리티를 CI에 상주 | **상주.** PR당 60~90초로 cladding이 한 번도 못 가졌던 관측 계약 회귀 그물을 얻는다 | +| Windows 엔트리 가드 | **동결**(U-50이 동작 변경 없이 추출+테이블 테스트). 수정은 `windows-latest` CI 레그와 함께 별도로 | +| 테스트 수 2,815 vs 2,821 | U-00에서 **1시간 상한**으로 규명, 못 밝히면 특성화 후 동결(이후 유닛 조사 금지) | + +## B8. 완료 정의 + +진척은 **줄 수가 아니라 분류별 작업목록 소진**으로 측정한다. 줄 수를 목표로 삼으면 숫자를 맞추려고 주석을 지우게 되고, 그게 금지된 부작용이다. + +**약속하는 숫자:** src 35,757 → ~32,400줄(**−9.4%**) · 주석 비중 28.5% → ~24% · tests 52,745 → ~50,800줄 · 모듈 경로 422(부재 0) → ~433(부재 0) · **`modules[]` 수리 0건 · `test_refs` 수리 0건 · 기존 스펙 항목 편집 2건** · 탐지기/스테이지/tier 불변. + +**정직한 상한:** 측정된 src 내 정확 교차 중복은 **256줄=0.7%**, 코드 수준 총 중복은 ~900~1,200줄. **−20% 이상을 약속하는 계획은 압축이 아니라 주석 삭제를 약속하는 것이다.** + +**DONE과 STOPPED의 구분은 기계적이다:** 모든 감사 도구를 돌려서 **잔여 등록부에 유닛 id와 함께 기록되지 않은 non-zero 발견이 하나라도 있으면 완료가 아니라 멈춘 것이다.** diff --git a/.refactor/REFACTOR.md b/.refactor/REFACTOR.md new file mode 100644 index 00000000..18a929e7 --- /dev/null +++ b/.refactor/REFACTOR.md @@ -0,0 +1,738 @@ +# cladding — refactor program design + +**Target:** `develop` @ v0.9.3, baseline commit `23ea6be`. **Executor:** an AI agent working unit by unit. +**Every number in this document was re-measured read-only this session.** Where a survey or an arm was wrong, the measured value is used and the correction is stated. + +--- + +## 1. What we are doing and what we are explicitly NOT doing + +We are compacting cladding **in place** — shrinking file contents, deleting provably-dead code, retiring duplicated logic into helpers, and putting the comment corpus under a machine-checked standard — while holding the observable contract (CLI, MCP, hooks, written artifacts, event ledger, gate dispositions) byte-identical, proven by a purpose-built parity harness that is itself mutation-tested before it is trusted. **ARM B won** because it is the only arm whose units already carry commands as their DONE conditions and because it discovered the one oracle nobody else has: `scripts/build.mjs` sets `minify: true` + `legalComments: 'none'` and `src/` contains **zero** `@__PURE__` / `@license` / `@preserve` annotations (verified), so a comment-only change to any of the 182 bundled source files **must** leave `dist/clad.js` byte-identical — turning the riskiest 40% of the work into a SHA-256 comparison. From **ARM C** we graft the parity harness design (freeze-not-mask determinism, alias tables rather than blanket masks, a constructed env, scripted git history, two-level stderr fidelity) and its **KILL CRITERION**: if the harness cannot prove it sees a planted change, the program stops. From **ARM A** we graft the additive-extraction phase — the `measure-extract` shape where a spec-pinned file stays at its path as a thin composition root and its body moves to a new sibling — admitted only *after* the MCP and bundle parity lanes exist, and we relax ARM B's "no new src file" rule accordingly: a new file costs exactly one `modules[]` line in the unit's own new spec entry, and that line is written by a tool, not by hand. + +**Explicitly NOT doing.** No file is renamed or moved (422 module paths are pinned by literal path across 275 spec entries, and **no `modules[]` repair writer exists anywhere in the codebase** — verified; only `src/spec/new.ts:310` emits `modules:`, at creation time). No behaviour change of any kind — every wire-visible change belongs to the 0.10.0 program (§8), including the persona-alias removal that all three arms wanted to fold in. No free-form "narrative comment" deletion: comment work is split into four classes and **class 4 is cut from the program** because no oracle in this repo can distinguish a good cut from a deleted decision record. No detector-table rewrite (measured ceiling: 455 lines = 1.3% of `src`, against a file count that is load-bearing in three places). No export hygiene (141 of the 261 unreferenced exports are type-only — types erase — and 106 are test seams already adjudicated in both directions by `tests/code-compact.test.ts:129-149`). No touching `src/graph/viewer/main.ts` (456 measured lines at 0% coverage). No `src/cli/scan/walker.ts` (its entrypoint-first ordering feeds `tests/cli/scan.test.ts`, cited by 32 `test_refs`). + +**Honest accounting of what is left behind if Phase 6 is declined (see §10 Q2):** `serve/server.ts` stays 2,030 lines, `cli/clad.ts` stays 1,364, `cli/hook.ts` stays 1,209, the 39 `.cladding` path literals stay across 21 files, and the `drive ↔ ui` directory cycle stays. + +--- + +## 2. The invariants + +The contract. Every one must hold **before** a unit starts and **after** it lands. `tools/checkpoint.ts` runs them in this order — cheapest and most diagnostic first, because the failing step index *is* the failure classifier (§7). + +| # | invariant | command | expected | +|---|---|---|---| +| **INV-1** | spec↔code map is exact | `npx tsx tools/audit/census.ts --assert` | `entries= modules=422 modules_absent=0 testrefs=243 testrefs_absent=0` | +| **INV-2** | scope was declared | `git diff --name-only HEAD` | ⊆ the unit record's `touch_allowed` | +| **INV-3** | fast tripwires green | `npx vitest run tests/code-compact.test.ts tests/self-consistency.test.ts tests/stages/detector-purity.test.ts tests/stages/interactive-profile-partition.test.ts tests/cli/verb-residue.test.ts tests/cli/gate-golden-matrix.test.ts tests/docs-prune.test.ts tests/plain-render.test.ts tests/terminology-canon.test.ts tests/instruction-led-language.test.ts tests/choreography-guard.test.ts` | exit 0 | +| **INV-4** | types | `npx tsc --noEmit` | exit 0 | +| **INV-4b** | type program is non-vacuous | `npx tsc --noEmit --listFiles \| grep -c '/src/'` | `185` (186 minus `src/graph/viewer/**`) | +| **INV-5** | lint | `npx eslint .` | exit 0, no output | +| **INV-6** | full suite — **never scoped** | `npm test` | `249` files, `0` failed | +| **INV-7** | public test-count claim | `npm run test-count -- --check` | `check passed` | +| **INV-8** | generated mirrors + committed bundle | `npm run build && git diff --exit-code` | exit 0 | +| **INV-9** | conformance | `npm run conformance` | exit 0 | +| **INV-10** | gate (also re-stamps attestation) | `node bin/clad check --tier=pre-push --strict` | GREEN | +| **INV-11** | attestation committed with the code | `git show --stat HEAD \| grep -c spec/attestation.yaml` | `1` on any unit that changed a claimed module | +| **INV-12** | parity | `npx tsx tools/parity/compare.ts --tier=fast` | `IDENTICAL` or every delta matched by a pre-registered `allow.yaml` entry | +| **INV-13** | the harness can still see a change | `npx tsx tools/parity/selftest.ts` | `/ REGRESSION` (N grows per lane) | +| **INV-14** | bundle identity for comment-only units | `shasum -a 256 dist/clad.js dist/viewer/app.js` | unchanged from the unit record's `inherits.bundle_sha` | +| **INV-15** | coverage did not fall | `npx vitest run --coverage` | exit 0 against the U-02 floor | +| **INV-16** | manifest honesty | `npx vitest run tests/manifest-honesty.test.ts` | green — `allDetectors.length` == detector file count == `plugin.json` numerator | +| **INV-17** | detector emission order | `npx vitest run tests/detector-order.test.ts` | golden array of 41 names, in order | +| **INV-18** | forbidden paths untouched | `git diff --name-only HEAD \| grep -E '^(src/cli/clad\.ts\|src/spec/(schema\.json\|types\.ts\|validate\.ts)\|src/agents/\|src/graph/viewer/)'` | empty, unless the unit record names the file **and** states why | +| **INV-19** | allowlist did not grow silently | `wc -l < tools/parity/allow.yaml` | equals `inherits.allowlist_entries` unless the unit registered a delta in its own prior commit | + +**Forbidden moves, for the whole program, no exceptions.** `src/cli/clad.ts` · `src/spec/schema.json` · `src/spec/types.ts` · `src/spec/validate.ts` · `src/agents/*.md` · `src/graph/viewer/main.ts` · `src/graph/viewer/styles.css` · the 13 `src/stages/*.ts` npm-script targets · `TIER_STAGES` out of `clad.ts` · any non-detector `.ts` inside `src/stages/detectors/`. +Reasons, each verified: `harness-integrity.ts:243-252` parses `clad.ts` as **text** and on a parse miss `return`s with *no finding*, while `scripts/build-plugin.mjs:481-509` uses the identical regex and on a miss only `console.warn`s — the checker and its writer go vacuous together, and `tests/stages/harness-integrity.test.ts:64-70` cannot catch it because it synthesises its own `clad.ts`. `src/spec/schema.json` has three independent hardcoded readers (`scripts/build.mjs:50`, `src/spec/validate.ts:16-18` **at import time**, `src/stages/detectors/meta-integrity.ts:34`) plus 18 claiming entries. `src/stages/detectors/` file count is read by two counters that structurally cannot disagree with each other while `allDetectors` is read by neither (INV-16 closes this). + +**Global serialization.** One structural unit in flight at a time — every source-changing commit rewrites the git-tracked 1.5 MB minified `plugins/claude-code/dist/clad.js`, and two structural branches produce a conflict no agent can resolve. Comment-only units are bundle-neutral (INV-14) and may be parallelised; their empty `git diff plugins/claude-code/dist/clad.js` is itself the proof that the commit was comment-only. + +**Warranty limits on INV-14, which must be written into the executing agent's brief.** BUNDLE-ID proves *runtime-semantic identity of bundled code*. It is blind to: (a) the **4 live `eslint-disable-next-line` directives** in `src/` (`src/cli/scan/scenarios.ts:35`, `src/cli/scan/dispatcher.ts:131`, `:211`, `src/adapters/sdk/anthropic.ts:102`) — deleting one turns lint red while the bundle stays identical; (b) the 4 src files in no bundle (`src/cli/benchmark.ts`, `src/optimizer/preamble.ts`, `src/optimizer/tail.ts`, `src/spec/cli.ts`); (c) `CONVENTION_DRIFT`, which requires the *first non-empty line* of every declared module to open a comment. All three are caught by INV-5 / INV-6 / INV-10 — but an agent handed "byte-identical bundle ⇒ no side effects" will rationally skip them, so the limits are stated, not implied. + +--- + +## 3. The parity harness (unit 0) + +Built as a top-level `tools/` directory. Verified free: `UNMAPPED_ARTIFACT`'s `scanPatterns` emits `src//**/*.` per declared layer, so nothing outside `src/` is scanned; `scripts/test-count.mjs --check` runs **first** in `npm run build` and counts `tests/**/*.test.ts`, so a harness built as vitest suites would block the build on case one; `tsx ^4.19.0` and `yaml` are already devDependencies. `tools/**/*.ts` files **are** claimed in their unit's `modules[]` (one line each) so they inherit `CONVENTION_DRIFT`, `MISSING_IMPLEMENTATION` and attestation coverage. + +``` +tools/ + checkpoint.ts runs INV-1..19 in order, prints one PASS/FAIL + parity/ + normalize.ts THE single rewrite pipeline — imported by BOTH capture and compare + capture.ts materialize fixtures → run case tables → write golden/ + compare.ts normalize → diff → verdict → exit 0/1 + selftest.ts apply each mutant, capture+compare, require REGRESSION + lanes/{cli,mcp,hook,artifact,events,bundle,cleanroom,tty}.ts + cases/{cli,mcp,hook,artifact}.yaml + fixtures/ golden/ mutants/ allow.yaml + audit/ + census.ts INV-1; also readManifest∩modules overlap, STALE_TESTS headroom + comments.ts the machine-checkable half of §4 + spec-remap.ts --claim --feature (append one modules[] line) +``` + +### 3.1 Fixture corpus — five tiers, four already in the repo + +| tier | source | drives | +|---|---|---| +| **FX-A `self`** | this repo at the pinned commit, extracted with `git archive` into a temp dir | richest spec (275 entries, 422 paths), all 41 detectors, real toolchain | +| **FX-B `existing-ts`** | copy of `tests/scenarios/_fixtures/sample-existing-ts` — **exclude the committed `.DS_Store`** | `init --scan`, `clarify`, `context`, `impact` | +| **FX-C `seeds`** | the 4 toolchain-less seeds from `tests/scenarios/vacuous-green-seeds.test.ts` | gate dispositions; its header already states the determinism rationale (no toolchain ⇒ 1.1/1.2/2.1/2.2 skip deterministically, no network) | +| **FX-D `greenfield-empty`** | **new** | bare `init`, the uninitialized MCP boundary, hook events with no spec | +| **FX-E `conformance`** | the existing runnable fixtures | captured as exit code + per-fixture verdict table | + +### 3.2 What each lane captures + +- **CLI** — an **explicit** case table in `cases/cli.yaml` (`{caseId, fixture, argv[], envDelta, mutating}`), never a generated permutation sweep: a generated matrix silently drops a case when a flag is renamed; an explicit table goes RED. Per case: argv, exit code, stdout bytes, stderr bytes, and for mutating cases a post-run sorted `path → sha256` tree manifest. Read-only sweep covers all 28 registrations × their `--json`/`--format` variants and all 28 ` --help`. Exit codes are captured from the spawned process, **never through a shell pipe** — `src/cli/clad.ts:835-840` deliberately sets `process.exitCode` and returns rather than calling `process.exit()`, because `--json` can exceed the 64 KB pipe buffer. +- **MCP** — in-process `Client` + `InMemoryTransport` + `buildServer({cwd})`, the idiom already proven at `tests/serve/description-budget.test.ts:31-35`. Capture `listTools()` (name, title, description **byte-exact**, and the SDK's zod→JSON-Schema serialization — a zod refactor can change the wire schema while the TS type is unchanged), `listResources()`, `listPrompts()`, the `instructions` string, the `capabilities` object, `readResource()` ×3, `getPrompt()` ×7 with and without `featureId`, `callTool()` ×22 on three fixtures **on both success and error branches** capturing the **whole response object** (not just `content[0].text`), the prepare→stage→apply onboarding triple, and the subscribe/unsubscribe `{}` replies. Serialize schemas twice: key-sorted (semantic) and declaration-order (host-observable). *Rationale for the whole-object rule:* measured in `src/serve/server.ts` — 22 `registerTool`, 26 `mcpPayload(`, **49** `type: 'text'` envelopes, **20** `schema_version` occurrences. Roughly half the responses carry neither `structuredContent` nor `schema_version`, so any envelope helper changes ~23 responses and a `listTools()`-only capture is structurally blind to it. +- **Hook** — cases are **sequences** (fresh `.cladding/`, payloads 1..N), because six sidecars persist across invocations. Each sequence runs **twice**: in-process via the exported `runHookEvent()` and as a subprocess via `node bin/clad hook < payload.json`; the two are diffed against each other as well as against the golden. An S↔B divergence is a bundle-entry regression and nothing else produces it. Must include the Stop-hook repeat-fingerprint demotion and `.cladding/stop-block.json` resurfacing on the next SessionStart. Golden includes final sidecar contents with `mtimeMs` masked. +- **Artifact** — after every mutating case, a sorted `path → sha256` manifest of the whole fixture **plus full text** for the ~30 governed paths. `.cladding/` is gitignored, so the manifest is the only way to see it move. +- **Events** — normalized ledger diff **plus** a per-case type histogram. A masked line-diff misses an event that stopped firing when the line count coincidentally matches; the histogram cannot. Assert the 9-member `ImpactSkipReason` enum is exhaustively reachable across the corpus. +- **Bundle (S vs B)** — the entire fast tier run twice: lane S (`npx tsx src/cli/clad.ts`) and lane B (`node bin/clad` with `dist/` freshly built), diffed against each other. `dist/clad.js` is minified with identifier renaming, so byte-diffing the bundle is meaningless; diffing its *behaviour* against source is not. Verified motivation: `__CLADDING_BUNDLED` appears in **17 src files and 0 test files**, and the only real-bundle execution anywhere is CI's `node bin/clad check --tier=pre-commit --strict` — 1 of 28 verbs, 1 of 3 tiers. +- **Clean-room** (per phase, not per unit) — `npm pack` → install into an empty dir → run the fast tier. The only thing that catches a new module falling outside `package.json` `files:` (verified: `["bin/","dist/",".claude-plugin/","plugins/","AGENTS.md",…]` — a new `src/` module reaches users only through the bundle). +- **TTY** — a small in-process lane stubbing `process.stdout.isTTY = true` and capturing writes through a fake stream. `src/ui/pulse.ts:49` gates on `isTTY`, so every piped capture otherwise records only the non-interactive branch — the branch a human never sees. No pty dependency. + +### 3.3 Determinism — seven sources, each neutralized deliberately + +1. **Wall clock** — 34 `Date.now()`/`new Date(` sites across 18 files; only `bundle` and `doctor-hosts` accept an injected clock. **Use the injection where it exists** so those goldens stay byte-exact; mask the rest as `«TS»`/`«DATE»`. `src/cli/doctor-hosts.ts:632-633` puts the date in the artifact **filename** — mask the path too. +2. **Clock-dependent detector verdicts** — `STALE_EVIDENCE` (90 d) and `STALE_TESTS` (`STALE_DAYS = 30`, verified) change `worst`/`anyFailed`, which is the primary parity signal. **Freeze, do not mask:** `utimesSync` every fixture file to one fixed epoch (making the `STALE_TESTS` delta identically zero) and seed evidence at `captureStart − 1 day`. Then add **one deliberate variant per detector** (a test back-dated 40 d, evidence back-dated 100 d) so the harness proves the detector still *fires*. A normalization that silences a detector everywhere is a harness that cannot see the detector break. +3. **Minted ids** — `src/spec/new.ts` seeds `F-`/`AC-`/`S-` ids from `slug|username|hostname|Date.now()|hrtime`; `src/serve/server.ts:536` mints `APPLY CLADDING `. **Alias table, not blanket mask:** snapshot the pre-run id set; only ids absent from it become `«F1»`/`«AC1»`/`«S1»`. Blanket-masking would erase every cross-reference signal in FX-A. Drive the MCP onboarding lane by echoing back the challenge the server actually returned. +4. **Machine + env** — 8 provider keys select the LLM path purely by presence; `src/stages/toolchain/detect.ts:436` scans the **entire** `process.env`. **Construct** the env: `{PATH, SHELL, TMPDIR}` + `TZ=UTC LANG=C HOME=/.home GIT_CONFIG_GLOBAL=/.gitconfig`, with the 8 keys explicitly unset. Record the constructed env in the manifest; a golden may never be compared against a capture taken under a different env. +5. **Git state** — `git describe --tags --abbrev=0` is the default `--since` for `changelog`, `report` and `bundle`, so tagging a release mid-program changes their entire output. **Script the history:** `git init`, fixed user, fixed `GIT_AUTHOR_DATE`/`GIT_COMMITTER_DATE`, fixed commits, one tag ⇒ SHAs are byte-identical and need no masking. For FX-A pass `--since ` explicitly on every case. +6. **Filesystem ordering** — `src/serve/server.ts:1884-1907` orders `clad_list_features` by shard mtime. The epoch freeze from (2) makes that a stable tie; **verify it empirically in the selftest**, do not assume it. +7. **Stage stderr** — `src/stages/util.ts:76` splices 2,000 chars of raw tsc/eslint/madge/secretlint/vitest output (absolute paths, versions, durations) into `check --json`. **Two levels.** L1, compared strictly: `{stage, label, status, exitCode}` plus the drift stage's full findings array with detector+severity+message+order (those messages are cladding-authored and pinned by `tests/plain-render.test.ts`). L2, compared loosely: `{present, lineCount, firstLineNormalized, lengthBucket}`. Record tool versions in the manifest so an L2 divergence is attributable to a toolchain bump. + +**Deterministic by construction — must NOT be normalized.** `spec/index.yaml` (double sort), `spec/attestation.yaml` (sorted modules, `` sentinel for a missing file), `graph export --format json|mermaid|dot|html` (`src/graph/layout3d.ts:10`: "every coordinate derives from FNV-1a(id); no Math.random / Date"), `oracle` AC sampling, `bundle` with an injected `now`. These five are the highest-signal cases in the corpus; compare them with **zero** normalization and put them in the fast tier. + +### 3.4 Comparison and verdicts + +Three verdicts. **IDENTICAL** — byte-equal after normalization. **EXPECTED-DELTA** — matches an entry in `tools/parity/allow.yaml`, where each entry carries `{caseId, exact unified-diff hunk (no wildcards), one-line reason, unit id, registered-in-commit}`. **REGRESSION** — everything else, exit 1. + +Two further rules, both load-bearing: **a stale allow entry is an error** — if an entry stops matching, the allowance outlived its change and must be deleted, otherwise the allowlist degenerates into blanket suppression, which is the vacuous-green pattern this repo exists to prevent. And **an agent may never add an allow entry to make its own unit pass** (§7 class D). + +JSON is canonicalized key-sorted for the semantic diff, with a separate declaration-order fingerprint. **ANSI is not stripped** — `src/ui/pulse.ts:31-46` emits real colour codes and a lost colour is a real regression. + +Two tiers: **fast** (~200 cases — CLI read-only, MCP listings, hooks, the five zero-normalization surfaces; target < 90 s) per unit; **full** (~1,200 cases incl. mutating, conformance, bundle S/B) per phase; **clean-room** per phase. + +### 3.5 The selftest — the kill criterion + +`tools/parity/mutants/` holds deliberate, reverted-after-capture mutations. Seven at minimum, growing by one per lane: + +1. change one word in a drift finding message · 2. reorder two keys in an MCP payload · 3. flip one exit code 1→2 · 4. delete one event emission · 5. change one field in `spec/index.yaml` · 6. flip one detector's severity · 7. change one byte of a persona prompt · 8. (hook lane) change one sidecar field name · 9. (bundle lane) break one module's entry guard. + +`npx tsx tools/parity/selftest.ts` applies each to a scratch worktree, captures, compares, and requires **REGRESSION for every one**. A mutant returning IDENTICAL names an over-normalization and blocks the unit. The likeliest over-normalizations, in order: (7) stderr fingerprinting, (3) id aliasing, (2) mtime freezing. + +> **KILL CRITERION.** If the selftest is not green on all mutants at U-11, **the program ends there**. An unfalsifiable harness is worse than no harness, because it converts "I checked" into "the tool said so". The selftest re-runs at every phase boundary; a failure there means every unit since the last green selftest was verified by a blind oracle and must be reverted (§7 class E). + +--- + +## 4. The comment standard + +### 4.1 `src/**/*.ts` + +Required, first byte of the file: + +``` +// Cladding · · — F- ← line 1, required +// +// ← required, ≥1 line +// +// @see ← optional, 0..n +``` + +| rule | machine-checkable? | how | +|---|---|---| +| **R1** line 1 matches `^// Cladding · [^·]+ · .+$`, optionally ` — F-` | **yes** | `comments.ts --rule=banner` | +| **R2** the block states a decision / constraint / rejected alternative, never a paraphrase of the signature | **no** — human | only presence is checked | +| **R3** header ≤ **12** lines; ≤ **24** for the 9 named contract modules (`src/spec/types.ts`, `src/stages/types.ts`, `src/adapters/types.ts`, `src/verdict/gate-progress.ts`, `src/stages/detectors/with-spec.ts`, `src/stages/util.ts`, `src/stages/detector-result-cache.ts`, `src/stages/detectors/unmapped-artifact.ts`, `src/stages/detectors/hardcoded-secret.ts`); per-file exemptions listed in `tools/audit/exemptions.yaml` with the unit id that granted them | **yes** | `--rule=header-cap` → `offenders=0 visited=186` | +| **R4** no header restates a feature's acceptance criteria verbatim | **no** — human | | +| **R5a** no count of anything the codebase owns — name the symbol (`allDetectors`) | **yes** | regex + a resolver that knows the true counts | +| **R5b** no `file:line` coordinates — cite the symbol | **yes** | `/\.(ts\|js\|mjs\|md):\d+/`, allow-listing `src/stages/finding-parser.ts` which quotes compiler output as sample data | +| **R5c** no future-release promise ("removed in 0.8"); past-tense provenance ("0.6.0 renamed X to Y") is allowed | **yes** | `/(removed\|lands\|ships\|deprecated) in v?0\.\d/` where the named version ≤ `package.json.version` | +| **R5d** no date as a *time claim* ("as of", "currently", "recently"); a date as a *decision label* ("the 2026-07-06 locale pivot") is allowed | **yes** | ISO date not preceded by a decision-label word | +| **R5e** no unresolvable repo path; no path outside the repo (use a full `https://` URL) | **yes** | filesystem resolve | +| **R5f** no bare SHA / PR number as the sole justification; `(#215)` may follow a stated reason | **yes** | regex | +| **R6** spec ids cited **bare** (`F-9af291fa`), never as `spec/features/F-…​.yaml` | **yes** | resolve against `spec/features/ ∪ spec/scenarios/ ∪ spec.yaml`, with a named allowlist for the 3 illustrative ids (`F-abc123`, `F-a3f9c2`, `F-083`) | +| **R7** all paths repo-root-relative, no leading `./` | **yes** | one convention replacing today's four | +| **R8** JSDoc: every exported symbol gets a one-line summary; `@param`/`@returns` **only** when the meaning is not recoverable from name+type; **`@throws` required** whenever the function can throw; non-exported helpers need no block | **partly** | `jsdoc/require-jsdoc` on exports (R8a); `@param x - <≤3 words containing x>` flagged as restatement (R8b); `@throws` is human | +| **R9** zero `TODO/FIXME/XXX/HACK` — already perfectly observed in 186 files | **yes** | regex | +| **R10** comments in English. The 6 load-bearing Hangul regex literals (`src/router/intent.ts:47,59,66,73,85`; `src/cli/hook.ts:240`) and `src/init/agents-md.ts`'s bilingual EARS example are **inputs**, not prose | **yes** | Hangul outside a string literal | +| **R11** `eslint-disable*` and `@ts-expect-error` are **code, not comments** — never deleted by a comment unit | **yes** | 4 live sites, enumerated in §2 | + +**Why R8 codifies the practice and not the aspiration.** Measured: 357 of 373 exported functions (96%) carry a doc block, but only 59 of 341 parameterized ones (17%) carry `@param` — and only 2 of 87 existing `@param` tags restate a name. `docs/code-style.md:33-43` mandates the full field set and is violated 282 times; mass-adding those tags would add ~800 lines of restatement and contradict the same document's Why>What principle. + +**Prerequisite, and it is the root cause.** `docs/code-style.md:3` declares itself the SSoT (echoed by `AGENTS.md:38`) while `docs/README.md:14` and `docs/ssot-model.md:63` file it as Tier-C legacy to be deprecated — and its §3 **mandates** `@see ironclad-design/
.md` and `@see iron-law.md`, neither of which exists in this repo (verified: `ls docs/ironclad-design` → no such directory; `find . -name iron-law.md -not -path ./node_modules/*` → 0 hits). Those two forms account for **36 of the dangling references** (19 + 17, measured). Until §3 is rewritten, every comment written to the current standard adds a new dangle. U-06 fixes this before any comment unit runs. + +**Before / after — src** + +```diff +-// Cladding · drift detectors · with-spec +-// +-// Shared spec-loading wrapper. The 11 SPEC-vs-REALITY detectors route +-// through withSpec: ac-drift, convention-drift, deliverable-integrity, +-// doc-reference-integrity, hollow-governance, missing-implementation, +-// project-context-drift, planned-backlog, missing-tests, scenario-coverage, +-// smoke-probe-demand. +-// +-// The 6 WITHIN-SPEC-VALIDITY detectors deliberately do NOT use withSpec … +-// … (38 more lines) … +-// @see iron-law.md stage_1.3 +-// @see spec/features/F-084.yaml AC-121 ++// Cladding · drift detectors · with-spec — F-9af291fa ++// ++// Load-failure policy for the whole detector layer. A detector that ++// compares SPEC against REALITY must route through withSpec, which ++// downgrades a load failure to `info` — returning [] instead was ++// rejected: it ships a Vacuous Green (the 2026-05 ledger audit found ++// the entire layer info-degrading on a schema-invalid spec, with a ++// full green gate). A detector that validates only WITHIN the spec ++// returns [] silently, because a missing spec is not its finding to ++// make; META_INTEGRITY carries the blocking signal instead. ++// The two rosters are derived by tests/detector-taxonomy.test.ts — ++// do not enumerate them here; the last enumeration drifted 11→21. +``` + +Header: 47 → 12 lines. R5a (counts) removed, R5e (2 dangling `@see`) removed, R6 satisfied, and the fact that was in the roster is now **derived by a test** (U-05) rather than restated in prose. + +### 4.2 `tests/**/*.ts` + +Required in **every** file, not only declared modules. This closes a verified structural blind spot: `CONVENTION_DRIFT` walks `features[].modules` only, 99 test files are declared and all 99 have headers, and the 25 headerless files are exactly the 25 that are undeclared. + +``` +// Cladding · — F- +// +// TEST-AUTHOR context: +// +// Sibling ownership: +// +// AC map: +// AC- +``` + +| rule | checkable? | +|---|---| +| **T1** line 1 names ≥1 F-id that resolves | **yes** | +| **T2** every `AC-` in the header resolves **and** resolves under a feature this file is a `test_ref` of | **yes** — this is the clause that makes the refactor auditable: it is how you prove a consolidated test still covers the same criteria | +| **T3** the TEST-AUTHOR line is present (19 of 272 files today) | presence **yes**; truthfulness **no** | +| **T4** sibling-ownership note wherever ≥3 suites share a directory | **no** — human | +| **T5** grep-shaped tripwire suites declare themselves (the `tests/code-compact.test.ts:1-15` form) and assemble their needles at runtime so they never self-trip | **yes** | +| **T6** inline comments explain *why an assertion has teeth*, not what the code does | **no** — human | + +Target comment share stays near today's measured 10.7% — tests are leaner by design. + +**Before / after — tests** + +```diff +-// Scenario helpers. +-// See tests/cli/refine.test.ts for the sibling suite. ++// Cladding · scenario fixture helpers — F-7c1d2e44 ++// ++// TEST-AUTHOR context: support module, not a suite. No assertions here. ++// ++// Sibling ownership: the clarify lane is pinned by ++// tests/cli/clarify.test.ts (renamed from refine.test.ts in 0.6.0). ++// This file owns fixture materialization only. +``` + +### 4.3 The four classes — and why class 4 is cut + +| class | content | DONE condition | lines | +|---|---|---|---| +| **1 — reference integrity** | 36 dangling `@see`, 12 unresolved F-ids, 4 path conventions → 1 | `comments.ts --rule=refs --assert-clean` → `findings=0 visited>150` | ≈ −125 | +| **2 — stale-by-construction** | counts, `file:line`, version promises, dates-as-time-claims, the `UNMAPPED_ARTIFACT` severity row, the EARS count stated 3× in one file, `drift.ts`'s abandoned-architecture header | one regex rule per ban, each with a planted-defect probe; `findings=0` | ≈ −60 deleted, ≈ −150 changed | +| **3 — header cap** | R3 | `--rule=header-cap` → `offenders=0 visited=186` | **−932** (measured, cap 12 / 24-exempt) | +| **4 — free-form narrative removal** | "history narration", "compress in place" | **none exists** | **CUT** | + +Class 4 is cut because parity is IDENTICAL either way, BUNDLE-ID is byte-identical either way, and coverage is unchanged either way — a 1,000-line deletion justified by "the reviewer judged it re-derivable" is an assertion, and the maintainer's bar is empirical evidence. The residue is recorded as accepted debt in §9, not deleted on judgement. + +**The one thing classes 1–3 must never do**, because nothing in this repo can catch it: **no gate check reads a single byte of `src/**` comment content.** Verified — `CONVENTION_DRIFT` checks only that the first non-empty character opens a comment; `REFERENCE_INTEGRITY` reads only `depends_on` / `superseded_by` / `scenarios[].features` and opens no source file; `DOC_LINK_INTEGRITY` walks `join(cwd,'docs')` only. **(This corrects the task brief's premise #5.)** So the risk is not that a check breaks — it is that the only record of an invariant vanishes with nothing turning red. **U-05 converts every such record into an executable assertion before any comment unit runs**, and the comment units carry a grep-checkable diff rule: *any deleted hunk matching `/MUST|never|only|invariant|severity|finally|rejected|DEFERRED/` must be replaced by a named test in the same commit.* + +--- + +## 5. The work units + +### 5.1 Granularity rule + +> **One unit = one commit = one reason to change, bounded by ≤400 changed lines and ≤12 touched files, closed by a DONE list in which every entry is a command with a literal expected output.** +> **If any DONE entry can only be written as prose, the unit is inadmissible** — split it, or build the instrument that produces the command first, or drop it. + +**Mechanical-rule exception to the 12-file cap.** A unit may touch a whole directory when (i) exactly one rule is applied, (ii) a tool asserts `offenders=0`, (iii) INV-14 shows the bundle byte-identical, and (iv) ≤400 lines change. The file cap exists to make `touch_allowed` verifiable by inspection; for a mechanical rule the tool *is* the verification. Only the class-3 header units and the test-scaffolding units use it, and each names the exception in its record. + +**Floor rule.** Do not split below one reason-to-change even when the line count is trivial. `tsconfig` (2 lines), the coverage ratchet (6), and the manifest-honesty test (15) stay three units: different rollbacks, different preconditions, different things made visible. + +### 5.2 Unit table + +Risk: **L** = revert is a single `git revert`, no derived artefacts · **M** = derived artefacts or generated mirrors move · **H** = spec YAML moves, or a silent-failure vector is in scope. + +| id | title | files | Δ lines | depends-on | risk | +|---|---|---|---|---|---| +| **U-00** | Baseline freeze (measure only) | 0 | 0 | — | L | +| **U-01** | `tsconfig` include repair | 1 (+`src/spec/cli.ts` fallout) | +2 / −1 | U-00 | L | +| **U-02** | Coverage ratchet at the measured floor | 1 | +6 | U-00 | L | +| **U-03** | `MANIFEST_HONESTY` test | 1 test + 6 READMEs | +15 | U-00 | M | +| **U-04** | Detector-order golden | 1 test + 6 READMEs | +30 | U-00 | M | +| **U-05** | Invariant lift: 5 comments → assertions | 4 tests + 6 READMEs | +180 | U-00 | M | +| **U-06** | `docs/code-style.md` §3 rewrite + SSoT contradiction | 3 docs | ~90 | U-00 | L | +| **U-07** | Dangling `test_ref` cleanup (2 archived entries) | 2 spec | −3 | U-00 | M | +| **U-10** | Parity core: `normalize` + fixtures + CLI lane | 8 tools | +1,100 | U-01 | L | +| **U-11** | Parity mutants + selftest ◀ **KILL CRITERION** | 3 tools + 1 test | +320 | U-10 | L | +| **U-12** | Parity MCP lane (+mutant) | 3 tools | +350 | U-11 | L | +| **U-13** | Parity hook lane, S+B dual (+mutant) | 3 tools | +300 | U-11 | L | +| **U-14** | Parity artifact + events + TTY lanes (+mutant) | 4 tools | +280 | U-11 | L | +| **U-15** | Parity bundle lane (S vs B) + clean-room | 3 tools | +280 | U-13 | M | +| **U-16** | `tools/audit/census.ts` + `comments.ts` + `checkpoint.ts` | 4 tools + 1 test | +700 | U-10 | L | +| **U-17** | `tools/spec-remap.ts --claim` | 1 tool + 1 test | +260 | U-16 | M | +| **U-20** | ESLint scope repair — **alone, formatting only** | 1 config + ~20 src | ~27 changed | U-11, U-12 | M | +| **U-30** | Delete `optimizer/preamble.ts` + `tail.ts` (ritual rehearsal) | 4 del + 3 spec + 6 READMEs | −170 | U-11, U-16 | **H** | +| **U-31** | Dead symbols: git-hook wrappers, `TIER_COL`, `getTierColor`, `void cwd` | 7 | −58 | U-30 | M | +| **U-40** | Comment class 1 — reference integrity | ~45 | −125 | U-06, U-16, U-20 | L | +| **U-41** | Comment class 2 — stale facts | ~30 | −60 / ~150 chg | U-05, U-40 | L | +| **U-42** | Header cap — `src/stages/detectors/` (30 over) | 30 | −330 | U-41 | L | +| **U-43** | Header cap — `src/cli/` + `src/stages/` (33 over) | 33 | −201 | U-42 | L | +| **U-44** | Header cap — remaining 15 directories (50 over) | 50 | −401 | U-43 | L | +| **U-50** | `isCliEntry` predicate extracted + table-tested | 3 + 1 test | +60 | U-15, U-05 | **H** | +| **U-51** | `cliEntry(importMetaUrl, fn)` applied to 15 runners | 15 | −60 | U-50 | M | +| **U-52** | `detectorBackedStage` (arch ≡ secret) | 3 | −30 | U-51, U-05 | M | +| **U-53** | `scopedStageCommand` + `gateScriptCommand` | 7 | −54 | U-52 | M | +| **U-54** | `readJsonOr` in `src/stages/**` (~10 sites) | 11 | −40 | U-53 | L | +| **U-55** | `hook.ts` sidecar factory + one counting home | 1 | −150 | U-13, U-05 | M | +| **U-56** | `server.ts` `specHandler` + `shimHandler` (in-file) | 1 | −170 | U-12 | M | +| **U-57** | `clad.ts` attestation EXEMPT/STAMP helpers (in-file) | 1 | −20 | U-15 | M | +| **U-58** | `renderScenarioYaml` + conventions table + micro-helpers | 5 | −50 | U-17 | M | +| **U-59** | `intent-onboarding` interpret merge — **CONDITIONAL** | 1 + fixtures | −65 | stub-dispatcher lane | **H** | +| **U-60** | `src/core/paths.ts` — the `.cladding` home | 22 | −45, +1 file | U-17, U-14 | M | +| **U-61** | `src/core/read.ts` — repo-wide read-with-fallback (batched ≤8 files) | 14 | −250, +1 file | U-60 | M | +| **U-62** | `src/stages/cli-entry.ts` + `command-stage.ts` extraction | 17 | −80, +2 files | U-51, U-53 | M | +| **U-63** | `src/serve/onboarding-staging.ts` extraction | 2 | ±0, +1 file | U-56 | M | +| **U-64** | `src/serve/tools/*.ts` + `resources.ts` + `prompts.ts` | 7 | +50, +5 files | U-63 | M | +| **U-65** | `src/cli/hook-sidecar.ts` + `hook-bash-lane.ts` | 3 | +24, +2 files | U-55 | M | +| **U-66** | `src/cli/program.ts` + `src/verdict/attestation-gate.ts` | 3 | −60, +2 files | U-57 | **H** | +| **U-67** | Break `drive ↔ ui`: `src/core/halt-reason.ts` | 4 | −5, +1 file | U-62 | M | +| **U-70** | Break the 5 cross-test source couplings | 6 tests | ~150 chg | U-11 | M | +| **U-71** | `tests/_support/` + migrate the 73 unreferenced files | 75 | −900, +2 files | U-70 | M | +| **U-72** | Migrate `tests/stages/` (pinned, contents only) | ~81 | −400 | U-71 | M | +| **U-73** | Migrate `tests/cli/` + `tests/spec/` | ~60 | −350 | U-72 | M | +| **U-74** | Migrate the remainder | ~35 | −250 | U-73 | M | +| **U-75** | Test header standard + the 25 headerless files | 25 + 1 test | +180 / −250 | U-16, U-74 | M | +| **U-80** | Pin renegotiation residue + exemption register | ~6 tests | ~80 chg | U-74 | M | +| **U-81** | Tooling disposition (a decision, not a cleanup) | varies | 0 to −2,300 | all | L | + +**49 units.** All three arms under-counted by roughly 2×. + +### 5.3 Unit blocks + +Every block below is executed with the §2 invariants as its outer contract; only the **unit-specific** verification is written out. + +--- + +#### PHASE 0 — Baseline and net + +**U-00 · Baseline freeze** +*Goal:* nothing in this program may be designed on an unmeasured number. +*Scope:* read-only; writes only to the scratchpad and to `.refactor/baseline.json`. +*Actions:* record at the pinned commit — per-directory `wc -l` and comment share; `vitest list --json` collected count **vs** `vitest run` executed count and **the explanation of the delta**; per-suite times from `.cladding/test-report.junit.xml`; per-file `coverage/coverage-summary.json`; the census tuple; max test-file age (`STALE_TESTS` headroom); tool versions of tsc/eslint/madge/secretlint/vitest; the `dist/` SHA-256 pair. +*Verify:* `census --emit` prints `entries=275 modules=422 modules_absent=0 testrefs=243 testrefs_absent=1`. Any other tuple means the working tree is not the assumed baseline — **stop**. +*Known baseline facts to record so no later unit investigates them as its own regression:* `README.md` badge pins **2815**, `.cladding/test-report.junit.xml` reports **2821** executed across 249 suites in 115.82 s — a **live, unexplained 6-test delta between `vitest list` and `vitest run`**. `scripts/test-count.mjs --check` compares against `vitest list` only, so the delta is stable and harmless. Characterize it here; never "fix" it inside another unit. +*Rollback:* n/a. + +**U-01 · `tsconfig` include repair** +*Goal:* stop type coverage being a side effect of test imports. +*Scope:* `tsconfig.json`; whatever `src/spec/cli.ts` surfaces. The unit's spec entry claims `tsconfig.json` in `modules[]` (verified: no entry claims it today). +*Evidence:* `include` currently lists `stages/**`, `spec/**`, `hitl/**`, `router/**`, `ui/**`, `cli/**`, `optimizer/**`, `events/**`, `drive/**` — **9 of 12 globs match nothing**; source moved under `src/` at the v0.2.16 layout change. Only `tests/**`, `conformance/**` and `vitest.config.ts` resolve. +*Actions:* `include: ["src/**/*.ts","tests/**/*.ts","conformance/**/*.ts","tools/**/*.ts","vitest.config.ts"]`, `exclude: ["src/graph/viewer/**"]` (DOM + `three` globals; already ESLint-ignored at `eslint.config.js:13`). +*Invariant preserved:* `tsc --noEmit` exit code stays 0. +*Verify:* INV-4 and **INV-4b** (`--listFiles | grep -c '/src/'` → `185`). +*Rollback:* revert one line. + +**U-02 · Coverage ratchet** — `vitest.config.ts` gains `thresholds` at the U-00-measured floor (`vitest.config.ts:32-45` declares none today, and `src/stages/cov.ts:4-9` delegates enforcement to the project, so `stage_2.2` passes at any coverage level). *Verify:* INV-15 exits 0 at baseline; then in a scratch worktree set `lines: 99` and confirm non-zero — the ratchet must be shown to bite. *Rollback:* revert 6 lines. + +**U-03 · `MANIFEST_HONESTY`** — new `tests/manifest-honesty.test.ts`: `expect(allDetectors.length).toBe(detectorFilesOnDisk())` **and** `expect(plugin.json.ironclad.current.detectors).toBe(\`${n}/${n}\`)`. +*Evidence, and it is a live vacuous green:* `ls src/stages/detectors/*.ts` = **44**; both `harness-integrity.ts:96-103` and `build-plugin.mjs` Phase D subtract the same 3 helpers → **41**; `allDetectors` = **41**; `plugin.json` = `"41/41"`. They agree by naming luck. `HARNESS_INTEGRITY` compares `plugin.json` to the **file count** and Phase D **writes** `plugin.json` from that same file count — they cannot disagree with each other — and nothing compares either to `allDetectors`. Adding a fourth non-detector helper ships a manifest advertising 42 while 41 run, **fully green**. +*Deliberately a test, not a 42nd detector* — a new detector file would itself trip Phase D and the 8 prose surfaces `self-consistency` pins. +*Verify:* green; then in a scratch worktree add `src/stages/detectors/zz-helper.ts` and confirm **RED**. Test count moves ⇒ `npm run test-count -- --write`, six READMEs, same commit. + +**U-04 · Detector-order golden** — new `tests/detector-order.test.ts` pinning `allDetectors.map(d => d.name)` against a literal 41-element array. +*Evidence:* `src/stages/drift.ts:29` snapshots `[...allDetectors]` and pushes findings in exactly that order. All 8 test files importing `allDetectors` assert length, uniqueness, catalog completeness and `subprocess` flags — **never sequence**. Order is user-visible in `check --json`, in the panel render, and — persisted — at `hook.ts:425` (`first: failures[0].detector` into `.cladding/stop-block.json`) and `hook.ts:436-439` (`failures.slice(0,2)` rendered to the user). Any ESLint import-sort `--fix` (U-20) would reorder it silently. +*Verify:* green; scratch-swap two entries → RED. + +**U-05 · Invariant lift — five comments become assertions** +*Goal:* convert the load-bearing records that no gate reads into tests, **before** any comment or shell unit can delete them. +*Scope:* 4 new/extended test files; no `src/` change. +*The five, each verified:* +1. **arch/secret never emit `warn`.** `src/stages/arch.ts:35-38` and `secret.ts:34-38` record that the detector emits only `error`/`info`, which is why their `findings.filter(f => f.severity === 'error')` is sound. If either ever gains a `warn`, stage_1.5/1.6 pass while `runDrift({strict:true})` fails — a split verdict inside one gate run. **No test asserts it.** → assert over the fixture corpus. +2. **`with-spec` taxonomy.** The roster is the adjudication of which detectors deliberately `return []` on spec-load failure. → `tests/detector-taxonomy.test.ts` derives both sets from the filesystem and asserts membership, so the comment can state the *rule* and the test owns the roster. +3. **Session-cache lifetime.** `src/spec/load.ts:57`, `src/stages/detector-result-cache.ts:30`, `src/stages/test-run-cache.ts` each state "callers MUST clear in a `finally`". → an `afterEach` guard in the shared test support asserting all three are clear. +4. **`isCliEntry` predicate.** See U-50. → table test including a Windows `argv[1]` row. +5. **Finding shape per detector.** Snapshot `{detector, severity, path, message}` for all 41 detectors over the corpus, **plus** an assertion that the corpus makes all 41 fire at least once (no such assertion exists today). This is what protects the two `detector|path` fingerprints and the SARIF sort key from a normalization. +*Verify:* each assertion planted-defect probed; test count moves ⇒ `test-count --write`. + +**U-06 · `docs/code-style.md` §3 rewrite + SSoT contradiction** — resolve the authority conflict (`code-style.md:3` and `AGENTS.md:38` say SSoT; `docs/README.md:14` and `docs/ssot-model.md:63` say Tier-C legacy), then rewrite §3 to name only reference forms that resolve inside this repo. *Verify:* `comments.ts --rule=refs` run against the standard's own examples → 0 findings. *Rollback:* revert. + +**U-07 · Dangling `test_ref` cleanup** — drop or repoint `tests/graph/viewer-render.test.ts` in `graph-viewer-obsidian-04f50847.yaml` and `graph-viewer-galaxy-8234ec3c.yaml`. Both are `status: archived` with `modules: []`, so `UNTESTED_AC` skips them — this is cosmetic, and saying so matters: **the surveys' other two reported dangles are false positives** living in scenario `response:` prose, not in `test_refs`. Do not "fix" them. *Verify:* INV-1 → `testrefs_absent=0`. + +--- + +#### PHASE 1 — The instruments + +**U-10 · Parity core** — §3.1–3.4 built: `normalize.ts` (imported by both capture and compare — if they normalize differently the harness is worthless), the five fixture tiers, `cases/cli.yaml`, `capture.ts`, `compare.ts`, `allow.yaml` (empty). *Verify:* `capture --lane=cli` twice in a row → IDENTICAL (determinism of the harness itself, before determinism of the product). *Rollback:* delete `tools/parity/`, remove the npm scripts, remove the spec entry — nothing in `src/` was touched. + +**U-11 · Mutants + selftest ◀ KILL CRITERION** — §3.5, seven mutants. *Verify:* `selftest` → `7/7 REGRESSION`. **If not green within this unit's budget, the program stops.** + +**U-12/13/14 · MCP, hook, artifact+events+TTY lanes** — §3.2, each adding its own mutant and re-running the selftest to `8/8`, `9/9`, `10/10`. U-13 additionally asserts S≡B for every hook sequence at baseline. + +**U-15 · Bundle lane + clean-room** — §3.2. *Verify:* fast tier S≡B; then in a scratch worktree break one module's entry guard and confirm S≢B. Clean-room: `npm pack` → install into an empty dir → fast tier green. + +**U-16 · Audit tools + checkpoint driver** — `census.ts` (INV-1 plus the `readManifest ∩ modules` overlap per feature and the `STALE_TESTS` headroom), `comments.ts` (the machine-checkable half of §4, with needles assembled at runtime — `['resolve','Threshold'].join('')`, the trick already used at `tests/code-compact.test.ts:25-29` — so the checker never self-trips), `checkpoint.ts` (runs INV-1..19 in order, one verdict). **All audit tools are read-only**: the tool that finds the problem never fixes it. *Verify:* `comments.ts` emits a finite worklist matching the independently-measured counts — ≥36 dangling `@see`, ≥12 unresolved F-ids, ≥7 `file:line`, ≥6 version promises; each rule has a planted-defect probe. + +**U-17 · `spec-remap --claim`** — appends exactly one `modules[]` line to one feature, using the byte-stable technique already proven in `src/spec/test-ref-repair.ts:141` (`body.split(ref).join(to)`) so the entry stays diff-clean elsewhere. Dry-run by default; `--apply` writes; refuses when the target path is already claimed by a different feature or during a git operation. **`--rename` is deliberately NOT built** — this program moves no file, and a rename mode would be an unused loaded gun (if it is ever built, it must be driven by `git diff --find-renames`, not basename: 9 of 183 src basenames are ambiguous and they are exactly `index.ts` ×3, `types.ts` ×5, `README.md` ×3, `render/report/stats/verdict/audit/spec-conformance`). *Verify:* `git diff --stat` after a claim shows `1 insertion(+)`. + +--- + +#### PHASE 2 — ESLint + +**U-20 · ESLint scope repair — alone** +*Goal:* apply the project rule block to the 186 src files it has never reached. +*Evidence:* `eslint.config.js:17` declares `files: ['stages/**/*.ts', …, 'drive/**/*.ts']` — flat-config globs resolve from the config directory, so **0 of 186** src files match; `tests/**` does match, which is why the asymmetry was invisible. Measured cost by simulating the rules: **27 problems (25 errors, 2 warnings), 100% auto-fixable, all 25 errors from the single `quotes` rule** — a ~20-file, ~27-line diff, not a tree-wide reflow. +*Actions:* prefix the 11 globs with `src/`; `npx eslint src --fix`. **This commit contains nothing but formatting.** +*Invariant:* zero behavioural change. Also: `eslint --fix` must not reorder imports (no import-sort rule is configured — confirm before running, because INV-17 depends on `allDetectors` order). +*Verify:* INV-5 exit 0; `compare --tier=full` → **IDENTICAL, allow.yaml empty**; INV-17 green; non-vacuity probe — `npx eslint src --rule '{"quotes":["error","double"]}'` must now report many errors, proving src is inside the rule scope. +*Rollback:* revert; the diff is mechanical. **Never bundle with a refactor unit.** + +--- + +#### PHASE 3 — Deletions + +**U-30 · Delete `src/optimizer/preamble.ts` + `tail.ts`** — the ritual rehearsal on the smallest possible surface. +*Evidence, three ways:* `grep -rn "preamble.js'\|tail.js'" src` → 0 importers (the only `preamble` hit in src is unrelated prose in `core/telemetry-summary.ts`); `git log --all -S"suppressPreamble" -- src` → one commit, the layout move, i.e. never wired; and both files are 2 of the only 4 src files reachable from neither esbuild entry point. `preamble.ts`'s regex still matches `Librarian`/`Specialists`, personas renamed in 0.6.0. +*Exact spec cost:* `F-041.yaml` — remove 2 `modules[]` lines, remove `AC-065` + `AC-066`, **retitle** (its title names "preamble suppression, tail-only logging"); `F-063.yaml` — remove 2 test module paths and `AC-161`; `conformance/fixtures.yaml` — remove the 2 `F-041_AC-065` / `F-041_AC-066` rows, **or `FIXTURE_REFERENCE_INVALID` fires**; then `clad sync` + a green strict pre-push. +*Red-inside-the-commit window (acceptable):* between dropping the ACs and dropping the fixture rows. +*Verify:* INV-1 → `modules=420 modules_absent=0`; `compare --tier=full` → IDENTICAL (dead code emits nothing); `test-count --write`. +*Rollback:* `git revert`, then `clad sync` + a green strict pre-push to re-derive. **This is the only unit in the program that edits a pre-existing `done` feature's ACs** (see §10 Q3). + +**U-31 · Dead symbols** — `src/init/git-hook.ts:100-122` (`renderPreCommitHook` / `installPreCommitHook`, self-described "Back-compat wrapper (pre-0.6 callers/tests)"; real importers use `installGitHook` / `enforcingHookInstalled`); `src/graph/stellar.ts` `TIER_COL` (its only importer `src/graph/viewer/main.ts:26` imports six symbols and `TIER_COL` is not among them, and `main.ts:502` says "Tier filter rows carry no color" — the constant's own comment is false); `src/graph/render.ts` `getTierColor`; `src/serve/server.ts` `registerPrompts`'s unused `cwd` + its `void cwd;`. Rewrite the affected test cases to the real API. **No file is deleted**, so `MISSING_IMPLEMENTATION` cannot fire and `modules[]` is untouched. *Verify:* `audit/exports` "truly unreachable" bucket is **empty**; tripwire asserting the four symbol names appear in no file under `src/` or `tests/` (needles assembled at runtime, walk >150 files); `test-count --write`. + +--- + +#### PHASE 4 — Comments + +**U-40 · Class 1, reference integrity** — worklist from `comments.ts --rule=refs`. Delete or repoint 36 `@see` targets (19 × `iron-law.md`, 17 × `ironclad-design/**` — neither exists); repoint the 12 unresolved F-ids (`F-084/085/087/088`, deleted by the v0.3.16 migration) or drop them; one path convention replacing four; delete the 7 `file:line` coordinates (≥3 already wrong, one pointing **inside `node_modules`**); fix `docs/spec-ids-multi-dev.md:179` and `spec/architecture.yaml:5`. +*Hard exclusion:* the six adapter files pinned by `tests/docs-prune.test.ts:157-167` must each keep the literal `docs/multi-provider-roadmap.md`, and the three transport files must keep `Transport architectural decision`. +*Verify:* `--rule=refs --assert-clean` → 0; **INV-14 bundle byte-identical**; `git diff plugins/claude-code/dist/clad.js` empty. + +**U-41 · Class 2, stale facts** — the counts (`with-spec.ts:23,30` says 11/6, actual 21/20 — replaced by U-05's derived taxonomy, not by a new number; `absence-of-governance.ts:5` says "the other 25", actual 40; `hardcoded-secret.ts:4` says "the 19-detector catalog", actual 41); the 24 `Detector #N` header lines (17 detectors carry none, and `README.md:10` already declares the filesystem authoritative — a second registry nothing enforces); `src/spec/types.ts:5,9,42` stating the EARS count three times ("5-pattern", "6 canonical", "5 EARS patterns") against a 6-member union; `drift.ts:8-12` describing an abandoned `registerDetector` architecture and naming `SECRETS_PRESENT`/`ARCH_DRIFT`, neither of which exists; `src/stages/detectors/README.md:16` declaring `UNMAPPED_ARTIFACT` severity `warn` while `:84` and `unmapped-artifact.ts:103` both say `error`; the 6 future-release promises; the 24 dates-as-time-claims. +*Split out, deliberately:* the `META_INTEGRITY` `spec/schema.json` vs `src/spec/schema.json` mismatch has **user-visible** halves — two finding messages and the repair card at `src/ui/softShell.ts:154` tell a user to look in a directory that has no such file. Fix the **comments** here; the strings go to §8. +*Keep:* `registerDetector` / `clearDetectors` themselves — 6 test files depend on them as an isolation seam. +*Verify:* `--rule=facts --assert-clean` → 0; a new assertion that parses the detector README catalog table and requires every declared severity to be in the set the file emits (0 divergences after, 1 before — record both); INV-14. + +**U-42/43/44 · Class 3, header cap** — R3 applied by directory batch. Measured overage at cap 12 with the 9 contract modules at 24: **113 files, 932 lines**, splitting as `stages/detectors` 30 files / −330 · `cli` + `stages` 33 files / −201 · the remaining 15 directories 50 files / −401. +*Actions per batch:* trim to line 1 + blank `//` + ≤10 lines of WHY. Overflow that is a genuine decision record moves to `docs/` behind a resolving `@see`; overflow that is summary or history is deleted. Any file that cannot meet the cap without losing a decision is added to `tools/audit/exemptions.yaml` **with this unit's id and the reason** (expected: `src/stages/detectors/spec-conformance.ts`, whose 51-line header carries the "DEFERRED to v2: a spec-rev hash" adjudication). +*Diff rule, grep-checkable:* any deleted hunk matching `/MUST|never|only|invariant|severity|finally|rejected|DEFERRED/` must be replaced by a named test in the same commit — or the hunk is restored. +*Verify per batch:* `--rule=header-cap` → `offenders=0 visited=186`; **INV-14 bundle byte-identical** (this is the strongest available evidence for a 300-line deletion: identical bytes out); INV-5; INV-6; INV-10. +*Rollback:* per batch — which is why it is three units and not one. + +--- + +#### PHASE 5 — In-place dedup + +**U-50 · `isCliEntry` predicate — extract and table-test first** +*Goal:* make the guard testable before 15 files depend on one copy of it. +*The finding, and it is not in any survey:* all 17 sites spell it `!globalThis.__CLADDING_BUNDLED && import.meta.url === \`file://${process.argv[1]}\``. On POSIX `argv[1]` is `/abs/x.ts` so the concatenation yields `file:///abs/x.ts` and matches. **On Windows `argv[1]` is `C:\…\x.ts`, so it yields `file://C:\…\x.ts`, which never equals Node's `file:///C:/…/x.ts`.** Every one of the 13 `stage:*` scripts and `src/cli/benchmark.ts:70` is therefore a silent no-op on Windows today — loads, prints nothing, exits 0. Coverage is zero either way (`__CLADDING_BUNDLED`: 17 src files, **0 test files**), CI is ubuntu, dev is darwin. +*Actions:* extract `isCliEntry(importMetaUrl, argv1, bundled): boolean` into `src/stages/util.ts` as a **pure function**; table-test it, including a `'C:\\r\\s.ts'` row that documents current behaviour. **Do not change the behaviour in this unit** — see §10 Q6. +*Invariant:* `__CLADDING_BUNDLED` semantics byte-for-byte; that guard is the only thing stopping the esbuild bundle firing all 13 stages on import. +*Verify:* the table test green; INV-14 (predicate extraction is a code change, so the bundle **will** move — this unit is not comment-only); S≡B on the bundle lane. + +**U-51 · `cliEntry(importMetaUrl, fn)` applied** — 15 runners collapse their trailer to one call. **`src/cli/clad.ts` keeps its own guard** (it is the bundle entry itself; importing `stages/util.js` for 4 lines changes the entry module's import graph for no gain). +*Cycle check, verified:* `src/stages/detectors/{hardcoded-secret,architecture-violation}.ts` already import `../util.js`, and `util.ts` currently imports only `node:fs` + `node:path`. **`execaSync` must never enter `util.ts`** — `tests/stages/interactive-profile-partition.test.ts:29` matches `SPAWNER_IMPORT` against each detector file's **own source text**, so moving a spawn into a shared helper makes the two subprocess-using detectors stop matching and the test **stops requiring `subprocess: true`** — going green harder while the guard it protects (a per-keystroke subprocess spawn in the PostToolUse lane) silently dies. +*Verify:* `for s in type lint drift secret commit arch unit cov smoke perf visual audit uat; do npm run stage:$s >/dev/null; echo "$s $?"; done` — exit-code vector identical to the U-00 recording; `npx madge --circular --extensions ts src` → 0; INV-3; S≡B. + +**U-52 · `detectorBackedStage`** — folds `arch.ts` ≡ `secret.ts` (3 semantic lines differ of 53). +*Two traps this unit must resolve explicitly, not inherit:* (a) their JSDoc contracts **differ** — secret documents a `cmd`/`args` override, arch documents only `cwd`; but both bodies read `readDetectorResult(detector.name, cwd) ?? detector.run(opts)`, so whenever a gate run has primed the session (including the Stop hook via `primeDetectorResultCache`) the overrides are **silently discarded**. Decide the precedence, document it, and test it — a factory that makes the asymmetry uniform and undocumented is strictly worse than the duplication. (b) The `never warn` invariant is now U-05's assertion, so the `filter(f => f.severity === 'error')` fold is defended by a test rather than a comment. +*Verify:* a new test that primes the cache with synthetic findings and asserts the decided precedence; INV-3; S≡B. + +**U-53 · `scopedStageCommand` + `gateScriptCommand`** — into `src/stages/toolchain/scoped-command.ts` (**not** `util.ts`; verified that nothing under `src/stages/toolchain/` imports `../util.js` and no detector imports `scoped-command.ts`, so **no detector's import graph changes at all**). Each returns `StageResult | {cmd, args}`; **`execaSync` stays in the caller**. The `if (!cmd || !args)` guards are **not** dead — `resolveStageCommand` returns `{cmd: repoGate?.cmd}`, `undefined` for an unregistered language. +*Verify:* `npm run conformance` exit 0 — the only place real `tsc`/`eslint`/`madge`/`secretlint` binaries run against synthetic repos, and the only live proof these six stages still resolve real commands; stage exit-code vector unchanged. + +**U-54 · `readJsonOr` in `src/stages/**`** — promote the good shape that already exists at `harness-integrity.ts:105-112` into `src/stages/util.ts` and migrate the ~10 sites in that tree. **Each site keeps the exact fallback value it returns today** — returning `[]` where a site returned `null` changes detector severity. Seven sites additionally guard `existsSync` *then* `try/catch`; the `existsSync` is redundant because the catch covers ENOENT, but **removing it is a separate decision** and is not taken here. *Verify:* U-05's per-detector finding-shape snapshot unchanged; parity full IDENTICAL. + +**U-55 · `hook.ts` sidecar factory** — one module-private `sidecar(cwd, filename)` returning `{read(defaults), write(v)}` replacing four families with identical shape (`SkipAgg`, `UnboundAgg`, `PushLedger`, tree snapshot; the source admits it — `:588` "Same sidecar discipline as SkipAgg"), plus a local `readJsonOr` for the file's 6 `JSON.parse(readFileSync(` sites, plus routing `renderSessionStartCard` through `computeInventory` instead of its own `parseYaml` (the same tally exists in four places). +*Invariants:* per-family field coercion stays **inside each family** — the generic only does parse-or-defaults. Every write keeps swallowing errors: 21 of the repo's 67 silently-swallowing catch blocks are in this file and that is the hook's contract (a broken ledger must never crash the host; `runHookCommand` always exits 0). stdout stays byte-identical — it is the entire protocol. `hook.ts` is claimed by 17 features: **it shrinks in place, it never moves.** +*The fingerprint trap, stated so the agent does not walk into it:* `hook.ts:412-414` computes `` `${f.detector}|${f.path}` `` and `src/verdict/gate-progress.ts:52` computes `` `${f.detector}|${f.path ?? ''}` `` — and `gate-progress.ts:25-26` *claims* they mirror each other, which is an explicit invitation to dedupe. **They are not the same function.** Unify them and any finding without a `path` flips between `X|` and `X|undefined`; every existing `.cladding/stop-block.json` on every adopter machine stops matching, so the first Stop after upgrade **re-blocks instead of demoting** — the exact failure the demotion exists to prevent. Both values are opaque sha256s and every test writes fresh state, so nothing turns red. **This unit does not unify them.** If they are ever unified, golden-vector tests (a fixed finding array containing one `path: undefined` row → an asserted literal sha256, one per call site) land first, plus a parity hook sequence that seeds an OLD-build `stop-block.json` and asserts demotion still fires. +*Verify:* the 9 `tests/cli/hook*.test.ts` suites green; parity hook lane IDENTICAL in **both** S and B lanes, including final sidecar contents. + +**U-56 · `server.ts` `specHandler` + `shimHandler` (in-file only)** — `specHandler(cwd, body)` owns `loadSpecOrError` → `'error' in loaded` → `try/catch` → envelope; `shimHandler(cwd, argv, body)` owns `engineShim → spawnSync → JSON.parse → error envelope`, duplicated verbatim at `:1099-1133` and `:1158-1191` (35 lines each for ~6 lines of difference). +*Non-negotiable:* the `server.registerTool(name, meta, handler)` **call shape** and every `title` / `description` / `inputSchema` literal stay byte-identical. Only handler *bodies* change. That is what makes the wire contract provably untouched — `listTools()`, the zod→JSON-Schema serialization and property declaration order are all outside the edited region. Tool names stay spelled as **literals** at the registration site: `tests/self-consistency.test.ts:160-167` scrapes `'clad_[a-z_]+'` out of this file by regex, and an interpolated name turns it red. +*The envelope trap:* 22 `registerTool` / 26 `mcpPayload` / **49** `type: 'text'` / **20** `schema_version` — so ~23 responses today carry **neither** `structuredContent` **nor** `schema_version`. **These two helpers must NOT normalize the envelope** — they own spec-loading and error translation only. Adding `structuredContent`/`schema_version` uniformly is a wire change belonging to §8, and it lands on four generated host mirrors this repo never executes. +*Verify:* parity MCP lane IDENTICAL on the **whole response object** for all 22 tools × success and error branches, in both serializations. + +**U-57 · `clad.ts` attestation helpers (in-file)** — collapse the 31-line EXEMPT/STAMP block at `:643-673` into two guarded helpers. Semantics untouchable: exemption applies only when `strict && (tier === 'pre-push' || tier === 'all') && !anyFailed`, and the stamp is skipped during a git operation. *Verify:* `tests/cli/gate-golden-matrix.test.ts` (the explicit characterization lock for `runCheckStages` — 0/1/2 exit contract, `worst` computation, strict skip-promotion demand table, all 15 runners stubbed) green; run `check --tier=pre-push --strict` twice — first stamps, second is green with no stamp. + +**U-58 · Small verbatim duplications** — `renderScenarioYaml` (byte-identical at `src/cli/clarify.ts:423-448` and `src/cli/init.ts:690-716`, with `clarify.ts:424-427` admitting the copy) → **`src/spec/render-scenario.ts`** (the structurally correct home; `cli → spec` is already a permitted edge, and this is why Phase 6's relaxation of the new-file rule pays for itself immediately); the 14-line conventions markdown table (`greenfield-seeds.ts:291-304` ≡ `llm.ts:344-357`); the 19-line exact clone `src/spec/inventory.ts:33-51` ≡ `src/stages/detectors/ai-hints-forbidden-pattern.ts:29-47` (the largest in `src`); `truncate` / `asString` / `truncateError` imported from one home. New file claimed via `spec-remap --claim`. *Verify:* artifact lane — run `clad init` and `clad clarify --no-llm` in two scratch fixtures before/after and `diff -r` the produced trees → identical. + +**U-59 · `intent-onboarding` interpret merge — CONDITIONAL** +*Change:* `interpretOnboardingWithFallback` (`:488-560`) and `interpretRefinementWithFallback` (`:812-878`) become thin wrappers over one `interpretWithFallback({buildPrompt, fallback, defaults})`. They are line-for-line identical except the prompt builder, the fallback producer, and three per-artifact defaults. +*The honest limitation:* every parity capture runs with the 8 provider keys unset (`src/cli/scan/dispatcher.ts:91-106` selects a provider purely from env presence), which forces the deterministic interpreter — so **the LLM branch is exercised by nothing**. This is the largest dedup in `cli/` and the one parity cannot see. +**GATE:** requires a stub-dispatcher lane that injects a deterministic dispatcher recording the emitted prompt **byte-exactly** and returning canned replies (all-sections-present and sentinel-missing), extending the `tests/cli/fixtures/host-smoke/*.txt` idiom. **If that lane is not built, drop this unit.** Merging it on unit-test evidence alone contradicts the program's premise. + +--- + +#### PHASE 6 — Additive extraction (admitted only after U-12 and U-15 exist) + +Shape, for every unit in this phase, taken verbatim from the repo's own precedent (`tests/measure-extract.test.ts:1-12` + `spec/features/measure-extract-1e9ef827.yaml`, which chose "the light variant that requires zero spec-shard module edits" because ~40 entries bind `clad.ts`): **the pinned file stays at its path as a thin composition root; the body moves to a new sibling; the new path is added by `spec-remap --claim` to the unit's own new spec entry, which also lists the already-claimed origin.** Cost per new file: one `modules[]` line, one `attested_modules` row, one rebuild. No path ever disappears, so `MISSING_IMPLEMENTATION` is structurally unreachable, `test_refs` are untouched, and `spec/index.yaml` / `spec.yaml::inventory` do not move (verified: they carry **counts, never paths** — `grep -c "src/" spec/index.yaml` → **0**; **this corrects the task brief's premise #4**). + +Each unit also ships a small structural tripwire suite in the `tests/measure-extract.test.ts` style — but with **superset** assertions, not `toEqual` on an export set, so a later legitimate addition does not turn it red. + +- **U-60 · `src/core/paths.ts`** — named accessors (`stateDir`, `configPath`, `eventsLog`, `stopBlock`, `auditLog`, `hookSidecar(name)`, …) replacing 39 `.cladding` literals across 21 files. **Split the API in two:** `fsPath()` (platform `join`) and `wirePath()` (always posix). Verified reason: `src/init/host-setup.ts:92` builds `RUNTIME_RELATIVE` with `join()` while `ignoreLocalRuntime` writes the **posix literals** `/.cladding/host/` and `/.cladding/setup-status.json` into `.git/info/exclude`, and `src/init/agents-md.ts:140` emits the posix string `node .cladding/host/serve.cjs` into the managed AGENTS.md block **that the agent then executes**. A single `join()`-shaped accessor backslashes that instruction on Windows. *Verify:* every string landing in a generated manifest or managed markdown block is `wirePath()`-shaped; artifact lane IDENTICAL; a `path.win32`-simulated test for `runtimeBody`, `ignoreLocalRuntime` and the AGENTS.md block. +- **U-61 · `src/core/read.ts`** — `readJsonOr` / `readYamlOr` for the remaining ~50 sites, batched ≤8 files per commit inside the unit. Each site keeps its exact fallback. *Verify:* per batch, U-05's finding-shape snapshot unchanged; parity full IDENTICAL. +- **U-62 · `src/stages/cli-entry.ts` + `command-stage.ts`** — the trailers and stage factories from U-51/U-52/U-53 move out of `util.ts` into dedicated modules; the 13 stage files stay at their paths (npm-script targets **and** spec module paths), reduced to ~8–12 lines each. **New files go in `src/stages/`, never `src/stages/detectors/`** (INV-16's rule). *Verify:* S≡B; stage exit-code vector; `tests/stages/interactive-profile-partition.test.ts` **upgraded** in this unit from a direct-import regex to a one-or-two-hop transitive closure, with a positive control (removing `subprocess:true` from a real detector in a scratch worktree must go RED). +- **U-63 · `src/serve/onboarding-staging.ts`** — the ~280 lines at `server.ts:356-634` (zod host-draft schema, deflate/inflate token codec, pending-preparation persistence + TTL purge, workspace snapshot hashing, rollback capture/restore). `approvalChallenge()` is part of the wire contract — `clad_init` requires the exact string back. The rollback capture/restore pair is atomic: extract together or not at all. +- **U-64 · `src/serve/tools/*.ts` + `resources.ts` + `prompts.ts`** — `src/serve/tools/` is a **nested** directory, invisible to `checkUndeclaredDirectories` (depth-1 only), but `scanPatterns` globs `src/serve/**/*.ts`, so every new file needs its `modules[]` line. **Never name a nested directory after an existing layer** — `importsLayer` matches by path segment, so `src/serve/spec/` or `src/cli/spec/` would false-fire `ARCHITECTURE_FROM_SPEC`. *Verify:* MCP lane IDENTICAL; INV-1 shows 0 unclaimed files. + *Also in scope:* persona resolution is candidate-ordered against `import.meta.url` (`src/agents/loader.ts:99-113` returns the first existing of `here/.md`, `here/agents/.md`, `here/../plugins/claude-code/agents/.md`, else falls back to `candidates[1]` **unconditionally**, so a miss surfaces only later as a read failure). Assert `resolveAgentPath` returns an existing file for all 5 personas in **both** lanes, and assert `scripts/build.mjs`'s copy source is the same directory `loadPersona` reads in dev. +- **U-65 · `src/cli/hook-sidecar.ts` + `hook-bash-lane.ts`** — **flat file names, not a `src/cli/hook/` directory**: `hook.ts` and a `hook/` sibling co-exist legally, but nine `tests/cli/hook*.test.ts` files and several globs make the ambiguity a needless risk. +- **U-66 · `src/cli/program.ts` + `src/verdict/attestation-gate.ts`** — the 263-line commander wiring moves out; the multi-line `.description(…)` prose is **relocated, never reflowed** (user-facing). **`TIER_STAGES` stays in `clad.ts` as a literal `export const` block** (INV-18). The `.command('')` literals stay spelled out — `self-consistency.test.ts:143` scrapes them, and `terminology-canon.test.ts:217-227` slices the `.command('status')` block. **Do not table-drive the registration** in this unit: a `{cmd, desc, opts[], action}` loop stops matching the regex and turns a correct change red; the honest fix is to export the verb list as a real array, which is §8 work (U-70 does the test-side half). *Verify:* `npm run build && git diff --exit-code` (proves Phase E still parsed `TIER_STAGES` — a stale `stages-implemented` shows as a diff); all 28 `--help` captures IDENTICAL. +- **U-67 · Break `drive ↔ ui`** — move the `HaltReason` type to `src/core/halt-reason.ts`; both `drive` and `ui` then import downward. *Evidence:* `src/ui/softShell.ts:13` imports `type HaltReason` from `../drive/halt.js` (tier 0 → tier 2) while `src/drive/loop.ts:38` imports `../ui/pulse.js`; Tarjan over all 186 files finds **0 file-level SCCs**, so `madge --circular` is green and structurally always will be — it sees files, not directories. + **Explicitly NOT in this unit, and not in this program:** adding `{from: ui, to: drive}` to `forbidden_imports`, extending `ES_IMPORT_RE` to match `export … from`, and deriving forbidden pairs from the tier order. All three are **detector behaviour changes** that would emit new `error`/`warn` findings on adopter repos (a barrel re-export; a tier-ordered `architecture.yaml`) and belong to §8. Watch also: `importRe` is a module-level `/g` regex whose single `lastIndex = 0` reset lives inside the per-file loop at `architecture-from-spec.ts:209` — extracting that loop without carrying the reset makes findings depend on the previous file's match position. + +--- + +#### PHASE 7 — Tests + +**U-70 · Break the five cross-test source couplings** — **before** any consolidation, correcting ARM C's placement. +*The five, verified:* `tests/terminology-canon.test.ts:249-271` slices `tests/self-consistency.test.ts` **by test name**; `tests/instruction-led-language.test.ts:215-221` regex-derives its byte ceiling from `tests/claude-md-diet.test.ts`'s source and `:300-319` pins that its needle set appears in **exactly one** file across 249 with `expect(hits).toHaveLength(2)`; `tests/code-compact.test.ts:145-149` asserts on `tests/optimizer/code-excerpt.test.ts`'s text; `tests/docs-prune.test.ts:225-239` slices `tests/scenarios/ab/_report.ts`. +*Actions:* export `CLAUDE_MD_SECTION_MAX_BYTES` from `src/init/host-instructions.ts` so the literal `1250` appears once (it appears three times today); replace each source-slice with a direct re-assertion of the property; convert the exactly-one-file census to a whitelist that tolerates additions by explicit opt-in. +*Verify:* `grep -rn "readFileSync.*tests/" tests --include='*.test.ts'` → only intended survivors; plant the original violation each assertion was written to catch and confirm it still goes RED. + +**U-71 · `tests/_support/` + the 73 unreferenced files** — `tmpRepo(prefix)` (mkdtemp + `onTestFinished` teardown) and a fluent `specFixture(dir).project(…).feature(…).write()`. +*Measured:* **461 `mkdtempSync` calls across 167 of 249 suites**; `schema: "0.1"` **201 times in 95 files**; 48 mutually-incompatible local helpers (`writeSpec` ×16 with five different signatures, `writeFeature` ×6, `seed` ×6, `writeMaster` ×5, `makeSpec` ×5, `writeShard` ×4, `mkSpec` ×3, `makeTmp` ×3). The only existing shared helper is imported by 7 files, all under `tests/scenarios/`. +*Why the pilot zone:* 176 of 249 suites are pinned by a `test_ref` (paths frozen, contents free); **73 files / 12,976 lines carry none** — the only zone where a mistake costs one revert instead of a spec sweep. +*Two hard constraints.* (a) **`tmpRepo()` is one directory per case, never reused within a file.** Verified reason: `src/spec/load.ts:57` `runCache` returns the cached Spec whenever `resolve(cwd) === runCache.cwd`, and `detector-result-cache.ts` / `test-run-cache.ts` are keyed the same way; `vitest.config.ts` sets no `pool`/`isolate`, so isolation is per **file** — exactly the scope consolidation operates in. Reusing one directory across cases makes case 2 silently read case 1's spec and case 1's cached arch/secret findings. (b) **Anything an assertion depends on stays literal at the call site**; only the invariant frame moves — a test whose fixture is hidden behind a builder default stops documenting what it asserts. +*The vacuous-pass trap this unit must defend against:* `src/stages/drift.ts:10-12` states outright that "with an empty registry the stage trivially passes — by design", and `clearDetectors()` empties the module-level array. Four suites (`scenario-coverage`, `planned-backlog`, `hollow-governance`, `drift-interactive-profile`) use `beforeEach: clearDetectors(); registerDetector(X)` and assert `expect(report.pass).toBe(true)` — **byte-identical to the empty-registry result**. Move that setup into a shared helper, or let one `beforeEach` shadow another, and the suite passes while asserting nothing. **Rule:** the shared helper asserts `registeredDetectors().map(d=>d.name)` equals the expected set before the act, and every `runDrift`-based test asserts a **positive** discriminator (`findings.some(f => f.detector === NAME)`) in the same act. +*Verify:* `npx vitest list --json` before/after → **identical test-name list**, not merely the same count; per-file coverage percentages do not decrease; INV-7 still `2815`. + +**U-72/73/74 · Migrate the pinned suites, contents only** — `tests/stages/` first (most uniform), then `tests/cli/` + `tests/spec/`, then the remainder. **No test file is renamed, split or deleted, and no `test()` block is renamed** — `UNTESTED_AC` resolves only the pre-`#` path part, so renaming a test *title* breaks human traceability silently rather than turning the gate red. The deliberate mutation probes must survive intact (`tests/instruction-led-language.test.ts:272-298`, `tests/spec-first-window-complete.test.ts:230-284`'s `vi.doMock`, `tests/readme-record-honesty.test.ts:118-122`, `tests/terminology-canon.test.ts:181-185`) — they are what prove the scanners still discriminate; re-run them explicitly after each batch. + +**U-75 · Test header standard** — apply §4.2 to all 272 files, starting with the 25 headerless ones; fix the ~69 stale path citations (`tests/scenarios/_helpers.ts:6` and `greenfield-lifecycle.test.ts:11` cite `tests/cli/refine.test.ts`, renamed to `clarify.test.ts` in 0.6.0; ~20 comments write `spec/load.ts` meaning `src/spec/…`, and `spec/` is a real top-level directory of YAML so these read as real paths that do not exist; `conformance/runner.ts:3` says "12 fixtures" while `.github/workflows/ci.yml:44` says "33 runnable pairs" — one is stale). *Verify:* T1/T2/T3/T5 assert clean over 272 files; `test-count --write`. + +--- + +#### PHASE 8 — Close + +**U-80 · Pin renegotiation residue** — for each pinning assertion the program legitimately loosened, a dated rationale comment in the repo's own amendment style (`tests/claude-md-diet.test.ts:78-84` is the model). Convert `tests/spec-first-window-complete.test.ts:205-217`'s `toEqual` on definition sites and importer names to a definition-count-of-1 plus a superset check, keeping the `vi.doMock` mutation probe untouched. **No assertion is deleted to make a diff green**; each keeps its purpose. + +**U-81 · Tooling disposition** — an explicit keep/delete decision per tool, recorded. Recommendation: **keep** `parity/lanes/bundle` (the only bundle coverage that exists), `spec-remap` (the repair writer the repo has always lacked), `audit/census` and `audit/comments` (the only comment-integrity check anywhere); **delete** the one-shot analyses after their worklists are exhausted. See §10 Q5. + +--- + +## 6. Checkpoint record format + +One YAML file per unit at `.refactor/units/.yaml`, committed **with** the unit. It is both the agent's **entry brief** — so it never re-derives a survey — and the **exit receipt**, so the next unit starts from measured state rather than from this document. Fields marked `[carry]` are copied into the next unit's `inherits`. + +```yaml +id: U-42 +title: "Header cap ≤12 — src/stages/detectors/" +phase: 4 +reason_to_change: "file-header length policy" # exactly ONE. Two reasons = two units. +mechanical_rule_exception: true # §5.1; lifts the 12-file cap + +inherits: # [carry] from the previous unit's exit block + baseline_commit: 23ea6be + census: {entries: 275, modules: 420, modules_absent: 0, testrefs: 243, testrefs_absent: 0} + test_count: {collected: 2815, executed: 2821, + delta_explained: "PRE-EXISTING vitest list-vs-run delta, characterised in U-00. DO NOT INVESTIGATE."} + coverage_floor: {lines: 85, branches: 76, functions: 88, statements: 84} + parity_selftest: {mutants: 10, regressed: 10, at_commit: } + bundle_sha: {clad: , viewer: } + allowlist_entries: 0 + stale_tests_headroom_days: 17.4 + detector_order_golden: tests/detector-order.test.ts + +preconditions: # hard gate; the agent refuses to start if unmet + units_done: [U-00, U-01, U-02, U-03, U-04, U-05, U-06, U-07, U-10..U-17, U-20, U-30, U-31, U-40, U-41] + assert: + - {cmd: "npx tsx tools/audit/census.ts --assert", expect: "exit 0"} + - {cmd: "npx tsx tools/parity/selftest.ts", expect: "10/10 REGRESSION"} + - {cmd: "git status --porcelain", expect: ""} + +touch_allowed: # EXHAUSTIVE. A diff outside this list is a class-A failure. + glob: "src/stages/detectors/*.ts" + max_files: 30 +touch_forbidden: + paths: [src/cli/clad.ts, src/spec/schema.json, src/spec/types.ts, src/spec/validate.ts, + "src/agents/*.md", "src/graph/viewer/**", src/stages/detectors/index.ts] + symbols: [TIER_STAGES] + directives_are_code: ["eslint-disable*", "@ts-expect-error"] # 4 live sites; never deleted + content_pins: + - {file: src/stages/detectors/with-spec.ts, keep: "load-failure policy WHY block", cap: 24} + - {file: src/stages/detectors/unmapped-artifact.ts, lines: "52-59", cap: 24} + - {file: src/stages/detectors/hardcoded-secret.ts, lines: "47-50", cap: 24} + diff_rule: "any deleted hunk matching /MUST|never|only|invariant|severity|finally|rejected|DEFERRED/ + must be replaced by a named test in the same commit, or restored" + +pins_that_can_fire: # PRE-COMPUTED. The agent must not discover these at checkpoint time. + - {test: tests/self-consistency.test.ts, why: "detector count vs 8 prose surfaces", expect: green} + - {test: tests/plain-render.test.ts, why: "pins finding message strings", expect: green} + - {test: tests/docs-prune.test.ts, why: "pins PRESENCE of docs/multi-provider-roadmap.md in 6 adapter files", + expect: green, note: "src/adapters/ NOT in scope this unit"} + +change: + spec_entry: F- # authored FIRST, status in_progress + spec_cost: {entries_edited: 0, entries_created: 1, modules_added: 0, testrefs_added: 0} + description: > + Trim every header in src/stages/detectors/ to ≤12 lines (≤24 for the 3 named + contract modules): line 1 banner, blank //, ≤10 lines of WHY. Overflow that is a + decision record moves to docs/ behind a resolving @see; overflow that is summary + or history is deleted. + +done_conditions: # every entry is a COMMAND + a LITERAL expected result. + - {cmd: "npx tsx tools/audit/comments.ts --rule=header-cap --dir=src/stages/detectors", + expect: "offenders=0 visited=44"} + - {cmd: "npx tsc --noEmit", expect: "exit 0"} + - {cmd: "npx eslint .", expect: "exit 0"} + - {cmd: "npm test", expect: "249 files, 2821 tests, 0 failed"} + - {cmd: "npm run test-count -- --check", expect: "check passed (2815)"} + - {cmd: "npm run build && git diff --exit-code", expect: "exit 0"} + - {cmd: "shasum -a 256 dist/clad.js", expect: ""} # comment-only ⇒ IDENTICAL + - {cmd: "npx tsx tools/parity/compare.ts --tier=fast", expect: "IDENTICAL 0 expected-deltas"} + - {cmd: "npm run conformance", expect: "exit 0"} + - {cmd: "node bin/clad check --tier=pre-push --strict", expect: "GREEN"} + - {cmd: "npx tsx tools/audit/census.ts --assert", expect: "modules=420 absent=0 testrefs=243 absent=0"} + +expected_deltas: [] # non-empty requires a written reason + a reviewer id, + # registered in ITS OWN prior commit. An agent may never + # add an entry to make its own unit pass. + +exit: + commit: + lines: {src: -330, tests: 0, spec: +18, tools: 0} + attestation_restamped: true + carry: + census: {entries: 276, modules: 420, modules_absent: 0, testrefs: 243, testrefs_absent: 0} + test_count: {collected: 2815, executed: 2821} + bundle_sha: {clad: , viewer: } + allowlist_entries: 0 + stale_tests_headroom_days: 17.1 # decrements with wall time — watch the 30-day cliff + residue: # what this unit deliberately did NOT do + - "src/stages/detectors/spec-conformance.ts header is 14 lines: 2 over cap, both + load-bearing (the DEFERRED-to-v2 spec-rev-hash adjudication). EXEMPTED — + recorded in tools/audit/exemptions.yaml with this unit id." +``` + +**Running record.** `.refactor/units/*.yaml` (one per unit, committed with it) · `.refactor/baseline.json` (U-00, immutable) · `.refactor/ledger.md` (one appended line per unit: id, commit, Δlines, verdict, residue count) · `tools/parity/allow.yaml` (registered deltas) · `tools/audit/exemptions.yaml` (granted header exemptions, each with a unit id). `residue` is what distinguishes DONE from stopped (§9). + +--- + +## 7. Failure protocol + +The response is determined by **which invariant failed**, never by judgement. This is why §2 is ordered cheapest-and-most-diagnostic first: the failing index *is* the classifier. + +| class | trigger | response | retry | +|---|---|---|---| +| **A — scope violation** | INV-2 fails (a path outside `touch_allowed`), or INV-1's tuple moved when `spec_cost` said it would not | **REVERT immediately.** The unit's declared scope was wrong; re-plan the unit — do not repair the diff | **no** | +| **B — own bug** | INV-6 fails on a test covering a file inside `touch_allowed` | **RETRY once in place.** An ordinary defect | **1** | +| **C — pin fired** | INV-3 red, or any repo-scanning tripwire red | **STOP. Do not touch the test.** Open a separate pin-renegotiation unit with a dated rationale, land it, then re-run this unit. **Editing a pin inside the unit that broke it is self-certification** — the exact thing this repo exists to prevent | **no** | +| **D — parity delta** | INV-12 reports a delta not in `allow.yaml` | **REVERT.** A new allow entry requires a written reason and a reviewer id, in its own commit, **before** the unit re-runs | **no** | +| **E — oracle blindness** | INV-13 fails at any phase boundary (a mutant returns IDENTICAL) | **REVERT EVERY UNIT SINCE THE LAST GREEN SELFTEST.** Everything verified by a blind oracle is unverified. Fix the normalization, then re-run the reverted units. This is why the selftest runs at every phase boundary, not once | **no** | +| **F — bundle moved on a comment unit** | INV-14 mismatch on a unit declared comment-only | **REVERT.** The unit changed code it believed it did not — the most valuable single signal in the program | **no** | +| **G — attestation only** | INV-10 red **solely** on `STALE_ATTESTATION` | **not a failure.** Re-stamp via the strict pre-push exemption and commit `spec/attestation.yaml` with the code. Note CI's final step is `--tier=pre-commit --strict`, which gets **no** exemption (`src/cli/clad.ts:643` gates EXEMPT/STAMP on `pre-push \|\| all`) — an un-restamped push is a red CI that reads like a regression | n/a | +| **H — test count** | INV-7 fails | **not a failure if the unit changed tests** — `npm run test-count -- --write`, six READMEs, same commit. If the unit changed no tests, it is class A | n/a | +| **I — stale tests** | INV-10 red on `STALE_TESTS` for files the unit never touched | **not a failure.** Working-copy mtime artefact (`STALE_DAYS = 30`, measured headroom ~19 days at U-00; a fresh CI checkout resets mtimes so it never breaks CI). Record it; **do not "fix" it by touching tests.** If the program exceeds the window, interleave a Phase-7 unit | n/a | +| **J — inadmissible** | a DONE entry cannot be written as a command | **the unit never starts.** Split it, build the instrument first, or drop it (U-59's GATE is the model: no stub-dispatcher lane ⇒ dropped, not downgraded to unit-test evidence) | n/a | + +**Escalation.** Two consecutive reverts on one unit ⇒ the unit is mis-scoped: split per §5.1 and re-plan; do not attempt a third pass at the original scope. Three reverts within one phase ⇒ **halt the phase**, re-run the U-00 baseline measurement, re-derive the phase's units from the new baseline. Any class E ⇒ **halt the program**, not just the phase. + +**Anti-rationalisation clause** — stated as a rule because an unattended agent will otherwise find the loophole. A unit may never reach GREEN by: (a) weakening a pinning test, (b) adding a parity allow entry, (c) lowering a coverage threshold, (d) narrowing `touch_allowed` after the fact, (e) writing the count or prose that a self-consistency test compares against instead of fixing the fact, or (f) deleting a mutant. Each of those is a green that certifies itself. + +--- + +## 8. Interaction with the 0.10.0 behaviour-change program + +**Rule zero: never a behaviour change and a refactor unit in the same commit.** A parity run with one intentional delta and one accidental one is unreadable — the accidental one hides inside the expected hunk. Every 0.10.0 unit registers its `allow.yaml` entry in its own commit, with a reason and a reviewer id, before the refactor resumes. + +**Rule one: refactor Phases 0 and 1 come first, unconditionally.** Not one behaviour unit may land before the parity harness exists and its selftest is green. Without it, every 0.10.0 change is verified by "the tests passed" — and the tests do not reach the bundle (1 verb of 28), the MCP response bodies, the hook sidecar sequences, or the written artifact tree. + +**Rule two: never a persona/prose edit in the same commit as code.** `tests/choreography-guard.test.ts` is 99 tests of prose assertions across 6 README variants, 6 persona sources, 3 built plugin mirrors and 4 locale SVGs, and its mirror assertions read `plugins/**`, which are **built** — so any persona edit requires `npm run build:plugin` in the same commit. + +| 0.10.0 unit | must come after | why | which refactor unit makes it easier | +|---|---|---|---| +| **Stop hook → report-only** | U-13 (hook lane), U-55 | The blocking decision is the single most user-visible behaviour; it needs a captured before/after of the exact sequence, in both S and B lanes | U-55 turns the stop-block sidecar into one `sidecar()`. **Hard constraint:** do not also unify the two `detector\|path` fingerprints in the same window (U-55's note) — if the report-only change and a fingerprint unification land together, every adopter's persisted `stop-block.json` silently stops matching and the failure is indistinguishable from the intended change | +| **Detector severity dial** | U-05, U-04, U-03 | U-05's `never warn` assertion is a **direct blocker**: if the dial can raise `ARCHITECTURE_VIOLATION` or `HARDCODED_SECRET` to `warn`, `src/stages/arch.ts` / `secret.ts`'s `filter(f => f.severity === 'error')` silently drops it and stage_1.5/1.6 pass while a strict drift run fails. Either exclude those two detectors from the dial or change the filter — the assertion forces the choice | U-52 gives one place to change the filter instead of two. U-04 protects emission order, which the dial's finding selection depends on | +| **Verification-capability disclosure** | **U-56, then U-63/U-64** | Adding disclosure fields to 22 hand-rolled response sites and *then* deduping them means the refactor chases a moving target. Measured: 49 `type: 'text'` envelopes vs 26 `mcpPayload` calls — ~23 responses today carry neither `structuredContent` nor `schema_version`, so **envelope normalization is itself the behaviour change** and belongs here, not in U-56 | U-56 makes it a one-place edit. U-12's MCP lane captures the whole response object on both branches, so the delta is explicit per tool | +| **`why` / `depends_on` mechanisms** | U-16 | `src/spec/schema.json` is claimed by 18 features and has `additionalProperties: false`, so any property change is adopter-visible and is its own feature with its own gate cycle | U-16's census makes the blast radius auditable before the edit | +| **Evidence producers** | **U-60** | A new writer into `.cladding/` must use the path accessors, or it adds to the 39 literals the refactor just removed | U-60 supplies `fsPath()`/`wirePath()` and the artifact lane already captures the whole `.cladding/` tree, so a new producer's output is diffed for free | +| **Instruction dedup** | U-75, and **alone** | Touches the AGENTS.md/CLAUDE.md generators and the personas — head-on collision with `choreography-guard` (99 tests), `claude-md-diet`'s byte-parity dogfood against this repo's own `CLAUDE.md`, and `shard-term-guard`. Requires `npm run build:plugin` in the same commit | U-70 removes the derived-ceiling coupling so the `1250` byte cap lives in one exported constant | +| **Persona alias removal** (moved here from all three arms) | U-12 | Removing `PERSONA_ALIASES` / `PERSONA_PROMPT_ALIASES` shrinks `listPrompts()` from 7 to 5 — a **wire-contract change**, so it violates the refactor's contract even though it is dead-code shaped. It is the ideal *first* 0.10.0 unit: small, obviously correct, and it exercises the `allow.yaml` machinery end to end | U-12 makes the delta a single registered hunk. Note `loader.ts:75` writes "removed in 0.8" to **stderr at runtime** and `server.ts:2023` embeds it in an MCP prompt description a host reads — so this also closes 3 of U-41's 6 version-promise findings | +| **`META_INTEGRITY` repair-card path fix** | U-41 | `meta-integrity.ts:34` reads `src/spec/schema.json` while two finding messages and `src/ui/softShell.ts:154` tell the user to restore `spec/schema.json`, which does not exist. The strings are **user-visible** and pinned by `plain-render` | U-41 fixes the comments so only the strings remain | +| **`token_budget_per_session` schema removal** | — | `additionalProperties: false` means removal breaks every adopter `spec.yaml` still carrying the field: a minor-version break, not a refactor. The refactor drops only cladding's own `spec.yaml:34` usage and the extraction paths, keeping `update.ts`'s deprecation report | — | +| **`ES_IMPORT_RE` + tier-derived forbidden imports** | U-67 | Both emit **new** findings on adopter repos (a barrel re-export → `error`; a tier-ordered `architecture.yaml` → `warn`, which `--strict` promotes). Shipping them inside a "break the cycle" unit would deliver a gate regression labelled as a refactor | U-67 does the type move; this does the detector change | +| **Polyglot language-table unification** | — | **Do not attempt as a dedup.** Two independent maps disagree today: `unmapped-artifact.ts:28-43` knows `rust/go/javascript`, while `language-config.ts:120-128` falls back to the TS config for everything but `typescript/kotlin/python`. Dedupe one way and every `UNMAPPED_ARTIFACT` error vanishes for Rust adopters (a vacuous green); dedupe the other and `CONVENTION_DRIFT` starts warning on `.rs` (a red gate on upgrade). Cladding's own suite is 100% TypeScript so **both directions are invisible here**. This is a behaviour feature needing a polyglot fixture matrix | — | + +**Interleaving shape.** Phases 0–1 (refactor) → then alternate: one 0.10.0 unit, one refactor unit, never concurrently, never in one commit. The 1.5 MB committed bundle makes concurrency impossible anyway. + +--- + +## 9. Definition of done + +**Progress is measured by per-class worklist burn-down, never by line count.** Line reduction is an exit statistic. A program that targets lines deletes comments to reach the number, which is precisely the side effect the maintainer forbade. + +| class | closure condition (a command with a literal result) | closed at | +|---|---|---| +| verification net | `tsc --listFiles \| grep -c '/src/'` = **185** · `eslint .` exit 0 with project rules matching **186** src files · `vitest run --coverage` exit 0 at the floor · `parity/selftest` **10/10** · bundle **S≡B** on the fast tier · clean-room fast tier green | Phase 1 | +| spec integrity | `census --assert` → `modules_absent=0 testrefs_absent=0` at every checkpoint | U-07 | +| manifest honesty | `allDetectors.length` == detector file count == `plugin.json` numerator, asserted by test | U-03 | +| invariant lift | the 5 records of §5 U-05 are executable assertions, each planted-defect probed | U-05 | +| reference integrity | `comments.ts --rule=refs --assert-clean` → `findings=0 visited>150` | U-40 | +| stale facts | `comments.ts --rule=facts --assert-clean` → `findings=0` | U-41 | +| header policy | `--rule=header-cap` → `offenders=0 visited=186`, every exemption carrying a unit id and a reason | U-44 | +| dead code | `audit/exports` "truly unreachable" bucket **empty** | U-31 | +| duplication | `audit/clones --min=12` → **0** cross-file runs above the declared threshold, or each survivor listed in `residue` with a reason | U-61 | +| boundaries | `madge --circular` **0** · `drive ↔ ui` cycle gone · **0** files moved · **0** pre-existing `modules[]` repaired | U-67 | +| tests | `vitest list --json` test-name list identical to U-71's entry snapshot except for units that declared a count change · all mutation probes still discriminate · T1/T2/T3/T5 clean over 272 files | U-75 | +| tooling | an explicit keep/delete decision recorded per tool | U-81 | + +**Numbers this program commits to.** + +| | before (measured) | after (projected) | Δ | +|---|---|---|---| +| src files | 186 | 197 (+13 new, −2 deleted) | +11 | +| src lines | **35,757** | ~32,400 | **−3,357 (−9.4%)** | +| src comment share | **28.5%** (10,227 lines) | ~24% (~7,800) | −2,400 | +| tests files | 272 | ~276 | +4 | +| tests lines | **52,745** | ~50,800 | **−1,945 (−3.7%)** | +| claimed module paths | **422** (0 absent) | ~433 (0 absent) | +11 | +| pre-existing spec entries **edited** | — | **2** (`F-041`, `F-063`, U-30 only) | — | +| `modules[]` paths **repaired** | — | **0** | — | +| `test_refs` **repaired** | — | **0** | — | +| new spec entries | 275 | ~324 | +49 | +| `tools/` lines (non-shipped) | 0 | ~3,300 | +3,300 | +| detectors / stages / tiers | 41 / 15 / 3 | **unchanged** | — | +| collected tests | **2,815** | 2,815 ± declared changes | — | + +Composition of the src reduction: dead code −250 · verified in-file duplication −700 · move-enabled dedup −250 (net of ~+160 new-file overhead) · comment classes 1–3 −1,117 measured + ~−1,040 from R5/R8 body rules · new-file headers +160. + +**The ceiling, stated honestly.** −3,357 (−9.4%) is what this program commits to. **Anyone promising more than −20% is promising comment deletion, not compaction:** measured exact cross-file duplication in `src` is **256 lines = 0.7%**, and total verified code-level duplication is ~900–1,200 lines. The gap between −9.4% and the ~−17% a full comment standardization would reach *is class 4*, and class 4 is cut. + +**Gate runtime.** Baseline **249 suites / 2,821 tests / 115.8 s summed** (wall clock lower — vitest pools); the six slowest suites are 58 s for 87 tests. Expected effect: `tsc` +2–5 s (the program gains `tools/**` and 2 previously-unchecked src files), `eslint` +3–6 s (186 files gain the project rules for the first time), `stage_1.3` ≈0 (same 41 detectors, same predicates), `stage_2.1` +8–12 s (new tool suites; the scaffolding consolidation removes *lines*, not temp directories, so it saves no seconds). Parity is **outside** the gate: +45–90 s per unit (fast tier), 6–12 min per phase. **No speed claim is made.** Each unit's checkpoint asserts summed suite time within ±10% of 115.8 s and per-suite times within ±30% — a regression outside that band is a finding to investigate, and it is the only performance signal this repo can currently produce. + +**DONE vs merely STOPPED.** DONE = every class at its closure condition **and** every unclosed item recorded in `residue` with a reason and a unit id. STOPPED = a class with a non-empty worklist and no admissible unit remaining. The distinguishing test is mechanical: run every audit tool; **any non-zero finding that is not in the residue register with a unit id is proof the program stopped.** A finding silently absent from both the worklist and the register is the exact failure mode this design exists to prevent. + +--- + +## 10. Open questions for the maintainer + +Genuine forks only — each changes what gets built, and preference decides. + +**Q1 — Header cap: 12/24-exempt, or 18/none?** Measured: cap 12 with 9 contract modules at 24 removes **932 lines across 113 files** and needs an exemption register; a flat cap of 18 removes **411 across 62** and needs none. The 12/24 variant is what §5's numbers assume. The trade is 521 lines against one more piece of machinery and a judgement call per exemption. + +**Q2 — Take Phase 6 (additive extraction) at all?** Without it the program is 8 units shorter, touches **zero** new src files, and ARM B's absolute guarantee holds — but `serve/server.ts` stays 2,030 lines, `cli/hook.ts` stays 1,209, `cli/clad.ts` stays 1,364, the 39 `.cladding` literals stay, and the `drive ↔ ui` cycle stays. With it: +13 files, +13 spec entries, ~+160 lines of new-file overhead, and the comprehension win. Phase 6 is the only part of the program whose value is not measurable by any oracle described here. + +**Q3 — U-30 edits two `done` features' acceptance criteria.** It is the only unit that does. The alternative is leaving 51 dead src lines and 117 dead test lines in the tree permanently, and the program's "zero pre-existing entries edited" guarantee then becomes absolute. Delete, or keep as declared debt? + +**Q4 — Persona aliases: 0.10.0 (as designed here) or folded into the refactor as an EXPECTED-DELTA?** All three arms wanted them in the refactor. This design moves them out because they change `listPrompts()` from 7 to 5, and "no side effects" should mean no side effects. Folding them back in is defensible and saves one hand-off. + +**Q5 — Does parity live in CI after the program?** Keeping the fast tier as a CI step costs ~60–90 s per PR and gives cladding the observable-contract regression net it has never had. Deleting it saves that, and the next refactor rebuilds ~2,300 lines. `spec-remap`, `census` and the bundle lane are recommended keeps regardless. + +**Q6 — Fix the Windows entry guard, or freeze it?** Verified: `import.meta.url === \`file://${process.argv[1]}\`` never matches on Windows, so all 13 `stage:*` scripts and `src/cli/benchmark.ts` are silent no-ops there today. U-50 extracts and table-tests the predicate **without changing behaviour**. Fixing it (`pathToFileURL(process.argv[1]).href`) makes 14 entry points start executing on Windows for the first time — a behaviour change with zero existing coverage on that platform, and one that would need a `windows-latest` CI leg to be worth anything. Fix in 0.10.0, or document and freeze? + +**Q7 — Is the 2,815-vs-2,821 test-count delta known?** `README.md` pins 2,815 (from `vitest list`); `.cladding/test-report.junit.xml` reports 2,821 executed. U-00 characterizes it and forbids later units from investigating it. If the maintainer already knows the cause, U-00 shrinks; if not, it is worth one hour before the program starts, because six tests that `list` cannot see are six tests `test-count --check` cannot protect. diff --git a/.refactor/ledger.md b/.refactor/ledger.md new file mode 100644 index 00000000..ea03801f --- /dev/null +++ b/.refactor/ledger.md @@ -0,0 +1,22 @@ +# 0.10.0 작업 원장 + +루프가 매 항목마다 한 줄을 추가한다. 규칙은 `.refactor/PLAN.md` §1~§2. +`status`: `IN_PROGRESS` → 항목을 시작할 때 · `DONE` / `FAIL` / `KILLED` → 끝날 때. +`IN_PROGRESS`로 끝나 있으면 컨텍스트를 잃은 것이므로 PLAN.md §5 "중간 복구"를 따른다. + +| id | status | commit | 날짜 | 결과 | +|---|---|---|---|---| +| S1 | DONE | 3c61dfc | 2026-08-10 | 이벤트 로그의 고유 head 251개를 `refs/replay/*`로 고정, 소실 0. 자동 `git gc`로부터 리플레이 코퍼스 보호됨 | +| S2 | KILLED | (이 커밋) | 2026-08-10 | M5 KILL — 로컬 CLI의 TTY·확인 문구·git/OS identity로 사람 출처를 검증할 수 없어 A10·A11을 큐에서 제거함 | +| S3 | DONE | (이 커밋) | 2026-08-10 | M7 PASS — Jest 30.2.0 all-skipped가 strict Unit을 통과하는 실제 갭 확인; 기존 JSON 파서는 호환되어 A6 Jest 범위 유지 | +| S4 | DONE | (이 커밋) | 2026-08-10 | 5b PASS — Git rename 기반 module claim 수리 14/14·오탐 0; 실증 없는 basename fallback은 제안-only로 축소 | +| P1 | FAIL | (이 커밋) | 2026-08-10 | marketplace source 누락은 확인·수정; Claude 2.1.224의 표준 hook 자동발견과 manifest 중복 선언이 기존 핀 테스트와 충돌해 P1P로 분리 | +| P1P | FAIL | (이 커밋) | 2026-08-10 | inline loader는 정상화됐으나 build:plugin이 허용 밖 stale engine mirror 60-byte delta를 발견해 P1B로 분리 | +| P1B | KILLED | (이 커밋) | 2026-08-10 | precondition 반증 — root dist는 gitignored이고 60-byte delta가 source에 없어 plugin mirror의 정답으로 사용할 수 없음 | +| P1G | DONE | (이 커밋) | 2026-08-10 | build:plugin을 source-first로 복구; root 결손 양성 대조·2회 결정성·plugin byte parity·actual loader 모두 통과 | +| P1R | DONE | (이 커밋) | 2026-08-10 | project 0.9.3 cache·hooks·engine parity 복구; cached SessionStart exit 0/context card/session_card_rendered 실증 | +| P2 | DONE | (이 커밋) | 2026-08-10 | 실제 bundle 5종 hook pulse·package-less cache·doctor text/JSON 검증; matrix 신선도 info; 2828/2828·verdict DONE·strict gate GREEN | +| P3 | DONE | (이 커밋) | 2026-08-10 | Stop·done·gate blocker와 알려진 실패 종료를 additive telemetry로 기록하고 후속 gate 관측을 doctor에서 집계; 실제 bundle 순차 검증·2834/2834 통과 | +| P4 | DONE | (이 커밋) | 2026-08-10 | 생성 CI를 runtime major.minor에 고정하고 미고정·floating GitHub Actions를 doctor text/JSON에서 경로별 진단; 실제 bundle·2839/2839 통과 | +| P5 | DONE | (이 커밋) | 2026-08-10 | strict attestation에 runtime version·blocking mode·detector SHA를 기록하고 init의 index union rule 보존·멱등성을 실제 bundle로 검증; 2845/2845 통과 | +| P6 | IN_PROGRESS | — | 2026-08-10 | 0.9.4 버전·릴리즈 기록·패키지·PR·배포 의례를 실증하며 진행 중 | diff --git a/.refactor/sim/5b.md b/.refactor/sim/5b.md new file mode 100644 index 00000000..de71399f --- /dev/null +++ b/.refactor/sim/5b.md @@ -0,0 +1,58 @@ +VERDICT: PASS + +# 5b — `repairModules` 정확도 백테스트 + +## 질문과 판정 기준 + +과거 `modules[]` 수리라는 독립 정답에 대해 Git rename 기반 알고리즘이 정확한가? basename만 같은 경로는 자동수리 근거로 충분한가? 오탐이 한 건이라도 나오거나 근거 없는 fallback을 자동 적용해야만 한다면 KILL한다. + +## 독립 정답 구성 + +`develop`의 first-parent 이력에서 `spec/features/*.yaml`이 바뀐 138개 커밋을 읽었다. 각 feature의 변경 전후 `modules[]`를 비교해, 이전 경로가 부모 트리에는 있고 결과 트리에는 없으며 새 경로는 그 반대인 같은-커밋 수리만 정답으로 삼았다. 제품 코드의 제안 결과를 정답 생성에 사용하지 않았다. + +정답은 `28fc6d8` 한 커밋의 3개 실제 rename과 이를 반영한 14개 module claim이었다. + +```text +src/agents/librarian.md -> src/agents/planner.md 5 claims +src/agents/specialists.md -> src/agents/developer.md 5 claims +src/cli/refine.ts -> src/cli/clarify.ts 4 claims +ground_truth_claims=14 +``` + +이 구성은 basename 추측이 아니라 Git rename 기록을 써야 한다는 기존 리팩터링 불변식과도 일치한다 (`.refactor/REFACTOR.md:390`). + +## 결과 1 — Git rename 증거 + +각 정답 커밋에서 `git diff -M50% `의 rename 쌍을 적용했다. + +```text +predictions=14 +correct=14 +wrong=0 +precision=100.0% +recall=100.0% +``` + +따라서 Git이 같은 diff에서 판정한 rename은 자동수리 근거로 충분했다. 과거 결과 파일의 현재 basename만 검색하는 기존 방식은 “유일 후보일 때만 고친다”는 보수적 형태이지만 (`src/spec/test-ref-repair.ts:68`, `src/spec/test-ref-repair.ts:97`), rename 인과관계 자체를 증명하지는 않는다. + +## 결과 2 — basename fallback의 한계 + +현재 `src/`에는 197개 파일과 183개 basename이 있고, 9개 basename이 23개 파일 사이에서 충돌한다. 현재 spec의 존재하는 source-file module claim 676개를 leave-one-out으로 평가하면 유일 basename은 587개를 맞히고 89개에서는 모호하여 abstain했다. + +```text +correct=587 +wrong=0 +ambiguous_abstain=89 +precision_among_predictions=100.0% +coverage=86.8% +``` + +그러나 이 검사는 현재 정답을 후보 집합에서 잠시 감춘 합성 검사다. first-parent의 `src/` 변경 148개 커밋을 rename 감지 없이 다시 읽어, 같은 커밋의 삭제/추가 중 동일 basename이고 추가 후보가 하나뿐인 실제 이동을 찾았지만 독립 정답은 0건이었다. 즉 unique-basename fallback이 과거 실제 이동을 맞혔다는 실증은 없으며, 자동 쓰기 권한을 줄 수 없다. 특히 기존 코드가 모호하거나 후보가 없으면 건너뛰는 이유도 바로 추측 금지다 (`src/spec/test-ref-repair.ts:105`). + +## 최적 정책 + +- 같은 diff의 Git rename 기록과 정확히 대응하는 stale module claim만 자동수리한다. +- unique-basename 결과는 dry-run 제안으로만 노출하고 명시적 선택 전에는 쓰지 않는다. +- basename이 모호하거나 Git rename과 충돌하면 아무것도 추측하지 않는다. + +이 경계는 독립 정답에서 검증된 14/14 자동수리를 보존하면서, 실증되지 않은 fallback의 오탐 가능성을 자동 변경 경로에서 제거한다. 따라서 좁혀진 `repairModules` 설계는 PASS이며 구현은 A9에 남긴다. diff --git a/.refactor/sim/M5.md b/.refactor/sim/M5.md new file mode 100644 index 00000000..8ce7081b --- /dev/null +++ b/.refactor/sim/M5.md @@ -0,0 +1,51 @@ +VERDICT: KILL + +# M5 — `clad sign-off` 출처 검증 + +## 질문과 판정 기준 + +`clad sign-off `가 `identity.author: human` 증거의 유일한 생산자가 되려면, 같은 작업 공간과 셸 권한을 가진 호스트 에이전트가 그 명령을 대신 실행해도 사람의 승인으로 기록되어서는 안 된다. 비대화형 실행을 막는 것만으로 부족하고, 승인 입력의 출처가 CLI 프로세스 밖의 신뢰 경계에서 검증되어야 한다. + +현재의 로컬·무설정 CLI 모델에는 그 경계가 없다. 따라서 A10의 `sign-off`는 검증 가능한 사람 증거 생산자가 될 수 없으며 S2를 KILL한다. + +## 근거 + +1. **호스트 에이전트가 CLI를 실행할 수 있다.** 핵심 역할인 orchestrator와 developer가 모두 `Bash`/`exec` 권한을 갖는다 (`src/agents/orchestrator.md:4-5`, `src/agents/developer.md:4-5`). 읽기 전용 reviewer도 `Bash`/`exec`를 갖는다 (`src/agents/reviewer.md:4-5`). 따라서 `sign-off`를 일반 CLI verb로 노출하면 사람과 에이전트가 같은 실행 경로를 쓴다. + +2. **TTY는 출처가 아니다.** 이 Codex 호스트에서 같은 Node 탐침을 기본 실행하면 다음과 같았다. + + ```text + {"stdin":false,"stdout":false} + ``` + + 호스트가 PTY를 요청한 동일 명령은 다음과 같았다. + + ```text + {"stdin":true,"stdout":true} + ``` + + 이어서 PTY 안에서 Node `readline`으로 `approval>`을 띄우고 에이전트가 `APPROVE`를 입력하자 `accepted=true`가 나왔다. 따라서 `process.stdin.isTTY`, `/dev/tty`, 대화형 재입력, 일회용 확인 문구는 일반적인 파이프와 CI는 거부할 수 있어도 사람과 PTY를 제어하는 에이전트를 구분하지 못한다. + +3. **git author와 OS user도 출처가 아니다.** 현재 identity 보조 함수는 git `user.name`, 없으면 OS username을 읽은 뒤 호출 주체와 무관하게 `author: 'human'`을 반환한다 (`src/events/log.ts:178-194`). 같은 계정에서 동작하는 에이전트가 이 값을 그대로 상속한다. 저장소의 기존 결정 기록도 git/OS 계정은 AI와 사람을 구분하지 못한다고 명시한다 (`docs/refinement-backlog.md:29`). + +4. **일회용 challenge는 의도 확인이지 출처 증명이 아니다.** 현재 init 경계는 완전한 사용자 응답이라고 설명된 challenge 문자열을 인자로 받아 문자열 일치만 검사한다 (`src/serve/server.ts:759-786`). 테스트 자체도 준비 응답에서 challenge를 읽어 프로그램적으로 그대로 넘긴다 (`tests/serve/init-tools.test.ts:65-68`, `tests/serve/init-tools.test.ts:372-377`). challenge를 볼 수 있는 에이전트는 사람 없이 같은 응답을 만들 수 있다. + +5. **잘못된 `human` 한 건이 바로 권한을 만든다.** 독립성 판정은 해당 피처 증거 중 `identity.author === 'human'` 또는 `blind === true`가 하나라도 있으면 `independent`로 바뀐다 (`src/hitl/independence.ts:58-68`). AC 수준의 anti-self-cert도 `human` 표식의 존재만 센다 (`src/hitl/anti-self-cert.ts:33-53`). 출처를 증명하지 못하는 `sign-off`를 추가하면 검증 불가능한 자기 신고가 실제 게이트 권한으로 승격된다. + +6. **CLI-only 불능은 이미 실증되어 있다.** 26개 CLI verb를 전수 탐침한 기록은 independence-eligible evidence를 쓰는 CLI 경로가 없고 `independence_policy: require`가 빠져나갈 수 없는 차단임을 확인했다 (`docs/dogfood/e2e-role-contract-2026-07-24.md:51-61`, `docs/dogfood/e2e-role-contract-2026-07-24.md:82-94`). 이번 M5는 단순 `sign-off` verb가 그 틈을 정직하게 메우지 못함을 추가로 확인한다. + +## 기각한 메커니즘 + +| 후보 | 기각 이유 | +|---|---| +| stdin/stdout TTY 검사 | 에이전트가 PTY를 할당할 수 있다 | +| 확인 문구 재입력 | 에이전트가 출력된 문구를 읽고 같은 PTY에 쓸 수 있다 | +| git author / OS username | 사람과 에이전트가 같은 계정 값을 상속한다 | +| `CI` 또는 호스트 환경 변수 검사 | 실행 주체가 지우거나 위조할 수 있는 자기 신고다 | +| 커밋 서명 존재 | 소프트웨어 키는 같은 프로세스가 사용할 수 있고 사용자 현존을 증명하지 않는다 | + +## 재개 조건과 큐 영향 + +신뢰할 수 있는 재개 조건은 CLI 프로세스가 위조할 수 없는 출처다. 예를 들면 인증된 호스트가 실제 사용자 메시지와 principal을 서명해 전달하거나, 사용자 현존을 강제하는 하드웨어 키가 challenge에 서명하고 cladding이 이를 검증하는 방식이다. 이는 현재의 portable·zero-config CLI 범위를 벗어난다. + +PLAN §3의 KILL 분기대로 A10과 A11을 큐에서 제거한다. `independence_policy: require`는 CLI-only 환경에서 만족 불가로 명시하며, 검증 가능한 외부 출처가 생기기 전에는 `human` 증거 writer를 추가하지 않는다. diff --git a/.refactor/sim/M7.md b/.refactor/sim/M7.md new file mode 100644 index 00000000..49dfd3cb --- /dev/null +++ b/.refactor/sim/M7.md @@ -0,0 +1,63 @@ +VERDICT: PASS + +# M7 — Jest 공허 가드 실증 + +## 질문 + +Jest 프로젝트에서 테스트 파일이 선언되어 있지만 전부 skip되어 실제 passing test가 0개일 때, strict Unit stage가 이를 `VACUOUS_TESTS`로 거부하는가? 갭이 있다면 기존 Vitest JSON 파서를 재사용할 수 있는가? + +## 실증 환경 + +- Node 26.0.0 +- Jest 30.2.0 +- Cladding 0.9.3, 현재 소스의 `runUnit({strict: true})` +- 저장소 밖 `/tmp/cladding-m7-jest-probe.ZkulyG` +- 픽스처: `test.skip` 하나이며 body는 실행되면 throw + +## 실증 1 — 실제 Jest는 공허한 suite를 GREEN으로 끝낸다 + +`jest vacuous.test.js --runInBand --no-colors` 결과: + +```text +Test Suites: 1 skipped, 0 of 1 total +Tests: 1 skipped, 1 total +Snapshots: 0 total +Ran all test suites matching vacuous.test.js. +jest_exit=0 +``` + +Jest는 총 테스트 수가 1이므로 현재 aggregate zero 패턴에 걸리지 않는다. 그 패턴은 요약에서 캡처한 모든 `total` 값이 0일 때만 발화한다 (`src/stages/unit.ts:49-68`). + +## 실증 2 — 현재 strict Unit stage가 실제로 놓친다 + +동일 Jest binary와 픽스처를 현재 `runUnit`에 넣은 결과: + +```text +M7_STAGE_RESULT={"stage":"stage_2.1","pass":true,"exitCode":0} +``` + +원인은 코드 경계와 일치한다. Jest는 toolchain에서 정식 test/coverage runner로 선택된다 (`src/stages/toolchain/detect.ts:652-657`). 그러나 per-file guard의 `guardOn`은 strict이면서 Vitest일 때만 참이다 (`src/stages/unit.ts:205-209`), JSON reporter도 그 분기에서만 추가된다 (`src/stages/unit.ts:222-229`). 따라서 Jest all-skipped는 aggregate zero 검사도 통과하고 per-file 검사에는 도달하지 않는다 (`src/stages/unit.ts:241-257`). + +## 실증 3 — 새 파서는 필요 없다 + +같은 Jest 실행에 `--json --outputFile=jest-results.json`을 추가한 native 결과의 핵심 shape: + +```json +{"success":true,"numTotalTests":1,"testResults":[{"status":"skipped","assertionResults":[{"status":"pending"}]}]} +``` + +현재 `parseExecutedPassCounts`에 이 파일을 직접 넣은 결과: + +```text +M7_JEST_COUNTS=[["/private/tmp/cladding-m7-jest-probe.ZkulyG/vacuous.test.js",0]] +``` + +기존 파서는 `testResults[].name`과 `assertionResults[].status`만 읽고 `passed`만 계수하므로 Jest shape도 그대로 처리한다 (`src/stages/vacuous-tests.ts:28-35`, `src/stages/vacuous-tests.ts:47-68`). 새 parser는 필요하지 않다. + +## 구현 경계와 주의점 + +A6의 Jest 부분은 `isJestRunner` 판별, `--json --outputFile=` 배선, 성공 시 기존 `vacuousDoneFindings` 호출, temp 정리를 추가하는 범위다. 다만 macOS에서 Jest는 `/tmp/...` 입력을 `/private/tmp/...`로 canonicalize했다. 현재 양쪽은 `path.resolve`만 사용한다 (`src/stages/vacuous-tests.ts:61`, `src/stages/vacuous-tests.ts:116`). A6의 live E2E는 이 alias를 포함하고, runner JSON과 `test_ref`를 같은 canonical path로 비교해야 한다. + +## 판정 + +갭이 실제 실행에서 재현됐고 기존 파서 재사용도 실제 Jest JSON으로 입증됐다. 따라서 `VERDICT: PASS`; PLAN의 A6에서 Jest 범위를 유지한다. diff --git a/.refactor/sim/P1.md b/.refactor/sim/P1.md new file mode 100644 index 00000000..0837b558 --- /dev/null +++ b/.refactor/sim/P1.md @@ -0,0 +1,38 @@ +# P1 — Claude Code 훅 배선 장애 기록 + +## 독립 증상 + +`claude plugin list`는 같은 project-scope 설치를 두 번 보고했고 둘 다 `Version: 0.4.0`, `Marketplace cladding failed to load: cache-miss`였다. 설치 레지스트리는 cladding 저장소와 다른 프로젝트가 존재하지 않는 동일 cache를 공유한다고 기록했다. + +```text +marketplace_source=/Users/qwerfunch/.claude/plugins/cladding +source_exists=false +cache=/Users/qwerfunch/.claude/plugins/cache/cladding/claude-code/0.4.0 +cache_has_hooks=false +cache_has_dist=false +``` + +현재 checkout은 plugin 0.9.3, bundled engine, 다섯 lifecycle event를 모두 갖고 있어 build 산출물 누락은 아니었다. 표준 hook 파일은 `plugins/claude-code/hooks/hooks.json:2`에 있고 build가 그 존재와 event 수를 검사한다 (`scripts/build-plugin.mjs:152`). + +## 1차 원인과 수정 방향 + +저장소의 `.claude/settings.json`은 `enabledPlugins["claude-code@cladding"]`만 선언했다. Claude Code의 현재 계약에서는 plugin enable이 다른 개발자에게 plugin을 설치하지 않으며, project가 `extraKnownMarketplaces`도 선언해야 trust 승인 뒤 설치할 수 있다. 삭제된 pre-0.9.0 directory marketplace가 user 설정에 남은 이 머신에서는 source를 찾지 못해 0.4.0 cache-miss가 지속됐다. + +maintainer dogfood는 현재 checkout을 검증해야 하므로 project marketplace를 `{source: "directory", path: "."}`로 선언하고 auto-update를 켠다. 상대 directory source는 Git worktree에서도 main checkout 기준으로 해석되는 Claude Code의 개발용 source다. + +## 실제 로더에서 발견한 핀 충돌 + +source를 GitHub checkout으로 임시 복구해 0.9.3 cache를 받자 `claude plugin list`의 실패 원인이 다음으로 바뀌었다. + +```text +Hook load failed: Duplicate hooks file detected: ./hooks/hooks.json resolves to +already-loaded file .../cache/cladding/claude-code/0.9.3/hooks/hooks.json. +The standard hooks/hooks.json is loaded automatically, so manifest.hooks should +only reference additional hook files. +``` + +현재 manifest는 표준 파일을 명시적으로 다시 선언한다 (`plugins/claude-code/.claude-plugin/plugin.json:35`). 기존 테스트는 바로 그 필드가 반드시 존재한다고 고정한다 (`tests/scripts/hooks-config.test.ts:68`). manifest를 올바르게 고치면 이 핀이 발화하므로 PLAN §4에 따라 P1에서 테스트나 manifest를 바꾸지 않는다. + +## 다음 경계 + +P1P에서 자동발견되는 표준 hook 파일은 유지하되 중복 manifest 필드를 제거하고 테스트 핀을 새 host 계약으로 재협상한다. 그 커밋이 독립적으로 GREEN이면 P1R에서 current checkout marketplace를 재등록하고 0.9.3 cache의 hooks/dist 및 실제 hook 출력을 확인한다. diff --git a/.refactor/sim/P1G.md b/.refactor/sim/P1G.md new file mode 100644 index 00000000..788bf1e9 --- /dev/null +++ b/.refactor/sim/P1G.md @@ -0,0 +1,38 @@ +# P1G — Claude plugin engine build provenance 실증 + +## 문제 + +standalone `npm run build:plugin`은 ignored `dist/clad.js`가 존재하기만 하면 출처와 신선도를 검사하지 않고 출하 plugin으로 복사했다. P1P에서 그 파일이 현재 source에는 없는 60 bytes를 품은 상태가 실제로 재현됐다. root `/dist/`는 `.gitignore:17`로 제외되므로 commit이나 source의 정답으로 쓸 수 없다. + +공개 npm command가 먼저 `scripts/build.mjs`를 실행하고 그 뒤에 mirror builder를 실행하도록 바꿨다 (`package.json:64`). direct builder의 계약도 두 public build command가 source-fresh root bundle을 선행한다는 사실로 맞췄다 (`scripts/build-plugin.mjs:29`, `scripts/build-plugin.mjs:123`). 회귀 테스트는 이 순서를 고정한다 (`tests/scripts/hooks-config.test.ts:86`). + +## 결손 입력 양성 대조 + +기존 ignored root bundle을 저장소 밖 임시 디렉터리로 이동해 `dist/clad.js`가 없는 것을 먼저 확인하고 standalone command를 실행했다. + +```text +pre_state_root_exists=no +command=npm run build:plugin +command_expansion=node scripts/build.mjs && node scripts/build-plugin.mjs +old_ignored_root_sha=664a2fc876b987bea96747a42071d6a959d039aa19cde8d7e188ba1db1bd7c04 +new_root_sha=2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e +plugin_sha=2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e +cmp_exit=0 +``` + +새 source build는 이미 커밋된 plugin mirror와 byte-identical했다. 따라서 P1B에서 mirror를 stale root 쪽으로 바꾸지 않은 결정이 옳았고, 오염은 ignored root에만 있었다. + +보관한 이전 root bundle은 삭제하지 않고 `/Users/qwerfunch/.Trash/cladding-p1g-build.9HC6My/stale-clad.js`로 이동했다. + +## 결정성 및 실제 loader + +같은 command를 두 번째 실행한 뒤 root/plugin SHA는 네 자리 모두 동일했고 tracked 생성 diff는 0개였다. + +```text +first_root=2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e +first_plugin=2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e +second_root=2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e +second_plugin=2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e +``` + +`claude --plugin-dir plugins/claude-code plugin list`는 `cladding@inline`, version 0.9.3, `Status: ✔ loaded`를 냈고 Duplicate hooks 오류는 없었다. source-first build와 표준 hook 자동발견이 함께 실제 host loader를 통과했다. diff --git a/.refactor/sim/P1P.md b/.refactor/sim/P1P.md new file mode 100644 index 00000000..ee703b2d --- /dev/null +++ b/.refactor/sim/P1P.md @@ -0,0 +1,42 @@ +# P1P — 표준 hook 자동발견 핀 재협상 기록 + +## 핀 변경의 독립 검증 + +Claude Code 2.1.224가 자동발견하는 `plugins/claude-code/hooks/hooks.json`은 그대로 두고, 같은 파일을 다시 가리키던 manifest `hooks` 필드만 제거했다. 기존 다섯 event와 matcher 단언은 유지했고, manifest 단언은 “표준 파일을 중복 선언하지 않는다”로 바꿨다 (`tests/scripts/hooks-config.test.ts:68`). + +수정 전 actual session-only loader: + +```text +cladding@inline +Version: 0.9.3 +Status: ✘ loaded with errors +Error: Hook load failed: Duplicate hooks file detected +``` + +수정 후 같은 `claude --plugin-dir plugins/claude-code plugin list`: + +```text +cladding@inline +Version: 0.9.3 +Status: ✔ loaded +``` + +`claude plugin validate .`도 exit 0이었지만 수정 전에도 통과했으므로 이 결함의 오라클로 세지 않는다. 실제 loader 상태 변화만 양성 증거다. + +## 범위 위반 신호 + +AGENTS.md가 요구하는 `npm run build:plugin`을 실행하자 manifest 외에 `plugins/claude-code/dist/clad.js`가 바뀌었다. 현재 root `dist/clad.js`와 생성 mirror SHA-256은 `664a2fc876b987bea96747a42071d6a959d039aa19cde8d7e188ba1db1bd7c04`로 같았고, 커밋된 plugin mirror는 `2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e`였다. + +공통 prefix/suffix를 제거한 실제 delta는 source의 missing-tool 분류 정규식에 이미 있는 다음 60 bytes다. + +```text +failed to load\\b.{0,40}\\b(module|rule|plugin|preset|config)| +``` + +P1P의 `touch_allowed` 밖이므로 생성된 mirror 변경은 HEAD로 복원했다. P1P는 FAIL로 닫았다. + +## P1B 입장검사에서 정정된 provenance + +위 60 bytes가 `src/stages/util.ts:56`에 있다는 최초 해석은 틀렸다. 그 줄의 현재 정규식에는 해당 분기가 없고 repo 전체 canonical source 검색도 0건이었다. 또한 root `/dist/`는 `.gitignore:17`로 제외되어 현재 checkout이나 commit의 정답이 아니다. 반면 `plugins/claude-code/dist/clad.js`는 추적되는 출하 artifact다. + +즉 standalone `build:plugin`이 출처 없는 로컬 root bundle을 출하 mirror에 복사한 것이며, plugin mirror를 root에 맞추는 P1B는 잘못된 방향이다. P1B는 제품 파일을 건드리기 전에 KILL한다. P1G가 `build:plugin` 자체를 source-first로 만든 뒤 생성 결과를 다시 측정한다. diff --git a/.refactor/sim/P1R.md b/.refactor/sim/P1R.md new file mode 100644 index 00000000..42312dc7 --- /dev/null +++ b/.refactor/sim/P1R.md @@ -0,0 +1,51 @@ +# P1R — Claude Code dogfood hook 실복구 + +## 복구 전 독립 상태 + +P1 시작 시 Claude registry에는 project-scope `claude-code@cladding` 0.4.0 설치가 두 개 있었고, marketplace는 이미 삭제된 `/Users/qwerfunch/.claude/plugins/cladding` directory를 가리켰다. 0.4.0 cache에는 hooks와 bundled engine이 없어 두 설치 모두 `cache-miss`로 load 실패했다. + +P1이 current-checkout marketplace 선언을 추가했고 (`.claude/settings.json:5`), P1P는 Claude Code 2.1.224가 자동발견하는 표준 `hooks/hooks.json`을 manifest에서 중복 선언하지 않게 했다 (`tests/scripts/hooks-config.test.ts:71`). P1G는 standalone plugin build가 ignored root bundle을 정답으로 오인하지 않도록 source-first로 만들었다 (`package.json:64`). + +## 실제 marketplace와 설치 복구 + +공유 설정에는 이식 가능한 `path: "."`을 유지했다. CLI 등록은 이를 user registry의 절대 checkout 경로로 해석했다. + +```text +marketplace=cladding +source=directory +path=/Users/qwerfunch/Developer/work/cladding +installLocation=/Users/qwerfunch/Developer/work/cladding +``` + +동일 `0.9.3` cache가 이전 GitHub 등록 때 이미 생겨 단순 update는 version만 바꾸고 stale manifest를 재사용했다. 현재 프로젝트 설치만 `--keep-data`로 uninstall/install하여 cache 내용을 강제로 현재 checkout에서 다시 복사했다. 다른 `/Users/qwerfunch/Developer/work/logcat-on`의 0.4.0 project 설치는 범위 밖이라 변경하지 않았다. + +```text +projectPath=/Users/qwerfunch/Developer/work/cladding +version=0.9.3 +installPath=/Users/qwerfunch/.claude/plugins/cache/cladding/claude-code/0.9.3 +status=enabled +cache_manifest_has_explicit_hooks=false +cache_hooks_file=true +checkout_engine_sha=2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e +cache_engine_sha=2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e +``` + +## 실제 cache의 hook 발화 + +설치된 cache engine을 Claude의 shipped command와 같은 인자로 직접 실행했다. + +```text +printf '{}' | node /dist/clad.js hook SessionStart +hook_exit=0 +stdout_bytes=652 +``` + +출력은 `cladding: 273 features (269 done, 0 in progress) · 2 scenarios`로 시작했고, 마지막 strict gate GREEN, context, 두 prefer 규칙, spec policy를 포함했다. 동시에 `.cladding/events.log.jsonl`에 다음 관측이 추가됐다. + +```text +type=session_card_rendered +payload.bytes=651 +head=c72616ad16035a4c4b07cf0bb37d9e5afd9d797b +``` + +stdout의 마지막 newline이 event payload byte 수에 포함되지 않아 `wc -c`와 1 byte 차이다. loader 등록, cache 내용, engine parity, command 출력, telemetry의 다섯 독립 표면이 모두 이어졌으므로 P1R은 PASS다. 새 Claude Code 세션부터 host가 복구된 plugin을 적용한다. diff --git a/.refactor/sim/P2.md b/.refactor/sim/P2.md new file mode 100644 index 00000000..4c1bce3f --- /dev/null +++ b/.refactor/sim/P2.md @@ -0,0 +1,51 @@ +# P2 — 훅 건강 가시화와 호스트 증거 신선도 + +## 기준선 + +P1R 직전 Claude project 설치는 삭제된 marketplace와 0.4.0 cache를 가리켰지만 `clad doctor`는 이를 전혀 알리지 못했다. 기존 이벤트로 훅 발화를 역산하는 것도 불가능했다. `SessionStart`는 카드가 비어 있으면, `UserPromptSubmit`은 제안이 없으면, `Stop`은 차단하지 않으면 이벤트를 쓰지 않고 `PreToolUse`에는 대응 이벤트가 아예 없다. 결과 이벤트의 부재를 훅 미발화로 해석하면 정상 호출도 죽은 배선으로 오인한다. + +호스트 매트릭스에는 이미 생성 시각과 Cladding 버전이 있었지만 `HOST_CLAIM_DRIFT`는 등급 fence만 읽었다. 현재 committed matrix는 2026-07-16의 v0.9.0 증거이고 실행 엔진은 v0.9.3이다. + +## 구현 결정 + +고빈도 훅 호출을 `events.log.jsonl`에 추가하지 않았다. 대신 `.cladding/hook-health.json` 한 파일이 다섯 고정 키(`SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, `Stop`)의 마지막 ISO 시각과 관측 엔진 버전만 원자적으로 덮어쓴다. 따라서 호출량과 파일 크기가 무관하며, spec 없는 디렉터리·알 수 없는 이벤트·손상된 파일은 `not-observed`로 fail-open한다. + +`clad doctor`의 text/JSON은 registry 설치 여부를 추측하지 않는다. 실제 runtime pulse가 하나라도 있을 때만 `observed`라고 하며, recorded/current version 일치와 다섯 이벤트의 시각 또는 `never observed`를 함께 낸다. npm 설치에는 `package.json`, Claude cache에는 `.claude-plugin/plugin.json`만 있으므로 중앙 버전 판독기는 두 manifest를 같은 우선순위로 읽는다. + +`HOST_CLAIM_DRIFT`는 positive README claim이 있을 때 matrix 생성 후 30일 초과 또는 현재보다 오래된 엔진 버전을 신선도 부채로 낸다. severity는 `info`다. Phase 0은 판정을 바꾸지 않으므로 기존 claim>grade 모순만 계속 `warn`이고, 신선도는 strict gate를 막지 않는다. + +## 독립 검증 + +관련 검사는 4개 파일 55/55 통과했다. + +```text +tests/cli/hook-health.test.ts 5 passed +tests/cli/doctor.test.ts 12 passed +tests/cli/setup.test.ts 23 passed +tests/stages/detectors/host-claim-drift.test.ts 15 passed +``` + +실제 출하 bundle `plugins/claude-code/dist/clad.js`을 다섯 이벤트에 별도 프로세스로 호출했다. 전부 exit 0이었고 SessionStart만 702 bytes context card를 냈으며 나머지는 protocol silence였다. 이어 같은 bundle의 `doctor --json`이 다음을 보고했다. + +```text +installation=observed +recordedVersion=0.9.3 +currentVersion=0.9.3 +versionCurrent=true +SessionStart/UserPromptSubmit/PreToolUse/PostToolUse/Stop = all non-null +``` + +`package.json` 없는 임시 Claude cache 구조에도 plugin subtree를 복사해 같은 bundle을 실행했다. `.claude-plugin/plugin.json`만 있는 상태에서 hook exit 0, doctor exit 0, recorded/current version 모두 0.9.3이었다. 이 양성 대조가 P1에서 실제로 발견한 cache 배포 형태를 재현한다. + +최종 detector 주석 변경 전후 `npm run build:plugin`의 shipped engine SHA는 모두 `19e5de1ff49bbd882a8f80aeb842885065a9429e6bab179f6c5068a1a8ee56f9`였다. 주석-only 변경이 번들 바이트를 움직이지 않는다는 오라클도 유지됐다. + +현재 저장소의 detector 단독 실행은 등급 모순 없이 다음 한 건만 냈다. + +```text +HOST_CLAIM_DRIFT info docs/dogfood/matrix.md +generated by cladding v0.9.0, before the current v0.9.3 +``` + +첫 전체 Vitest와 즉시 겹쳐 시작한 부분 재실행은 다른 workspace의 장시간 Node 테스트까지 동시에 돌아가는 동안 5초짜리 deliverable subprocess 14건을 timeout시켰다. 제품 관련 검사는 모두 통과했고, 실패한 네 파일을 단일 워커로 독립 실행하자 51/51이 12.16초에 통과했다. 이어 전체 스위트를 단일 워커로 실행해 **250/250 files, 2827/2827 tests**가 152.41초에 통과했다. 외부 부하가 사라진 뒤 요구된 기본 병렬 명령 `npm test`를 그대로 재실행했고, **250/250 files, 2828/2828 tests**가 14.74초에 깨끗하게 통과했다. + +`clad done F-96fa5622`는 완료 상태를 임시 적용한 strict pre-push에서 오래된 attestation만 재검증해 새로 도장했고, 나머지 모든 단계가 GREEN이라 전환을 유지했다. 전환 후 `clad verdict --json`은 `DONE`, `remaining: []`였고 별도 pre-commit 및 strict pre-push 재실행도 모두 exit 0이었다. diff --git a/.refactor/sim/P3.md b/.refactor/sim/P3.md new file mode 100644 index 00000000..a61460b4 --- /dev/null +++ b/.refactor/sim/P3.md @@ -0,0 +1,58 @@ +# P3 — Stop·완료 결과 계수기 + +## 기준선과 질문 + +기존 lifecycle ledger는 `stop_blocked` 89건을 갖고 있었지만 각 이벤트에는 `{count, fingerprint, head, identity}`만 있었다. 동일 지문 두 번째 Stop은 아무 이벤트 없이 허용됐고, `done_attempted`에는 실패 원인이 없었다. 따라서 Stop이 실제로 무엇을 막았는지, 알려진 실패 상태로 몇 번 종료됐는지, 같은 지문을 후속 게이트도 관측했는지를 로그에서 답할 수 없었다. + +P3 직전 실제 출하 bundle의 doctor 기준선은 다음이었다. + +```text +blocked=89 +exitsRecorded=0 +observedByLaterGate=0 +notObservedByLaterGate=89 +``` + +## 구현 결정 + +정책은 바꾸지 않고 기존 이벤트에 additive 증거만 붙였다. `stop_blocked`와 새 `stop_exit_recorded`는 전체 실패 수·고정 지문·정렬된 detector 이름·최신 관측 게이트 대비 새/기존 실패 수·dirty path 교집합을 기록한다. `done_attempted`와 `gate_run`은 정렬된 blocker 이름을 기록하고, gate에는 Stop의 배포된 `detector|path` 계산과 호환되는 `stopFingerprint`를 추가했다. + +기존 `.cladding/stop-block.json`의 호환성이 가장 중요하므로 hook의 지문 코드는 공용화하거나 수정하지 않았다. 게이트 쪽 계산을 별도로 두고 고정 SHA 벡터로 잠갔다. gate dedupe는 HEAD/tier/strict/worst뿐 아니라 blocker 증거까지 같을 때만 적용한다. 단, `stop_blocked` 뒤 첫 동일 gate는 상관관계를 남기기 위해 보존하고 그 다음 exact repeat부터 다시 dedupe한다. + +후속 관측 여부는 새 sidecar 없이 이벤트를 뒤에서 앞으로 한 번 순회해 계산한다. 각 `stop_blocked`보다 뒤에 동일한 `stopFingerprint`의 `gate_run`이 있으면 관측된 것으로 센다. 구버전 이벤트의 누락 필드는 0/미관측으로 처리한다. + +## 실제 출하 bundle 순차 검증 + +`plugins/claude-code/dist/clad.js`를 현재 dogfood 저장소에서 직접 호출했다. 추적 파일이 수정된 상태라 첫 Stop은 1178개 strict drift finding을 차단했고 다음 payload를 남겼다. + +```text +stop_blocked +count=1178 +detectors=[INVENTORY_DRIFT, STALE_ATTESTATION, UNVERIFIED_AC] +introduced=1178 preexisting=0 dirty_hit=true +fingerprint=64c93891cf8a35a22709016310325b9c3f70ec4dc67d9cfa765636f116bb2b11 +``` + +같은 입력을 같은 bundle에 다시 보냈을 때 exit 0, stdout 0 bytes였고, 기존 allow/demote 동작을 유지하면서 같은 필드와 지문의 `stop_exit_recorded` 한 건이 추가됐다. 이어 실제 `check --tier=pre-commit --strict --json`은 Drift RED, Architecture/Secret GREEN을 냈고 gate event의 blocker 집합과 `stopFingerprint`가 위 Stop 이벤트와 정확히 같았다. + +그 직후 실제 `doctor --json`은 기준선 대비 정확히 한 건씩 증가했다. + +```text +blocked=90 +exitsRecorded=1 +observedByLaterGate=1 +notObservedByLaterGate=89 +unresolvedStopBlock=true +``` + +텍스트 doctor도 `stop exits recorded: 1`과 `blocked fingerprints later seen by a gate: 1/90`을 표시했다. 이 순차 실험은 event producer, bundle entry, dedupe 예외, read-time reducer, text/JSON surface를 한 번에 통과한다. + +기능을 `done`으로 승격한 뒤 같은 출하 bundle의 Stop을 다시 호출했을 때 stdout은 비었고 unresolved stop-block sidecar는 제거됐다. 마지막 `done_attempted`는 해당 기능에 `kept=true`, `blockers=[]`, `worst=0`을 기록했다. 따라서 차단·동일 지문 종료·후속 게이트 관측뿐 아니라 정상 완료 경로도 실제 bundle에서 닫혔다. + +## 자동 검증 + +관련 6개 파일의 최신 집중 실행은 **6/6 files, 99/99 tests**가 통과했다. 여기에는 배포 지문의 고정 SHA, 구버전 payload 관용, gate 사이에 Stop이 있을 때의 dedupe 예외, 같은 RED 결과에서 blocker만 바뀌는 양성 대조, green/red done blocker가 포함된다. + +첫 기본 병렬 전체 실행은 blocker-dedupe 양성 대조 추가 전 상태에서 **251/251 files, 2833/2833 tests**가 17.93초에 통과했다. 양성 대조 추가 뒤 실행은 다른 workspace의 `flutter test --coverage`·strict gate와 겹쳐 5초 subprocess timeout만 냈다. 해당 외부 부하가 사라진 뒤 남은 multi-probe 파일은 단일 워커 **25/25**가 6.36초에 통과했고, 요구된 기본 병렬 `npm test`를 수정 없이 다시 실행해 **251/251 files, 2834/2834 tests**가 21.54초에 깨끗하게 통과했다. 테스트 timeout·임계값·핀은 바꾸지 않았다. + +`npm run typecheck`, `npm run lint`, `npm run build:plugin`도 통과했고 생성된 Claude bundle SHA-256은 `7d93c2daadc6e85c1f41d9508893bf3f7220ae7018591e434ac906eac010f0f1`이다. `clad done`이 내부 strict gate를 통과해 기능 status와 attestation을 함께 갱신했으며, 마지막 명시적 pre-commit gate도 Drift·Architecture·Secret 전부 GREEN이었다. 명시적 strict pre-push는 다른 workspace의 병렬 검증과 겹친 실행에서 Coverage의 고정 5초 경계를 일시적으로 넘었지만 소스·임계값을 바꾸지 않은 재실행에서 Type·Lint·Drift·Architecture·Secret·Unit·Coverage·Deliverable이 모두 GREEN이었고 attestation을 새로 찍었다. 최종 `clad verdict --json`은 `DONE`, `next_action=null`, 남은 항목 0을 반환했다. diff --git a/.refactor/sim/P4.md b/.refactor/sim/P4.md new file mode 100644 index 00000000..832610a0 --- /dev/null +++ b/.refactor/sim/P4.md @@ -0,0 +1,33 @@ +# P4 — CI 버전 고정과 doctor 경고 + +## 기준선 + +P4 시작 시 실행 binary는 `0.9.3`이었고 `scaffoldCiWorkflow`가 만든 authoritative gate는 다음처럼 버전 selector가 없었다. + +```text +npx --yes cladding check --tier=pre-push --strict --json +``` + +따라서 오늘 생성한 workflow도 다음 major/minor 릴리즈가 배포되면 검증 없이 그 버전을 내려받을 수 있었다. 기존 `clad doctor`는 이 상태를 읽지 않았다. + +## 구현 결정 + +생성 시 실행 중인 Cladding SemVer를 숫자 `major.minor`로 줄여 npm package spec에 붙인다. `0.9.3`은 `cladding@0.9`가 된다. patch 보안·버그 수정은 같은 release line에서 받을 수 있고, 다음 minor/major로 자동 이동하지 않는다. runtime manifest가 없거나 SemVer가 아니면 미고정 명령으로 물러서지 않고 workflow 생성을 건너뛰며 이유를 반환한다. 이미 존재하는 workflow는 버전 판독보다 먼저 `exists`로 처리해 기존 non-overwrite 계약을 유지한다. + +doctor의 읽기 전용 진단은 `.github/workflows` 아래 `.yml`·`.yaml`을 결정적 순서로 훑는다. 주석을 제외한 `npx cladding` 호출에서 selector가 없거나 `latest` 같은 floating selector면 프로젝트 상대 경로를 `ciVersion.unpinnedWorkflows[]`에 넣고 text에도 같은 경로를 경고한다. 숫자 `major.minor`, `major.minor.patch`, prerelease selector는 안전한 고정으로 처리한다. 진단은 doctor의 기존 관측 계약대로 exit 0이며 workflow를 수정하지 않는다. + +## 실제 출하 bundle 순차 검증 + +`plugins/claude-code/dist/clad.js`로 빈 임시 프로젝트에 실제 `init --no-llm --with-ci --json`을 실행했다. 생성 결과는 authoritative gate를 보고했고 실제 workflow의 명령은 다음과 같았다. + +```text +npx --yes cladding@0.9 check --tier=pre-push --strict --json +``` + +같은 bundle의 `doctor --json`은 pinned 상태에서 `{"unpinnedWorkflows":[]}`를 냈다. 그 임시 workflow에서 selector만 제거한 뒤 text doctor는 `CI version pinning` 아래 `.github/workflows/cladding.yml`을 정확히 지목하고 `cladding@0.9` remediation을 표시했으며 exit 0을 유지했다. JSON doctor도 정확히 같은 상대 경로 한 건을 반환했다. 이 실험은 source helper만이 아니라 실제 생성 CLI, bundle entry, greenfield doctor early-return, text/JSON surface를 함께 통과한다. + +## 자동 검증 + +집중 실행은 **3/3 files, 26/26 tests**가 통과했다. 여기에는 yml/yaml·중첩 경로·unpinned·floating tag 양성 대조, 숫자 selector·주석·무관 명령 음성 대조, runtime version 결손 시 no-write, 기존 workflow non-overwrite, doctor text/JSON exit 0이 포함된다. + +요구된 기본 병렬 `npm test`는 **252/252 files, 2839/2839 tests**가 17.32초에 통과했다. `npm run typecheck`, `npm run lint`, `npm run build:plugin`도 통과했고 생성된 Claude bundle SHA-256은 `4afdb5108009228f7fece8fb40e5119bddc345068fb8888c68856e7de345c5fb`이다. 첫 `clad done`은 Coverage의 기존 시간 민감 실행이 일시적으로 실패해 status를 유지했지만 소스·테스트·임계값 변경 없는 허용된 한 번의 재시도에서 strict gate가 GREEN이 되어 기능과 attestation을 정상 승격했다. 마지막 명시적 pre-commit은 Drift·Architecture·Secret, strict pre-push는 Type·Lint·Drift·Architecture·Secret·Unit·Coverage·Deliverable 전부 GREEN이었고 attestation을 새로 찍었다. 최종 `clad verdict --json`은 `DONE`, `next_action=null`, 남은 항목 0을 반환했다. diff --git a/.refactor/sim/P5.md b/.refactor/sim/P5.md new file mode 100644 index 00000000..ea133c98 --- /dev/null +++ b/.refactor/sim/P5.md @@ -0,0 +1,41 @@ +# P5 — attestation 정책 도장과 merge attribute + +## 기준선 + +P5 시작 시 `spec/attestation.yaml` v2는 완료 기능의 모듈 해시와 기능 표지만 기록했다. 어떤 Cladding 버전과 detector registry가 어떤 차단 정책으로 그 검증을 통과시켰는지는 파일에 남지 않았다. `clad init`도 `.gitignore`만 관리했고 새 채택자의 `.gitattributes`에는 append-only 파생 index를 위한 `spec/index.yaml merge=union` 규칙을 만들지 않았다. + +## 형식과 호환성 결정 + +GREEN strict pre-push/all 게이트만 기존 attestation의 맨 앞에 다음 정책 identity를 쓴다. + +```yaml +policy: + cladding: "0.9.3" + blocking: strict + detectors_sha256: <64-character lowercase SHA-256> +``` + +detector digest는 registry의 선언 순서, 안정된 이름, subprocess 여부를 NUL로 구분해 전부 SHA-256에 넣는다. 함수 직렬화처럼 빌드 도구에 흔들리는 표현은 쓰지 않으며 구현 바이트의 identity는 함께 기록한 Cladding 버전이 맡는다. writer는 같은 입력을 LF·정렬 순서로 byte-identical하게 다시 쓴다. 기존 v1/v2 파일은 migration 없이 계속 읽고 `policy: null`로 노출하므로 기존 freshness 판정은 바뀌지 않는다. + +`clad init`은 `.gitattributes`가 없으면 만들고, 있으면 사용자 내용을 그대로 보존한 채 정확한 `spec/index.yaml merge=union` 한 줄만 덧붙인다. 이미 정확한 줄이 있으면 파일은 byte-identical하다. `spec/attestation.yaml`에는 union merge를 절대로 지정하지 않는다. 충돌 영역에 휩쓸린 오래된 해시를 조용히 되살릴 수 있기 때문이다. + +## 실제 출하 bundle init 검증 + +생성된 `plugins/claude-code/dist/clad.js`를 빈 임시 프로젝트에서 실행했다. 미리 넣은 `*.md linguist-detectable`은 보존됐고 다음 관리 섹션이 덧붙었다. + +```gitattributes +# Cladding derived feature index +spec/index.yaml merge=union +``` + +동일 bundle init을 두 번째 실행하자 `created: []`와 `already present`를 보고했고 파일 SHA-256은 실행 전후 모두 `b2f719bca17be0636edb5b5e8cd15400fdc0fbf01560859953a53f299c6937af`였다. attestation merge rule은 생기지 않았다. 임시 프로젝트는 검증 뒤 `~/.Trash/cladding-p5.MtMYYW`로 옮겨 복구 가능하게 정리했다. + +## 자동 검증 + +집중 실행은 **3/3 files, 35/35 tests**가 통과했다. 정책 writer/reader 결정성, legacy policy-less v2 관용, detector order/name/subprocess 양성 대조, strict-only writer 호출, `.gitattributes` 생성·보존·중복 방지·attestation 음성 대조를 포함한다. `npm run typecheck`, `npm run lint`, `npm run build:plugin`도 통과했고 생성된 Claude bundle SHA-256은 `866f2f71ae036df742f984837e20de57ed99a210422065c4a2cbfc8117baae00`이다. + +요구된 기본 병렬 `npm test`의 최종 실행은 **253/253 files, 2845/2845 tests**가 통과했다. 그 전에 macOS XProtect가 약 95% CPU를 쓰던 실행에서 `hook-telemetry`의 30초 timeout 한 건이 발생했지만 동일 파일 단독 실행은 **14/14**로 통과했다. 다음 전체 실행에서는 `drift-scale`이 16.89초로 15초 예산을 넘었지만 단독 실행은 5.87초였고, 외부 부하가 가라앉은 뒤 변경 없는 전체 재실행은 75.69초에 전부 통과했다. timeout이나 성능·coverage 임계는 바꾸지 않았다. + +실제 bundle strict 검증에서는 첫 실행의 Unit과 두 번째 실행의 Coverage가 기존 시간 민감 테스트 때문에 실패했다. 원인 확인용 독립 Coverage는 기능 테스트를 모두 통과한 채 기존 성능 예산 세 개만 초과했다: 10k watched-path membership 69.90ms/50ms, 700-node 3D layout 6.29s/3s, 5,000-shard drift 23.61s/15s. 세 테스트를 Coverage 계측 그대로 격리하면 **91/91**이 통과했고 각각 50ms 미만, 2.17초, 5.95초였다. 이어진 머신 정지/재개 구간에는 무관한 두 동기 픽스처가 527초를 소비했지만 재개 직후 단독 실행은 **13/13**, 1.83초였다. 이 테스트와 임계는 P5 범위 밖이며 수정하지 않았다. + +안정된 상태에서 worker 경쟁만 2개로 제한한 전체 Coverage는 **253/253 files, 2845/2845 tests**, line coverage **86.09%**로 통과했다. 같은 조건의 실제 출하 bundle strict gate도 Type·Lint·Unit·Coverage·Deliverable을 전부 통과해 attestation을 썼다. 정책은 running version `0.9.3`, `blocking: strict`, detector SHA-256 `133c1ab691da7642223bcfe93ecdf4dc253f1aba08ee4e1bad865e427a2c37db`였고, `clad done F-caff8598`의 다음 strict gate가 새 기능 표지까지 포함해 status를 `done`으로 승격했다. 마지막 attestation SHA-256은 `66d32cae1622953d551d041d4b576a8d717d4e179a092fcfb4a21eeb16d836f7`이고 `clad verdict --json`은 `DONE`, `next_action=null`, 남은 항목 0을 반환했다. diff --git a/.refactor/sim/P6.md b/.refactor/sim/P6.md new file mode 100644 index 00000000..5d65839d --- /dev/null +++ b/.refactor/sim/P6.md @@ -0,0 +1,52 @@ +# P6 — 0.9.4 릴리즈 증거 + +## 릴리즈 표면 + +P6는 Phase 0의 P2~P5를 독립 패치 릴리즈로 묶는다. `node scripts/version-bump.mjs 0.9.4`가 package, 세 호스트 manifest, marketplace, CLI/server 상수, CLI 테스트, root spec의 11개 버전 표면을 갱신했다. 여섯 README는 `0.9.4`, 277개 기능 중 273개 완료, 253개 테스트 파일, 2,845개 테스트, 2026-08 상태로 맞췄다. CHANGELOG에는 live hook health, Stop/완료 결과 증거, 생성 CI의 release-line pin, attestation 정책 identity, 안전한 merge attribute와 dogfood wiring 복구를 기록했다. + +빌드는 source에서 root bundle과 모든 plugin mirror를 다시 만들었다. source CLI, Claude plugin bundle, 깨끗한 설치의 CLI가 모두 `0.9.4`를 보고했고 최종 Claude bundle SHA-256은 `60a5a226a5aba4f5fd2e1913ba80d982a01d2622174c454865babe9664d61526`이다. + +## 의존성 보안 + +최초 production audit는 MCP SDK 1.29.0 아래의 Hono adapter, Hono, fast-uri, ip-address, body-parser를 통해 알려진 취약점 6건을 보고했다. SDK만 1.30.0으로 올렸을 때도 잠금파일에 남은 하위 패키지 때문에 5건이 남는 양성 대조를 확인했다. 호환 범위의 patched dependency graph를 갱신한 뒤 실제 해석 버전은 다음과 같다. + +```text +@modelcontextprotocol/sdk 1.30.0 +@hono/node-server 2.1.0 +hono 4.13.1 +fast-uri 3.1.5 +ip-address 10.4.0 +body-parser 2.3.0 +``` + +개발 도구 쪽 vite, postcss, js-yaml, nanoid 등도 같은 audit fix에서 patched compatible version으로 갱신됐다. 최종 `npm audit --omit=dev --json`과 `npm audit --json`은 모두 low/moderate/high/critical 0, total 0을 보고했다. 직접 production dependency 추가는 없고 기존 MCP SDK selector만 `^1.30.0`으로 이동했다. + +## 자동 검증 + +의존성 갱신 뒤 `npm run build`가 41/41 detector와 15개 stage mirror를 포함해 통과했다. 서버, MCP transport, 실제 transport loop, setup, bundle 집중 실행은 **8/8 files, 143/143 tests**였다. 이어 요구된 기본 `npm test`는 **253/253 files, 2845/2845 tests**가 18.31초에 통과했다. `npm run typecheck`와 `npm run lint`도 exit 0이었다. + +`npm run conformance`는 선언된 33/33 fixture가 기대 결과와 일치해 `iron_law: L4`를 보고했다. 변경 직후 strict pre-push의 Drift는 기존 attestation의 stale entry를 정확히 찾았고, 같은 전체 실행이 나머지 gate를 재검증한 뒤 `spec/attestation.yaml`을 새 트리로 다시 썼다. 이어진 두 strict pre-push 실행은 Type·Lint·Drift·Architecture·Secret·Unit·Coverage·Deliverable을 모두 GREEN으로 확인했다. + +종료 코드를 별도 표식으로 남기려던 이후 strict 실행에서는 Coverage만 일시적으로 RED였고 나머지 단계는 계속 GREEN이었다. 같은 worktree에서 임계나 worker 설정을 바꾸지 않고 gate가 호출하는 `npx vitest run --coverage`를 독립 실행하자 **253/253 files, 2845/2845 tests**, line coverage **86.09%**, exit 0으로 통과했다. gate의 dual-reporter 인자까지 같은 전체 실행에서 실패를 펼쳐 보니 기존 `layout3d` 700-node 성능 테스트 하나가 3,000ms 예산에 3,756ms를 쓴 것이 전부였다. 같은 coverage+dual-reporter 조건으로 그 파일을 격리하자 **12/12**, 659ms로 통과했다. + +이는 P5에서 이미 격리한 시간 민감 테스트와 호스트 CPU 경합의 재현이므로 코드·테스트·임계값은 수정하지 않았다. Vitest가 공식적으로 읽는 `VITEST_MAX_WORKERS`로 검증 프로세스의 worker 경쟁만 제한했다. 두 worker의 full coverage와 strict가 한 차례 GREEN이었지만 이후 실행에서는 전체 지연이 다른 시간예산을 건드려, 양 끝을 피하는 네 worker로 최종 gate를 고정했다. 격리 coverage가 잠시 덮어쓴 1.2% summary 때문에 앞단 Drift가 RED인 양성 대조도 확인하고 full report를 복원한 뒤, `VITEST_MAX_WORKERS=4 node bin/clad check --tier=pre-push --strict`를 실행했다. 최종 결과는 Type·Lint·Drift·Architecture·Secret·Unit·Coverage·Deliverable 전부 GREEN, exit 0이었고 `spec/attestation.yaml`을 0.9.4 strict 정책으로 갱신했다. + +## 실제 tarball 설치 + +최종 빌드에서 `npm pack --json`으로 만든 `cladding-0.9.4.tgz`를 빈 임시 prefix에 설치하고 그 설치본의 executable을 직접 호출했다. + +```text +package=cladding@0.9.4 +tarball_size=2028280 +unpacked_size=7334345 +entries=487 +integrity=sha512-gpa2P2d5uM4Jz+0hkEUdhgS9ftpCI+7Dcsw9BZMonhtthmp4F/ymCuTrJi2CDr0LSiRBhhoSJfRH0ZpHmzspxA== +shasum=4d0519e0e63a60735df80dc00750019fb69a5de4 +installed_cli=0.9.4 +``` + +설치본에는 `dist/clad.js`, `dist/schema.json`, Claude plugin bundle, AGENTS.md, README, CHANGELOG가 있었고 contributor-only `conformance/runner.ts`와 `.refactor/PLAN.md`는 없었다. 임시 pack/install tree는 삭제하지 않고 각각 `/Users/qwerfunch/.Trash/cladding-p6-pack.zEf30p`, `/Users/qwerfunch/.Trash/cladding-p6-install.IZPqOR`로 옮겨 복구 가능하게 보존했다. + +## 외부 릴리즈 경계 + +로컬 릴리즈 후보의 내용과 재현 가능한 검증은 위 증거로 닫혔다. P6의 최종 DONE 판정은 작성자와 분리된 리뷰, feature branch의 `develop` 병합, `develop`의 `main` merge commit, `v0.9.4` 태그, npm publish, non-draft GitHub release, develop backmerge까지 실제 원격 상태로 확인한 뒤에만 기록한다. diff --git a/.refactor/units/P1.yaml b/.refactor/units/P1.yaml new file mode 100644 index 00000000..3c6eec4c --- /dev/null +++ b/.refactor/units/P1.yaml @@ -0,0 +1,31 @@ +id: P1 +started: 2026-08-10 +inherits: + head: e57bd8cef91f20be3e40bcbae40b6489ba0b1747 + tree_clean: true +preconditions: + - {cmd: "test \"$(node bin/clad --version)\" = \"0.9.3\"", expect: "exit 0"} + - {cmd: "node -e \"const s=require('./.claude/settings.json'); if(s.enabledPlugins?.['claude-code@cladding']!==true||s.extraKnownMarketplaces)process.exit(1)\"", expect: "exit 0"} + - {cmd: "test ! -e /Users/qwerfunch/.claude/plugins/cladding", expect: "exit 0"} + - {cmd: "claude plugin list | grep -q 'Version: 0.4.0'", expect: "exit 0"} + - {cmd: "claude plugin list | grep -q 'cache-miss'", expect: "exit 0"} +touch_allowed: + - .claude/settings.json + - tests/scripts/hooks-config.test.ts + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/P1.yaml + - .refactor/sim/P1.md + - spec/attestation.yaml +done_conditions: + - {cmd: "node -e \"const s=require('./.claude/settings.json'); const m=s.extraKnownMarketplaces?.cladding; if(s.enabledPlugins?.['claude-code@cladding']!==true||m?.source?.source!=='directory'||m.source.path!=='.'||m.autoUpdate!==true)process.exit(1)\"", expect: "exit 0"} + - {cmd: "npx vitest run tests/scripts/hooks-config.test.ts", expect: "exit 0"} + - {cmd: "claude plugin validate .", expect: "exit 0 with warnings only"} + - {cmd: "claude plugin list | grep -q 'Version: 0.9.3'", expect: "exit 0"} + - {cmd: "test -f /Users/qwerfunch/.claude/plugins/cache/cladding/claude-code/0.9.3/hooks/hooks.json", expect: "exit 0"} + - {cmd: "test -f /Users/qwerfunch/.claude/plugins/cache/cladding/claude-code/0.9.3/dist/clad.js", expect: "exit 0"} + - {cmd: "test -f .refactor/sim/P1.md", expect: "exit 0"} +exit: + commit: "(this commit)" + verdict: FAIL + residue: "P1 did not change the manifest or its pin. P1P must remove the duplicate explicit hooks declaration and renegotiate the pin; P1R then re-registers the current checkout and proves a live hook invocation." diff --git a/.refactor/units/P1B.yaml b/.refactor/units/P1B.yaml new file mode 100644 index 00000000..22722e91 --- /dev/null +++ b/.refactor/units/P1B.yaml @@ -0,0 +1,19 @@ +id: P1B +started: null +inherits: + head: 40b323f4069e7228aaab0a9ffdc65d3b55d0deed + tree_clean: true +preconditions: + - {cmd: "test \"$(shasum -a 256 dist/clad.js | cut -d' ' -f1)\" = \"664a2fc876b987bea96747a42071d6a959d039aa19cde8d7e188ba1db1bd7c04\"", observed: "exit 0"} + - {cmd: "test \"$(shasum -a 256 plugins/claude-code/dist/clad.js | cut -d' ' -f1)\" = \"2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e\"", observed: "exit 0"} + - {cmd: "grep -Fq 'failed to load\\b.{0,40}\\b(module|rule|plugin|preset|config)' src/stages/util.ts", observed: "exit 1 — precondition failed"} +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/P1B.yaml + - .refactor/sim/P1P.md +done_conditions: [] +exit: + commit: "(this commit)" + verdict: KILLED + residue: "No product or generated file changed. P1G must make the standalone build:plugin command rebuild dist/clad.js from source before copying it; an ignored local bundle is not an oracle." diff --git a/.refactor/units/P1G.yaml b/.refactor/units/P1G.yaml new file mode 100644 index 00000000..66339539 --- /dev/null +++ b/.refactor/units/P1G.yaml @@ -0,0 +1,33 @@ +id: P1G +started: 2026-08-10 +inherits: + head: 2184bee4162298ab904a753b3bbf7999b78df957 + tree_clean: true +preconditions: + - {cmd: "node -e \"const p=require('./package.json'); if(p.scripts['build:plugin']!=='node scripts/build-plugin.mjs')process.exit(1)\"", expect: "exit 0"} + - {cmd: "git check-ignore -q dist/clad.js", expect: "exit 0"} + - {cmd: "test \"$(shasum -a 256 dist/clad.js | cut -d' ' -f1)\" = \"664a2fc876b987bea96747a42071d6a959d039aa19cde8d7e188ba1db1bd7c04\"", expect: "exit 0"} + - {cmd: "test \"$(shasum -a 256 plugins/claude-code/dist/clad.js | cut -d' ' -f1)\" = \"2e87133715a75f1aa6db43fc84fd3c6f01dd912a4b2a809c24e1bf1e9943596e\"", expect: "exit 0"} + - {cmd: "node -e \"const p=require('./plugins/claude-code/.claude-plugin/plugin.json'); if(Object.hasOwn(p,'hooks'))process.exit(1)\"", expect: "exit 0"} +touch_allowed: + - package.json + - scripts/build-plugin.mjs + - tests/scripts/hooks-config.test.ts + - plugins/claude-code/dist/clad.js + - .refactor/ledger.md + - .refactor/units/P1G.yaml + - .refactor/sim/P1G.md + - spec/attestation.yaml +done_conditions: + - {cmd: "node -e \"const p=require('./package.json'); if(p.scripts['build:plugin']!=='node scripts/build.mjs && node scripts/build-plugin.mjs')process.exit(1)\"", expect: "exit 0"} + - {cmd: "npx vitest run tests/scripts/hooks-config.test.ts", expect: "6 tests passed"} + - {cmd: "npm run build:plugin", expect: "exit 0 from a missing dist/clad.js pre-state"} + - {cmd: "cmp -s dist/clad.js plugins/claude-code/dist/clad.js", expect: "exit 0"} + - {cmd: "npm run build:plugin", expect: "second build has identical root/plugin SHA-256"} + - {cmd: "node -e \"const {spawnSync}=require('child_process'); const r=spawnSync('claude',['--plugin-dir','plugins/claude-code','plugin','list'],{encoding:'utf8'}); const b=r.stdout.split('cladding@inline')[1]??''; if(r.status!==0||!/Status: .* loaded/.test(b)||/Duplicate hooks/.test(b))process.exit(1)\"", expect: "exit 0"} + - {cmd: "npm test", expect: "249 files and 2817 tests passed"} + - {cmd: "test -f .refactor/sim/P1G.md", expect: "exit 0"} +exit: + commit: "(this commit)" + verdict: PASS + residue: "The old untracked root bundle was preserved in ~/.Trash for recovery. P1R still must register the current-checkout marketplace cache and prove a real hook command emits from that installed cache." diff --git a/.refactor/units/P1P.yaml b/.refactor/units/P1P.yaml new file mode 100644 index 00000000..b458240a --- /dev/null +++ b/.refactor/units/P1P.yaml @@ -0,0 +1,30 @@ +id: P1P +started: 2026-08-10 +inherits: + head: 0470e879a0dc36dc4fd815a60db0b3fee5772e49 + tree_clean: true +preconditions: + - {cmd: "test \"$(node bin/clad --version)\" = \"0.9.3\"", expect: "exit 0"} + - {cmd: "node -e \"const p=require('./plugins/claude-code/.claude-plugin/plugin.json'); if(p.hooks!=='./hooks/hooks.json')process.exit(1)\"", expect: "exit 0"} + - {cmd: "claude --plugin-dir plugins/claude-code plugin list | grep -q 'Duplicate hooks file detected'", expect: "exit 0"} + - {cmd: "grep -q \"expect(plugin.hooks).toBe('./hooks/hooks.json')\" tests/scripts/hooks-config.test.ts", expect: "exit 0"} +touch_allowed: + - plugins/claude-code/.claude-plugin/plugin.json + - tests/scripts/hooks-config.test.ts + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/P1P.yaml + - .refactor/sim/P1P.md + - spec/attestation.yaml +done_conditions: + - {cmd: "node -e \"const p=require('./plugins/claude-code/.claude-plugin/plugin.json'); if(Object.hasOwn(p,'hooks'))process.exit(1)\"", expect: "exit 0"} + - {cmd: "node -e \"const h=require('./plugins/claude-code/hooks/hooks.json').hooks; if(Object.keys(h).length!==5)process.exit(1)\"", expect: "exit 0"} + - {cmd: "npx vitest run tests/scripts/hooks-config.test.ts", expect: "exit 0"} + - {cmd: "npm run build:plugin", expect: "exit 0 and no files outside touch_allowed changed"} + - {cmd: "claude plugin validate .", expect: "exit 0 with warnings only"} + - {cmd: "node -e \"const {spawnSync}=require('child_process'); const r=spawnSync('claude',['--plugin-dir','plugins/claude-code','plugin','list'],{encoding:'utf8'}); const b=r.stdout.split('cladding@inline')[1]??''; if(r.status!==0||!/Status: .* loaded/.test(b)||/Duplicate hooks/.test(b))process.exit(1)\"", expect: "exit 0"} + - {cmd: "test -f .refactor/sim/P1P.md", expect: "exit 0"} +exit: + commit: "(this commit)" + verdict: FAIL + residue: "The manifest/test pin change is retained because the actual inline loader passed. The generated plugin dist change was restored; P1B must synchronize that pre-existing 60-byte engine mirror delta in isolation before P1R." diff --git a/.refactor/units/P1R.yaml b/.refactor/units/P1R.yaml new file mode 100644 index 00000000..69dc06bf --- /dev/null +++ b/.refactor/units/P1R.yaml @@ -0,0 +1,30 @@ +id: P1R +started: 2026-08-10 +inherits: + head: 042b28bd7611ef9ae1ca2a4e4c2ce0bd5ebb742c + tree_clean: true +preconditions: + - {cmd: "node -e \"const s=require('./.claude/settings.json'); const m=s.extraKnownMarketplaces?.cladding; if(m?.source?.source!=='directory'||m.source.path!=='.'||m.autoUpdate!==true)process.exit(1)\"", expect: "exit 0"} + - {cmd: "claude plugin marketplace list --json | grep -q '\"source\": \"github\"'", expect: "exit 0"} + - {cmd: "claude plugin marketplace list --json | grep -q '\"repo\": \"qwerfunch/cladding\"'", expect: "exit 0"} + - {cmd: "node -e \"const p=require('./plugins/claude-code/.claude-plugin/plugin.json'); if(Object.hasOwn(p,'hooks'))process.exit(1)\"", expect: "exit 0"} + - {cmd: "node -e \"const p=require('/Users/qwerfunch/.claude/plugins/cache/cladding/claude-code/0.9.3/.claude-plugin/plugin.json'); if(p.hooks!=='./hooks/hooks.json')process.exit(1)\"", expect: "exit 0"} +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/P1R.yaml + - .refactor/sim/P1R.md +done_conditions: + - {cmd: "node -e \"const {spawnSync}=require('child_process'); const r=spawnSync('claude',['plugin','marketplace','list','--json'],{encoding:'utf8'}); const m=JSON.parse(r.stdout).find(x=>x.name==='cladding'); if(r.status!==0||m?.source!=='directory'||m.path!==process.cwd())process.exit(1)\"", expect: "exit 0"} + - {cmd: "node -e \"const fs=require('fs'); const p=JSON.parse(fs.readFileSync('/Users/qwerfunch/.claude/plugins/installed_plugins.json','utf8')).plugins['claude-code@cladding'].find(x=>x.projectPath===process.cwd()); if(p?.version!=='0.9.3'||!p.installPath.endsWith('/cache/cladding/claude-code/0.9.3'))process.exit(1)\"", expect: "exit 0"} + - {cmd: "node -e \"const p=require('/Users/qwerfunch/.claude/plugins/cache/cladding/claude-code/0.9.3/.claude-plugin/plugin.json'); if(Object.hasOwn(p,'hooks'))process.exit(1)\"", expect: "exit 0"} + - {cmd: "test -f /Users/qwerfunch/.claude/plugins/cache/cladding/claude-code/0.9.3/hooks/hooks.json", expect: "exit 0"} + - {cmd: "cmp -s plugins/claude-code/dist/clad.js /Users/qwerfunch/.claude/plugins/cache/cladding/claude-code/0.9.3/dist/clad.js", expect: "exit 0"} + - {cmd: "claude plugin list | grep -q 'Status: ✔ enabled'", expect: "exit 0"} + - {cmd: "test -s /tmp/cladding-p1r-session-card.txt", expect: "exit 0"} + - {cmd: "grep -q 'cladding' /tmp/cladding-p1r-session-card.txt", expect: "exit 0"} + - {cmd: "test -f .refactor/sim/P1R.md", expect: "exit 0"} +exit: + commit: "(this commit)" + verdict: PASS + residue: "The separate logcat-on project still intentionally retains its out-of-scope 0.4.0 project install. Claude Code must start a new session to pick up the recovered cladding project plugin automatically." diff --git a/.refactor/units/P2.yaml b/.refactor/units/P2.yaml new file mode 100644 index 00000000..d4d7d4b8 --- /dev/null +++ b/.refactor/units/P2.yaml @@ -0,0 +1,42 @@ +id: P2 +started: 2026-08-10 +inherits: + head: fa228c3 + tree_clean: true +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/P2.yaml + - .refactor/sim/P2.md + - spec.yaml + - spec/index.yaml + - spec/attestation.yaml + - spec/features/hook-health-observability-*.yaml + - src/cli/hook-health.ts + - src/cli/hook.ts + - src/cli/doctor.ts + - src/cli/clad.ts + - src/init/host-setup.ts + - src/stages/detectors/host-claim-drift.ts + - tests/cli/hook-health.test.ts + - tests/cli/doctor.test.ts + - tests/cli/setup.test.ts + - tests/stages/detectors/host-claim-drift.test.ts + - skills/doctor/SKILL.md + - plugins/codex/skills/doctor/SKILL.md + - plugins/antigravity/skills/doctor/SKILL.md + - plugins/claude-code/dist/clad.js +done_conditions: + - {cmd: "npm test -- --run tests/cli/hook-health.test.ts tests/cli/doctor.test.ts tests/stages/detectors/host-claim-drift.test.ts", expect: "exit 0"} + - {cmd: "npm run build:plugin", expect: "exit 0 and source-fresh plugin engine"} + - {cmd: "npm test", expect: "exit 0"} + - {cmd: "npm run typecheck", expect: "exit 0"} + - {cmd: "npm run lint", expect: "exit 0"} + - {cmd: "node bin/clad verdict --json", expect: "DONE/green for the P2 feature"} + - {cmd: "node bin/clad done ", expect: "exit 0; status earned as done"} + - {cmd: "node bin/clad check --tier=pre-commit", expect: "exit 0"} + - {cmd: "node bin/clad check --tier=pre-push --strict", expect: "exit 0"} +exit: + commit: (this commit) + verdict: PASS + residue: "0.9.4 이전 cache는 새 pulse가 생길 때까지 not-observed가 정직한 상태다. README 테스트 수 2815 표시는 P6 릴리즈에서 2828로 갱신한다. committed host matrix의 v0.9.0 신선도 info는 실제 호스트 재검증 동의 전에는 자동으로 지우지 않는다." diff --git a/.refactor/units/P3.yaml b/.refactor/units/P3.yaml new file mode 100644 index 00000000..12461660 --- /dev/null +++ b/.refactor/units/P3.yaml @@ -0,0 +1,52 @@ +id: P3 +started: 2026-08-10 +inherits: + head: 9c16973 + tree_clean: true +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/P3.yaml + - .refactor/sim/P3.md + - docs/glossary.md + - spec.yaml + - spec/index.yaml + - spec/attestation.yaml + - spec/_doc-links.yaml + - spec/features/stop-outcome-telemetry-*.yaml + - spec/features/lifecycle-events-identity-b84c38.yaml + - src/events/log.ts + - src/events/stop-telemetry.ts + - src/verdict/gate-progress.ts + - src/cli/hook.ts + - src/cli/clad.ts + - src/cli/done.ts + - src/cli/doctor.ts + - tests/events/log.test.ts + - tests/events/stop-telemetry.test.ts + - tests/cli/hook.test.ts + - tests/cli/gate-golden-matrix.test.ts + - tests/cli/done.test.ts + - tests/cli/doctor.test.ts + - skills/doctor/SKILL.md + - plugins/codex/skills/doctor/SKILL.md + - plugins/antigravity/skills/doctor/SKILL.md + - plugins/claude-code/dist/clad.js +done_conditions: + - {cmd: "npm test -- --run tests/events/log.test.ts tests/events/stop-telemetry.test.ts tests/cli/hook.test.ts tests/cli/gate-golden-matrix.test.ts tests/cli/done.test.ts tests/cli/doctor.test.ts", expect: "exit 0"} + - {cmd: "npm run build:plugin", expect: "exit 0 and source-fresh plugin engine"} + - {cmd: "npm test", expect: "exit 0"} + - {cmd: "npm run typecheck", expect: "exit 0"} + - {cmd: "npm run lint", expect: "exit 0"} + - {cmd: "node bin/clad verdict --json", expect: "DONE/green after the P3 feature is earned"} + - {cmd: "node bin/clad done ", expect: "exit 0; status earned as done"} + - {cmd: "node bin/clad check --tier=pre-commit", expect: "exit 0"} + - {cmd: "node bin/clad check --tier=pre-push --strict", expect: "exit 0"} +exit: + commit: (this commit) + verdict: PASS + residue: + - README test-count claim 2815 predates the current 2834 tests; release-wide refresh belongs to P6. + - Events written before schema 0.9.4 have no blocker evidence and therefore remain conservatively unobserved. + - introduced/preexisting compares with the latest observed gate; it is attribution evidence, not session causality. + - The 4–6 week or 50-event policy decision remains with A1; P3 only supplies the measurement. diff --git a/.refactor/units/P4.yaml b/.refactor/units/P4.yaml new file mode 100644 index 00000000..f2751a13 --- /dev/null +++ b/.refactor/units/P4.yaml @@ -0,0 +1,43 @@ +id: P4 +started: 2026-08-10 +inherits: + head: 632b0da + tree_clean: true +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/P4.yaml + - .refactor/sim/P4.md + - spec.yaml + - spec/index.yaml + - spec/attestation.yaml + - spec/_doc-links.yaml + - spec/features/ci-version-pinning-*.yaml + - src/cli/ci-version.ts + - src/cli/init.ts + - src/cli/doctor.ts + - tests/cli/ci-version.test.ts + - tests/cli/doctor.test.ts + - tests/init/git-hook.test.ts + - skills/doctor/SKILL.md + - plugins/codex/skills/doctor/SKILL.md + - plugins/antigravity/skills/doctor/SKILL.md + - plugins/claude-code/dist/clad.js +done_conditions: + - {cmd: "npm test -- --run tests/cli/ci-version.test.ts tests/init/git-hook.test.ts tests/cli/doctor.test.ts", expect: "exit 0"} + - {cmd: "npm run build:plugin", expect: "exit 0 and source-fresh plugin engine"} + - {cmd: "npm test", expect: "exit 0"} + - {cmd: "npm run typecheck", expect: "exit 0"} + - {cmd: "npm run lint", expect: "exit 0"} + - {cmd: "node bin/clad verdict --json", expect: "DONE/green after the P4 feature is earned"} + - {cmd: "node bin/clad done ", expect: "exit 0; status earned as done"} + - {cmd: "node bin/clad check --tier=pre-commit", expect: "exit 0"} + - {cmd: "node bin/clad check --tier=pre-push --strict", expect: "exit 0"} +exit: + commit: (this commit) + verdict: PASS + residue: + - Existing workflows remain user-owned and are never rewritten; doctor reports the paths only. + - The major.minor selector intentionally accepts patch updates within the release line. + - Diagnosis covers GitHub Actions npx Cladding package calls; indirect actions and other CI/package managers are outside P4. + - P6 still owns the actual 0.9.4 version bump and the README test-count refresh from 2815 to 2839. diff --git a/.refactor/units/P5.yaml b/.refactor/units/P5.yaml new file mode 100644 index 00000000..0d5bcecb --- /dev/null +++ b/.refactor/units/P5.yaml @@ -0,0 +1,50 @@ +id: P5 +started: 2026-08-10 +inherits: + head: a72bebb + tree_clean: true +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/P5.yaml + - .refactor/sim/P5.md + - docs/spec-ids-multi-dev.md + - spec.yaml + - spec/index.yaml + - spec/attestation.yaml + - spec/_doc-links.yaml + - spec/features/attestation-policy-stamp-*.yaml + - src/spec/attestation.ts + - src/cli/clad.ts + - src/cli/init.ts + - tests/spec/attestation-policy.test.ts + - tests/cli/gate-golden-matrix.test.ts + - tests/cli/init.test.ts + - skills/check/SKILL.md + - skills/init/SKILL.md + - plugins/codex/skills/check/SKILL.md + - plugins/codex/skills/init/SKILL.md + - plugins/antigravity/skills/check/SKILL.md + - plugins/antigravity/skills/init/SKILL.md + - plugins/claude-code/commands/init.md + - plugins/claude-code/dist/clad.js + - plugins/gemini-cli/commands/init.toml +done_conditions: + - {cmd: "npm test -- --run tests/spec/attestation-policy.test.ts tests/cli/gate-golden-matrix.test.ts tests/cli/init.test.ts", expect: "exit 0"} + - {cmd: "npm run build:plugin", expect: "exit 0 and source-fresh plugin artifacts"} + - {cmd: "npm test", expect: "exit 0"} + - {cmd: "npm run typecheck", expect: "exit 0"} + - {cmd: "npm run lint", expect: "exit 0"} + - {cmd: "node bin/clad verdict --json", expect: "DONE/green after the P5 feature is earned"} + - {cmd: "node bin/clad done ", expect: "exit 0; status earned as done"} + - {cmd: "node bin/clad check --tier=pre-commit", expect: "exit 0"} + - {cmd: "node bin/clad check --tier=pre-push --strict", expect: "exit 0"} +exit: + commit: (this commit) + verdict: PASS + residue: + - Legacy policy-less attestations remain readable as policy unknown until the next green strict gate. + - Detector SHA identifies registry order, name, and subprocess classification; Cladding version identifies implementation bytes. + - Existing adopter .gitattributes content is preserved; init appends only the exact index rule. + - Attestation deliberately gets no merge driver. + - P6 owns the actual 0.9.4 version bump and README test count update from 2815 to 2845. diff --git a/.refactor/units/P6.yaml b/.refactor/units/P6.yaml new file mode 100644 index 00000000..17ae7556 --- /dev/null +++ b/.refactor/units/P6.yaml @@ -0,0 +1,46 @@ +id: P6 +started: 2026-08-10 +inherits: + head: e82374b + tree_clean: true +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/P6.yaml + - .refactor/sim/P6.md + - .claude-plugin/marketplace.json + - CHANGELOG.md + - README.md + - README.ko.md + - README.ja.md + - README.zh.md + - README.html + - README.ko.html + - package.json + - package-lock.json + - plugins/claude-code/.claude-plugin/plugin.json + - plugins/claude-code/dist/clad.js + - plugins/codex/.codex-plugin/plugin.json + - plugins/gemini-cli/gemini-extension.json + - spec.yaml + - spec/attestation.yaml + - src/cli/clad.ts + - src/serve/server.ts + - tests/cli/clad.test.ts +done_conditions: + - {cmd: "node bin/clad --version", expect: "0.9.4"} + - {cmd: "node scripts/test-count.mjs --check", expect: "2845 tests and exit 0"} + - {cmd: "npm run build", expect: "exit 0 and source-fresh package/plugin artifacts"} + - {cmd: "npm test", expect: "253/253 files and 2845/2845 tests"} + - {cmd: "npm run typecheck", expect: "exit 0"} + - {cmd: "npm run lint", expect: "exit 0"} + - {cmd: "npm run conformance", expect: "declared L4 corpus green"} + - {cmd: "node bin/clad check --tier=pre-push --strict", expect: "exit 0 and 0.9.4 policy attestation"} + - {cmd: "npm pack --json", expect: "exit 0; packed tarball installs and reports 0.9.4"} + - {cmd: "git tag --list v0.9.4", expect: "v0.9.4 after reviewed main merge"} + - {cmd: "npm view cladding@0.9.4 version", expect: "0.9.4 after publish"} + - {cmd: "gh release view v0.9.4 --json tagName,isDraft,isPrerelease", expect: "published non-draft, non-prerelease v0.9.4"} +exit: + commit: pending + verdict: pending + residue: pending diff --git a/.refactor/units/S2.yaml b/.refactor/units/S2.yaml new file mode 100644 index 00000000..c49101a2 --- /dev/null +++ b/.refactor/units/S2.yaml @@ -0,0 +1,23 @@ +id: S2 +started: 2026-08-10 +inherits: + head: d730526d856ce5c3b7e077f1af8583d4ba37bd73 + tree_clean: true +preconditions: + - {cmd: "test \"$(node bin/clad --version)\" = \"0.9.3\"", expect: "exit 0"} + - {cmd: "test ! -e .refactor/sim/M5.md", expect: "exit 0"} + - {cmd: "test -d src/agents", expect: "exit 0"} +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/S2.yaml + - .refactor/sim/M5.md +done_conditions: + - {cmd: "test -f .refactor/sim/M5.md", expect: "exit 0"} + - {cmd: "head -1 .refactor/sim/M5.md | grep -qE '^VERDICT: (PASS|KILL|INCONCLUSIVE)$'", expect: "exit 0"} + - {cmd: "grep -c '^VERDICT: ' .refactor/sim/M5.md", expect: "1"} + - {cmd: "grep -qE '`[^`]+:[0-9]+`' .refactor/sim/M5.md", expect: "exit 0"} +exit: + commit: "(this commit)" + verdict: KILLED + residue: "A10/A11 removed; CLI-only independence_policy: require remains unsatisfiable until an authenticated host assertion or hardware-backed user-presence proof exists." diff --git a/.refactor/units/S3.yaml b/.refactor/units/S3.yaml new file mode 100644 index 00000000..8e2d4e3a --- /dev/null +++ b/.refactor/units/S3.yaml @@ -0,0 +1,24 @@ +id: S3 +started: 2026-08-10 +inherits: + head: 7e5f0391ce1f797e7879af497db34d5a7383543b + tree_clean: true +preconditions: + - {cmd: "test \"$(node bin/clad --version)\" = \"0.9.3\"", expect: "exit 0"} + - {cmd: "test ! -e .refactor/sim/M7.md", expect: "exit 0"} + - {cmd: "test -f src/stages/vacuous-tests.ts", expect: "exit 0"} + - {cmd: "test -f src/stages/unit.ts", expect: "exit 0"} +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/S3.yaml + - .refactor/sim/M7.md +done_conditions: + - {cmd: "test -f .refactor/sim/M7.md", expect: "exit 0"} + - {cmd: "head -1 .refactor/sim/M7.md | grep -qE '^VERDICT: (PASS|KILL|INCONCLUSIVE)$'", expect: "exit 0"} + - {cmd: "grep -c '^VERDICT: ' .refactor/sim/M7.md", expect: "1"} + - {cmd: "grep -qE '`[^`]+:[0-9]+`' .refactor/sim/M7.md", expect: "exit 0"} +exit: + commit: "(this commit)" + verdict: PASS + residue: "A6 must wire Jest JSON output into the existing parser and cover macOS /tmp -> /private/tmp canonical-path normalization; implementation intentionally deferred to A6." diff --git a/.refactor/units/S4.yaml b/.refactor/units/S4.yaml new file mode 100644 index 00000000..ed35bb1a --- /dev/null +++ b/.refactor/units/S4.yaml @@ -0,0 +1,24 @@ +id: S4 +started: 2026-08-10 +inherits: + head: 27ed45263320fe5707061f6b6b39445ed1fc07f4 + tree_clean: true +preconditions: + - {cmd: "test \"$(node bin/clad --version)\" = \"0.9.3\"", expect: "exit 0"} + - {cmd: "test ! -e .refactor/sim/5b.md", expect: "exit 0"} + - {cmd: "git cat-file -e 28fc6d828812df87ade923912320a3c30fe469f6^{commit}", expect: "exit 0"} + - {cmd: "node -e \"require('yaml')\"", expect: "exit 0"} +touch_allowed: + - .refactor/PLAN.md + - .refactor/ledger.md + - .refactor/units/S4.yaml + - .refactor/sim/5b.md +done_conditions: + - {cmd: "test -f .refactor/sim/5b.md", expect: "exit 0"} + - {cmd: "head -1 .refactor/sim/5b.md | grep -qE '^VERDICT: (PASS|KILL|INCONCLUSIVE)$'", expect: "exit 0"} + - {cmd: "grep -c '^VERDICT: ' .refactor/sim/5b.md", expect: "1"} + - {cmd: "grep -qE '`[^`]+:[0-9]+`' .refactor/sim/5b.md", expect: "exit 0"} +exit: + commit: "(this commit)" + verdict: PASS + residue: "A9 may auto-repair only an exact same-diff Git rename; unique-basename candidates remain dry-run suggestions requiring explicit selection because history supplied zero independent fallback move cases." diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b2041b6..37fc37d1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,35 @@ All notable changes to Cladding are documented here. Format: [Keep a Changelog 1.1.0](https://keepachangelog.com/en/1.1.0/). Versioning: [Semantic Versioning 2.0](https://semver.org/spec/v2.0.0.html). +## [0.9.4] — The gate judges the sources on disk (2026-08-26) + +**In one line:** the language check reads your sources instead of your build manifest — projects it wrongly blocked now pass honestly — the module-honesty scan works for any language your spec teaches it, the gate config survives a fresh clone, and cladding now proves its own host hooks fired, records stop and completion outcomes, pins generated CI, and stamps every verified tree with the policy that earned it. + +### Added + +- **Runner-less skips name their exit.** A project whose language cladding cannot drive used to pass the gate with most stages silently skipped and no mention of the way out. Command-stage skips now carry a machine-readable reason, and when checks skipped for lack of a runner, the result ends with one line naming those stages and the `gate.commands` declaration that turns them on — committable, so CI runs the same gate you do. By-design skips (no oracles, no declared deliverable) stay untouched: prescribing commands there would be a false cure. +- **Live hook health in `clad doctor`.** A bounded sidecar records the last observed `SessionStart`, `UserPromptSubmit`, `PreToolUse`, `PostToolUse`, and `Stop` pulse plus the engine version. Text and JSON doctor output distinguish a working installation from one that has never been observed, including package-less Claude cache installations. +- **Outcome evidence for Stop and completion.** `stop_blocked`, `stop_exit_recorded`, `done_attempted`, and `gate_run` events now carry stable blocker identities, introduced/pre-existing counts, dirty-path intersection, and a compatible fingerprint. Doctor reports whether a blocked fingerprint was later seen by a gate. +- **Verification-policy identity in `spec/attestation.yaml`.** A GREEN strict gate records the running Cladding version, strict blocking mode, and a full SHA-256 of detector order, name, and subprocess classification. Older policy-less attestations remain readable. +- **Safe merge attributes for new projects.** `clad init` preserves existing `.gitattributes`, adds `spec/index.yaml merge=union` exactly once, and deliberately leaves `spec/attestation.yaml` on ordinary conflict handling. + +### Changed + +- **The language check now judges the sources on disk, not the build manifest.** The manifest chain reads build orchestration, so a C++ SDK driven by Gradle or a Rust core shipped through npm was mislabelled by construction — measured across realistic repo shapes, the old comparison blocked 12 of 19 normal projects under `--strict`, including labels cladding's own onboarding had just written. `TECH_STACK_MISMATCH` now reads the observed source distribution from one shared vocabulary: a language it does not know, or a tree with under five classified files, produces silence instead of a false alarm; a declared language absent from the sources still warns with the evidence in the message; a declared language present but under 10% is disclosed at info and never blocks. Gate-command selection still uses the manifest chain — "what do we run" and "what is this project" are different questions, and only the second one moved. +- **The module-honesty scan now derives its universe from evidence.** `UNMAPPED_ARTIFACT` picked one file extension from a six-language table; declaring cpp, java, or csharp fell through to `*.ts`, scanned nothing, and passed vacuously on exactly the projects the check exists for. The scan now unites the extensions observed in the tree with the extensions of modules the spec claims under its layer roots — so an unknown language enters the universe the moment a feature claims a file in it — and infers scan roots from the claimed paths themselves (the Kotlin `src/main/kotlin` layout now comes out of inference, not a table). A root must carry at least a quarter of the layer-claimed modules, which keeps directories that merely reuse a layer name from flooding the scan. +- **Generated CI stays on the current release line.** New workflows run `cladding@` instead of an unbounded package selector. `clad doctor` names existing GitHub Actions workflows that use an unversioned or floating `npx cladding` command without modifying them. +- **Plugin mirrors are built from source before distribution.** Standalone `npm run build:plugin` no longer treats a stale or missing root bundle as authoritative, and Claude hook metadata relies on the host's standard hook discovery without duplicate declarations. + +### Fixed + +- **The gate config can finally be committed.** `clad init` ignored `.cladding/` with the directory form, and git never re-includes under an excluded directory — so `.cladding/config.yaml`, the file that carries every documented gate override, was impossible to commit: fresh clones and CI silently ran a different gate than the author tuned. New projects now get `.cladding/*` plus `!.cladding/config.yaml`. Existing projects are never rewritten; `clad doctor` reports a blocked gate config in text and JSON instead, the same read-only posture as the unpinned-CI report. +- **Measured before release** (docs/ab-evaluation/case-version-ab-093-vs-next.md): across 32 realistic repo shapes the old language check wrongly blocked 12 normal projects and the new one blocks none, with no drift catch lost on either side. In a blinded live comparison on the motivating shape, an honest green was impossible on 0.9.3 (agents either misdeclared the language or kept the truth and a red gate) and completed honestly 3 of 3 times on this release, at a ~21% lower median token cost (n=3); a plain-TypeScript control showed no difference, so the saving is specific to what was broken. +- **The dogfood host wiring now points at the current checkout and 0.9.x cache.** The recovery was verified through the installed Claude cache and a real `SessionStart` card rather than inferred from configuration text. + +### Security + +- **The MCP transport dependency graph now resolves to patched runtime packages.** The SDK and its Hono, URI, address, and body-parser dependencies were refreshed; both the production-only and complete npm audits report zero known vulnerabilities. + ## [0.9.3] — The review packet shows how the contract itself moved (2026-08-04) **In one line:** a pull request now shows which acceptance criteria were rewritten while the code changed, and the architecture gate stops failing on generated build output. diff --git a/README.html b/README.html index 1a91d7f2..1d91cb42 100644 --- a/README.html +++ b/README.html @@ -235,7 +235,7 @@

cladding

ironclad spec - tests + tests detectors license

@@ -271,7 +271,7 @@

cladding

- cladding builds itself with cladding too — 269 of its 273 features cleared this same gate, the first L4 implementation of the Ironclad standard. + cladding builds itself with cladding too — 269 of its 277 features cleared this same gate, the first L4 implementation of the Ironclad standard.

@@ -556,8 +556,8 @@

Status

version
-
v0.9.3
-
2026-07
+
v0.9.4
+
2026-08
conformance
@@ -566,7 +566,7 @@

Status

tests
-
2815/2815
+
2981/2981
all pass
@@ -576,13 +576,13 @@

Status

features
-
273
-
269 done · self-spec
+
281
+
277 done · self-spec
-

249 test files · 6 capabilities · coverage drop blocked by the COVERAGE_DROP detector

+

253 test files · 6 capabilities · coverage drop blocked by the COVERAGE_DROP detector

Road to Ironclad 1.0 — 1.0 locks only when two independent implementations pass the L4 conformance fixtures (GOVERNANCE § 1). cladding is the first.
diff --git a/README.ja.md b/README.ja.md index 13fb81ce..704ef536 100644 --- a/README.ja.md +++ b/README.ja.md @@ -12,7 +12,7 @@

ironclad spec - tests + tests detectors license

@@ -347,9 +347,9 @@ clad update # 3. プロジェクト接続と派生状態を更新 | Version | 準拠レベル | Tests | Gate | Features | |---|---|---|---|---| -| v0.9.3(2026-08) | L4 · [自己申告](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2815 / 2815 | 15 段階 · 41 detectors | 273(269 done) | +| v0.9.4(2026-08) | L4 · [自己申告](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2981 / 2981 | 15 段階 · 41 detectors | 281(277 done) | -249 test files · capability 6 個 · カバレッジ低下は COVERAGE_DROP detector がブロック +253 test files · capability 6 個 · カバレッジ低下は COVERAGE_DROP detector がブロック > **Ironclad 1.0 への道** — 1.0 は *独立した二つの実装が L4 準拠フィクスチャを通過してはじめて* 確定する([GOVERNANCE § 1](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md))。cladding はその一つ目だ。 diff --git a/README.ko.html b/README.ko.html index a99bc012..fbb0522f 100644 --- a/README.ko.html +++ b/README.ko.html @@ -277,7 +277,7 @@

cladding

ironclad spec - tests + tests detectors license

@@ -304,7 +304,7 @@

cladding

- cladding은 자기 자신도 cladding으로 만든다 — 기능 273개 중 269개가 같은 게이트를 통과했고, Ironclad 표준을 L4로 구현한 첫 사례다. + cladding은 자기 자신도 cladding으로 만든다 — 기능 281개 중 277개가 같은 게이트를 통과했고, Ironclad 표준을 L4로 구현한 첫 사례다.

@@ -590,8 +590,8 @@

Status

version
-
v0.9.3
-
2026-07
+
v0.9.4
+
2026-08
준수 등급
@@ -600,7 +600,7 @@

Status

tests
-
2815/2815
+
2981/2981
all pass
@@ -610,13 +610,13 @@

Status

features
-
273
-
269 done · 자기 스펙
+
281
+
277 done · 자기 스펙
-

249 test files · capability 6개 · coverage는 COVERAGE_DROP detector가 하락 차단

+

253 test files · capability 6개 · coverage는 COVERAGE_DROP detector가 하락 차단

Ironclad 1.0까지의 길 — 1.0은 독립적인 두 개의 구현이 L4 검증 셋을 통과해야 잠긴다 (GOVERNANCE § 1). cladding이 첫 번째.
diff --git a/README.ko.md b/README.ko.md index bbfa7ee1..947eae9f 100644 --- a/README.ko.md +++ b/README.ko.md @@ -12,7 +12,7 @@

ironclad spec - tests + tests detectors license

@@ -346,9 +346,9 @@ clad update # 3. 프로젝트 연결과 파생 데이터를 함께 | version | 준수 등급 | tests | gate | features | |---|---|---|---|---| -| v0.9.3 · 2026-08 | L4 · [L0–L4 중 최고 · 자가 선언](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2815 / 2815 · all pass | 15 단계 · 41 detectors | 273 · 269 done · 자기 스펙 | +| v0.9.4 · 2026-08 | L4 · [L0–L4 중 최고 · 자가 선언](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2981 / 2981 · all pass | 15 단계 · 41 detectors | 281 · 277 done · 자기 스펙 | -249 test files · capability 6개 · coverage는 COVERAGE_DROP detector가 하락 차단 +253 test files · capability 6개 · coverage는 COVERAGE_DROP detector가 하락 차단 > **Ironclad 1.0까지의 길** — 1.0은 *독립적인 두 개의 구현이 L4 검증 셋을 통과해야* 잠긴다 ([GOVERNANCE § 1](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md)). cladding이 첫 번째. diff --git a/README.md b/README.md index 48df0442..fa60cd25 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@

ironclad spec - tests + tests detectors license

@@ -360,9 +360,9 @@ Reconcile the drift the update flagged. | Version | Conformance | Tests | Gate | Features | |---|---|---|---|---| -| v0.9.3 (2026-08) | L4 · [self-declared](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2815 / 2815 | 15 stages · 41 detectors | 273 (269 done) | +| v0.9.4 (2026-08) | L4 · [self-declared](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2981 / 2981 | 15 stages · 41 detectors | 281 (277 done) | -249 test files · 6 capabilities · coverage drop blocked by the COVERAGE_DROP detector +253 test files · 6 capabilities · coverage drop blocked by the COVERAGE_DROP detector > **Road to Ironclad 1.0** — 1.0 locks only when *two independent implementations pass the L4 conformance fixtures* ([GOVERNANCE § 1](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md)). cladding is the first. diff --git a/README.zh.md b/README.zh.md index ff68b5df..0870b492 100644 --- a/README.zh.md +++ b/README.zh.md @@ -12,7 +12,7 @@

ironclad spec - tests + tests detectors license

@@ -343,9 +343,9 @@ clad update # 3. 刷新项目连接和派生状态 | 版本 | 一致性 | Tests | Gate | Features | |---|---|---|---|---| -| v0.9.3(2026-08) | L4 · [自我声明](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2815 / 2815 | 15 阶段 · 41 检测器 | 273(269 done) | +| v0.9.4(2026-08) | L4 · [自我声明](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md) | 2981 / 2981 | 15 阶段 · 41 检测器 | 281(277 done) | -249 个测试文件 · 6 项 capability · 覆盖率下降由 COVERAGE_DROP 检测器拦下 +253 个测试文件 · 6 项 capability · 覆盖率下降由 COVERAGE_DROP 检测器拦下 > **通往 Ironclad 1.0 之路** —— 只有当*两个独立实现都通过 L4 一致性测试夹具*时,1.0 才会锁定([GOVERNANCE § 1](https://github.com/qwerfunch/ironclad/blob/main/GOVERNANCE.md))。cladding 是第一个。 diff --git a/conformance/fixtures.yaml b/conformance/fixtures.yaml index 5b714c79..d84c580b 100644 --- a/conformance/fixtures.yaml +++ b/conformance/fixtures.yaml @@ -175,7 +175,7 @@ fixtures: - name: F-013_AC-021 stage: documentary kind: runnable - description: "F-013/AC-021 — When spec.project.language differs from the language resolved by the toolchain manifest chain, the detector shall emit a warn-severity finding." + description: "F-013/AC-021 — When the declared language is absent from the observed sources with at least five classified files, the detector shall emit a warn-severity finding naming the observed distribution (evidence-based since F-9e1279d4; the manifest chain is no longer consulted for identity)." - name: F-014_AC-022 stage: documentary kind: runnable diff --git a/conformance/runner.ts b/conformance/runner.ts index b3fb50f6..0ae9325e 100644 --- a/conformance/runner.ts +++ b/conformance/runner.ts @@ -647,22 +647,27 @@ const fixtures: readonly Fixture[] = [ }, { // F-013/AC-021 — TECH_STACK_MISMATCH warn when spec.project.language - // differs from what the toolchain detection chain returns. The warn + // is absent from the OBSERVED SOURCES (evidence-based since + // F-9e1279d4 — the manifest chain is no longer consulted for + // identity). Five .ts files clear the evidence floor (5), python is + // absent from the observed set, so exactly one warn fires. The warn // does not fail drift (default severity is warn, not error), so // pass remains true; the assertion is on the finding shape. // - // The fixture writes `.secretlintrc.json` because adding package.json - // makes the toolchain pick TypeScript, which makes HARDCODED_SECRET - // try to invoke secretlint via npx — without a config file the - // scanner exits non-zero and emits an error finding that would mask - // the warn we are actually probing for. + // The fixture writes `.secretlintrc.json` because package.json makes + // the toolchain pick TypeScript for GATE COMMANDS, which makes + // HARDCODED_SECRET try to invoke secretlint via npx — without a + // config file the scanner exits non-zero and emits an error finding + // that would mask the warn we are actually probing for. id: 'F-013_AC-021', stage: 'stage_1.3', expectedPass: true, setup(d) { mkdirSync(join(d, 'stages'), {recursive: true}); mkdirSync(join(d, 'spec'), {recursive: true}); - writeTs(d, 'stages/dummy.ts', '// fixture stub\nexport const ok = true;\n'); + for (let i = 1; i <= 5; i++) { + writeTs(d, `stages/dummy${i}.ts`, '// fixture stub\nexport const ok = true;\n'); + } writeFileSync(join(d, 'package.json'), PKG_JSON); writeFileSync(join(d, '.secretlintrc.json'), SECRETLINTRC); writeFileSync( @@ -672,8 +677,8 @@ const fixtures: readonly Fixture[] = [ properties: {schema: {}, project: {}, features: {}}, }), ); - // spec.project.language = python, but package.json + .ts source - // make the toolchain resolve to typescript → mismatch. + // spec.project.language = python, but five observed .ts sources + // put python absent from the evidence → warn (F-9e1279d4 contract). writeFileSync( join(d, 'spec.yaml'), 'schema: "0.1"\n' + @@ -682,7 +687,7 @@ const fixtures: readonly Fixture[] = [ ' - id: F-001\n' + ' title: t\n' + ' status: done\n' + - ' modules: [stages/dummy.ts, spec/schema.json]\n' + + ' modules: [stages/dummy1.ts, stages/dummy2.ts, stages/dummy3.ts, stages/dummy4.ts, stages/dummy5.ts, spec/schema.json]\n' + ' acceptance_criteria:\n' + ' - id: AC-001\n' + ' ears: ubiquitous\n' + diff --git a/docs/ab-evaluation-extended/scenarios/dashboard/report.md b/docs/ab-evaluation-extended/scenarios/dashboard/report.md index b6ae05d1..38f19e54 100644 --- a/docs/ab-evaluation-extended/scenarios/dashboard/report.md +++ b/docs/ab-evaluation-extended/scenarios/dashboard/report.md @@ -67,7 +67,7 @@ Four deterministic drift scenarios injected at feature-30 state. "Caught" = at l | Scenario | A (Cladding) caught? | A new detectors | B (Vanilla) caught? | B new detectors | |---|:---:|---|:---:|---| -| DI-1 Stale module reference (rename src/components/Header.tsx → src/components/Header.RENAMED.tsx without spec update) | ✅ | MISSING_IMPLEMENTATION, STATUS_DRIFT | · | — | +| DI-1 Stale module reference (rename src/components/Header.tsx → src/components/Header.RENAMED.tsx without spec update) | ✅ | MISSING_IMPLEMENTATION, UNMAPPED_ARTIFACT, STATUS_DRIFT | · | — | | DI-2 Architecture violation (src/lib/filter.ts imports ../components/Header) | ✅ | ARCHITECTURE_FROM_SPEC, INFERABLE_DEPENDS_ON | · | — | | DI-3 Hardcoded secret (add API key constant to src/lib/export-config.ts) | · | — | · | — | | DI-4 Untested AC (add AC-003 to spec/features/metric-card-2ed463.yaml without test) | ✅ | MISSING_TESTS | N/A | N/A | diff --git a/docs/ab-evaluation-extended/scenarios/task-manager/report.md b/docs/ab-evaluation-extended/scenarios/task-manager/report.md index def634e6..f19f960f 100644 --- a/docs/ab-evaluation-extended/scenarios/task-manager/report.md +++ b/docs/ab-evaluation-extended/scenarios/task-manager/report.md @@ -69,7 +69,7 @@ Four deterministic drift scenarios injected at feature-30 state. "Caught" = at l | Scenario | A (Cladding) caught? | A new detectors | B (Vanilla) caught? | B new detectors | |---|:---:|---|:---:|---| -| DI-1 Stale module reference (rename src/components/Header.tsx → src/components/Header.RENAMED.tsx without spec update) | ✅ | MISSING_IMPLEMENTATION, STATUS_DRIFT | · | — | +| DI-1 Stale module reference (rename src/components/Header.tsx → src/components/Header.RENAMED.tsx without spec update) | ✅ | MISSING_IMPLEMENTATION, UNMAPPED_ARTIFACT, STATUS_DRIFT | · | — | | DI-2 Architecture violation (src/lib/filter.ts imports ../components/Header) | ✅ | ARCHITECTURE_FROM_SPEC, INFERABLE_DEPENDS_ON | · | — | | DI-3 Hardcoded secret (add API key constant to src/lib/export-import.ts) | · | — | · | — | | DI-4 Untested AC (add AC-003 to spec/features/add-task-3cbf38.yaml without test) | ✅ | MISSING_TESTS | N/A | N/A | diff --git a/docs/ab-evaluation/case-payment-saas.md b/docs/ab-evaluation/case-payment-saas.md index 6c64f936..01122958 100644 --- a/docs/ab-evaluation/case-payment-saas.md +++ b/docs/ab-evaluation/case-payment-saas.md @@ -41,7 +41,7 @@ no spec, no scenarios, no architecture invariants. | Forbidden-import rules | 2 | 0 | +2 | | Detector errors | 0 | 1 | -1 | | Detector warnings | 1 | 3 | -2 | -| Detector infos | 13 | 28 | -15 | +| Detector infos | 12 | 28 | -16 | | Tiered doc files | 2 | 0 | +2 | | Tiered docs (lines) | 61 | 0 | +61 | | Other doc files | 0 | 1 | -1 | @@ -56,7 +56,7 @@ no spec, no scenarios, no architecture invariants. **Detector outcomes** (META_INTEGRITY + HARDCODED_SECRET excluded — toolchain-only checks): ``` -A (Cladding) — errors: 0 warns: 1 infos: 13 +A (Cladding) — errors: 0 warns: 1 infos: 12 B (Vanilla) — errors: 1 warns: 3 infos: 28 Sample errors: @@ -80,7 +80,7 @@ B (Vanilla) — errors: 1 warns: 3 infos: 28 | Forbidden-import rules | 2 | 0 | +2 | | Detector errors | 1 | 1 | +0 | | Detector warnings | 3 | 3 | +0 | -| Detector infos | 15 | 28 | -13 | +| Detector infos | 14 | 28 | -14 | | Tiered doc files | 2 | 0 | +2 | | Tiered docs (lines) | 61 | 0 | +61 | | Other doc files | 0 | 1 | -1 | @@ -95,7 +95,7 @@ B (Vanilla) — errors: 1 warns: 3 infos: 28 **Detector outcomes** (META_INTEGRITY + HARDCODED_SECRET excluded — toolchain-only checks): ``` -A (Cladding) — errors: 1 warns: 3 infos: 15 +A (Cladding) — errors: 1 warns: 3 infos: 14 Sample errors: - [AC_DRIFT] F-4db939.AC-002 EARS: ears='unwanted' requires condition starting with 'if' — empty @@ -109,7 +109,7 @@ B (Vanilla) — errors: 1 warns: 3 infos: 28 - **Structured artifacts**: cladding produces 9 tier-banner-bearing files vs vanilla's 0. - **Spec ↔ code traceability**: cladding emits 1 feature(s), 2 AC(s), 2 scenario(s), 3 capability(s); vanilla has 0 of each. - **Architecture enforcement**: cladding declares 3 layer(s) with 2 forbidden-import rule(s); vanilla has 0. -- **Detector behavior**: cladding-managed tree → 1 error(s) / 3 warn(s) / 15 info(s). Vanilla tree → 1 / 3 / 28. The detectors that gate against spec (REFERENCE_INTEGRITY, MISSING_IMPLEMENTATION, ARCHITECTURE_FROM_SPEC, CAPABILITIES_FEATURE_MAPPING) need cladding's artifacts to evaluate — without them they silently pass. The "0 errors on vanilla" therefore is **absence of signal**, not absence of drift. +- **Detector behavior**: cladding-managed tree → 1 error(s) / 3 warn(s) / 14 info(s). Vanilla tree → 1 / 3 / 28. The detectors that gate against spec (REFERENCE_INTEGRITY, MISSING_IMPLEMENTATION, ARCHITECTURE_FROM_SPEC, CAPABILITIES_FEATURE_MAPPING) need cladding's artifacts to evaluate — without them they silently pass. The "0 errors on vanilla" therefore is **absence of signal**, not absence of drift. - **Token cost**: cladding's cumulative artifact + code consumes ~1943 tokens vs vanilla's ~1399 (heuristic chars/4) — Δ ≈ 544 tokens, the price of structure. - **Code surface**: vanilla writes 5 source file(s) / 126 LoC + 2 test file(s) / 4 test case(s); cladding writes 1 / 11 + 1 / 1. (Vanilla front-loads code, cladding front-loads spec — both converge by M2.) diff --git a/docs/ab-evaluation/case-version-ab-093-vs-next.md b/docs/ab-evaluation/case-version-ab-093-vs-next.md new file mode 100644 index 00000000..9efa72e0 --- /dev/null +++ b/docs/ab-evaluation/case-version-ab-093-vs-next.md @@ -0,0 +1,97 @@ + + +# Version A/B: released 0.9.3 vs the language-agnostic core + +Blinded, pre-registered comparison of the released `cladding@0.9.3` against +develop at `21f5c92` (PRs #253/#255/#256), run before deciding the release and +its claims. Axes: tokens, wall time, and honesty outcomes. Method constraints +inherited from this repository's A/B history: correctness re-measurement +banned (four prior NULLs), discriminating-power pilot gate, deterministic +side-tables first, medians for small n, and NULL acceptance pre-registered +(a tie forces the release notes down, not the data up). + +## Arms and blinding + +- **K** = `cladding@0.9.3` from the npm registry (the real user baseline); + **M** = `npm pack` of develop. Isolated prefixes, SHA-recorded, PATH-prepended + so bare `clad` resolves to the arm; `command -v clad` logged per run as a + hard precondition. +- Measured agents: `claude -p --model opus`, identical byte-for-byte prompts, + no version strings, no experiment mention. 15-minute cap (never hit). + +## Scenarios (pre-registered) + +| | Subject | Task | Hypothesis | +|---|---|---|---| +| SC1 | C++ product under a Gradle host | onboard + one full feature cycle to a green strict gate | K fails or misrepresents, or costs ≥2×; M completes honestly | +| SC2 | make-driven C library (vocabulary-unknown) | make the four skipped command stages actually run | M higher success / cheaper | +| SC3 | plain TypeScript | same task as SC1 | **NULL expected** (control) | + +## Deterministic side-tables (agent-free, run first) + +- 32-shape corpus, `TECH_STACK_MISMATCH` verdicts: **0.9.3 wrongly blocks 12 + of 25 normal shapes; develop 0** — missed drifts 0 on both (the residue case + moves warn→info, recorded as the accepted relaxation). +- Same tree, only `spec.project.language` varied (2×2): 0.9.3 blocks `cpp` + and passes `java`; develop passes both. **Honest-green is mechanically + impossible on 0.9.3 for this shape** — the lie is engine-forced, not an + agent's whim. +- Fresh-clone gate-config survival: 0.9.3 uncommittable; develop committable. + +## Live results (medians; individual values in the run logs) + +| | K (0.9.3) | M (develop) | Δ | +|---|---|---|---| +| **SC1 honest-green** | **0/3** (2 lie-green `language: java`, 1 honest-red) | **3/3** (`language: cpp`, gate 0) | the primary result | +| SC1 tokens / cost / turns | 3.31M / $2.95 / 50 | 2.60M / $2.29 / 49 | **−21% / −22% / ≈** | +| SC2 success (4 stages run) | 3/3 | 3/3 | **NULL** — opus-tier agents find `gate.commands` unaided | +| SC2 tokens / cost / turns | 0.65M / $0.62 / 20 | 0.53M / $0.46 / 18 | −18% / −26% / −2 — consistent direction, small n | +| SC3 control tokens | 1.28M | 1.40M | +9% → **NULL holds**; M's SC1/SC2 savings are treatment-specific, not global | + +The costliest single run was K's honest-red (4.96M tokens, 65 turns): the +agent kept `cpp`, fought an unresolvable finding, and surrendered the green — +the cost of honesty on the old engine, measured. + +Wall-clock is **demoted to indicative only**: a driver-resurrection incident +(below) ran some cells concurrently, contaminating wall times. Tokens, turns, +costs, and outcomes are unaffected by contention. + +## Verdicts against the pre-registered rules + +1. **H1 confirmed.** On the motivating shape, 0.9.3 offers only lie-green or + honest-red; develop completes honestly 3/3, ~21% cheaper. Backed by the + mechanical 2×2, so the honesty axis does not rest on n=3. +2. **H2 success-rate NULL, honestly recorded.** Capable agents discover the + escape without the guidance line; the guidance's measured value at this + agent tier is a consistent but small efficiency edge. The line's design + rationale (surfaces measured at zero mentions; a weaker-agent failure + demonstrated in the gate.language E2E) stands, but no success-rate claim + may cite this experiment. +3. **H3 control NULL as required** — the strongest internal validity check: + the new version is not globally cheaper; it is cheaper exactly where the + old one was wrong. + +## Release-claim implications + +- May claim: "projects the old check wrongly blocked now pass honestly" + (deterministic + live), "the only green on such shapes used to require a + false language entry" (mechanical), token/cost medians with n=3 stated. +- May NOT claim: success-rate improvements from the skip guidance, wall-time + improvements, or any TS-project improvement (control was NULL by design). + +## Incident (recorded, affects wall-clock only) + +The first run driver was sequential; a mid-experiment parallelization killed +the wrong PID, and the original runner's own babysitter loop resurrected the +sequential driver, which then re-ran and overwrote cells the parallel driver +had completed. Contained by snapshot + targeted kill; every surviving cell is +one complete, internally consistent run; the overwritten cells' first-run +outcome lines survive in the parallel driver's log and match the surviving +reruns' outcomes in every case. Lesson recorded: a detached driver plus an +agent-owned watchdog is two sources of truth — kill by process pattern and +stop the owning agent together. + +## Raw artifacts + +Scratchpad `ab-ver/`: per-run `result.json` / `score.json` / `env.log`, +`pdrive.log`, `provenance.log`, snapshots. Not committed (session-local). diff --git a/docs/glossary.md b/docs/glossary.md index 5aca0da2..61f7a13f 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -154,7 +154,9 @@ four distinct Korean words too, so the conflation cannot survive translation: `stage_started` · `stage_completed` · `feature_activated` · `feature_completed` · `evidence_recorded` · `drift_detected` · `feature_checkpoint` · `feature_rolled_back` · `sentinel_miss` -Added 0.6.0 (F-b84c38 — payloads carry `identity` + `head`): `feature_created` (spec shard authored) · `scenario_created` · `done_attempted` (gated flip, kept or reverted) · `gate_run` (tier verification outcome; deduped per identical HEAD/tier/strict/worst) · `stop_blocked` (F-1d23a6 — the Stop host hook blocked a session end on a fresh failure fingerprint; identical fingerprints demote without an event). `design_impact_resolved` records that a structural feature's reviewed Tier-B changes were applied. +Added 0.6.0 (F-b84c38 — payloads carry `identity` + `head`): `feature_created` (spec shard authored) · `scenario_created` · `done_attempted` (gated flip, kept or reverted) · `gate_run` (tier verification outcome; deduped per identical HEAD/tier/strict/worst and, since 0.9.4, blocker evidence) · `stop_blocked` (F-1d23a6 — the Stop host hook blocked a session end on a fresh failure fingerprint; identical fingerprints demote). `design_impact_resolved` records that a structural feature's reviewed Tier-B changes were applied. + +Added 0.9.4 (F-1aab1bba — Stop outcome counters): `stop_exit_recorded` records the existing identical-fingerprint demotion as a known-failing exit. `stop_blocked`, `gate_run`, and `done_attempted` carry additive compact blocker evidence so `clad doctor` can derive whether a blocked fingerprint appeared in a later gate without a second correlation state file. Added 0.8.0 (F-6ba22c5c — value-delivery telemetry, so a silent surface is distinguishable from an unwired one): `impact_card_fired` (a PostToolUse impact card produced output — payload file/feature/impacted/tests/unledgered) · `impact_card_skipped` (the card was skipped — `reason` ∈ a closed enum, one per degrade branch; the two high-frequency reasons are aggregated to one event per debounce window) · `session_card_rendered` (a non-empty SessionStart card — payload bytes) · `prompt_suggestion_served` (a non-empty UserPromptSubmit suggestion — payload kind) · `working_set_served` (an MCP read serve of `clad_get_working_set` / `clad_get_context` / `clad_get_impact` — payload tool/query/resolved). Summarized by `clad measure --sessions` as DELIVERY (did the surfaces fire), never adoption. diff --git a/docs/refinement-backlog.md b/docs/refinement-backlog.md index fd21bd58..258dbfb7 100644 --- a/docs/refinement-backlog.md +++ b/docs/refinement-backlog.md @@ -15,6 +15,11 @@ Survivors of the 2026-07-03 whole-repo audit (baseline: `clad check --strict` 40 | B10 | spec-conformance stage npx cold-boot | stage_2.3 boots a third vitest via `npx` (spec-conformance.ts:75). Dormant on this repo (stage skips without oracle tests); only matters for adopters with oracle policies. Optimize the spawn (direct bin resolution) when it first shows up in an adopter profile. | S/S/L | | B11 | Complete the 0.6.0 verb-rename residue (refine→clarify, drive→run, panel→status) | Surfaced by the alias removal (F-d25041ac): provenance banners still say `clad init / clad refine` (src/cli/init.ts, scan/*, spec/new.ts, clarify.ts), init.ts:415/422/428 user-facing remediation messages recommend the removed verb, detector messages in project-context-drift/spec-conformance/fixture-reference name it, and the banner strings are EXACT-MATCH test-pinned (tests/scenarios/ab/_drift-injection.ts:64, ab-extended/_curator.ts:1038/1054/1087) — a coherent ~15-src + ~8-fixture migration, deliberately not smuggled into the 2-module alias-removal feature. Highest-severity slice — the init.ts remediation messages — was extracted and fixed pre-release (F-fe0f7a96); remaining scope = banners + fixtures + 3 stale internal comments (init.ts:390, scan/intent-onboarding.ts:696, scan/onboarding-state.ts:7). | M/M/M | +| B12 | Legacy narrow fallback is cladding-shaped | Below the 8-feature scale gate, UNMAPPED_ARTIFACT falls back to the literals `src/stages/**/*.ts` + `src/spec/**/*.ts` — cladding's own layout. In adopter repos it matches nothing (zero module honesty for the first seven features) and in a TS adopter that happens to have `src/stages/` it scans the WRONG thing. Measured in the 2026-08-26 external E2E (D2): 7 features → 0 findings, 8 → 18 on the same tree. Candidate: derive a minimal evidence universe below the gate too, or make the fallback empty + info. Needs its own review — the scale gate guards a real false-RED class (day-1 adoption). | M/S/M | +| B13 | Init seeds a language nothing on disk supports | `clad init` on a zig-only tree seeds `language: typescript` (greenfield default) while the evidence path resolves `unknown` — the spec then carries a claim no detector will ever contradict (TECH_STACK_MISMATCH is correctly silent on sub-floor/unknown evidence). External E2E 2026-08-26 (D4). Candidate: seed the observed dominant when available, else omit/`unknown`. Schema requires `language`, so `unknown` is the honest floor. | S/S/L | +| B14 | Per-detector language resolution disagrees with evidence | ARCHITECTURE_FROM_SPEC (via resolveLanguageConfig) resolves 'java' on a cpp-spec, cpp-majority tree because unknown spec labels fall through to the manifest chain (External E2E 2026-08-26, D5). This is the Phase-3 seam already planned: derive the 4 LanguageConfig consumers (COVERAGE_DROP, STALE_TESTS, CONVENTION_DRIFT, ARCHITECTURE_FROM_SPEC) from evidence instead of TS/manifest fallback. Own feature cycle + own corpus. | M/M/M | +| B15 | Post-init scaffold check contradicts init's own output | Right after `clad init` printed `created spec/scenarios/README.md`, the next check reports `spec/scenarios is absent — scaffold incomplete` (info) though the directory exists (External E2E 2026-08-26, D3). Pre-existing; likely a path/existence probe mismatch. | S/S/L | + ## Reviewed and REJECTED — do not re-open without new evidence - **Merge unit (2.1) + coverage (2.2) into one vitest run**: conformance/fixtures.yaml:82-85 pins "tests green + coverage below floor" as distinct stage outcomes; `mvn jacoco:report` runs no tests on JVM; gate-golden-matrix.test.ts pins stage independence. The double suite run is the deliberate price of separable verdicts. diff --git a/docs/spec-ids-multi-dev.md b/docs/spec-ids-multi-dev.md index ed37c585..237b9993 100644 --- a/docs/spec-ids-multi-dev.md +++ b/docs/spec-ids-multi-dev.md @@ -117,6 +117,7 @@ The two derived files are configured differently in `.gitattributes` on purpose: | `spec/attestation.yaml` | *(no attribute — deliberate)* | `merge=union` here silently reverts uncontested edits that get swept into an adjacent conflict zone (experimentally confirmed). A plain, loud conflict is safe — it heals via the ritual above. | This table is pinned to the real repository state: if `.gitattributes` ever changes for either file, update it here. +`clad init` creates or appends the exact `spec/index.yaml merge=union` line while preserving every existing attribute; it never assigns a merge driver to `spec/attestation.yaml`. ## Legacy F-NNN ↔ new F-`hash` diff --git a/package-lock.json b/package-lock.json index 75f0bdaf..9d727103 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,16 @@ { "name": "cladding", - "version": "0.9.3", + "version": "0.9.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cladding", - "version": "0.9.3", + "version": "0.9.4", "license": "MIT", "dependencies": { "@anthropic-ai/sdk": "^0.96.0", - "@modelcontextprotocol/sdk": "^1.29.0", + "@modelcontextprotocol/sdk": "^1.30.0", "smol-toml": "^1.6.1" }, "bin": { @@ -184,44 +184,10 @@ "node": ">=14.17.0" } }, - "node_modules/@emnapi/core": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", - "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/wasi-threads": "1.2.1", - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/runtime": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", - "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@emnapi/wasi-threads": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", - "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.0.tgz", - "integrity": "sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz", + "integrity": "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ==", "cpu": [ "ppc64" ], @@ -236,9 +202,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.0.tgz", - "integrity": "sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.2.tgz", + "integrity": "sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg==", "cpu": [ "arm" ], @@ -253,9 +219,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.0.tgz", - "integrity": "sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz", + "integrity": "sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A==", "cpu": [ "arm64" ], @@ -270,9 +236,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.0.tgz", - "integrity": "sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.2.tgz", + "integrity": "sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q==", "cpu": [ "x64" ], @@ -287,9 +253,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.0.tgz", - "integrity": "sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz", + "integrity": "sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw==", "cpu": [ "arm64" ], @@ -304,9 +270,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.0.tgz", - "integrity": "sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz", + "integrity": "sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw==", "cpu": [ "x64" ], @@ -321,9 +287,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.0.tgz", - "integrity": "sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz", + "integrity": "sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw==", "cpu": [ "arm64" ], @@ -338,9 +304,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.0.tgz", - "integrity": "sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz", + "integrity": "sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg==", "cpu": [ "x64" ], @@ -355,9 +321,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.0.tgz", - "integrity": "sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz", + "integrity": "sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w==", "cpu": [ "arm" ], @@ -372,9 +338,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.0.tgz", - "integrity": "sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz", + "integrity": "sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug==", "cpu": [ "arm64" ], @@ -389,9 +355,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.0.tgz", - "integrity": "sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz", + "integrity": "sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ==", "cpu": [ "ia32" ], @@ -406,9 +372,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.0.tgz", - "integrity": "sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz", + "integrity": "sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ==", "cpu": [ "loong64" ], @@ -423,9 +389,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.0.tgz", - "integrity": "sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz", + "integrity": "sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA==", "cpu": [ "mips64el" ], @@ -440,9 +406,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.0.tgz", - "integrity": "sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz", + "integrity": "sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ==", "cpu": [ "ppc64" ], @@ -457,9 +423,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.0.tgz", - "integrity": "sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz", + "integrity": "sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA==", "cpu": [ "riscv64" ], @@ -474,9 +440,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.0.tgz", - "integrity": "sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz", + "integrity": "sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg==", "cpu": [ "s390x" ], @@ -491,9 +457,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.0.tgz", - "integrity": "sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz", + "integrity": "sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ==", "cpu": [ "x64" ], @@ -508,9 +474,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.0.tgz", - "integrity": "sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz", + "integrity": "sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw==", "cpu": [ "arm64" ], @@ -525,9 +491,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.0.tgz", - "integrity": "sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz", + "integrity": "sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw==", "cpu": [ "x64" ], @@ -542,9 +508,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.0.tgz", - "integrity": "sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz", + "integrity": "sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ==", "cpu": [ "arm64" ], @@ -559,9 +525,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.0.tgz", - "integrity": "sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz", + "integrity": "sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw==", "cpu": [ "x64" ], @@ -576,9 +542,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.0.tgz", - "integrity": "sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz", + "integrity": "sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q==", "cpu": [ "arm64" ], @@ -593,9 +559,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.0.tgz", - "integrity": "sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz", + "integrity": "sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g==", "cpu": [ "x64" ], @@ -610,9 +576,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.0.tgz", - "integrity": "sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz", + "integrity": "sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ==", "cpu": [ "arm64" ], @@ -627,9 +593,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.0.tgz", - "integrity": "sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz", + "integrity": "sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA==", "cpu": [ "ia32" ], @@ -644,9 +610,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.0.tgz", - "integrity": "sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz", + "integrity": "sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g==", "cpu": [ "x64" ], @@ -712,9 +678,9 @@ "license": "MIT" }, "node_modules/@eslint/config-array/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "dependencies": { @@ -810,9 +776,9 @@ "license": "MIT" }, "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "dependencies": { @@ -888,12 +854,12 @@ } }, "node_modules/@hono/node-server": { - "version": "1.19.14", - "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.14.tgz", - "integrity": "sha512-GwtvgtXxnWsucXvbQXkRgqksiH2Qed37H9xHZocE5sA3N8O8O8/8FA3uclQXxXVzc9XBZuEOMK7+r02FmSpHtw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-2.1.0.tgz", + "integrity": "sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg==", "license": "MIT", "engines": { - "node": ">=18.14.1" + "node": ">=20" }, "peerDependencies": { "hono": "^4" @@ -994,12 +960,12 @@ } }, "node_modules/@modelcontextprotocol/sdk": { - "version": "1.29.0", - "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz", - "integrity": "sha512-zo37mZA9hJWpULgkRpowewez1y6ML5GsXJPY8FI0tBBCd77HEvza4jDqRKOXgHNn867PVGCyTdzqpz0izu5ZjQ==", + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.30.0.tgz", + "integrity": "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA==", "license": "MIT", "dependencies": { - "@hono/node-server": "^1.19.9", + "@hono/node-server": "^1.19.9 || ^2.0.5", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", @@ -1033,29 +999,10 @@ } } }, - "node_modules/@napi-rs/wasm-runtime": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", - "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@tybys/wasm-util": "^0.10.1" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/Brooooooklyn" - }, - "peerDependencies": { - "@emnapi/core": "^1.7.1", - "@emnapi/runtime": "^1.7.1" - } - }, "node_modules/@oxc-project/types": { - "version": "0.130.0", - "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz", - "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==", + "version": "0.143.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.143.0.tgz", + "integrity": "sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA==", "dev": true, "license": "MIT", "funding": { @@ -1063,9 +1010,9 @@ } }, "node_modules/@rolldown/binding-android-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz", - "integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz", + "integrity": "sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw==", "cpu": [ "arm64" ], @@ -1080,9 +1027,9 @@ } }, "node_modules/@rolldown/binding-darwin-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz", - "integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA==", "cpu": [ "arm64" ], @@ -1097,9 +1044,9 @@ } }, "node_modules/@rolldown/binding-darwin-x64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz", - "integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA==", "cpu": [ "x64" ], @@ -1114,9 +1061,9 @@ } }, "node_modules/@rolldown/binding-freebsd-x64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz", - "integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz", + "integrity": "sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg==", "cpu": [ "x64" ], @@ -1131,9 +1078,9 @@ } }, "node_modules/@rolldown/binding-linux-arm-gnueabihf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz", - "integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz", + "integrity": "sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw==", "cpu": [ "arm" ], @@ -1148,13 +1095,16 @@ } }, "node_modules/@rolldown/binding-linux-arm64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz", - "integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz", + "integrity": "sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1165,13 +1115,16 @@ } }, "node_modules/@rolldown/binding-linux-arm64-musl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz", - "integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz", + "integrity": "sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1182,13 +1135,16 @@ } }, "node_modules/@rolldown/binding-linux-ppc64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz", - "integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz", + "integrity": "sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1199,13 +1155,16 @@ } }, "node_modules/@rolldown/binding-linux-s390x-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz", - "integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz", + "integrity": "sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1216,13 +1175,16 @@ } }, "node_modules/@rolldown/binding-linux-x64-gnu": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz", - "integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz", + "integrity": "sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1233,13 +1195,16 @@ } }, "node_modules/@rolldown/binding-linux-x64-musl": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz", - "integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz", + "integrity": "sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1250,9 +1215,9 @@ } }, "node_modules/@rolldown/binding-openharmony-arm64": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz", - "integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz", + "integrity": "sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug==", "cpu": [ "arm64" ], @@ -1266,29 +1231,10 @@ "node": "^20.19.0 || >=22.12.0" } }, - "node_modules/@rolldown/binding-wasm32-wasi": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz", - "integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==", - "cpu": [ - "wasm32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@emnapi/core": "1.10.0", - "@emnapi/runtime": "1.10.0", - "@napi-rs/wasm-runtime": "^1.1.4" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - } - }, "node_modules/@rolldown/binding-win32-arm64-msvc": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz", - "integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz", + "integrity": "sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw==", "cpu": [ "arm64" ], @@ -1303,9 +1249,9 @@ } }, "node_modules/@rolldown/binding-win32-x64-msvc": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz", - "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz", + "integrity": "sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg==", "cpu": [ "x64" ], @@ -1698,17 +1644,6 @@ "node": ">=18" } }, - "node_modules/@tybys/wasm-util": { - "version": "0.10.2", - "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz", - "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, "node_modules/@types/chai": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", @@ -2460,20 +2395,20 @@ } }, "node_modules/body-parser": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz", - "integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.3.0.tgz", + "integrity": "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw==", "license": "MIT", "dependencies": { "bytes": "^3.1.2", - "content-type": "^1.0.5", + "content-type": "^2.0.0", "debug": "^4.4.3", - "http-errors": "^2.0.0", - "iconv-lite": "^0.7.0", + "http-errors": "^2.0.1", + "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", - "qs": "^6.14.1", - "raw-body": "^3.0.1", - "type-is": "^2.0.1" + "qs": "^6.15.2", + "raw-body": "^3.0.2", + "type-is": "^2.1.0" }, "engines": { "node": ">=18" @@ -2483,6 +2418,19 @@ "url": "https://opencollective.com/express" } }, + "node_modules/body-parser/node_modules/content-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz", + "integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/boundary": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/boundary/-/boundary-2.0.0.tgz", @@ -2491,16 +2439,16 @@ "license": "BSD-2-Clause" }, "node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/buffer": { @@ -3129,9 +3077,9 @@ } }, "node_modules/esbuild": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.0.tgz", - "integrity": "sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==", + "version": "0.28.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.2.tgz", + "integrity": "sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -3142,32 +3090,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.0", - "@esbuild/android-arm": "0.28.0", - "@esbuild/android-arm64": "0.28.0", - "@esbuild/android-x64": "0.28.0", - "@esbuild/darwin-arm64": "0.28.0", - "@esbuild/darwin-x64": "0.28.0", - "@esbuild/freebsd-arm64": "0.28.0", - "@esbuild/freebsd-x64": "0.28.0", - "@esbuild/linux-arm": "0.28.0", - "@esbuild/linux-arm64": "0.28.0", - "@esbuild/linux-ia32": "0.28.0", - "@esbuild/linux-loong64": "0.28.0", - "@esbuild/linux-mips64el": "0.28.0", - "@esbuild/linux-ppc64": "0.28.0", - "@esbuild/linux-riscv64": "0.28.0", - "@esbuild/linux-s390x": "0.28.0", - "@esbuild/linux-x64": "0.28.0", - "@esbuild/netbsd-arm64": "0.28.0", - "@esbuild/netbsd-x64": "0.28.0", - "@esbuild/openbsd-arm64": "0.28.0", - "@esbuild/openbsd-x64": "0.28.0", - "@esbuild/openharmony-arm64": "0.28.0", - "@esbuild/sunos-x64": "0.28.0", - "@esbuild/win32-arm64": "0.28.0", - "@esbuild/win32-ia32": "0.28.0", - "@esbuild/win32-x64": "0.28.0" + "@esbuild/aix-ppc64": "0.28.2", + "@esbuild/android-arm": "0.28.2", + "@esbuild/android-arm64": "0.28.2", + "@esbuild/android-x64": "0.28.2", + "@esbuild/darwin-arm64": "0.28.2", + "@esbuild/darwin-x64": "0.28.2", + "@esbuild/freebsd-arm64": "0.28.2", + "@esbuild/freebsd-x64": "0.28.2", + "@esbuild/linux-arm": "0.28.2", + "@esbuild/linux-arm64": "0.28.2", + "@esbuild/linux-ia32": "0.28.2", + "@esbuild/linux-loong64": "0.28.2", + "@esbuild/linux-mips64el": "0.28.2", + "@esbuild/linux-ppc64": "0.28.2", + "@esbuild/linux-riscv64": "0.28.2", + "@esbuild/linux-s390x": "0.28.2", + "@esbuild/linux-x64": "0.28.2", + "@esbuild/netbsd-arm64": "0.28.2", + "@esbuild/netbsd-x64": "0.28.2", + "@esbuild/openbsd-arm64": "0.28.2", + "@esbuild/openbsd-x64": "0.28.2", + "@esbuild/openharmony-arm64": "0.28.2", + "@esbuild/sunos-x64": "0.28.2", + "@esbuild/win32-arm64": "0.28.2", + "@esbuild/win32-ia32": "0.28.2", + "@esbuild/win32-x64": "0.28.2" } }, "node_modules/escape-html": { @@ -3326,9 +3274,9 @@ "license": "MIT" }, "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "dependencies": { @@ -3632,9 +3580,9 @@ "license": "Unlicense" }, "node_modules/fast-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", - "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", "funding": [ { "type": "github", @@ -4002,9 +3950,9 @@ } }, "node_modules/hono": { - "version": "4.12.19", - "resolved": "https://registry.npmjs.org/hono/-/hono-4.12.19.tgz", - "integrity": "sha512-xa3eYXYXx68XTT4hZ7dRzsXBhaq85ToSrlUJNoR0gwz/1Ap/CNwX47wfvV7pc/xWhjKVVkLT7zBJy8chhNguqQ==", + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/hono/-/hono-4.13.1.tgz", + "integrity": "sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw==", "license": "MIT", "engines": { "node": ">=16.9.0" @@ -4161,9 +4109,9 @@ "license": "ISC" }, "node_modules/ip-address": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", - "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", "license": "MIT", "engines": { "node": ">= 12" @@ -4395,10 +4343,20 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], "license": "MIT", "dependencies": { "argparse": "^2.0.1" @@ -4494,9 +4452,9 @@ } }, "node_modules/lightningcss": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", - "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", "dev": true, "license": "MPL-2.0", "dependencies": { @@ -4510,23 +4468,23 @@ "url": "https://opencollective.com/parcel" }, "optionalDependencies": { - "lightningcss-android-arm64": "1.32.0", - "lightningcss-darwin-arm64": "1.32.0", - "lightningcss-darwin-x64": "1.32.0", - "lightningcss-freebsd-x64": "1.32.0", - "lightningcss-linux-arm-gnueabihf": "1.32.0", - "lightningcss-linux-arm64-gnu": "1.32.0", - "lightningcss-linux-arm64-musl": "1.32.0", - "lightningcss-linux-x64-gnu": "1.32.0", - "lightningcss-linux-x64-musl": "1.32.0", - "lightningcss-win32-arm64-msvc": "1.32.0", - "lightningcss-win32-x64-msvc": "1.32.0" + "lightningcss-android-arm64": "1.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" } }, "node_modules/lightningcss-android-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", - "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", "cpu": [ "arm64" ], @@ -4545,9 +4503,9 @@ } }, "node_modules/lightningcss-darwin-arm64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", - "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", "cpu": [ "arm64" ], @@ -4566,9 +4524,9 @@ } }, "node_modules/lightningcss-darwin-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", - "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", "cpu": [ "x64" ], @@ -4587,9 +4545,9 @@ } }, "node_modules/lightningcss-freebsd-x64": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", - "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", "cpu": [ "x64" ], @@ -4608,9 +4566,9 @@ } }, "node_modules/lightningcss-linux-arm-gnueabihf": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", - "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", "cpu": [ "arm" ], @@ -4629,13 +4587,16 @@ } }, "node_modules/lightningcss-linux-arm64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", - "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -4650,13 +4611,16 @@ } }, "node_modules/lightningcss-linux-arm64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", - "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -4671,13 +4635,16 @@ } }, "node_modules/lightningcss-linux-x64-gnu": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", - "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -4692,13 +4659,16 @@ } }, "node_modules/lightningcss-linux-x64-musl": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", - "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MPL-2.0", "optional": true, "os": [ @@ -4713,9 +4683,9 @@ } }, "node_modules/lightningcss-win32-arm64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", - "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", "cpu": [ "arm64" ], @@ -4734,9 +4704,9 @@ } }, "node_modules/lightningcss-win32-x64-msvc": { - "version": "1.32.0", - "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", - "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", "cpu": [ "x64" ], @@ -5087,9 +5057,9 @@ "license": "MIT" }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", "dev": true, "funding": [ { @@ -5488,9 +5458,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", "dev": true, "license": "MIT", "engines": { @@ -5520,9 +5490,9 @@ } }, "node_modules/postcss": { - "version": "8.5.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", - "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "dev": true, "funding": [ { @@ -5540,7 +5510,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -5889,13 +5859,13 @@ "license": "ISC" }, "node_modules/rolldown": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.1.tgz", - "integrity": "sha512-X0KQHljNnEkWNqqiz9zJrGunh1B0HgOxLXvnFpCOcadzcy5qohZ3tqMEUg00vncoRovXuK3ZqCT9KnnKzoInFQ==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.3.tgz", + "integrity": "sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A==", "dev": true, "license": "MIT", "dependencies": { - "@oxc-project/types": "=0.130.0", + "@oxc-project/types": "=0.143.0", "@rolldown/pluginutils": "^1.0.0" }, "bin": { @@ -5905,21 +5875,20 @@ "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rolldown/binding-android-arm64": "1.0.1", - "@rolldown/binding-darwin-arm64": "1.0.1", - "@rolldown/binding-darwin-x64": "1.0.1", - "@rolldown/binding-freebsd-x64": "1.0.1", - "@rolldown/binding-linux-arm-gnueabihf": "1.0.1", - "@rolldown/binding-linux-arm64-gnu": "1.0.1", - "@rolldown/binding-linux-arm64-musl": "1.0.1", - "@rolldown/binding-linux-ppc64-gnu": "1.0.1", - "@rolldown/binding-linux-s390x-gnu": "1.0.1", - "@rolldown/binding-linux-x64-gnu": "1.0.1", - "@rolldown/binding-linux-x64-musl": "1.0.1", - "@rolldown/binding-openharmony-arm64": "1.0.1", - "@rolldown/binding-wasm32-wasi": "1.0.1", - "@rolldown/binding-win32-arm64-msvc": "1.0.1", - "@rolldown/binding-win32-x64-msvc": "1.0.1" + "@rolldown/binding-android-arm64": "1.2.3", + "@rolldown/binding-darwin-arm64": "1.2.3", + "@rolldown/binding-darwin-x64": "1.2.3", + "@rolldown/binding-freebsd-x64": "1.2.3", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.3", + "@rolldown/binding-linux-arm64-gnu": "1.2.3", + "@rolldown/binding-linux-arm64-musl": "1.2.3", + "@rolldown/binding-linux-ppc64-gnu": "1.2.3", + "@rolldown/binding-linux-s390x-gnu": "1.2.3", + "@rolldown/binding-linux-x64-gnu": "1.2.3", + "@rolldown/binding-linux-x64-musl": "1.2.3", + "@rolldown/binding-openharmony-arm64": "1.2.3", + "@rolldown/binding-win32-arm64-msvc": "1.2.3", + "@rolldown/binding-win32-x64-msvc": "1.2.3" } }, "node_modules/router": { @@ -6674,9 +6643,9 @@ } }, "node_modules/tinyglobby": { - "version": "0.2.16", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", - "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", "dev": true, "license": "MIT", "dependencies": { @@ -6769,14 +6738,6 @@ "node": ">=6" } }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true - }, "node_modules/tsx": { "version": "4.22.1", "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.1.tgz", @@ -6974,17 +6935,17 @@ } }, "node_modules/vite": { - "version": "8.0.13", - "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.13.tgz", - "integrity": "sha512-MFtjBYgzmSxmgA4RAfjIyXWpGe1oALnjgUTzzV7QLx/TKxCzjtMH6Fd9/eVK+5Fg1qNoz5VAwsmMs/NofrmJvw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.1.tgz", + "integrity": "sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==", "dev": true, "license": "MIT", "dependencies": { - "lightningcss": "^1.32.0", - "picomatch": "^4.0.4", - "postcss": "^8.5.14", - "rolldown": "1.0.1", - "tinyglobby": "^0.2.16" + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.25", + "rolldown": "~1.2.1", + "tinyglobby": "^0.2.17" }, "bin": { "vite": "bin/vite.js" @@ -7000,7 +6961,7 @@ }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", - "@vitejs/devtools": "^0.1.18", + "@vitejs/devtools": "^0.4.0", "esbuild": "^0.27.0 || ^0.28.0", "jiti": ">=1.21.0", "less": "^4.0.0", diff --git a/package.json b/package.json index a0834f37..de91477a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cladding", - "version": "0.9.3", + "version": "0.9.4", "description": "Spec-driven verification layer for AI coding agents — Claude Code · Codex · Gemini · Antigravity · Cursor. Intent in before it writes, result verified against your spec after. Reference implementation of the Ironclad standard.", "type": "module", "license": "MIT", @@ -61,7 +61,7 @@ "typecheck": "tsc --noEmit", "lint": "eslint .", "build": "node scripts/test-count.mjs --check && node scripts/build.mjs && node scripts/build-plugin.mjs", - "build:plugin": "node scripts/build-plugin.mjs", + "build:plugin": "node scripts/build.mjs && node scripts/build-plugin.mjs", "watch": "node --watch-path=./src scripts/build.mjs", "version-bump": "node scripts/version-bump.mjs", "test-count": "node scripts/test-count.mjs", @@ -91,7 +91,7 @@ }, "dependencies": { "@anthropic-ai/sdk": "^0.96.0", - "@modelcontextprotocol/sdk": "^1.29.0", + "@modelcontextprotocol/sdk": "^1.30.0", "smol-toml": "^1.6.1" } } diff --git a/plugins/antigravity/skills/check/SKILL.md b/plugins/antigravity/skills/check/SKILL.md index fe7bb3ea..a8a755a4 100644 --- a/plugins/antigravity/skills/check/SKILL.md +++ b/plugins/antigravity/skills/check/SKILL.md @@ -29,4 +29,6 @@ the project: fast inner-loop feedback while implementing. - `clad check --tier=pre-push --strict` — the full gate (type / lint / unit / cov + drift). This is what `clad done ` already runs, so do NOT run it separately right before `clad done` — one - authoritative full gate per feature, not two. See `docs/feature-cycle.md` § Gate economy. + authoritative full gate per feature, not two. A GREEN run refreshes `spec/attestation.yaml` with the + running Cladding version, strict blocking mode, detector-catalog SHA-256, module hashes, and feature + markers. See `docs/feature-cycle.md` § Gate economy. diff --git a/plugins/antigravity/skills/doctor/SKILL.md b/plugins/antigravity/skills/doctor/SKILL.md index 10214faa..5425d651 100644 --- a/plugins/antigravity/skills/doctor/SKILL.md +++ b/plugins/antigravity/skills/doctor/SKILL.md @@ -1,5 +1,5 @@ --- -description: Summarise .cladding/events.log.jsonl — sentinel-miss frequency by phase × cause × fallback plus the top missed sentinels. Use when the user asks whether their LLM dispatcher (MCP sampling host, Anthropic SDK, …) is healthy, when scan / drive results look thinner than expected, or as a one-shot triage before tuning model / max_tokens / temperature. Activate only when the connected project contains spec.yaml or the user explicitly names Cladding; ignore ordinary requests in uninitialized projects. +description: Diagnose Cladding runtime health — Claude Code hook liveness and version, CI package pinning, lifecycle governance, and sentinel-miss frequency by phase × cause × fallback. Use when hooks may be silent, CI may float across Cladding releases, scan or run results look thinner than expected, or before tuning the host model or transport. Activate only when the connected project contains spec.yaml or the user explicitly names Cladding; ignore ordinary requests in uninitialized projects. --- # Cladding doctor @@ -7,13 +7,16 @@ description: Summarise .cladding/events.log.jsonl — sentinel-miss frequency by Run `clad doctor` from the project root. The verb is observability — it never mutates the working tree. - `--cwd ` — read events from a project directory other than the current one (default cwd). -- `--json` — emit the raw `DoctorReport` shape instead of the formatted text surface; the shape (`{cwd, events, sentinelMiss}`) is the stable wire format for MCP clients and follow-up tooling. +- `--json` — emit the raw `DoctorReport` shape instead of the formatted text surface; the additive shape (`{cwd, events, sentinelMiss, governance, hooks, ciVersion}`) is the stable wire format for MCP clients and follow-up tooling. The text surface prints: 1. One pulse line with total events and total sentinel-miss count (`pass` when zero misses, `note` otherwise). 2. An event-type breakdown line (one `=` token per non-zero `EventType`). -3. When sentinel-miss events exist: +3. Claude Code hook health: whether the runtime has actually been observed, whether the observed engine version matches the current CLI, and the last firing time (or `never observed`) for session start, prompt submit, before edit, after edit, and session stop. +4. A non-blocking CI warning naming each GitHub Actions workflow that invokes an unversioned or floating `npx cladding` package. Numeric selectors such as `cladding@0.9` and `cladding@0.9.4` stay quiet. +5. Governance counts for gate runs, done attempts and rejections, stop blocks, known-failing Stop exits, blocked fingerprints reproduced by a later gate, and attestation state. +6. When sentinel-miss events exist: - `by phase` / `by cause` / `by fallback` aggregates from the v0.3.39 telemetry payload. - Top-5 missed sentinels (`CONVENTIONS_MD` / `ARCHITECTURE_YAML` / `SCENARIO_FLOWS` / `CAPABILITIES_YAML` / `WHY` / `WHAT` / `PURPOSE`) sorted by count desc, name asc. - Last 3 unique dispatcher error strings (most recent first; errors are truncated to 200 chars at the emit site). @@ -27,6 +30,7 @@ The text surface prints: ## When to run - After `clad init --scan` to confirm the scan refinement ran with full LLM coverage (no `sentinel_miss` events). +- After installing or updating the Claude Code plugin to confirm a new session actually fired the shipped hooks and loaded the current engine. - After `clad run` to confirm the autonomous loop received refined replies from the configured host. - Periodically in CI to track miss rate across sampling-policy changes. - Before reporting "the LLM seems off" to a host (Claude Code / Cursor / Continue) — the breakdown tells you whether the issue is dispatcher transport (`cause: dispatcher_error`) or model output quality (`cause: blank_section`). diff --git a/plugins/antigravity/skills/init/SKILL.md b/plugins/antigravity/skills/init/SKILL.md index a7cb3156..1a45dcca 100644 --- a/plugins/antigravity/skills/init/SKILL.md +++ b/plugins/antigravity/skills/init/SKILL.md @@ -25,4 +25,6 @@ Do not run `clad init` in a shell from an AI-host onboarding session. Do not use `clad_prepare_init` does not modify the workspace, and `clad_stage_init` writes only ignored runtime state. Never call stage and apply in the same assistant turn. Only `clad_init` writes authored artifacts, after explicit user confirmation plus schema and freshness validation. A stale, malformed, or replayed apply request must be prepared again. +Initialization also creates or appends `spec/index.yaml merge=union` in `.gitattributes`. It preserves every existing attribute and never assigns a merge driver to `spec/attestation.yaml`; the strict gate rewrites that verification record canonically after an ordinary merge. + The raw CLI remains available for terminal, CI, offline, and explicitly configured SDK automation; it is not the primary host onboarding path. diff --git a/plugins/claude-code/.claude-plugin/plugin.json b/plugins/claude-code/.claude-plugin/plugin.json index ff06fc9a..041ffa2b 100644 --- a/plugins/claude-code/.claude-plugin/plugin.json +++ b/plugins/claude-code/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "cladding", - "version": "0.9.3", + "version": "0.9.4", "description": "Reference implementation of the Ironclad standard — multi-agent dev harness for Claude Code.", "author": { "name": "qwerfunch" @@ -32,7 +32,6 @@ "description": "cladding MCP server — exposes spec / drift / events / personas as tools, resources, prompts. Runs the engine bundled with this plugin (no global `clad` on PATH required). Auto-starts when this plugin is enabled; no manual `claude mcp add` needed." } }, - "hooks": "./hooks/hooks.json", "ironclad": { "spec-version": "0.0.23", "spec-url": "https://github.com/qwerfunch/ironclad", diff --git a/plugins/claude-code/commands/init.md b/plugins/claude-code/commands/init.md index a7cb3156..1a45dcca 100644 --- a/plugins/claude-code/commands/init.md +++ b/plugins/claude-code/commands/init.md @@ -25,4 +25,6 @@ Do not run `clad init` in a shell from an AI-host onboarding session. Do not use `clad_prepare_init` does not modify the workspace, and `clad_stage_init` writes only ignored runtime state. Never call stage and apply in the same assistant turn. Only `clad_init` writes authored artifacts, after explicit user confirmation plus schema and freshness validation. A stale, malformed, or replayed apply request must be prepared again. +Initialization also creates or appends `spec/index.yaml merge=union` in `.gitattributes`. It preserves every existing attribute and never assigns a merge driver to `spec/attestation.yaml`; the strict gate rewrites that verification record canonically after an ordinary merge. + The raw CLI remains available for terminal, CI, offline, and explicitly configured SDK automation; it is not the primary host onboarding path. diff --git a/plugins/claude-code/dist/clad.js b/plugins/claude-code/dist/clad.js index 5b5522e8..4460b1e9 100755 --- a/plugins/claude-code/dist/clad.js +++ b/plugins/claude-code/dist/clad.js @@ -4,102 +4,102 @@ const require = __claddingCreateRequire(import.meta.url); // Marker for stages/*.ts: when true, the per-stage CLI-entry guard // short-circuits so the bundle doesn't fire every stage at startup. globalThis.__CLADDING_BUNDLED = true; -var Yde=Object.create;var PA=Object.defineProperty;var Xde=Object.getOwnPropertyDescriptor;var Qde=Object.getOwnPropertyNames;var efe=Object.getPrototypeOf,tfe=Object.prototype.hasOwnProperty;var Ge=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var y=(t,e)=>()=>(t&&(e=t(t=0)),e);var v=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Dr=(t,e)=>{for(var r in e)PA(t,r,{get:e[r],enumerable:!0})},rfe=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Qde(e))!tfe.call(t,i)&&i!==r&&PA(t,i,{get:()=>e[i],enumerable:!(n=Xde(e,i))||n.enumerable});return t};var St=(t,e,r)=>(r=t!=null?Yde(efe(t)):{},rfe(e||!t||!t.__esModule?PA(r,"default",{value:t,enumerable:!0}):r,t));var lf=v(DA=>{var ky=class extends Error{constructor(e,r,n){super(n),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=r,this.exitCode=e,this.nestedError=void 0}},CA=class extends ky{constructor(e){super(1,"commander.invalidArgument",e),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}};DA.CommanderError=ky;DA.InvalidArgumentError=CA});var Ey=v(jA=>{var{InvalidArgumentError:nfe}=lf(),NA=class{constructor(e,r){switch(this.description=r||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,e[0]){case"<":this.required=!0,this._name=e.slice(1,-1);break;case"[":this.required=!1,this._name=e.slice(1,-1);break;default:this.required=!0,this._name=e;break}this._name.endsWith("...")&&(this.variadic=!0,this._name=this._name.slice(0,-3))}name(){return this._name}_collectValue(e,r){return r===this.defaultValue||!Array.isArray(r)?[e]:(r.push(e),r)}default(e,r){return this.defaultValue=e,this.defaultValueDescription=r,this}argParser(e){return this.parseArg=e,this}choices(e){return this.argChoices=e.slice(),this.parseArg=(r,n)=>{if(!this.argChoices.includes(r))throw new nfe(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._collectValue(r,n):r},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}};function ife(t){let e=t.name()+(t.variadic===!0?"...":"");return t.required?"<"+e+">":"["+e+"]"}jA.Argument=NA;jA.humanReadableArgName=ife});var LA=v(FA=>{var{humanReadableArgName:ofe}=Ey(),MA=class{constructor(){this.helpWidth=void 0,this.minWidthToWrap=40,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}prepareContext(e){this.helpWidth=this.helpWidth??e.helpWidth??80}visibleCommands(e){let r=e.commands.filter(i=>!i._hidden),n=e._getHelpCommand();return n&&!n._hidden&&r.push(n),this.sortSubcommands&&r.sort((i,o)=>i.name().localeCompare(o.name())),r}compareOptions(e,r){let n=i=>i.short?i.short.replace(/^-/,""):i.long.replace(/^--/,"");return n(e).localeCompare(n(r))}visibleOptions(e){let r=e.options.filter(i=>!i.hidden),n=e._getHelpOption();if(n&&!n.hidden){let i=n.short&&e._findOption(n.short),o=n.long&&e._findOption(n.long);!i&&!o?r.push(n):n.long&&!o?r.push(e.createOption(n.long,n.description)):n.short&&!i&&r.push(e.createOption(n.short,n.description))}return this.sortOptions&&r.sort(this.compareOptions),r}visibleGlobalOptions(e){if(!this.showGlobalOptions)return[];let r=[];for(let n=e.parent;n;n=n.parent){let i=n.options.filter(o=>!o.hidden);r.push(...i)}return this.sortOptions&&r.sort(this.compareOptions),r}visibleArguments(e){return e._argsDescription&&e.registeredArguments.forEach(r=>{r.description=r.description||e._argsDescription[r.name()]||""}),e.registeredArguments.find(r=>r.description)?e.registeredArguments:[]}subcommandTerm(e){let r=e.registeredArguments.map(n=>ofe(n)).join(" ");return e._name+(e._aliases[0]?"|"+e._aliases[0]:"")+(e.options.length?" [options]":"")+(r?" "+r:"")}optionTerm(e){return e.flags}argumentTerm(e){return e.name()}longestSubcommandTermLength(e,r){return r.visibleCommands(e).reduce((n,i)=>Math.max(n,this.displayWidth(r.styleSubcommandTerm(r.subcommandTerm(i)))),0)}longestOptionTermLength(e,r){return r.visibleOptions(e).reduce((n,i)=>Math.max(n,this.displayWidth(r.styleOptionTerm(r.optionTerm(i)))),0)}longestGlobalOptionTermLength(e,r){return r.visibleGlobalOptions(e).reduce((n,i)=>Math.max(n,this.displayWidth(r.styleOptionTerm(r.optionTerm(i)))),0)}longestArgumentTermLength(e,r){return r.visibleArguments(e).reduce((n,i)=>Math.max(n,this.displayWidth(r.styleArgumentTerm(r.argumentTerm(i)))),0)}commandUsage(e){let r=e._name;e._aliases[0]&&(r=r+"|"+e._aliases[0]);let n="";for(let i=e.parent;i;i=i.parent)n=i.name()+" "+n;return n+r+" "+e.usage()}commandDescription(e){return e.description()}subcommandDescription(e){return e.summary()||e.description()}optionDescription(e){let r=[];if(e.argChoices&&r.push(`choices: ${e.argChoices.map(n=>JSON.stringify(n)).join(", ")}`),e.defaultValue!==void 0&&(e.required||e.optional||e.isBoolean()&&typeof e.defaultValue=="boolean")&&r.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),e.presetArg!==void 0&&e.optional&&r.push(`preset: ${JSON.stringify(e.presetArg)}`),e.envVar!==void 0&&r.push(`env: ${e.envVar}`),r.length>0){let n=`(${r.join(", ")})`;return e.description?`${e.description} ${n}`:n}return e.description}argumentDescription(e){let r=[];if(e.argChoices&&r.push(`choices: ${e.argChoices.map(n=>JSON.stringify(n)).join(", ")}`),e.defaultValue!==void 0&&r.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),r.length>0){let n=`(${r.join(", ")})`;return e.description?`${e.description} ${n}`:n}return e.description}formatItemList(e,r,n){return r.length===0?[]:[n.styleTitle(e),...r,""]}groupItems(e,r,n){let i=new Map;return e.forEach(o=>{let s=n(o);i.has(s)||i.set(s,[])}),r.forEach(o=>{let s=n(o);i.has(s)||i.set(s,[]),i.get(s).push(o)}),i}formatHelp(e,r){let n=r.padWidth(e,r),i=r.helpWidth??80;function o(d,f){return r.formatItem(d,n,f,r)}let s=[`${r.styleTitle("Usage:")} ${r.styleUsage(r.commandUsage(e))}`,""],a=r.commandDescription(e);a.length>0&&(s=s.concat([r.boxWrap(r.styleCommandDescription(a),i),""]));let c=r.visibleArguments(e).map(d=>o(r.styleArgumentTerm(r.argumentTerm(d)),r.styleArgumentDescription(r.argumentDescription(d))));if(s=s.concat(this.formatItemList("Arguments:",c,r)),this.groupItems(e.options,r.visibleOptions(e),d=>d.helpGroupHeading??"Options:").forEach((d,f)=>{let p=d.map(m=>o(r.styleOptionTerm(r.optionTerm(m)),r.styleOptionDescription(r.optionDescription(m))));s=s.concat(this.formatItemList(f,p,r))}),r.showGlobalOptions){let d=r.visibleGlobalOptions(e).map(f=>o(r.styleOptionTerm(r.optionTerm(f)),r.styleOptionDescription(r.optionDescription(f))));s=s.concat(this.formatItemList("Global Options:",d,r))}return this.groupItems(e.commands,r.visibleCommands(e),d=>d.helpGroup()||"Commands:").forEach((d,f)=>{let p=d.map(m=>o(r.styleSubcommandTerm(r.subcommandTerm(m)),r.styleSubcommandDescription(r.subcommandDescription(m))));s=s.concat(this.formatItemList(f,p,r))}),s.join(` -`)}displayWidth(e){return _4(e).length}styleTitle(e){return e}styleUsage(e){return e.split(" ").map(r=>r==="[options]"?this.styleOptionText(r):r==="[command]"?this.styleSubcommandText(r):r[0]==="["||r[0]==="<"?this.styleArgumentText(r):this.styleCommandText(r)).join(" ")}styleCommandDescription(e){return this.styleDescriptionText(e)}styleOptionDescription(e){return this.styleDescriptionText(e)}styleSubcommandDescription(e){return this.styleDescriptionText(e)}styleArgumentDescription(e){return this.styleDescriptionText(e)}styleDescriptionText(e){return e}styleOptionTerm(e){return this.styleOptionText(e)}styleSubcommandTerm(e){return e.split(" ").map(r=>r==="[options]"?this.styleOptionText(r):r[0]==="["||r[0]==="<"?this.styleArgumentText(r):this.styleSubcommandText(r)).join(" ")}styleArgumentTerm(e){return this.styleArgumentText(e)}styleOptionText(e){return e}styleArgumentText(e){return e}styleSubcommandText(e){return e}styleCommandText(e){return e}padWidth(e,r){return Math.max(r.longestOptionTermLength(e,r),r.longestGlobalOptionTermLength(e,r),r.longestSubcommandTermLength(e,r),r.longestArgumentTermLength(e,r))}preformatted(e){return/\n[^\S\r\n]/.test(e)}formatItem(e,r,n,i){let s=" ".repeat(2);if(!n)return s+e;let a=e.padEnd(r+e.length-i.displayWidth(e)),c=2,u=(this.helpWidth??80)-r-c-2,d;return utypeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var y=(t,e,r)=>()=>{if(r)throw r[0];try{return t&&(e=t(t=0)),e}catch(n){throw r=[n],n}};var v=(t,e)=>()=>{try{return e||t((e={exports:{}}).exports,e),e.exports}catch(r){throw e=0,r}},Nr=(t,e)=>{for(var r in e)zA(t,r,{get:e[r],enumerable:!0})},Ufe=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ffe(e))!zfe.call(t,i)&&i!==r&&zA(t,i,{get:()=>e[i],enumerable:!(n=Mfe(e,i))||n.enumerable});return t};var wt=(t,e,r)=>(r=t!=null?jfe(Lfe(t)):{},Ufe(e||!t||!t.__esModule?zA(r,"default",{value:t,enumerable:!0}):r,t));var ff=v(qA=>{var Oy=class extends Error{constructor(e,r,n){super(n),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=r,this.exitCode=e,this.nestedError=void 0}},UA=class extends Oy{constructor(e){super(1,"commander.invalidArgument",e),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}};qA.CommanderError=Oy;qA.InvalidArgumentError=UA});var Ty=v(BA=>{var{InvalidArgumentError:qfe}=ff(),HA=class{constructor(e,r){switch(this.description=r||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,e[0]){case"<":this.required=!0,this._name=e.slice(1,-1);break;case"[":this.required=!1,this._name=e.slice(1,-1);break;default:this.required=!0,this._name=e;break}this._name.endsWith("...")&&(this.variadic=!0,this._name=this._name.slice(0,-3))}name(){return this._name}_collectValue(e,r){return r===this.defaultValue||!Array.isArray(r)?[e]:(r.push(e),r)}default(e,r){return this.defaultValue=e,this.defaultValueDescription=r,this}argParser(e){return this.parseArg=e,this}choices(e){return this.argChoices=e.slice(),this.parseArg=(r,n)=>{if(!this.argChoices.includes(r))throw new qfe(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._collectValue(r,n):r},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}};function Hfe(t){let e=t.name()+(t.variadic===!0?"...":"");return t.required?"<"+e+">":"["+e+"]"}BA.Argument=HA;BA.humanReadableArgName=Hfe});var VA=v(ZA=>{var{humanReadableArgName:Bfe}=Ty(),GA=class{constructor(){this.helpWidth=void 0,this.minWidthToWrap=40,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}prepareContext(e){this.helpWidth=this.helpWidth??e.helpWidth??80}visibleCommands(e){let r=e.commands.filter(i=>!i._hidden),n=e._getHelpCommand();return n&&!n._hidden&&r.push(n),this.sortSubcommands&&r.sort((i,o)=>i.name().localeCompare(o.name())),r}compareOptions(e,r){let n=i=>i.short?i.short.replace(/^-/,""):i.long.replace(/^--/,"");return n(e).localeCompare(n(r))}visibleOptions(e){let r=e.options.filter(i=>!i.hidden),n=e._getHelpOption();if(n&&!n.hidden){let i=n.short&&e._findOption(n.short),o=n.long&&e._findOption(n.long);!i&&!o?r.push(n):n.long&&!o?r.push(e.createOption(n.long,n.description)):n.short&&!i&&r.push(e.createOption(n.short,n.description))}return this.sortOptions&&r.sort(this.compareOptions),r}visibleGlobalOptions(e){if(!this.showGlobalOptions)return[];let r=[];for(let n=e.parent;n;n=n.parent){let i=n.options.filter(o=>!o.hidden);r.push(...i)}return this.sortOptions&&r.sort(this.compareOptions),r}visibleArguments(e){return e._argsDescription&&e.registeredArguments.forEach(r=>{r.description=r.description||e._argsDescription[r.name()]||""}),e.registeredArguments.find(r=>r.description)?e.registeredArguments:[]}subcommandTerm(e){let r=e.registeredArguments.map(n=>Bfe(n)).join(" ");return e._name+(e._aliases[0]?"|"+e._aliases[0]:"")+(e.options.length?" [options]":"")+(r?" "+r:"")}optionTerm(e){return e.flags}argumentTerm(e){return e.name()}longestSubcommandTermLength(e,r){return r.visibleCommands(e).reduce((n,i)=>Math.max(n,this.displayWidth(r.styleSubcommandTerm(r.subcommandTerm(i)))),0)}longestOptionTermLength(e,r){return r.visibleOptions(e).reduce((n,i)=>Math.max(n,this.displayWidth(r.styleOptionTerm(r.optionTerm(i)))),0)}longestGlobalOptionTermLength(e,r){return r.visibleGlobalOptions(e).reduce((n,i)=>Math.max(n,this.displayWidth(r.styleOptionTerm(r.optionTerm(i)))),0)}longestArgumentTermLength(e,r){return r.visibleArguments(e).reduce((n,i)=>Math.max(n,this.displayWidth(r.styleArgumentTerm(r.argumentTerm(i)))),0)}commandUsage(e){let r=e._name;e._aliases[0]&&(r=r+"|"+e._aliases[0]);let n="";for(let i=e.parent;i;i=i.parent)n=i.name()+" "+n;return n+r+" "+e.usage()}commandDescription(e){return e.description()}subcommandDescription(e){return e.summary()||e.description()}optionDescription(e){let r=[];if(e.argChoices&&r.push(`choices: ${e.argChoices.map(n=>JSON.stringify(n)).join(", ")}`),e.defaultValue!==void 0&&(e.required||e.optional||e.isBoolean()&&typeof e.defaultValue=="boolean")&&r.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),e.presetArg!==void 0&&e.optional&&r.push(`preset: ${JSON.stringify(e.presetArg)}`),e.envVar!==void 0&&r.push(`env: ${e.envVar}`),r.length>0){let n=`(${r.join(", ")})`;return e.description?`${e.description} ${n}`:n}return e.description}argumentDescription(e){let r=[];if(e.argChoices&&r.push(`choices: ${e.argChoices.map(n=>JSON.stringify(n)).join(", ")}`),e.defaultValue!==void 0&&r.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),r.length>0){let n=`(${r.join(", ")})`;return e.description?`${e.description} ${n}`:n}return e.description}formatItemList(e,r,n){return r.length===0?[]:[n.styleTitle(e),...r,""]}groupItems(e,r,n){let i=new Map;return e.forEach(o=>{let s=n(o);i.has(s)||i.set(s,[])}),r.forEach(o=>{let s=n(o);i.has(s)||i.set(s,[]),i.get(s).push(o)}),i}formatHelp(e,r){let n=r.padWidth(e,r),i=r.helpWidth??80;function o(d,f){return r.formatItem(d,n,f,r)}let s=[`${r.styleTitle("Usage:")} ${r.styleUsage(r.commandUsage(e))}`,""],a=r.commandDescription(e);a.length>0&&(s=s.concat([r.boxWrap(r.styleCommandDescription(a),i),""]));let c=r.visibleArguments(e).map(d=>o(r.styleArgumentTerm(r.argumentTerm(d)),r.styleArgumentDescription(r.argumentDescription(d))));if(s=s.concat(this.formatItemList("Arguments:",c,r)),this.groupItems(e.options,r.visibleOptions(e),d=>d.helpGroupHeading??"Options:").forEach((d,f)=>{let p=d.map(m=>o(r.styleOptionTerm(r.optionTerm(m)),r.styleOptionDescription(r.optionDescription(m))));s=s.concat(this.formatItemList(f,p,r))}),r.showGlobalOptions){let d=r.visibleGlobalOptions(e).map(f=>o(r.styleOptionTerm(r.optionTerm(f)),r.styleOptionDescription(r.optionDescription(f))));s=s.concat(this.formatItemList("Global Options:",d,r))}return this.groupItems(e.commands,r.visibleCommands(e),d=>d.helpGroup()||"Commands:").forEach((d,f)=>{let p=d.map(m=>o(r.styleSubcommandTerm(r.subcommandTerm(m)),r.styleSubcommandDescription(r.subcommandDescription(m))));s=s.concat(this.formatItemList(f,p,r))}),s.join(` +`)}displayWidth(e){return C4(e).length}styleTitle(e){return e}styleUsage(e){return e.split(" ").map(r=>r==="[options]"?this.styleOptionText(r):r==="[command]"?this.styleSubcommandText(r):r[0]==="["||r[0]==="<"?this.styleArgumentText(r):this.styleCommandText(r)).join(" ")}styleCommandDescription(e){return this.styleDescriptionText(e)}styleOptionDescription(e){return this.styleDescriptionText(e)}styleSubcommandDescription(e){return this.styleDescriptionText(e)}styleArgumentDescription(e){return this.styleDescriptionText(e)}styleDescriptionText(e){return e}styleOptionTerm(e){return this.styleOptionText(e)}styleSubcommandTerm(e){return e.split(" ").map(r=>r==="[options]"?this.styleOptionText(r):r[0]==="["||r[0]==="<"?this.styleArgumentText(r):this.styleSubcommandText(r)).join(" ")}styleArgumentTerm(e){return this.styleArgumentText(e)}styleOptionText(e){return e}styleArgumentText(e){return e}styleSubcommandText(e){return e}styleCommandText(e){return e}padWidth(e,r){return Math.max(r.longestOptionTermLength(e,r),r.longestGlobalOptionTermLength(e,r),r.longestSubcommandTermLength(e,r),r.longestArgumentTermLength(e,r))}preformatted(e){return/\n[^\S\r\n]/.test(e)}formatItem(e,r,n,i){let s=" ".repeat(2);if(!n)return s+e;let a=e.padEnd(r+e.length-i.displayWidth(e)),c=2,u=(this.helpWidth??80)-r-c-2,d;return u{let a=s.match(i);if(a===null){o.push("");return}let c=[a.shift()],l=this.displayWidth(c[0]);a.forEach(u=>{let d=this.displayWidth(u);if(l+d<=r){c.push(u),l+=d;return}o.push(c.join(""));let f=u.trimStart();c=[f],l=this.displayWidth(f)}),o.push(c.join(""))}),o.join(` -`)}};function _4(t){let e=/\x1b\[\d*(;\d*)*m/g;return t.replace(e,"")}FA.Help=MA;FA.stripColor=_4});var BA=v(qA=>{var{InvalidArgumentError:sfe}=lf(),zA=class{constructor(e,r){this.flags=e,this.description=r||"",this.required=e.includes("<"),this.optional=e.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(e),this.mandatory=!1;let n=afe(e);this.short=n.shortFlag,this.long=n.longFlag,this.negate=!1,this.long&&(this.negate=this.long.startsWith("--no-")),this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0,this.helpGroupHeading=void 0}default(e,r){return this.defaultValue=e,this.defaultValueDescription=r,this}preset(e){return this.presetArg=e,this}conflicts(e){return this.conflictsWith=this.conflictsWith.concat(e),this}implies(e){let r=e;return typeof e=="string"&&(r={[e]:!0}),this.implied=Object.assign(this.implied||{},r),this}env(e){return this.envVar=e,this}argParser(e){return this.parseArg=e,this}makeOptionMandatory(e=!0){return this.mandatory=!!e,this}hideHelp(e=!0){return this.hidden=!!e,this}_collectValue(e,r){return r===this.defaultValue||!Array.isArray(r)?[e]:(r.push(e),r)}choices(e){return this.argChoices=e.slice(),this.parseArg=(r,n)=>{if(!this.argChoices.includes(r))throw new sfe(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._collectValue(r,n):r},this}name(){return this.long?this.long.replace(/^--/,""):this.short.replace(/^-/,"")}attributeName(){return this.negate?b4(this.name().replace(/^no-/,"")):b4(this.name())}helpGroup(e){return this.helpGroupHeading=e,this}is(e){return this.short===e||this.long===e}isBoolean(){return!this.required&&!this.optional&&!this.negate}},UA=class{constructor(e){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,e.forEach(r=>{r.negate?this.negativeOptions.set(r.attributeName(),r):this.positiveOptions.set(r.attributeName(),r)}),this.negativeOptions.forEach((r,n)=>{this.positiveOptions.has(n)&&this.dualOptions.add(n)})}valueFromOption(e,r){let n=r.attributeName();if(!this.dualOptions.has(n))return!0;let i=this.negativeOptions.get(n).presetArg,o=i!==void 0?i:!1;return r.negate===(o===e)}};function b4(t){return t.split("-").reduce((e,r)=>e+r[0].toUpperCase()+r.slice(1))}function afe(t){let e,r,n=/^-[^-]$/,i=/^--[^-]/,o=t.split(/[ |,]+/).concat("guard");if(n.test(o[0])&&(e=o.shift()),i.test(o[0])&&(r=o.shift()),!e&&n.test(o[0])&&(e=o.shift()),!e&&i.test(o[0])&&(e=r,r=o.shift()),o[0].startsWith("-")){let s=o[0],a=`option creation failed due to '${s}' in option flags '${t}'`;throw/^-[^-][^-]/.test(s)?new Error(`${a} +`)}};function C4(t){let e=/\x1b\[\d*(;\d*)*m/g;return t.replace(e,"")}ZA.Help=GA;ZA.stripColor=C4});var YA=v(JA=>{var{InvalidArgumentError:Gfe}=ff(),WA=class{constructor(e,r){this.flags=e,this.description=r||"",this.required=e.includes("<"),this.optional=e.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(e),this.mandatory=!1;let n=Zfe(e);this.short=n.shortFlag,this.long=n.longFlag,this.negate=!1,this.long&&(this.negate=this.long.startsWith("--no-")),this.defaultValue=void 0,this.defaultValueDescription=void 0,this.presetArg=void 0,this.envVar=void 0,this.parseArg=void 0,this.hidden=!1,this.argChoices=void 0,this.conflictsWith=[],this.implied=void 0,this.helpGroupHeading=void 0}default(e,r){return this.defaultValue=e,this.defaultValueDescription=r,this}preset(e){return this.presetArg=e,this}conflicts(e){return this.conflictsWith=this.conflictsWith.concat(e),this}implies(e){let r=e;return typeof e=="string"&&(r={[e]:!0}),this.implied=Object.assign(this.implied||{},r),this}env(e){return this.envVar=e,this}argParser(e){return this.parseArg=e,this}makeOptionMandatory(e=!0){return this.mandatory=!!e,this}hideHelp(e=!0){return this.hidden=!!e,this}_collectValue(e,r){return r===this.defaultValue||!Array.isArray(r)?[e]:(r.push(e),r)}choices(e){return this.argChoices=e.slice(),this.parseArg=(r,n)=>{if(!this.argChoices.includes(r))throw new Gfe(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._collectValue(r,n):r},this}name(){return this.long?this.long.replace(/^--/,""):this.short.replace(/^-/,"")}attributeName(){return this.negate?D4(this.name().replace(/^no-/,"")):D4(this.name())}helpGroup(e){return this.helpGroupHeading=e,this}is(e){return this.short===e||this.long===e}isBoolean(){return!this.required&&!this.optional&&!this.negate}},KA=class{constructor(e){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,e.forEach(r=>{r.negate?this.negativeOptions.set(r.attributeName(),r):this.positiveOptions.set(r.attributeName(),r)}),this.negativeOptions.forEach((r,n)=>{this.positiveOptions.has(n)&&this.dualOptions.add(n)})}valueFromOption(e,r){let n=r.attributeName();if(!this.dualOptions.has(n))return!0;let i=this.negativeOptions.get(n).presetArg,o=i!==void 0?i:!1;return r.negate===(o===e)}};function D4(t){return t.split("-").reduce((e,r)=>e+r[0].toUpperCase()+r.slice(1))}function Zfe(t){let e,r,n=/^-[^-]$/,i=/^--[^-]/,o=t.split(/[ |,]+/).concat("guard");if(n.test(o[0])&&(e=o.shift()),i.test(o[0])&&(r=o.shift()),!e&&n.test(o[0])&&(e=o.shift()),!e&&i.test(o[0])&&(e=r,r=o.shift()),o[0].startsWith("-")){let s=o[0],a=`option creation failed due to '${s}' in option flags '${t}'`;throw/^-[^-][^-]/.test(s)?new Error(`${a} - a short flag is a single dash and a single character - either use a single dash and a single character (for a short flag) - or use a double dash for a long option (and can have two, like '--ws, --workspace')`):n.test(s)?new Error(`${a} - too many short flags`):i.test(s)?new Error(`${a} - too many long flags`):new Error(`${a} -- unrecognised flag format`)}if(e===void 0&&r===void 0)throw new Error(`option creation failed due to no flags found in '${t}'.`);return{shortFlag:e,longFlag:r}}qA.Option=zA;qA.DualOptions=UA});var S4=v(v4=>{function cfe(t,e){if(Math.abs(t.length-e.length)>3)return Math.max(t.length,e.length);let r=[];for(let n=0;n<=t.length;n++)r[n]=[n];for(let n=0;n<=e.length;n++)r[0][n]=n;for(let n=1;n<=e.length;n++)for(let i=1;i<=t.length;i++){let o=1;t[i-1]===e[n-1]?o=0:o=1,r[i][n]=Math.min(r[i-1][n]+1,r[i][n-1]+1,r[i-1][n-1]+o),i>1&&n>1&&t[i-1]===e[n-2]&&t[i-2]===e[n-1]&&(r[i][n]=Math.min(r[i][n],r[i-2][n-2]+1))}return r[t.length][e.length]}function lfe(t,e){if(!e||e.length===0)return"";e=Array.from(new Set(e));let r=t.startsWith("--");r&&(t=t.slice(2),e=e.map(s=>s.slice(2)));let n=[],i=3,o=.4;return e.forEach(s=>{if(s.length<=1)return;let a=cfe(t,s),c=Math.max(t.length,s.length);(c-a)/c>o&&(as.localeCompare(a)),r&&(n=n.map(s=>`--${s}`)),n.length>1?` +- unrecognised flag format`)}if(e===void 0&&r===void 0)throw new Error(`option creation failed due to no flags found in '${t}'.`);return{shortFlag:e,longFlag:r}}JA.Option=WA;JA.DualOptions=KA});var j4=v(N4=>{function Vfe(t,e){if(Math.abs(t.length-e.length)>3)return Math.max(t.length,e.length);let r=[];for(let n=0;n<=t.length;n++)r[n]=[n];for(let n=0;n<=e.length;n++)r[0][n]=n;for(let n=1;n<=e.length;n++)for(let i=1;i<=t.length;i++){let o=1;t[i-1]===e[n-1]?o=0:o=1,r[i][n]=Math.min(r[i-1][n]+1,r[i][n-1]+1,r[i-1][n-1]+o),i>1&&n>1&&t[i-1]===e[n-2]&&t[i-2]===e[n-1]&&(r[i][n]=Math.min(r[i][n],r[i-2][n-2]+1))}return r[t.length][e.length]}function Wfe(t,e){if(!e||e.length===0)return"";e=Array.from(new Set(e));let r=t.startsWith("--");r&&(t=t.slice(2),e=e.map(s=>s.slice(2)));let n=[],i=3,o=.4;return e.forEach(s=>{if(s.length<=1)return;let a=Vfe(t,s),c=Math.max(t.length,s.length);(c-a)/c>o&&(as.localeCompare(a)),r&&(n=n.map(s=>`--${s}`)),n.length>1?` (Did you mean one of ${n.join(", ")}?)`:n.length===1?` -(Did you mean ${n[0]}?)`:""}v4.suggestSimilar=lfe});var k4=v(WA=>{var ufe=Ge("node:events").EventEmitter,HA=Ge("node:child_process"),po=Ge("node:path"),Ay=Ge("node:fs"),Be=Ge("node:process"),{Argument:dfe,humanReadableArgName:ffe}=Ey(),{CommanderError:GA}=lf(),{Help:pfe,stripColor:mfe}=LA(),{Option:w4,DualOptions:hfe}=BA(),{suggestSimilar:x4}=S4(),ZA=class t extends ufe{constructor(e){super(),this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!1,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=e||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._savedState=null,this._outputConfiguration={writeOut:r=>Be.stdout.write(r),writeErr:r=>Be.stderr.write(r),outputError:(r,n)=>n(r),getOutHelpWidth:()=>Be.stdout.isTTY?Be.stdout.columns:void 0,getErrHelpWidth:()=>Be.stderr.isTTY?Be.stderr.columns:void 0,getOutHasColors:()=>VA()??(Be.stdout.isTTY&&Be.stdout.hasColors?.()),getErrHasColors:()=>VA()??(Be.stderr.isTTY&&Be.stderr.hasColors?.()),stripColor:r=>mfe(r)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={},this._helpGroupHeading=void 0,this._defaultCommandGroup=void 0,this._defaultOptionGroup=void 0}copyInheritedSettings(e){return this._outputConfiguration=e._outputConfiguration,this._helpOption=e._helpOption,this._helpCommand=e._helpCommand,this._helpConfiguration=e._helpConfiguration,this._exitCallback=e._exitCallback,this._storeOptionsAsProperties=e._storeOptionsAsProperties,this._combineFlagAndOptionalValue=e._combineFlagAndOptionalValue,this._allowExcessArguments=e._allowExcessArguments,this._enablePositionalOptions=e._enablePositionalOptions,this._showHelpAfterError=e._showHelpAfterError,this._showSuggestionAfterError=e._showSuggestionAfterError,this}_getCommandAndAncestors(){let e=[];for(let r=this;r;r=r.parent)e.push(r);return e}command(e,r,n){let i=r,o=n;typeof i=="object"&&i!==null&&(o=i,i=null),o=o||{};let[,s,a]=e.match(/([^ ]+) *(.*)/),c=this.createCommand(s);return i&&(c.description(i),c._executableHandler=!0),o.isDefault&&(this._defaultCommandName=c._name),c._hidden=!!(o.noHelp||o.hidden),c._executableFile=o.executableFile||null,a&&c.arguments(a),this._registerCommand(c),c.parent=this,c.copyInheritedSettings(this),i?this:c}createCommand(e){return new t(e)}createHelp(){return Object.assign(new pfe,this.configureHelp())}configureHelp(e){return e===void 0?this._helpConfiguration:(this._helpConfiguration=e,this)}configureOutput(e){return e===void 0?this._outputConfiguration:(this._outputConfiguration={...this._outputConfiguration,...e},this)}showHelpAfterError(e=!0){return typeof e!="string"&&(e=!!e),this._showHelpAfterError=e,this}showSuggestionAfterError(e=!0){return this._showSuggestionAfterError=!!e,this}addCommand(e,r){if(!e._name)throw new Error(`Command passed to .addCommand() must have a name -- specify the name in Command constructor or using .name()`);return r=r||{},r.isDefault&&(this._defaultCommandName=e._name),(r.noHelp||r.hidden)&&(e._hidden=!0),this._registerCommand(e),e.parent=this,e._checkForBrokenPassThrough(),this}createArgument(e,r){return new dfe(e,r)}argument(e,r,n,i){let o=this.createArgument(e,r);return typeof n=="function"?o.default(i).argParser(n):o.default(n),this.addArgument(o),this}arguments(e){return e.trim().split(/ +/).forEach(r=>{this.argument(r)}),this}addArgument(e){let r=this.registeredArguments.slice(-1)[0];if(r?.variadic)throw new Error(`only the last argument can be variadic '${r.name()}'`);if(e.required&&e.defaultValue!==void 0&&e.parseArg===void 0)throw new Error(`a default value for a required argument is never used: '${e.name()}'`);return this.registeredArguments.push(e),this}helpCommand(e,r){if(typeof e=="boolean")return this._addImplicitHelpCommand=e,e&&this._defaultCommandGroup&&this._initCommandGroup(this._getHelpCommand()),this;let n=e??"help [command]",[,i,o]=n.match(/([^ ]+) *(.*)/),s=r??"display help for command",a=this.createCommand(i);return a.helpOption(!1),o&&a.arguments(o),s&&a.description(s),this._addImplicitHelpCommand=!0,this._helpCommand=a,(e||r)&&this._initCommandGroup(a),this}addHelpCommand(e,r){return typeof e!="object"?(this.helpCommand(e,r),this):(this._addImplicitHelpCommand=!0,this._helpCommand=e,this._initCommandGroup(e),this)}_getHelpCommand(){return this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))?(this._helpCommand===void 0&&this.helpCommand(void 0,void 0),this._helpCommand):null}hook(e,r){let n=["preSubcommand","preAction","postAction"];if(!n.includes(e))throw new Error(`Unexpected value for event passed to hook : '${e}'. -Expecting one of '${n.join("', '")}'`);return this._lifeCycleHooks[e]?this._lifeCycleHooks[e].push(r):this._lifeCycleHooks[e]=[r],this}exitOverride(e){return e?this._exitCallback=e:this._exitCallback=r=>{if(r.code!=="commander.executeSubCommandAsync")throw r},this}_exit(e,r,n){this._exitCallback&&this._exitCallback(new GA(e,r,n)),Be.exit(e)}action(e){let r=n=>{let i=this.registeredArguments.length,o=n.slice(0,i);return this._storeOptionsAsProperties?o[i]=this:o[i]=this.opts(),o.push(this),e.apply(this,o)};return this._actionHandler=r,this}createOption(e,r){return new w4(e,r)}_callParseArg(e,r,n,i){try{return e.parseArg(r,n)}catch(o){if(o.code==="commander.invalidArgument"){let s=`${i} ${o.message}`;this.error(s,{exitCode:o.exitCode,code:o.code})}throw o}}_registerOption(e){let r=e.short&&this._findOption(e.short)||e.long&&this._findOption(e.long);if(r){let n=e.long&&this._findOption(e.long)?e.long:e.short;throw new Error(`Cannot add option '${e.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${n}' -- already used by option '${r.flags}'`)}this._initOptionGroup(e),this.options.push(e)}_registerCommand(e){let r=i=>[i.name()].concat(i.aliases()),n=r(e).find(i=>this._findCommand(i));if(n){let i=r(this._findCommand(n)).join("|"),o=r(e).join("|");throw new Error(`cannot add command '${o}' as already have command '${i}'`)}this._initCommandGroup(e),this.commands.push(e)}addOption(e){this._registerOption(e);let r=e.name(),n=e.attributeName();if(e.negate){let o=e.long.replace(/^--no-/,"--");this._findOption(o)||this.setOptionValueWithSource(n,e.defaultValue===void 0?!0:e.defaultValue,"default")}else e.defaultValue!==void 0&&this.setOptionValueWithSource(n,e.defaultValue,"default");let i=(o,s,a)=>{o==null&&e.presetArg!==void 0&&(o=e.presetArg);let c=this.getOptionValue(n);o!==null&&e.parseArg?o=this._callParseArg(e,o,c,s):o!==null&&e.variadic&&(o=e._collectValue(o,c)),o==null&&(e.negate?o=!1:e.isBoolean()||e.optional?o=!0:o=""),this.setOptionValueWithSource(n,o,a)};return this.on("option:"+r,o=>{let s=`error: option '${e.flags}' argument '${o}' is invalid.`;i(o,s,"cli")}),e.envVar&&this.on("optionEnv:"+r,o=>{let s=`error: option '${e.flags}' value '${o}' from env '${e.envVar}' is invalid.`;i(o,s,"env")}),this}_optionEx(e,r,n,i,o){if(typeof r=="object"&&r instanceof w4)throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");let s=this.createOption(r,n);if(s.makeOptionMandatory(!!e.mandatory),typeof i=="function")s.default(o).argParser(i);else if(i instanceof RegExp){let a=i;i=(c,l)=>{let u=a.exec(c);return u?u[0]:l},s.default(o).argParser(i)}else s.default(i);return this.addOption(s)}option(e,r,n,i){return this._optionEx({},e,r,n,i)}requiredOption(e,r,n,i){return this._optionEx({mandatory:!0},e,r,n,i)}combineFlagAndOptionalValue(e=!0){return this._combineFlagAndOptionalValue=!!e,this}allowUnknownOption(e=!0){return this._allowUnknownOption=!!e,this}allowExcessArguments(e=!0){return this._allowExcessArguments=!!e,this}enablePositionalOptions(e=!0){return this._enablePositionalOptions=!!e,this}passThroughOptions(e=!0){return this._passThroughOptions=!!e,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties(e=!0){if(this.options.length)throw new Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw new Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!e,this}getOptionValue(e){return this._storeOptionsAsProperties?this[e]:this._optionValues[e]}setOptionValue(e,r){return this.setOptionValueWithSource(e,r,void 0)}setOptionValueWithSource(e,r,n){return this._storeOptionsAsProperties?this[e]=r:this._optionValues[e]=r,this._optionValueSources[e]=n,this}getOptionValueSource(e){return this._optionValueSources[e]}getOptionValueSourceWithGlobals(e){let r;return this._getCommandAndAncestors().forEach(n=>{n.getOptionValueSource(e)!==void 0&&(r=n.getOptionValueSource(e))}),r}_prepareUserArgs(e,r){if(e!==void 0&&!Array.isArray(e))throw new Error("first parameter to parse must be array or undefined");if(r=r||{},e===void 0&&r.from===void 0){Be.versions?.electron&&(r.from="electron");let i=Be.execArgv??[];(i.includes("-e")||i.includes("--eval")||i.includes("-p")||i.includes("--print"))&&(r.from="eval")}e===void 0&&(e=Be.argv),this.rawArgs=e.slice();let n;switch(r.from){case void 0:case"node":this._scriptPath=e[1],n=e.slice(2);break;case"electron":Be.defaultApp?(this._scriptPath=e[1],n=e.slice(2)):n=e.slice(1);break;case"user":n=e.slice(0);break;case"eval":n=e.slice(1);break;default:throw new Error(`unexpected parse option { from: '${r.from}' }`)}return!this._name&&this._scriptPath&&this.nameFromFilename(this._scriptPath),this._name=this._name||"program",n}parse(e,r){this._prepareForParse();let n=this._prepareUserArgs(e,r);return this._parseCommand([],n),this}async parseAsync(e,r){this._prepareForParse();let n=this._prepareUserArgs(e,r);return await this._parseCommand([],n),this}_prepareForParse(){this._savedState===null?this.saveStateBeforeParse():this.restoreStateBeforeParse()}saveStateBeforeParse(){this._savedState={_name:this._name,_optionValues:{...this._optionValues},_optionValueSources:{...this._optionValueSources}}}restoreStateBeforeParse(){if(this._storeOptionsAsProperties)throw new Error(`Can not call parse again when storeOptionsAsProperties is true. -- either make a new Command for each call to parse, or stop storing options as properties`);this._name=this._savedState._name,this._scriptPath=null,this.rawArgs=[],this._optionValues={...this._savedState._optionValues},this._optionValueSources={...this._savedState._optionValueSources},this.args=[],this.processedArgs=[]}_checkForMissingExecutable(e,r,n){if(Ay.existsSync(e))return;let i=r?`searched for local subcommand relative to directory '${r}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",o=`'${e}' does not exist +(Did you mean ${n[0]}?)`:""}N4.suggestSimilar=Wfe});var z4=v(rO=>{var Kfe=Ze("node:events").EventEmitter,XA=Ze("node:child_process"),mo=Ze("node:path"),Ry=Ze("node:fs"),He=Ze("node:process"),{Argument:Jfe,humanReadableArgName:Yfe}=Ty(),{CommanderError:QA}=ff(),{Help:Xfe,stripColor:Qfe}=VA(),{Option:M4,DualOptions:epe}=YA(),{suggestSimilar:F4}=j4(),eO=class t extends Kfe{constructor(e){super(),this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!1,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=e||"",this._optionValues={},this._optionValueSources={},this._storeOptionsAsProperties=!1,this._actionHandler=null,this._executableHandler=!1,this._executableFile=null,this._executableDir=null,this._defaultCommandName=null,this._exitCallback=null,this._aliases=[],this._combineFlagAndOptionalValue=!0,this._description="",this._summary="",this._argsDescription=void 0,this._enablePositionalOptions=!1,this._passThroughOptions=!1,this._lifeCycleHooks={},this._showHelpAfterError=!1,this._showSuggestionAfterError=!0,this._savedState=null,this._outputConfiguration={writeOut:r=>He.stdout.write(r),writeErr:r=>He.stderr.write(r),outputError:(r,n)=>n(r),getOutHelpWidth:()=>He.stdout.isTTY?He.stdout.columns:void 0,getErrHelpWidth:()=>He.stderr.isTTY?He.stderr.columns:void 0,getOutHasColors:()=>tO()??(He.stdout.isTTY&&He.stdout.hasColors?.()),getErrHasColors:()=>tO()??(He.stderr.isTTY&&He.stderr.hasColors?.()),stripColor:r=>Qfe(r)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={},this._helpGroupHeading=void 0,this._defaultCommandGroup=void 0,this._defaultOptionGroup=void 0}copyInheritedSettings(e){return this._outputConfiguration=e._outputConfiguration,this._helpOption=e._helpOption,this._helpCommand=e._helpCommand,this._helpConfiguration=e._helpConfiguration,this._exitCallback=e._exitCallback,this._storeOptionsAsProperties=e._storeOptionsAsProperties,this._combineFlagAndOptionalValue=e._combineFlagAndOptionalValue,this._allowExcessArguments=e._allowExcessArguments,this._enablePositionalOptions=e._enablePositionalOptions,this._showHelpAfterError=e._showHelpAfterError,this._showSuggestionAfterError=e._showSuggestionAfterError,this}_getCommandAndAncestors(){let e=[];for(let r=this;r;r=r.parent)e.push(r);return e}command(e,r,n){let i=r,o=n;typeof i=="object"&&i!==null&&(o=i,i=null),o=o||{};let[,s,a]=e.match(/([^ ]+) *(.*)/),c=this.createCommand(s);return i&&(c.description(i),c._executableHandler=!0),o.isDefault&&(this._defaultCommandName=c._name),c._hidden=!!(o.noHelp||o.hidden),c._executableFile=o.executableFile||null,a&&c.arguments(a),this._registerCommand(c),c.parent=this,c.copyInheritedSettings(this),i?this:c}createCommand(e){return new t(e)}createHelp(){return Object.assign(new Xfe,this.configureHelp())}configureHelp(e){return e===void 0?this._helpConfiguration:(this._helpConfiguration=e,this)}configureOutput(e){return e===void 0?this._outputConfiguration:(this._outputConfiguration={...this._outputConfiguration,...e},this)}showHelpAfterError(e=!0){return typeof e!="string"&&(e=!!e),this._showHelpAfterError=e,this}showSuggestionAfterError(e=!0){return this._showSuggestionAfterError=!!e,this}addCommand(e,r){if(!e._name)throw new Error(`Command passed to .addCommand() must have a name +- specify the name in Command constructor or using .name()`);return r=r||{},r.isDefault&&(this._defaultCommandName=e._name),(r.noHelp||r.hidden)&&(e._hidden=!0),this._registerCommand(e),e.parent=this,e._checkForBrokenPassThrough(),this}createArgument(e,r){return new Jfe(e,r)}argument(e,r,n,i){let o=this.createArgument(e,r);return typeof n=="function"?o.default(i).argParser(n):o.default(n),this.addArgument(o),this}arguments(e){return e.trim().split(/ +/).forEach(r=>{this.argument(r)}),this}addArgument(e){let r=this.registeredArguments.slice(-1)[0];if(r?.variadic)throw new Error(`only the last argument can be variadic '${r.name()}'`);if(e.required&&e.defaultValue!==void 0&&e.parseArg===void 0)throw new Error(`a default value for a required argument is never used: '${e.name()}'`);return this.registeredArguments.push(e),this}helpCommand(e,r){if(typeof e=="boolean")return this._addImplicitHelpCommand=e,e&&this._defaultCommandGroup&&this._initCommandGroup(this._getHelpCommand()),this;let n=e??"help [command]",[,i,o]=n.match(/([^ ]+) *(.*)/),s=r??"display help for command",a=this.createCommand(i);return a.helpOption(!1),o&&a.arguments(o),s&&a.description(s),this._addImplicitHelpCommand=!0,this._helpCommand=a,(e||r)&&this._initCommandGroup(a),this}addHelpCommand(e,r){return typeof e!="object"?(this.helpCommand(e,r),this):(this._addImplicitHelpCommand=!0,this._helpCommand=e,this._initCommandGroup(e),this)}_getHelpCommand(){return this._addImplicitHelpCommand??(this.commands.length&&!this._actionHandler&&!this._findCommand("help"))?(this._helpCommand===void 0&&this.helpCommand(void 0,void 0),this._helpCommand):null}hook(e,r){let n=["preSubcommand","preAction","postAction"];if(!n.includes(e))throw new Error(`Unexpected value for event passed to hook : '${e}'. +Expecting one of '${n.join("', '")}'`);return this._lifeCycleHooks[e]?this._lifeCycleHooks[e].push(r):this._lifeCycleHooks[e]=[r],this}exitOverride(e){return e?this._exitCallback=e:this._exitCallback=r=>{if(r.code!=="commander.executeSubCommandAsync")throw r},this}_exit(e,r,n){this._exitCallback&&this._exitCallback(new QA(e,r,n)),He.exit(e)}action(e){let r=n=>{let i=this.registeredArguments.length,o=n.slice(0,i);return this._storeOptionsAsProperties?o[i]=this:o[i]=this.opts(),o.push(this),e.apply(this,o)};return this._actionHandler=r,this}createOption(e,r){return new M4(e,r)}_callParseArg(e,r,n,i){try{return e.parseArg(r,n)}catch(o){if(o.code==="commander.invalidArgument"){let s=`${i} ${o.message}`;this.error(s,{exitCode:o.exitCode,code:o.code})}throw o}}_registerOption(e){let r=e.short&&this._findOption(e.short)||e.long&&this._findOption(e.long);if(r){let n=e.long&&this._findOption(e.long)?e.long:e.short;throw new Error(`Cannot add option '${e.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${n}' +- already used by option '${r.flags}'`)}this._initOptionGroup(e),this.options.push(e)}_registerCommand(e){let r=i=>[i.name()].concat(i.aliases()),n=r(e).find(i=>this._findCommand(i));if(n){let i=r(this._findCommand(n)).join("|"),o=r(e).join("|");throw new Error(`cannot add command '${o}' as already have command '${i}'`)}this._initCommandGroup(e),this.commands.push(e)}addOption(e){this._registerOption(e);let r=e.name(),n=e.attributeName();if(e.negate){let o=e.long.replace(/^--no-/,"--");this._findOption(o)||this.setOptionValueWithSource(n,e.defaultValue===void 0?!0:e.defaultValue,"default")}else e.defaultValue!==void 0&&this.setOptionValueWithSource(n,e.defaultValue,"default");let i=(o,s,a)=>{o==null&&e.presetArg!==void 0&&(o=e.presetArg);let c=this.getOptionValue(n);o!==null&&e.parseArg?o=this._callParseArg(e,o,c,s):o!==null&&e.variadic&&(o=e._collectValue(o,c)),o==null&&(e.negate?o=!1:e.isBoolean()||e.optional?o=!0:o=""),this.setOptionValueWithSource(n,o,a)};return this.on("option:"+r,o=>{let s=`error: option '${e.flags}' argument '${o}' is invalid.`;i(o,s,"cli")}),e.envVar&&this.on("optionEnv:"+r,o=>{let s=`error: option '${e.flags}' value '${o}' from env '${e.envVar}' is invalid.`;i(o,s,"env")}),this}_optionEx(e,r,n,i,o){if(typeof r=="object"&&r instanceof M4)throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");let s=this.createOption(r,n);if(s.makeOptionMandatory(!!e.mandatory),typeof i=="function")s.default(o).argParser(i);else if(i instanceof RegExp){let a=i;i=(c,l)=>{let u=a.exec(c);return u?u[0]:l},s.default(o).argParser(i)}else s.default(i);return this.addOption(s)}option(e,r,n,i){return this._optionEx({},e,r,n,i)}requiredOption(e,r,n,i){return this._optionEx({mandatory:!0},e,r,n,i)}combineFlagAndOptionalValue(e=!0){return this._combineFlagAndOptionalValue=!!e,this}allowUnknownOption(e=!0){return this._allowUnknownOption=!!e,this}allowExcessArguments(e=!0){return this._allowExcessArguments=!!e,this}enablePositionalOptions(e=!0){return this._enablePositionalOptions=!!e,this}passThroughOptions(e=!0){return this._passThroughOptions=!!e,this._checkForBrokenPassThrough(),this}_checkForBrokenPassThrough(){if(this.parent&&this._passThroughOptions&&!this.parent._enablePositionalOptions)throw new Error(`passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`)}storeOptionsAsProperties(e=!0){if(this.options.length)throw new Error("call .storeOptionsAsProperties() before adding options");if(Object.keys(this._optionValues).length)throw new Error("call .storeOptionsAsProperties() before setting option values");return this._storeOptionsAsProperties=!!e,this}getOptionValue(e){return this._storeOptionsAsProperties?this[e]:this._optionValues[e]}setOptionValue(e,r){return this.setOptionValueWithSource(e,r,void 0)}setOptionValueWithSource(e,r,n){return this._storeOptionsAsProperties?this[e]=r:this._optionValues[e]=r,this._optionValueSources[e]=n,this}getOptionValueSource(e){return this._optionValueSources[e]}getOptionValueSourceWithGlobals(e){let r;return this._getCommandAndAncestors().forEach(n=>{n.getOptionValueSource(e)!==void 0&&(r=n.getOptionValueSource(e))}),r}_prepareUserArgs(e,r){if(e!==void 0&&!Array.isArray(e))throw new Error("first parameter to parse must be array or undefined");if(r=r||{},e===void 0&&r.from===void 0){He.versions?.electron&&(r.from="electron");let i=He.execArgv??[];(i.includes("-e")||i.includes("--eval")||i.includes("-p")||i.includes("--print"))&&(r.from="eval")}e===void 0&&(e=He.argv),this.rawArgs=e.slice();let n;switch(r.from){case void 0:case"node":this._scriptPath=e[1],n=e.slice(2);break;case"electron":He.defaultApp?(this._scriptPath=e[1],n=e.slice(2)):n=e.slice(1);break;case"user":n=e.slice(0);break;case"eval":n=e.slice(1);break;default:throw new Error(`unexpected parse option { from: '${r.from}' }`)}return!this._name&&this._scriptPath&&this.nameFromFilename(this._scriptPath),this._name=this._name||"program",n}parse(e,r){this._prepareForParse();let n=this._prepareUserArgs(e,r);return this._parseCommand([],n),this}async parseAsync(e,r){this._prepareForParse();let n=this._prepareUserArgs(e,r);return await this._parseCommand([],n),this}_prepareForParse(){this._savedState===null?this.saveStateBeforeParse():this.restoreStateBeforeParse()}saveStateBeforeParse(){this._savedState={_name:this._name,_optionValues:{...this._optionValues},_optionValueSources:{...this._optionValueSources}}}restoreStateBeforeParse(){if(this._storeOptionsAsProperties)throw new Error(`Can not call parse again when storeOptionsAsProperties is true. +- either make a new Command for each call to parse, or stop storing options as properties`);this._name=this._savedState._name,this._scriptPath=null,this.rawArgs=[],this._optionValues={...this._savedState._optionValues},this._optionValueSources={...this._savedState._optionValueSources},this.args=[],this.processedArgs=[]}_checkForMissingExecutable(e,r,n){if(Ry.existsSync(e))return;let i=r?`searched for local subcommand relative to directory '${r}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",o=`'${e}' does not exist - if '${n}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead - if the default executable name is not suitable, use the executableFile option to supply a custom name or path - - ${i}`;throw new Error(o)}_executeSubCommand(e,r){r=r.slice();let n=!1,i=[".js",".ts",".tsx",".mjs",".cjs"];function o(u,d){let f=po.resolve(u,d);if(Ay.existsSync(f))return f;if(i.includes(po.extname(d)))return;let p=i.find(m=>Ay.existsSync(`${f}${m}`));if(p)return`${f}${p}`}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let s=e._executableFile||`${this._name}-${e._name}`,a=this._executableDir||"";if(this._scriptPath){let u;try{u=Ay.realpathSync(this._scriptPath)}catch{u=this._scriptPath}a=po.resolve(po.dirname(u),a)}if(a){let u=o(a,s);if(!u&&!e._executableFile&&this._scriptPath){let d=po.basename(this._scriptPath,po.extname(this._scriptPath));d!==this._name&&(u=o(a,`${d}-${e._name}`))}s=u||s}n=i.includes(po.extname(s));let c;Be.platform!=="win32"?n?(r.unshift(s),r=$4(Be.execArgv).concat(r),c=HA.spawn(Be.argv[0],r,{stdio:"inherit"})):c=HA.spawn(s,r,{stdio:"inherit"}):(this._checkForMissingExecutable(s,a,e._name),r.unshift(s),r=$4(Be.execArgv).concat(r),c=HA.spawn(Be.execPath,r,{stdio:"inherit"})),c.killed||["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach(d=>{Be.on(d,()=>{c.killed===!1&&c.exitCode===null&&c.kill(d)})});let l=this._exitCallback;c.on("close",u=>{u=u??1,l?l(new GA(u,"commander.executeSubCommandAsync","(close)")):Be.exit(u)}),c.on("error",u=>{if(u.code==="ENOENT")this._checkForMissingExecutable(s,a,e._name);else if(u.code==="EACCES")throw new Error(`'${s}' not executable`);if(!l)Be.exit(1);else{let d=new GA(1,"commander.executeSubCommandAsync","(error)");d.nestedError=u,l(d)}}),this.runningCommand=c}_dispatchSubcommand(e,r,n){let i=this._findCommand(e);i||this.help({error:!0}),i._prepareForParse();let o;return o=this._chainOrCallSubCommandHook(o,i,"preSubcommand"),o=this._chainOrCall(o,()=>{if(i._executableHandler)this._executeSubCommand(i,r.concat(n));else return i._parseCommand(r,n)}),o}_dispatchHelpCommand(e){e||this.help();let r=this._findCommand(e);return r&&!r._executableHandler&&r.help(),this._dispatchSubcommand(e,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){this.registeredArguments.forEach((e,r)=>{e.required&&this.args[r]==null&&this.missingArgument(e.name())}),!(this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)&&this.args.length>this.registeredArguments.length&&this._excessArguments(this.args)}_processArguments(){let e=(n,i,o)=>{let s=i;if(i!==null&&n.parseArg){let a=`error: command-argument value '${i}' is invalid for argument '${n.name()}'.`;s=this._callParseArg(n,i,o,a)}return s};this._checkNumberOfArguments();let r=[];this.registeredArguments.forEach((n,i)=>{let o=n.defaultValue;n.variadic?ie(n,a,s),n.defaultValue))):o===void 0&&(o=[]):ir()):r()}_chainOrCallHooks(e,r){let n=e,i=[];return this._getCommandAndAncestors().reverse().filter(o=>o._lifeCycleHooks[r]!==void 0).forEach(o=>{o._lifeCycleHooks[r].forEach(s=>{i.push({hookedCommand:o,callback:s})})}),r==="postAction"&&i.reverse(),i.forEach(o=>{n=this._chainOrCall(n,()=>o.callback(o.hookedCommand,this))}),n}_chainOrCallSubCommandHook(e,r,n){let i=e;return this._lifeCycleHooks[n]!==void 0&&this._lifeCycleHooks[n].forEach(o=>{i=this._chainOrCall(i,()=>o(this,r))}),i}_parseCommand(e,r){let n=this.parseOptions(r);if(this._parseOptionsEnv(),this._parseOptionsImplied(),e=e.concat(n.operands),r=n.unknown,this.args=e.concat(r),e&&this._findCommand(e[0]))return this._dispatchSubcommand(e[0],e.slice(1),r);if(this._getHelpCommand()&&e[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(e[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(r),this._dispatchSubcommand(this._defaultCommandName,e,r);this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName&&this.help({error:!0}),this._outputHelpIfRequested(n.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let i=()=>{n.unknown.length>0&&this.unknownOption(n.unknown[0])},o=`command:${this.name()}`;if(this._actionHandler){i(),this._processArguments();let s;return s=this._chainOrCallHooks(s,"preAction"),s=this._chainOrCall(s,()=>this._actionHandler(this.processedArgs)),this.parent&&(s=this._chainOrCall(s,()=>{this.parent.emit(o,e,r)})),s=this._chainOrCallHooks(s,"postAction"),s}if(this.parent?.listenerCount(o))i(),this._processArguments(),this.parent.emit(o,e,r);else if(e.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",e,r);this.listenerCount("command:*")?this.emit("command:*",e,r):this.commands.length?this.unknownCommand():(i(),this._processArguments())}else this.commands.length?(i(),this.help({error:!0})):(i(),this._processArguments())}_findCommand(e){if(e)return this.commands.find(r=>r._name===e||r._aliases.includes(e))}_findOption(e){return this.options.find(r=>r.is(e))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach(e=>{e.options.forEach(r=>{r.mandatory&&e.getOptionValue(r.attributeName())===void 0&&e.missingMandatoryOptionValue(r)})})}_checkForConflictingLocalOptions(){let e=this.options.filter(n=>{let i=n.attributeName();return this.getOptionValue(i)===void 0?!1:this.getOptionValueSource(i)!=="default"});e.filter(n=>n.conflictsWith.length>0).forEach(n=>{let i=e.find(o=>n.conflictsWith.includes(o.attributeName()));i&&this._conflictingOption(n,i)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach(e=>{e._checkForConflictingLocalOptions()})}parseOptions(e){let r=[],n=[],i=r;function o(u){return u.length>1&&u[0]==="-"}let s=u=>/^-(\d+|\d*\.\d+)(e[+-]?\d+)?$/.test(u)?!this._getCommandAndAncestors().some(d=>d.options.map(f=>f.short).some(f=>/^-\d$/.test(f))):!1,a=null,c=null,l=0;for(;l2&&u[0]==="-"&&u[1]!=="-"){let d=this._findOption(`-${u[1]}`);if(d){d.required||d.optional&&this._combineFlagAndOptionalValue?this.emit(`option:${d.name()}`,u.slice(2)):(this.emit(`option:${d.name()}`),c=`-${u.slice(2)}`);continue}}if(/^--[^=]+=/.test(u)){let d=u.indexOf("="),f=this._findOption(u.slice(0,d));if(f&&(f.required||f.optional)){this.emit(`option:${f.name()}`,u.slice(d+1));continue}}if(i===r&&o(u)&&!(this.commands.length===0&&s(u))&&(i=n),(this._enablePositionalOptions||this._passThroughOptions)&&r.length===0&&n.length===0){if(this._findCommand(u)){r.push(u),n.push(...e.slice(l));break}else if(this._getHelpCommand()&&u===this._getHelpCommand().name()){r.push(u,...e.slice(l));break}else if(this._defaultCommandName){n.push(u,...e.slice(l));break}}if(this._passThroughOptions){i.push(u,...e.slice(l));break}i.push(u)}return{operands:r,unknown:n}}opts(){if(this._storeOptionsAsProperties){let e={},r=this.options.length;for(let n=0;nObject.assign(e,r.opts()),{})}error(e,r){this._outputConfiguration.outputError(`${e} + - ${i}`;throw new Error(o)}_executeSubCommand(e,r){r=r.slice();let n=!1,i=[".js",".ts",".tsx",".mjs",".cjs"];function o(u,d){let f=mo.resolve(u,d);if(Ry.existsSync(f))return f;if(i.includes(mo.extname(d)))return;let p=i.find(m=>Ry.existsSync(`${f}${m}`));if(p)return`${f}${p}`}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let s=e._executableFile||`${this._name}-${e._name}`,a=this._executableDir||"";if(this._scriptPath){let u;try{u=Ry.realpathSync(this._scriptPath)}catch{u=this._scriptPath}a=mo.resolve(mo.dirname(u),a)}if(a){let u=o(a,s);if(!u&&!e._executableFile&&this._scriptPath){let d=mo.basename(this._scriptPath,mo.extname(this._scriptPath));d!==this._name&&(u=o(a,`${d}-${e._name}`))}s=u||s}n=i.includes(mo.extname(s));let c;He.platform!=="win32"?n?(r.unshift(s),r=L4(He.execArgv).concat(r),c=XA.spawn(He.argv[0],r,{stdio:"inherit"})):c=XA.spawn(s,r,{stdio:"inherit"}):(this._checkForMissingExecutable(s,a,e._name),r.unshift(s),r=L4(He.execArgv).concat(r),c=XA.spawn(He.execPath,r,{stdio:"inherit"})),c.killed||["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach(d=>{He.on(d,()=>{c.killed===!1&&c.exitCode===null&&c.kill(d)})});let l=this._exitCallback;c.on("close",u=>{u=u??1,l?l(new QA(u,"commander.executeSubCommandAsync","(close)")):He.exit(u)}),c.on("error",u=>{if(u.code==="ENOENT")this._checkForMissingExecutable(s,a,e._name);else if(u.code==="EACCES")throw new Error(`'${s}' not executable`);if(!l)He.exit(1);else{let d=new QA(1,"commander.executeSubCommandAsync","(error)");d.nestedError=u,l(d)}}),this.runningCommand=c}_dispatchSubcommand(e,r,n){let i=this._findCommand(e);i||this.help({error:!0}),i._prepareForParse();let o;return o=this._chainOrCallSubCommandHook(o,i,"preSubcommand"),o=this._chainOrCall(o,()=>{if(i._executableHandler)this._executeSubCommand(i,r.concat(n));else return i._parseCommand(r,n)}),o}_dispatchHelpCommand(e){e||this.help();let r=this._findCommand(e);return r&&!r._executableHandler&&r.help(),this._dispatchSubcommand(e,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){this.registeredArguments.forEach((e,r)=>{e.required&&this.args[r]==null&&this.missingArgument(e.name())}),!(this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)&&this.args.length>this.registeredArguments.length&&this._excessArguments(this.args)}_processArguments(){let e=(n,i,o)=>{let s=i;if(i!==null&&n.parseArg){let a=`error: command-argument value '${i}' is invalid for argument '${n.name()}'.`;s=this._callParseArg(n,i,o,a)}return s};this._checkNumberOfArguments();let r=[];this.registeredArguments.forEach((n,i)=>{let o=n.defaultValue;n.variadic?ie(n,a,s),n.defaultValue))):o===void 0&&(o=[]):ir()):r()}_chainOrCallHooks(e,r){let n=e,i=[];return this._getCommandAndAncestors().reverse().filter(o=>o._lifeCycleHooks[r]!==void 0).forEach(o=>{o._lifeCycleHooks[r].forEach(s=>{i.push({hookedCommand:o,callback:s})})}),r==="postAction"&&i.reverse(),i.forEach(o=>{n=this._chainOrCall(n,()=>o.callback(o.hookedCommand,this))}),n}_chainOrCallSubCommandHook(e,r,n){let i=e;return this._lifeCycleHooks[n]!==void 0&&this._lifeCycleHooks[n].forEach(o=>{i=this._chainOrCall(i,()=>o(this,r))}),i}_parseCommand(e,r){let n=this.parseOptions(r);if(this._parseOptionsEnv(),this._parseOptionsImplied(),e=e.concat(n.operands),r=n.unknown,this.args=e.concat(r),e&&this._findCommand(e[0]))return this._dispatchSubcommand(e[0],e.slice(1),r);if(this._getHelpCommand()&&e[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(e[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(r),this._dispatchSubcommand(this._defaultCommandName,e,r);this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName&&this.help({error:!0}),this._outputHelpIfRequested(n.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let i=()=>{n.unknown.length>0&&this.unknownOption(n.unknown[0])},o=`command:${this.name()}`;if(this._actionHandler){i(),this._processArguments();let s;return s=this._chainOrCallHooks(s,"preAction"),s=this._chainOrCall(s,()=>this._actionHandler(this.processedArgs)),this.parent&&(s=this._chainOrCall(s,()=>{this.parent.emit(o,e,r)})),s=this._chainOrCallHooks(s,"postAction"),s}if(this.parent?.listenerCount(o))i(),this._processArguments(),this.parent.emit(o,e,r);else if(e.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",e,r);this.listenerCount("command:*")?this.emit("command:*",e,r):this.commands.length?this.unknownCommand():(i(),this._processArguments())}else this.commands.length?(i(),this.help({error:!0})):(i(),this._processArguments())}_findCommand(e){if(e)return this.commands.find(r=>r._name===e||r._aliases.includes(e))}_findOption(e){return this.options.find(r=>r.is(e))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach(e=>{e.options.forEach(r=>{r.mandatory&&e.getOptionValue(r.attributeName())===void 0&&e.missingMandatoryOptionValue(r)})})}_checkForConflictingLocalOptions(){let e=this.options.filter(n=>{let i=n.attributeName();return this.getOptionValue(i)===void 0?!1:this.getOptionValueSource(i)!=="default"});e.filter(n=>n.conflictsWith.length>0).forEach(n=>{let i=e.find(o=>n.conflictsWith.includes(o.attributeName()));i&&this._conflictingOption(n,i)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach(e=>{e._checkForConflictingLocalOptions()})}parseOptions(e){let r=[],n=[],i=r;function o(u){return u.length>1&&u[0]==="-"}let s=u=>/^-(\d+|\d*\.\d+)(e[+-]?\d+)?$/.test(u)?!this._getCommandAndAncestors().some(d=>d.options.map(f=>f.short).some(f=>/^-\d$/.test(f))):!1,a=null,c=null,l=0;for(;l2&&u[0]==="-"&&u[1]!=="-"){let d=this._findOption(`-${u[1]}`);if(d){d.required||d.optional&&this._combineFlagAndOptionalValue?this.emit(`option:${d.name()}`,u.slice(2)):(this.emit(`option:${d.name()}`),c=`-${u.slice(2)}`);continue}}if(/^--[^=]+=/.test(u)){let d=u.indexOf("="),f=this._findOption(u.slice(0,d));if(f&&(f.required||f.optional)){this.emit(`option:${f.name()}`,u.slice(d+1));continue}}if(i===r&&o(u)&&!(this.commands.length===0&&s(u))&&(i=n),(this._enablePositionalOptions||this._passThroughOptions)&&r.length===0&&n.length===0){if(this._findCommand(u)){r.push(u),n.push(...e.slice(l));break}else if(this._getHelpCommand()&&u===this._getHelpCommand().name()){r.push(u,...e.slice(l));break}else if(this._defaultCommandName){n.push(u,...e.slice(l));break}}if(this._passThroughOptions){i.push(u,...e.slice(l));break}i.push(u)}return{operands:r,unknown:n}}opts(){if(this._storeOptionsAsProperties){let e={},r=this.options.length;for(let n=0;nObject.assign(e,r.opts()),{})}error(e,r){this._outputConfiguration.outputError(`${e} `,this._outputConfiguration.writeErr),typeof this._showHelpAfterError=="string"?this._outputConfiguration.writeErr(`${this._showHelpAfterError} `):this._showHelpAfterError&&(this._outputConfiguration.writeErr(` -`),this.outputHelp({error:!0}));let n=r||{},i=n.exitCode||1,o=n.code||"commander.error";this._exit(i,o,e)}_parseOptionsEnv(){this.options.forEach(e=>{if(e.envVar&&e.envVar in Be.env){let r=e.attributeName();(this.getOptionValue(r)===void 0||["default","config","env"].includes(this.getOptionValueSource(r)))&&(e.required||e.optional?this.emit(`optionEnv:${e.name()}`,Be.env[e.envVar]):this.emit(`optionEnv:${e.name()}`))}})}_parseOptionsImplied(){let e=new hfe(this.options),r=n=>this.getOptionValue(n)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(n));this.options.filter(n=>n.implied!==void 0&&r(n.attributeName())&&e.valueFromOption(this.getOptionValue(n.attributeName()),n)).forEach(n=>{Object.keys(n.implied).filter(i=>!r(i)).forEach(i=>{this.setOptionValueWithSource(i,n.implied[i],"implied")})})}missingArgument(e){let r=`error: missing required argument '${e}'`;this.error(r,{code:"commander.missingArgument"})}optionMissingArgument(e){let r=`error: option '${e.flags}' argument missing`;this.error(r,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(e){let r=`error: required option '${e.flags}' not specified`;this.error(r,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(e,r){let n=s=>{let a=s.attributeName(),c=this.getOptionValue(a),l=this.options.find(d=>d.negate&&a===d.attributeName()),u=this.options.find(d=>!d.negate&&a===d.attributeName());return l&&(l.presetArg===void 0&&c===!1||l.presetArg!==void 0&&c===l.presetArg)?l:u||s},i=s=>{let a=n(s),c=a.attributeName();return this.getOptionValueSource(c)==="env"?`environment variable '${a.envVar}'`:`option '${a.flags}'`},o=`error: ${i(e)} cannot be used with ${i(r)}`;this.error(o,{code:"commander.conflictingOption"})}unknownOption(e){if(this._allowUnknownOption)return;let r="";if(e.startsWith("--")&&this._showSuggestionAfterError){let i=[],o=this;do{let s=o.createHelp().visibleOptions(o).filter(a=>a.long).map(a=>a.long);i=i.concat(s),o=o.parent}while(o&&!o._enablePositionalOptions);r=x4(e,i)}let n=`error: unknown option '${e}'${r}`;this.error(n,{code:"commander.unknownOption"})}_excessArguments(e){if(this._allowExcessArguments)return;let r=this.registeredArguments.length,n=r===1?"":"s",o=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${r} argument${n} but got ${e.length}.`;this.error(o,{code:"commander.excessArguments"})}unknownCommand(){let e=this.args[0],r="";if(this._showSuggestionAfterError){let i=[];this.createHelp().visibleCommands(this).forEach(o=>{i.push(o.name()),o.alias()&&i.push(o.alias())}),r=x4(e,i)}let n=`error: unknown command '${e}'${r}`;this.error(n,{code:"commander.unknownCommand"})}version(e,r,n){if(e===void 0)return this._version;this._version=e,r=r||"-V, --version",n=n||"output the version number";let i=this.createOption(r,n);return this._versionOptionName=i.attributeName(),this._registerOption(i),this.on("option:"+i.name(),()=>{this._outputConfiguration.writeOut(`${e} -`),this._exit(0,"commander.version",e)}),this}description(e,r){return e===void 0&&r===void 0?this._description:(this._description=e,r&&(this._argsDescription=r),this)}summary(e){return e===void 0?this._summary:(this._summary=e,this)}alias(e){if(e===void 0)return this._aliases[0];let r=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler&&(r=this.commands[this.commands.length-1]),e===r._name)throw new Error("Command alias can't be the same as its name");let n=this.parent?._findCommand(e);if(n){let i=[n.name()].concat(n.aliases()).join("|");throw new Error(`cannot add alias '${e}' to command '${this.name()}' as already have command '${i}'`)}return r._aliases.push(e),this}aliases(e){return e===void 0?this._aliases:(e.forEach(r=>this.alias(r)),this)}usage(e){if(e===void 0){if(this._usage)return this._usage;let r=this.registeredArguments.map(n=>ffe(n));return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?r:[]).join(" ")}return this._usage=e,this}name(e){return e===void 0?this._name:(this._name=e,this)}helpGroup(e){return e===void 0?this._helpGroupHeading??"":(this._helpGroupHeading=e,this)}commandsGroup(e){return e===void 0?this._defaultCommandGroup??"":(this._defaultCommandGroup=e,this)}optionsGroup(e){return e===void 0?this._defaultOptionGroup??"":(this._defaultOptionGroup=e,this)}_initOptionGroup(e){this._defaultOptionGroup&&!e.helpGroupHeading&&e.helpGroup(this._defaultOptionGroup)}_initCommandGroup(e){this._defaultCommandGroup&&!e.helpGroup()&&e.helpGroup(this._defaultCommandGroup)}nameFromFilename(e){return this._name=po.basename(e,po.extname(e)),this}executableDir(e){return e===void 0?this._executableDir:(this._executableDir=e,this)}helpInformation(e){let r=this.createHelp(),n=this._getOutputContext(e);r.prepareContext({error:n.error,helpWidth:n.helpWidth,outputHasColors:n.hasColors});let i=r.formatHelp(this,r);return n.hasColors?i:this._outputConfiguration.stripColor(i)}_getOutputContext(e){e=e||{};let r=!!e.error,n,i,o;return r?(n=a=>this._outputConfiguration.writeErr(a),i=this._outputConfiguration.getErrHasColors(),o=this._outputConfiguration.getErrHelpWidth()):(n=a=>this._outputConfiguration.writeOut(a),i=this._outputConfiguration.getOutHasColors(),o=this._outputConfiguration.getOutHelpWidth()),{error:r,write:a=>(i||(a=this._outputConfiguration.stripColor(a)),n(a)),hasColors:i,helpWidth:o}}outputHelp(e){let r;typeof e=="function"&&(r=e,e=void 0);let n=this._getOutputContext(e),i={error:n.error,write:n.write,command:this};this._getCommandAndAncestors().reverse().forEach(s=>s.emit("beforeAllHelp",i)),this.emit("beforeHelp",i);let o=this.helpInformation({error:n.error});if(r&&(o=r(o),typeof o!="string"&&!Buffer.isBuffer(o)))throw new Error("outputHelp callback must return a string or a Buffer");n.write(o),this._getHelpOption()?.long&&this.emit(this._getHelpOption().long),this.emit("afterHelp",i),this._getCommandAndAncestors().forEach(s=>s.emit("afterAllHelp",i))}helpOption(e,r){return typeof e=="boolean"?(e?(this._helpOption===null&&(this._helpOption=void 0),this._defaultOptionGroup&&this._initOptionGroup(this._getHelpOption())):this._helpOption=null,this):(this._helpOption=this.createOption(e??"-h, --help",r??"display help for command"),(e||r)&&this._initOptionGroup(this._helpOption),this)}_getHelpOption(){return this._helpOption===void 0&&this.helpOption(void 0,void 0),this._helpOption}addHelpOption(e){return this._helpOption=e,this._initOptionGroup(e),this}help(e){this.outputHelp(e);let r=Number(Be.exitCode??0);r===0&&e&&typeof e!="function"&&e.error&&(r=1),this._exit(r,"commander.help","(outputHelp)")}addHelpText(e,r){let n=["beforeAll","before","after","afterAll"];if(!n.includes(e))throw new Error(`Unexpected value for position to addHelpText. +`),this.outputHelp({error:!0}));let n=r||{},i=n.exitCode||1,o=n.code||"commander.error";this._exit(i,o,e)}_parseOptionsEnv(){this.options.forEach(e=>{if(e.envVar&&e.envVar in He.env){let r=e.attributeName();(this.getOptionValue(r)===void 0||["default","config","env"].includes(this.getOptionValueSource(r)))&&(e.required||e.optional?this.emit(`optionEnv:${e.name()}`,He.env[e.envVar]):this.emit(`optionEnv:${e.name()}`))}})}_parseOptionsImplied(){let e=new epe(this.options),r=n=>this.getOptionValue(n)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(n));this.options.filter(n=>n.implied!==void 0&&r(n.attributeName())&&e.valueFromOption(this.getOptionValue(n.attributeName()),n)).forEach(n=>{Object.keys(n.implied).filter(i=>!r(i)).forEach(i=>{this.setOptionValueWithSource(i,n.implied[i],"implied")})})}missingArgument(e){let r=`error: missing required argument '${e}'`;this.error(r,{code:"commander.missingArgument"})}optionMissingArgument(e){let r=`error: option '${e.flags}' argument missing`;this.error(r,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(e){let r=`error: required option '${e.flags}' not specified`;this.error(r,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(e,r){let n=s=>{let a=s.attributeName(),c=this.getOptionValue(a),l=this.options.find(d=>d.negate&&a===d.attributeName()),u=this.options.find(d=>!d.negate&&a===d.attributeName());return l&&(l.presetArg===void 0&&c===!1||l.presetArg!==void 0&&c===l.presetArg)?l:u||s},i=s=>{let a=n(s),c=a.attributeName();return this.getOptionValueSource(c)==="env"?`environment variable '${a.envVar}'`:`option '${a.flags}'`},o=`error: ${i(e)} cannot be used with ${i(r)}`;this.error(o,{code:"commander.conflictingOption"})}unknownOption(e){if(this._allowUnknownOption)return;let r="";if(e.startsWith("--")&&this._showSuggestionAfterError){let i=[],o=this;do{let s=o.createHelp().visibleOptions(o).filter(a=>a.long).map(a=>a.long);i=i.concat(s),o=o.parent}while(o&&!o._enablePositionalOptions);r=F4(e,i)}let n=`error: unknown option '${e}'${r}`;this.error(n,{code:"commander.unknownOption"})}_excessArguments(e){if(this._allowExcessArguments)return;let r=this.registeredArguments.length,n=r===1?"":"s",o=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${r} argument${n} but got ${e.length}.`;this.error(o,{code:"commander.excessArguments"})}unknownCommand(){let e=this.args[0],r="";if(this._showSuggestionAfterError){let i=[];this.createHelp().visibleCommands(this).forEach(o=>{i.push(o.name()),o.alias()&&i.push(o.alias())}),r=F4(e,i)}let n=`error: unknown command '${e}'${r}`;this.error(n,{code:"commander.unknownCommand"})}version(e,r,n){if(e===void 0)return this._version;this._version=e,r=r||"-V, --version",n=n||"output the version number";let i=this.createOption(r,n);return this._versionOptionName=i.attributeName(),this._registerOption(i),this.on("option:"+i.name(),()=>{this._outputConfiguration.writeOut(`${e} +`),this._exit(0,"commander.version",e)}),this}description(e,r){return e===void 0&&r===void 0?this._description:(this._description=e,r&&(this._argsDescription=r),this)}summary(e){return e===void 0?this._summary:(this._summary=e,this)}alias(e){if(e===void 0)return this._aliases[0];let r=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler&&(r=this.commands[this.commands.length-1]),e===r._name)throw new Error("Command alias can't be the same as its name");let n=this.parent?._findCommand(e);if(n){let i=[n.name()].concat(n.aliases()).join("|");throw new Error(`cannot add alias '${e}' to command '${this.name()}' as already have command '${i}'`)}return r._aliases.push(e),this}aliases(e){return e===void 0?this._aliases:(e.forEach(r=>this.alias(r)),this)}usage(e){if(e===void 0){if(this._usage)return this._usage;let r=this.registeredArguments.map(n=>Yfe(n));return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?r:[]).join(" ")}return this._usage=e,this}name(e){return e===void 0?this._name:(this._name=e,this)}helpGroup(e){return e===void 0?this._helpGroupHeading??"":(this._helpGroupHeading=e,this)}commandsGroup(e){return e===void 0?this._defaultCommandGroup??"":(this._defaultCommandGroup=e,this)}optionsGroup(e){return e===void 0?this._defaultOptionGroup??"":(this._defaultOptionGroup=e,this)}_initOptionGroup(e){this._defaultOptionGroup&&!e.helpGroupHeading&&e.helpGroup(this._defaultOptionGroup)}_initCommandGroup(e){this._defaultCommandGroup&&!e.helpGroup()&&e.helpGroup(this._defaultCommandGroup)}nameFromFilename(e){return this._name=mo.basename(e,mo.extname(e)),this}executableDir(e){return e===void 0?this._executableDir:(this._executableDir=e,this)}helpInformation(e){let r=this.createHelp(),n=this._getOutputContext(e);r.prepareContext({error:n.error,helpWidth:n.helpWidth,outputHasColors:n.hasColors});let i=r.formatHelp(this,r);return n.hasColors?i:this._outputConfiguration.stripColor(i)}_getOutputContext(e){e=e||{};let r=!!e.error,n,i,o;return r?(n=a=>this._outputConfiguration.writeErr(a),i=this._outputConfiguration.getErrHasColors(),o=this._outputConfiguration.getErrHelpWidth()):(n=a=>this._outputConfiguration.writeOut(a),i=this._outputConfiguration.getOutHasColors(),o=this._outputConfiguration.getOutHelpWidth()),{error:r,write:a=>(i||(a=this._outputConfiguration.stripColor(a)),n(a)),hasColors:i,helpWidth:o}}outputHelp(e){let r;typeof e=="function"&&(r=e,e=void 0);let n=this._getOutputContext(e),i={error:n.error,write:n.write,command:this};this._getCommandAndAncestors().reverse().forEach(s=>s.emit("beforeAllHelp",i)),this.emit("beforeHelp",i);let o=this.helpInformation({error:n.error});if(r&&(o=r(o),typeof o!="string"&&!Buffer.isBuffer(o)))throw new Error("outputHelp callback must return a string or a Buffer");n.write(o),this._getHelpOption()?.long&&this.emit(this._getHelpOption().long),this.emit("afterHelp",i),this._getCommandAndAncestors().forEach(s=>s.emit("afterAllHelp",i))}helpOption(e,r){return typeof e=="boolean"?(e?(this._helpOption===null&&(this._helpOption=void 0),this._defaultOptionGroup&&this._initOptionGroup(this._getHelpOption())):this._helpOption=null,this):(this._helpOption=this.createOption(e??"-h, --help",r??"display help for command"),(e||r)&&this._initOptionGroup(this._helpOption),this)}_getHelpOption(){return this._helpOption===void 0&&this.helpOption(void 0,void 0),this._helpOption}addHelpOption(e){return this._helpOption=e,this._initOptionGroup(e),this}help(e){this.outputHelp(e);let r=Number(He.exitCode??0);r===0&&e&&typeof e!="function"&&e.error&&(r=1),this._exit(r,"commander.help","(outputHelp)")}addHelpText(e,r){let n=["beforeAll","before","after","afterAll"];if(!n.includes(e))throw new Error(`Unexpected value for position to addHelpText. Expecting one of '${n.join("', '")}'`);let i=`${e}Help`;return this.on(i,o=>{let s;typeof r=="function"?s=r({error:o.error,command:o.command}):s=r,s&&o.write(`${s} -`)}),this}_outputHelpIfRequested(e){let r=this._getHelpOption();r&&e.find(i=>r.is(i))&&(this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)"))}};function $4(t){return t.map(e=>{if(!e.startsWith("--inspect"))return e;let r,n="127.0.0.1",i="9229",o;return(o=e.match(/^(--inspect(-brk)?)$/))!==null?r=o[1]:(o=e.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null?(r=o[1],/^\d+$/.test(o[3])?i=o[3]:n=o[3]):(o=e.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null&&(r=o[1],n=o[3],i=o[4]),r&&i!=="0"?`${r}=${n}:${parseInt(i)+1}`:e})}function VA(){if(Be.env.NO_COLOR||Be.env.FORCE_COLOR==="0"||Be.env.FORCE_COLOR==="false")return!1;if(Be.env.FORCE_COLOR||Be.env.CLICOLOR_FORCE!==void 0)return!0}WA.Command=ZA;WA.useColor=VA});var O4=v(Tn=>{var{Argument:E4}=Ey(),{Command:KA}=k4(),{CommanderError:gfe,InvalidArgumentError:A4}=lf(),{Help:yfe}=LA(),{Option:T4}=BA();Tn.program=new KA;Tn.createCommand=t=>new KA(t);Tn.createOption=(t,e)=>new T4(t,e);Tn.createArgument=(t,e)=>new E4(t,e);Tn.Command=KA;Tn.Option=T4;Tn.Argument=E4;Tn.Help=yfe;Tn.CommanderError=gfe;Tn.InvalidArgumentError=A4;Tn.InvalidOptionArgumentError=A4});var De=v(Qt=>{"use strict";var YA=Symbol.for("yaml.alias"),C4=Symbol.for("yaml.document"),Ty=Symbol.for("yaml.map"),D4=Symbol.for("yaml.pair"),XA=Symbol.for("yaml.scalar"),Oy=Symbol.for("yaml.seq"),mo=Symbol.for("yaml.node.type"),xfe=t=>!!t&&typeof t=="object"&&t[mo]===YA,$fe=t=>!!t&&typeof t=="object"&&t[mo]===C4,kfe=t=>!!t&&typeof t=="object"&&t[mo]===Ty,Efe=t=>!!t&&typeof t=="object"&&t[mo]===D4,N4=t=>!!t&&typeof t=="object"&&t[mo]===XA,Afe=t=>!!t&&typeof t=="object"&&t[mo]===Oy;function j4(t){if(t&&typeof t=="object")switch(t[mo]){case Ty:case Oy:return!0}return!1}function Tfe(t){if(t&&typeof t=="object")switch(t[mo]){case YA:case Ty:case XA:case Oy:return!0}return!1}var Ofe=t=>(N4(t)||j4(t))&&!!t.anchor;Qt.ALIAS=YA;Qt.DOC=C4;Qt.MAP=Ty;Qt.NODE_TYPE=mo;Qt.PAIR=D4;Qt.SCALAR=XA;Qt.SEQ=Oy;Qt.hasAnchor=Ofe;Qt.isAlias=xfe;Qt.isCollection=j4;Qt.isDocument=$fe;Qt.isMap=kfe;Qt.isNode=Tfe;Qt.isPair=Efe;Qt.isScalar=N4;Qt.isSeq=Afe});var uf=v(QA=>{"use strict";var Ut=De(),Nr=Symbol("break visit"),M4=Symbol("skip children"),Ti=Symbol("remove node");function Ry(t,e){let r=F4(e);Ut.isDocument(t)?tl(null,t.contents,r,Object.freeze([t]))===Ti&&(t.contents=null):tl(null,t,r,Object.freeze([]))}Ry.BREAK=Nr;Ry.SKIP=M4;Ry.REMOVE=Ti;function tl(t,e,r,n){let i=L4(t,e,r,n);if(Ut.isNode(i)||Ut.isPair(i))return z4(t,n,i),tl(t,i,r,n);if(typeof i!="symbol"){if(Ut.isCollection(e)){n=Object.freeze(n.concat(e));for(let o=0;o{"use strict";var U4=De(),Rfe=uf(),Ife={"!":"%21",",":"%2C","[":"%5B","]":"%5D","{":"%7B","}":"%7D"},Pfe=t=>t.replace(/[!,[\]{}]/g,e=>Ife[e]),df=class t{constructor(e,r){this.docStart=null,this.docEnd=!1,this.yaml=Object.assign({},t.defaultYaml,e),this.tags=Object.assign({},t.defaultTags,r)}clone(){let e=new t(this.yaml,this.tags);return e.docStart=this.docStart,e}atDocument(){let e=new t(this.yaml,this.tags);switch(this.yaml.version){case"1.1":this.atNextDocument=!0;break;case"1.2":this.atNextDocument=!1,this.yaml={explicit:t.defaultYaml.explicit,version:"1.2"},this.tags=Object.assign({},t.defaultTags);break}return e}add(e,r){this.atNextDocument&&(this.yaml={explicit:t.defaultYaml.explicit,version:"1.1"},this.tags=Object.assign({},t.defaultTags),this.atNextDocument=!1);let n=e.trim().split(/[ \t]+/),i=n.shift();switch(i){case"%TAG":{if(n.length!==2&&(r(0,"%TAG directive should contain exactly two parts"),n.length<2))return!1;let[o,s]=n;return this.tags[o]=s,!0}case"%YAML":{if(this.yaml.explicit=!0,n.length!==1)return r(0,"%YAML directive should contain exactly one part"),!1;let[o]=n;if(o==="1.1"||o==="1.2")return this.yaml.version=o,!0;{let s=/^\d+\.\d+$/.test(o);return r(6,`Unsupported YAML version ${o}`,s),!1}}default:return r(0,`Unknown directive ${i}`,!0),!1}}tagName(e,r){if(e==="!")return"!";if(e[0]!=="!")return r(`Not a valid tag: ${e}`),null;if(e[1]==="<"){let s=e.slice(2,-1);return s==="!"||s==="!!"?(r(`Verbatim tags aren't resolved, so ${e} is invalid.`),null):(e[e.length-1]!==">"&&r("Verbatim tags must end with a >"),s)}let[,n,i]=e.match(/^(.*!)([^!]*)$/s);i||r(`The ${e} tag has no suffix`);let o=this.tags[n];if(o)try{return o+decodeURIComponent(i)}catch(s){return r(String(s)),null}return n==="!"?e:(r(`Could not resolve tag: ${e}`),null)}tagString(e){for(let[r,n]of Object.entries(this.tags))if(e.startsWith(n))return r+Pfe(e.substring(n.length));return e[0]==="!"?e:`!<${e}>`}toString(e){let r=this.yaml.explicit?[`%YAML ${this.yaml.version||"1.2"}`]:[],n=Object.entries(this.tags),i;if(e&&n.length>0&&U4.isNode(e.contents)){let o={};Rfe.visit(e.contents,(s,a)=>{U4.isNode(a)&&a.tag&&(o[a.tag]=!0)}),i=Object.keys(o)}else i=[];for(let[o,s]of n)o==="!!"&&s==="tag:yaml.org,2002:"||(!e||i.some(a=>a.startsWith(s)))&&r.push(`%TAG ${o} ${s}`);return r.join(` -`)}};df.defaultYaml={explicit:!1,version:"1.2"};df.defaultTags={"!!":"tag:yaml.org,2002:"};q4.Directives=df});var Py=v(ff=>{"use strict";var B4=De(),Cfe=uf();function Dfe(t){if(/[\x00-\x19\s,[\]{}]/.test(t)){let r=`Anchor must not contain whitespace or control characters: ${JSON.stringify(t)}`;throw new Error(r)}return!0}function H4(t){let e=new Set;return Cfe.visit(t,{Value(r,n){n.anchor&&e.add(n.anchor)}}),e}function G4(t,e){for(let r=1;;++r){let n=`${t}${r}`;if(!e.has(n))return n}}function Nfe(t,e){let r=[],n=new Map,i=null;return{onAnchor:o=>{r.push(o),i??(i=H4(t));let s=G4(e,i);return i.add(s),s},setAnchors:()=>{for(let o of r){let s=n.get(o);if(typeof s=="object"&&s.anchor&&(B4.isScalar(s.node)||B4.isCollection(s.node)))s.node.anchor=s.anchor;else{let a=new Error("Failed to resolve repeated object (this should not happen)");throw a.source=o,a}}},sourceObjects:n}}ff.anchorIsValid=Dfe;ff.anchorNames=H4;ff.createNodeAnchors=Nfe;ff.findNewAnchor=G4});var tT=v(Z4=>{"use strict";function pf(t,e,r,n){if(n&&typeof n=="object")if(Array.isArray(n))for(let i=0,o=n.length;i{"use strict";var jfe=De();function V4(t,e,r){if(Array.isArray(t))return t.map((n,i)=>V4(n,String(i),r));if(t&&typeof t.toJSON=="function"){if(!r||!jfe.hasAnchor(t))return t.toJSON(e,r);let n={aliasCount:0,count:1,res:void 0};r.anchors.set(t,n),r.onCreate=o=>{n.res=o,delete r.onCreate};let i=t.toJSON(e,r);return r.onCreate&&r.onCreate(i),i}return typeof t=="bigint"&&!r?.keep?Number(t):t}W4.toJS=V4});var Cy=v(J4=>{"use strict";var Mfe=tT(),K4=De(),Ffe=Vo(),rT=class{constructor(e){Object.defineProperty(this,K4.NODE_TYPE,{value:e})}clone(){let e=Object.create(Object.getPrototypeOf(this),Object.getOwnPropertyDescriptors(this));return this.range&&(e.range=this.range.slice()),e}toJS(e,{mapAsMap:r,maxAliasCount:n,onAnchor:i,reviver:o}={}){if(!K4.isDocument(e))throw new TypeError("A document argument is required");let s={anchors:new Map,doc:e,keep:!0,mapAsMap:r===!0,mapKeyWarned:!1,maxAliasCount:typeof n=="number"?n:100},a=Ffe.toJS(this,"",s);if(typeof i=="function")for(let{count:c,res:l}of s.anchors.values())i(l,c);return typeof o=="function"?Mfe.applyReviver(o,{"":a},"",a):a}};J4.NodeBase=rT});var mf=v(Y4=>{"use strict";var Lfe=Py(),zfe=uf(),nl=De(),Ufe=Cy(),qfe=Vo(),nT=class extends Ufe.NodeBase{constructor(e){super(nl.ALIAS),this.source=e,Object.defineProperty(this,"tag",{set(){throw new Error("Alias nodes cannot have tags")}})}resolve(e,r){if(r?.maxAliasCount===0)throw new ReferenceError("Alias resolution is disabled");let n;r?.aliasResolveCache?n=r.aliasResolveCache:(n=[],zfe.visit(e,{Node:(o,s)=>{(nl.isAlias(s)||nl.hasAnchor(s))&&n.push(s)}}),r&&(r.aliasResolveCache=n));let i;for(let o of n){if(o===this)break;o.anchor===this.source&&(i=o)}return i}toJSON(e,r){if(!r)return{source:this.source};let{anchors:n,doc:i,maxAliasCount:o}=r,s=this.resolve(i,r);if(!s){let c=`Unresolved alias (the anchor must be set before the alias): ${this.source}`;throw new ReferenceError(c)}let a=n.get(s);if(a||(qfe.toJS(s,null,r),a=n.get(s)),a?.res===void 0){let c="This should not happen: Alias anchor was not resolved?";throw new ReferenceError(c)}if(o>=0&&(a.count+=1,a.aliasCount===0&&(a.aliasCount=Dy(i,s,n)),a.count*a.aliasCount>o)){let c="Excessive alias count indicates a resource exhaustion attack";throw new ReferenceError(c)}return a.res}toString(e,r,n){let i=`*${this.source}`;if(e){if(Lfe.anchorIsValid(this.source),e.options.verifyAliasOrder&&!e.anchors.has(this.source)){let o=`Unresolved alias (the anchor must be set before the alias): ${this.source}`;throw new Error(o)}if(e.implicitKey)return`${i} `}return i}};function Dy(t,e,r){if(nl.isAlias(e)){let n=e.resolve(t),i=r&&n&&r.get(n);return i?i.count*i.aliasCount:0}else if(nl.isCollection(e)){let n=0;for(let i of e.items){let o=Dy(t,i,r);o>n&&(n=o)}return n}else if(nl.isPair(e)){let n=Dy(t,e.key,r),i=Dy(t,e.value,r);return Math.max(n,i)}return 1}Y4.Alias=nT});var Dt=v(iT=>{"use strict";var Bfe=De(),Hfe=Cy(),Gfe=Vo(),Zfe=t=>!t||typeof t!="function"&&typeof t!="object",Wo=class extends Hfe.NodeBase{constructor(e){super(Bfe.SCALAR),this.value=e}toJSON(e,r){return r?.keep?this.value:Gfe.toJS(this.value,e,r)}toString(){return String(this.value)}};Wo.BLOCK_FOLDED="BLOCK_FOLDED";Wo.BLOCK_LITERAL="BLOCK_LITERAL";Wo.PLAIN="PLAIN";Wo.QUOTE_DOUBLE="QUOTE_DOUBLE";Wo.QUOTE_SINGLE="QUOTE_SINGLE";iT.Scalar=Wo;iT.isScalarValue=Zfe});var hf=v(Q4=>{"use strict";var Vfe=mf(),fa=De(),X4=Dt(),Wfe="tag:yaml.org,2002:";function Kfe(t,e,r){if(e){let n=r.filter(o=>o.tag===e),i=n.find(o=>!o.format)??n[0];if(!i)throw new Error(`Tag ${e} not found`);return i}return r.find(n=>n.identify?.(t)&&!n.format)}function Jfe(t,e,r){if(fa.isDocument(t)&&(t=t.contents),fa.isNode(t))return t;if(fa.isPair(t)){let d=r.schema[fa.MAP].createNode?.(r.schema,null,r);return d.items.push(t),d}(t instanceof String||t instanceof Number||t instanceof Boolean||typeof BigInt<"u"&&t instanceof BigInt)&&(t=t.valueOf());let{aliasDuplicateObjects:n,onAnchor:i,onTagObj:o,schema:s,sourceObjects:a}=r,c;if(n&&t&&typeof t=="object"){if(c=a.get(t),c)return c.anchor??(c.anchor=i(t)),new Vfe.Alias(c.anchor);c={anchor:null,node:null},a.set(t,c)}e?.startsWith("!!")&&(e=Wfe+e.slice(2));let l=Kfe(t,e,s.tags);if(!l){if(t&&typeof t.toJSON=="function"&&(t=t.toJSON()),!t||typeof t!="object"){let d=new X4.Scalar(t);return c&&(c.node=d),d}l=t instanceof Map?s[fa.MAP]:Symbol.iterator in Object(t)?s[fa.SEQ]:s[fa.MAP]}o&&(o(l),delete r.onTagObj);let u=l?.createNode?l.createNode(r.schema,t,r):typeof l?.nodeClass?.from=="function"?l.nodeClass.from(r.schema,t,r):new X4.Scalar(t);return e?u.tag=e:l.default||(u.tag=l.tag),c&&(c.node=u),u}Q4.createNode=Jfe});var jy=v(Ny=>{"use strict";var Yfe=hf(),Oi=De(),Xfe=Cy();function oT(t,e,r){let n=r;for(let i=e.length-1;i>=0;--i){let o=e[i];if(typeof o=="number"&&Number.isInteger(o)&&o>=0){let s=[];s[o]=n,n=s}else n=new Map([[o,n]])}return Yfe.createNode(n,void 0,{aliasDuplicateObjects:!1,keepUndefined:!1,onAnchor:()=>{throw new Error("This should not happen, please report a bug.")},schema:t,sourceObjects:new Map})}var e6=t=>t==null||typeof t=="object"&&!!t[Symbol.iterator]().next().done,sT=class extends Xfe.NodeBase{constructor(e,r){super(e),Object.defineProperty(this,"schema",{value:r,configurable:!0,enumerable:!1,writable:!0})}clone(e){let r=Object.create(Object.getPrototypeOf(this),Object.getOwnPropertyDescriptors(this));return e&&(r.schema=e),r.items=r.items.map(n=>Oi.isNode(n)||Oi.isPair(n)?n.clone(e):n),this.range&&(r.range=this.range.slice()),r}addIn(e,r){if(e6(e))this.add(r);else{let[n,...i]=e,o=this.get(n,!0);if(Oi.isCollection(o))o.addIn(i,r);else if(o===void 0&&this.schema)this.set(n,oT(this.schema,i,r));else throw new Error(`Expected YAML collection at ${n}. Remaining path: ${i}`)}}deleteIn(e){let[r,...n]=e;if(n.length===0)return this.delete(r);let i=this.get(r,!0);if(Oi.isCollection(i))return i.deleteIn(n);throw new Error(`Expected YAML collection at ${r}. Remaining path: ${n}`)}getIn(e,r){let[n,...i]=e,o=this.get(n,!0);return i.length===0?!r&&Oi.isScalar(o)?o.value:o:Oi.isCollection(o)?o.getIn(i,r):void 0}hasAllNullValues(e){return this.items.every(r=>{if(!Oi.isPair(r))return!1;let n=r.value;return n==null||e&&Oi.isScalar(n)&&n.value==null&&!n.commentBefore&&!n.comment&&!n.tag})}hasIn(e){let[r,...n]=e;if(n.length===0)return this.has(r);let i=this.get(r,!0);return Oi.isCollection(i)?i.hasIn(n):!1}setIn(e,r){let[n,...i]=e;if(i.length===0)this.set(n,r);else{let o=this.get(n,!0);if(Oi.isCollection(o))o.setIn(i,r);else if(o===void 0&&this.schema)this.set(n,oT(this.schema,i,r));else throw new Error(`Expected YAML collection at ${n}. Remaining path: ${i}`)}}};Ny.Collection=sT;Ny.collectionFromPath=oT;Ny.isEmptyPath=e6});var gf=v(My=>{"use strict";var Qfe=t=>t.replace(/^(?!$)(?: $)?/gm,"#");function aT(t,e){return/^\n+$/.test(t)?t.substring(1):e?t.replace(/^(?! *$)/gm,e):t}var epe=(t,e,r)=>t.endsWith(` -`)?aT(r,e):r.includes(` +`)}),this}_outputHelpIfRequested(e){let r=this._getHelpOption();r&&e.find(i=>r.is(i))&&(this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)"))}};function L4(t){return t.map(e=>{if(!e.startsWith("--inspect"))return e;let r,n="127.0.0.1",i="9229",o;return(o=e.match(/^(--inspect(-brk)?)$/))!==null?r=o[1]:(o=e.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null?(r=o[1],/^\d+$/.test(o[3])?i=o[3]:n=o[3]):(o=e.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null&&(r=o[1],n=o[3],i=o[4]),r&&i!=="0"?`${r}=${n}:${parseInt(i)+1}`:e})}function tO(){if(He.env.NO_COLOR||He.env.FORCE_COLOR==="0"||He.env.FORCE_COLOR==="false")return!1;if(He.env.FORCE_COLOR||He.env.CLICOLOR_FORCE!==void 0)return!0}rO.Command=eO;rO.useColor=tO});var B4=v(Tn=>{var{Argument:U4}=Ty(),{Command:nO}=z4(),{CommanderError:tpe,InvalidArgumentError:q4}=ff(),{Help:rpe}=VA(),{Option:H4}=YA();Tn.program=new nO;Tn.createCommand=t=>new nO(t);Tn.createOption=(t,e)=>new H4(t,e);Tn.createArgument=(t,e)=>new U4(t,e);Tn.Command=nO;Tn.Option=H4;Tn.Argument=U4;Tn.Help=rpe;Tn.CommanderError=tpe;Tn.InvalidArgumentError=q4;Tn.InvalidOptionArgumentError=q4});var De=v(er=>{"use strict";var oO=Symbol.for("yaml.alias"),W4=Symbol.for("yaml.document"),Iy=Symbol.for("yaml.map"),K4=Symbol.for("yaml.pair"),sO=Symbol.for("yaml.scalar"),Py=Symbol.for("yaml.seq"),ho=Symbol.for("yaml.node.type"),cpe=t=>!!t&&typeof t=="object"&&t[ho]===oO,lpe=t=>!!t&&typeof t=="object"&&t[ho]===W4,upe=t=>!!t&&typeof t=="object"&&t[ho]===Iy,dpe=t=>!!t&&typeof t=="object"&&t[ho]===K4,J4=t=>!!t&&typeof t=="object"&&t[ho]===sO,fpe=t=>!!t&&typeof t=="object"&&t[ho]===Py;function Y4(t){if(t&&typeof t=="object")switch(t[ho]){case Iy:case Py:return!0}return!1}function ppe(t){if(t&&typeof t=="object")switch(t[ho]){case oO:case Iy:case sO:case Py:return!0}return!1}var mpe=t=>(J4(t)||Y4(t))&&!!t.anchor;er.ALIAS=oO;er.DOC=W4;er.MAP=Iy;er.NODE_TYPE=ho;er.PAIR=K4;er.SCALAR=sO;er.SEQ=Py;er.hasAnchor=mpe;er.isAlias=cpe;er.isCollection=Y4;er.isDocument=lpe;er.isMap=upe;er.isNode=ppe;er.isPair=dpe;er.isScalar=J4;er.isSeq=fpe});var pf=v(aO=>{"use strict";var Ut=De(),jr=Symbol("break visit"),X4=Symbol("skip children"),Oi=Symbol("remove node");function Cy(t,e){let r=Q4(e);Ut.isDocument(t)?il(null,t.contents,r,Object.freeze([t]))===Oi&&(t.contents=null):il(null,t,r,Object.freeze([]))}Cy.BREAK=jr;Cy.SKIP=X4;Cy.REMOVE=Oi;function il(t,e,r,n){let i=eH(t,e,r,n);if(Ut.isNode(i)||Ut.isPair(i))return tH(t,n,i),il(t,i,r,n);if(typeof i!="symbol"){if(Ut.isCollection(e)){n=Object.freeze(n.concat(e));for(let o=0;o{"use strict";var rH=De(),hpe=pf(),gpe={"!":"%21",",":"%2C","[":"%5B","]":"%5D","{":"%7B","}":"%7D"},ype=t=>t.replace(/[!,[\]{}]/g,e=>gpe[e]),mf=class t{constructor(e,r){this.docStart=null,this.docEnd=!1,this.yaml=Object.assign({},t.defaultYaml,e),this.tags=Object.assign({},t.defaultTags,r)}clone(){let e=new t(this.yaml,this.tags);return e.docStart=this.docStart,e}atDocument(){let e=new t(this.yaml,this.tags);switch(this.yaml.version){case"1.1":this.atNextDocument=!0;break;case"1.2":this.atNextDocument=!1,this.yaml={explicit:t.defaultYaml.explicit,version:"1.2"},this.tags=Object.assign({},t.defaultTags);break}return e}add(e,r){this.atNextDocument&&(this.yaml={explicit:t.defaultYaml.explicit,version:"1.1"},this.tags=Object.assign({},t.defaultTags),this.atNextDocument=!1);let n=e.trim().split(/[ \t]+/),i=n.shift();switch(i){case"%TAG":{if(n.length!==2&&(r(0,"%TAG directive should contain exactly two parts"),n.length<2))return!1;let[o,s]=n;return this.tags[o]=s,!0}case"%YAML":{if(this.yaml.explicit=!0,n.length!==1)return r(0,"%YAML directive should contain exactly one part"),!1;let[o]=n;if(o==="1.1"||o==="1.2")return this.yaml.version=o,!0;{let s=/^\d+\.\d+$/.test(o);return r(6,`Unsupported YAML version ${o}`,s),!1}}default:return r(0,`Unknown directive ${i}`,!0),!1}}tagName(e,r){if(e==="!")return"!";if(e[0]!=="!")return r(`Not a valid tag: ${e}`),null;if(e[1]==="<"){let s=e.slice(2,-1);return s==="!"||s==="!!"?(r(`Verbatim tags aren't resolved, so ${e} is invalid.`),null):(e[e.length-1]!==">"&&r("Verbatim tags must end with a >"),s)}let[,n,i]=e.match(/^(.*!)([^!]*)$/s);i||r(`The ${e} tag has no suffix`);let o=this.tags[n];if(o)try{return o+decodeURIComponent(i)}catch(s){return r(String(s)),null}return n==="!"?e:(r(`Could not resolve tag: ${e}`),null)}tagString(e){for(let[r,n]of Object.entries(this.tags))if(e.startsWith(n))return r+ype(e.substring(n.length));return e[0]==="!"?e:`!<${e}>`}toString(e){let r=this.yaml.explicit?[`%YAML ${this.yaml.version||"1.2"}`]:[],n=Object.entries(this.tags),i;if(e&&n.length>0&&rH.isNode(e.contents)){let o={};hpe.visit(e.contents,(s,a)=>{rH.isNode(a)&&a.tag&&(o[a.tag]=!0)}),i=Object.keys(o)}else i=[];for(let[o,s]of n)o==="!!"&&s==="tag:yaml.org,2002:"||(!e||i.some(a=>a.startsWith(s)))&&r.push(`%TAG ${o} ${s}`);return r.join(` +`)}};mf.defaultYaml={explicit:!1,version:"1.2"};mf.defaultTags={"!!":"tag:yaml.org,2002:"};nH.Directives=mf});var Ny=v(hf=>{"use strict";var iH=De(),_pe=pf();function bpe(t){if(/[\x00-\x19\s,[\]{}]/.test(t)){let r=`Anchor must not contain whitespace or control characters: ${JSON.stringify(t)}`;throw new Error(r)}return!0}function oH(t){let e=new Set;return _pe.visit(t,{Value(r,n){n.anchor&&e.add(n.anchor)}}),e}function sH(t,e){for(let r=1;;++r){let n=`${t}${r}`;if(!e.has(n))return n}}function vpe(t,e){let r=[],n=new Map,i=null;return{onAnchor:o=>{r.push(o),i??(i=oH(t));let s=sH(e,i);return i.add(s),s},setAnchors:()=>{for(let o of r){let s=n.get(o);if(typeof s=="object"&&s.anchor&&(iH.isScalar(s.node)||iH.isCollection(s.node)))s.node.anchor=s.anchor;else{let a=new Error("Failed to resolve repeated object (this should not happen)");throw a.source=o,a}}},sourceObjects:n}}hf.anchorIsValid=bpe;hf.anchorNames=oH;hf.createNodeAnchors=vpe;hf.findNewAnchor=sH});var lO=v(aH=>{"use strict";function gf(t,e,r,n){if(n&&typeof n=="object")if(Array.isArray(n))for(let i=0,o=n.length;i{"use strict";var Spe=De();function cH(t,e,r){if(Array.isArray(t))return t.map((n,i)=>cH(n,String(i),r));if(t&&typeof t.toJSON=="function"){if(!r||!Spe.hasAnchor(t))return t.toJSON(e,r);let n={aliasCount:0,count:1,res:void 0};r.anchors.set(t,n),r.onCreate=o=>{n.res=o,delete r.onCreate};let i=t.toJSON(e,r);return r.onCreate&&r.onCreate(i),i}return typeof t=="bigint"&&!r?.keep?Number(t):t}lH.toJS=cH});var jy=v(dH=>{"use strict";var wpe=lO(),uH=De(),xpe=Wo(),uO=class{constructor(e){Object.defineProperty(this,uH.NODE_TYPE,{value:e})}clone(){let e=Object.create(Object.getPrototypeOf(this),Object.getOwnPropertyDescriptors(this));return this.range&&(e.range=this.range.slice()),e}toJS(e,{mapAsMap:r,maxAliasCount:n,onAnchor:i,reviver:o}={}){if(!uH.isDocument(e))throw new TypeError("A document argument is required");let s={anchors:new Map,doc:e,keep:!0,mapAsMap:r===!0,mapKeyWarned:!1,maxAliasCount:typeof n=="number"?n:100},a=xpe.toJS(this,"",s);if(typeof i=="function")for(let{count:c,res:l}of s.anchors.values())i(l,c);return typeof o=="function"?wpe.applyReviver(o,{"":a},"",a):a}};dH.NodeBase=uO});var yf=v(fH=>{"use strict";var $pe=Ny(),kpe=pf(),sl=De(),Epe=jy(),Ape=Wo(),dO=class extends Epe.NodeBase{constructor(e){super(sl.ALIAS),this.source=e,Object.defineProperty(this,"tag",{set(){throw new Error("Alias nodes cannot have tags")}})}resolve(e,r){if(r?.maxAliasCount===0)throw new ReferenceError("Alias resolution is disabled");let n;r?.aliasResolveCache?n=r.aliasResolveCache:(n=[],kpe.visit(e,{Node:(o,s)=>{(sl.isAlias(s)||sl.hasAnchor(s))&&n.push(s)}}),r&&(r.aliasResolveCache=n));let i;for(let o of n){if(o===this)break;o.anchor===this.source&&(i=o)}return i}toJSON(e,r){if(!r)return{source:this.source};let{anchors:n,doc:i,maxAliasCount:o}=r,s=this.resolve(i,r);if(!s){let c=`Unresolved alias (the anchor must be set before the alias): ${this.source}`;throw new ReferenceError(c)}let a=n.get(s);if(a||(Ape.toJS(s,null,r),a=n.get(s)),a?.res===void 0){let c="This should not happen: Alias anchor was not resolved?";throw new ReferenceError(c)}if(o>=0&&(a.count+=1,a.aliasCount===0&&(a.aliasCount=My(i,s,n)),a.count*a.aliasCount>o)){let c="Excessive alias count indicates a resource exhaustion attack";throw new ReferenceError(c)}return a.res}toString(e,r,n){let i=`*${this.source}`;if(e){if($pe.anchorIsValid(this.source),e.options.verifyAliasOrder&&!e.anchors.has(this.source)){let o=`Unresolved alias (the anchor must be set before the alias): ${this.source}`;throw new Error(o)}if(e.implicitKey)return`${i} `}return i}};function My(t,e,r){if(sl.isAlias(e)){let n=e.resolve(t),i=r&&n&&r.get(n);return i?i.count*i.aliasCount:0}else if(sl.isCollection(e)){let n=0;for(let i of e.items){let o=My(t,i,r);o>n&&(n=o)}return n}else if(sl.isPair(e)){let n=My(t,e.key,r),i=My(t,e.value,r);return Math.max(n,i)}return 1}fH.Alias=dO});var Dt=v(fO=>{"use strict";var Ope=De(),Tpe=jy(),Rpe=Wo(),Ipe=t=>!t||typeof t!="function"&&typeof t!="object",Ko=class extends Tpe.NodeBase{constructor(e){super(Ope.SCALAR),this.value=e}toJSON(e,r){return r?.keep?this.value:Rpe.toJS(this.value,e,r)}toString(){return String(this.value)}};Ko.BLOCK_FOLDED="BLOCK_FOLDED";Ko.BLOCK_LITERAL="BLOCK_LITERAL";Ko.PLAIN="PLAIN";Ko.QUOTE_DOUBLE="QUOTE_DOUBLE";Ko.QUOTE_SINGLE="QUOTE_SINGLE";fO.Scalar=Ko;fO.isScalarValue=Ipe});var _f=v(mH=>{"use strict";var Ppe=yf(),ha=De(),pH=Dt(),Cpe="tag:yaml.org,2002:";function Dpe(t,e,r){if(e){let n=r.filter(o=>o.tag===e),i=n.find(o=>!o.format)??n[0];if(!i)throw new Error(`Tag ${e} not found`);return i}return r.find(n=>n.identify?.(t)&&!n.format)}function Npe(t,e,r){if(ha.isDocument(t)&&(t=t.contents),ha.isNode(t))return t;if(ha.isPair(t)){let d=r.schema[ha.MAP].createNode?.(r.schema,null,r);return d.items.push(t),d}(t instanceof String||t instanceof Number||t instanceof Boolean||typeof BigInt<"u"&&t instanceof BigInt)&&(t=t.valueOf());let{aliasDuplicateObjects:n,onAnchor:i,onTagObj:o,schema:s,sourceObjects:a}=r,c;if(n&&t&&typeof t=="object"){if(c=a.get(t),c)return c.anchor??(c.anchor=i(t)),new Ppe.Alias(c.anchor);c={anchor:null,node:null},a.set(t,c)}e?.startsWith("!!")&&(e=Cpe+e.slice(2));let l=Dpe(t,e,s.tags);if(!l){if(t&&typeof t.toJSON=="function"&&(t=t.toJSON()),!t||typeof t!="object"){let d=new pH.Scalar(t);return c&&(c.node=d),d}l=t instanceof Map?s[ha.MAP]:Symbol.iterator in Object(t)?s[ha.SEQ]:s[ha.MAP]}o&&(o(l),delete r.onTagObj);let u=l?.createNode?l.createNode(r.schema,t,r):typeof l?.nodeClass?.from=="function"?l.nodeClass.from(r.schema,t,r):new pH.Scalar(t);return e?u.tag=e:l.default||(u.tag=l.tag),c&&(c.node=u),u}mH.createNode=Npe});var Ly=v(Fy=>{"use strict";var jpe=_f(),Ti=De(),Mpe=jy();function pO(t,e,r){let n=r;for(let i=e.length-1;i>=0;--i){let o=e[i];if(typeof o=="number"&&Number.isInteger(o)&&o>=0){let s=[];s[o]=n,n=s}else n=new Map([[o,n]])}return jpe.createNode(n,void 0,{aliasDuplicateObjects:!1,keepUndefined:!1,onAnchor:()=>{throw new Error("This should not happen, please report a bug.")},schema:t,sourceObjects:new Map})}var hH=t=>t==null||typeof t=="object"&&!!t[Symbol.iterator]().next().done,mO=class extends Mpe.NodeBase{constructor(e,r){super(e),Object.defineProperty(this,"schema",{value:r,configurable:!0,enumerable:!1,writable:!0})}clone(e){let r=Object.create(Object.getPrototypeOf(this),Object.getOwnPropertyDescriptors(this));return e&&(r.schema=e),r.items=r.items.map(n=>Ti.isNode(n)||Ti.isPair(n)?n.clone(e):n),this.range&&(r.range=this.range.slice()),r}addIn(e,r){if(hH(e))this.add(r);else{let[n,...i]=e,o=this.get(n,!0);if(Ti.isCollection(o))o.addIn(i,r);else if(o===void 0&&this.schema)this.set(n,pO(this.schema,i,r));else throw new Error(`Expected YAML collection at ${n}. Remaining path: ${i}`)}}deleteIn(e){let[r,...n]=e;if(n.length===0)return this.delete(r);let i=this.get(r,!0);if(Ti.isCollection(i))return i.deleteIn(n);throw new Error(`Expected YAML collection at ${r}. Remaining path: ${n}`)}getIn(e,r){let[n,...i]=e,o=this.get(n,!0);return i.length===0?!r&&Ti.isScalar(o)?o.value:o:Ti.isCollection(o)?o.getIn(i,r):void 0}hasAllNullValues(e){return this.items.every(r=>{if(!Ti.isPair(r))return!1;let n=r.value;return n==null||e&&Ti.isScalar(n)&&n.value==null&&!n.commentBefore&&!n.comment&&!n.tag})}hasIn(e){let[r,...n]=e;if(n.length===0)return this.has(r);let i=this.get(r,!0);return Ti.isCollection(i)?i.hasIn(n):!1}setIn(e,r){let[n,...i]=e;if(i.length===0)this.set(n,r);else{let o=this.get(n,!0);if(Ti.isCollection(o))o.setIn(i,r);else if(o===void 0&&this.schema)this.set(n,pO(this.schema,i,r));else throw new Error(`Expected YAML collection at ${n}. Remaining path: ${i}`)}}};Fy.Collection=mO;Fy.collectionFromPath=pO;Fy.isEmptyPath=hH});var bf=v(zy=>{"use strict";var Fpe=t=>t.replace(/^(?!$)(?: $)?/gm,"#");function hO(t,e){return/^\n+$/.test(t)?t.substring(1):e?t.replace(/^(?! *$)/gm,e):t}var Lpe=(t,e,r)=>t.endsWith(` +`)?hO(r,e):r.includes(` `)?` -`+aT(r,e):(t.endsWith(" ")?"":" ")+r;My.indentComment=aT;My.lineComment=epe;My.stringifyComment=Qfe});var r6=v(yf=>{"use strict";var tpe="flow",cT="block",Fy="quoted";function rpe(t,e,r="flow",{indentAtStart:n,lineWidth:i=80,minContentWidth:o=20,onFold:s,onOverflow:a}={}){if(!i||i<0)return t;ii-Math.max(2,o)?l.push(0):d=i-n);let f,p,m=!1,h=-1,g=-1,b=-1;r===cT&&(h=t6(t,h,e.length),h!==-1&&(d=h+c));for(let S;S=t[h+=1];){if(r===Fy&&S==="\\"){switch(g=h,t[h+1]){case"x":h+=3;break;case"u":h+=5;break;case"U":h+=9;break;default:h+=1}b=h}if(S===` -`)r===cT&&(h=t6(t,h,e.length)),d=h+e.length+c,f=void 0;else{if(S===" "&&p&&p!==" "&&p!==` +`+hO(r,e):(t.endsWith(" ")?"":" ")+r;zy.indentComment=hO;zy.lineComment=Lpe;zy.stringifyComment=Fpe});var yH=v(vf=>{"use strict";var zpe="flow",gO="block",Uy="quoted";function Upe(t,e,r="flow",{indentAtStart:n,lineWidth:i=80,minContentWidth:o=20,onFold:s,onOverflow:a}={}){if(!i||i<0)return t;ii-Math.max(2,o)?l.push(0):d=i-n);let f,p,m=!1,h=-1,g=-1,b=-1;r===gO&&(h=gH(t,h,e.length),h!==-1&&(d=h+c));for(let S;S=t[h+=1];){if(r===Uy&&S==="\\"){switch(g=h,t[h+1]){case"x":h+=3;break;case"u":h+=5;break;case"U":h+=9;break;default:h+=1}b=h}if(S===` +`)r===gO&&(h=gH(t,h,e.length)),d=h+e.length+c,f=void 0;else{if(S===" "&&p&&p!==" "&&p!==` `&&p!==" "){let x=t[h+1];x&&x!==" "&&x!==` -`&&x!==" "&&(f=h)}if(h>=d)if(f)l.push(f),d=f+c,f=void 0;else if(r===Fy){for(;p===" "||p===" ";)p=S,S=t[h+=1],m=!0;let x=h>b+1?h-2:g-1;if(u[x])return t;l.push(x),u[x]=!0,d=x+c,f=void 0}else m=!0}p=S}if(m&&a&&a(),l.length===0)return t;s&&s();let _=t.slice(0,l[0]);for(let S=0;S{"use strict";var Yn=Dt(),Ko=r6(),zy=(t,e)=>({indentAtStart:e?t.indent.length:t.indentAtStart,lineWidth:t.options.lineWidth,minContentWidth:t.options.minContentWidth}),Uy=t=>/^(%|---|\.\.\.)/m.test(t);function npe(t,e,r){if(!e||e<0)return!1;let n=e-r,i=t.length;if(i<=n)return!1;for(let o=0,s=0;on)return!0;if(s=o+1,i-s<=n)return!1}return!0}function _f(t,e){let r=JSON.stringify(t);if(e.options.doubleQuotedAsJSON)return r;let{implicitKey:n}=e,i=e.options.doubleQuotedMinMultiLineLength,o=e.indent||(Uy(t)?" ":""),s="",a=0;for(let c=0,l=r[c];l;l=r[++c])if(l===" "&&r[c+1]==="\\"&&r[c+2]==="n"&&(s+=r.slice(a,c)+"\\ ",c+=1,a=c,l="\\"),l==="\\")switch(r[c+1]){case"u":{s+=r.slice(a,c);let u=r.substr(c+2,4);switch(u){case"0000":s+="\\0";break;case"0007":s+="\\a";break;case"000b":s+="\\v";break;case"001b":s+="\\e";break;case"0085":s+="\\N";break;case"00a0":s+="\\_";break;case"2028":s+="\\L";break;case"2029":s+="\\P";break;default:u.substr(0,2)==="00"?s+="\\x"+u.substr(2):s+=r.substr(c,6)}c+=5,a=c+1}break;case"n":if(n||r[c+2]==='"'||r.length=d)if(f)l.push(f),d=f+c,f=void 0;else if(r===Uy){for(;p===" "||p===" ";)p=S,S=t[h+=1],m=!0;let x=h>b+1?h-2:g-1;if(u[x])return t;l.push(x),u[x]=!0,d=x+c,f=void 0}else m=!0}p=S}if(m&&a&&a(),l.length===0)return t;s&&s();let _=t.slice(0,l[0]);for(let S=0;S{"use strict";var Xn=Dt(),Jo=yH(),Hy=(t,e)=>({indentAtStart:e?t.indent.length:t.indentAtStart,lineWidth:t.options.lineWidth,minContentWidth:t.options.minContentWidth}),By=t=>/^(%|---|\.\.\.)/m.test(t);function qpe(t,e,r){if(!e||e<0)return!1;let n=e-r,i=t.length;if(i<=n)return!1;for(let o=0,s=0;on)return!0;if(s=o+1,i-s<=n)return!1}return!0}function Sf(t,e){let r=JSON.stringify(t);if(e.options.doubleQuotedAsJSON)return r;let{implicitKey:n}=e,i=e.options.doubleQuotedMinMultiLineLength,o=e.indent||(By(t)?" ":""),s="",a=0;for(let c=0,l=r[c];l;l=r[++c])if(l===" "&&r[c+1]==="\\"&&r[c+2]==="n"&&(s+=r.slice(a,c)+"\\ ",c+=1,a=c,l="\\"),l==="\\")switch(r[c+1]){case"u":{s+=r.slice(a,c);let u=r.substr(c+2,4);switch(u){case"0000":s+="\\0";break;case"0007":s+="\\a";break;case"000b":s+="\\v";break;case"001b":s+="\\e";break;case"0085":s+="\\N";break;case"00a0":s+="\\_";break;case"2028":s+="\\L";break;case"2029":s+="\\P";break;default:u.substr(0,2)==="00"?s+="\\x"+u.substr(2):s+=r.substr(c,6)}c+=5,a=c+1}break;case"n":if(n||r[c+2]==='"'||r.length `;let d,f;for(f=r.length;f>0;--f){let w=r[f-1];if(w!==` `&&w!==" "&&w!==" ")break}let p=r.substring(f),m=p.indexOf(` `);m===-1?d="-":r===p||m!==p.length-1?(d="+",o&&o()):d="",p&&(r=r.slice(0,-p.length),p[p.length-1]===` -`&&(p=p.slice(0,-1)),p=p.replace(uT,`$&${l}`));let h=!1,g,b=-1;for(g=0;g{O=!0});let A=Ko.foldFlowLines(`${_}${w}${p}`,l,Ko.FOLD_BLOCK,T);if(!O)return`>${x} -${l}${A}`}return r=r.replace(/\n+/g,`$&${l}`),`|${x} -${l}${_}${r}${p}`}function ipe(t,e,r,n){let{type:i,value:o}=t,{actualString:s,implicitKey:a,indent:c,indentStep:l,inFlow:u}=e;if(a&&o.includes(` -`)||u&&/[[\]{},]/.test(o))return il(o,e);if(/^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(o))return a||u||!o.includes(` -`)?il(o,e):Ly(t,e,r,n);if(!a&&!u&&i!==Yn.Scalar.PLAIN&&o.includes(` -`))return Ly(t,e,r,n);if(Uy(o)){if(c==="")return e.forceBlockIndent=!0,Ly(t,e,r,n);if(a&&c===l)return il(o,e)}let d=o.replace(/\n+/g,`$& -${c}`);if(s){let f=h=>h.default&&h.tag!=="tag:yaml.org,2002:str"&&h.test?.test(d),{compat:p,tags:m}=e.doc.schema;if(m.some(f)||p?.some(f))return il(o,e)}return a?d:Ko.foldFlowLines(d,c,Ko.FOLD_FLOW,zy(e,!1))}function ope(t,e,r,n){let{implicitKey:i,inFlow:o}=e,s=typeof t.value=="string"?t:Object.assign({},t,{value:String(t.value)}),{type:a}=t;a!==Yn.Scalar.QUOTE_DOUBLE&&/[\x00-\x08\x0b-\x1f\x7f-\x9f\u{D800}-\u{DFFF}]/u.test(s.value)&&(a=Yn.Scalar.QUOTE_DOUBLE);let c=u=>{switch(u){case Yn.Scalar.BLOCK_FOLDED:case Yn.Scalar.BLOCK_LITERAL:return i||o?il(s.value,e):Ly(s,e,r,n);case Yn.Scalar.QUOTE_DOUBLE:return _f(s.value,e);case Yn.Scalar.QUOTE_SINGLE:return lT(s.value,e);case Yn.Scalar.PLAIN:return ipe(s,e,r,n);default:return null}},l=c(a);if(l===null){let{defaultKeyType:u,defaultStringType:d}=e.options,f=i&&u||d;if(l=c(f),l===null)throw new Error(`Unsupported default string type ${f}`)}return l}n6.stringifyString=ope});var vf=v(dT=>{"use strict";var spe=Py(),Jo=De(),ape=gf(),cpe=bf();function lpe(t,e){let r=Object.assign({blockQuote:!0,commentString:ape.stringifyComment,defaultKeyType:null,defaultStringType:"PLAIN",directives:null,doubleQuotedAsJSON:!1,doubleQuotedMinMultiLineLength:40,falseStr:"false",flowCollectionPadding:!0,indentSeq:!0,lineWidth:80,minContentWidth:20,nullStr:"null",simpleKeys:!1,singleQuote:null,trailingComma:!1,trueStr:"true",verifyAliasOrder:!0},t.schema.toStringOptions,e),n;switch(r.collectionStyle){case"block":n=!1;break;case"flow":n=!0;break;default:n=null}return{anchors:new Set,doc:t,flowCollectionPadding:r.flowCollectionPadding?" ":"",indent:"",indentStep:typeof r.indent=="number"?" ".repeat(r.indent):" ",inFlow:n,options:r}}function upe(t,e){if(e.tag){let i=t.filter(o=>o.tag===e.tag);if(i.length>0)return i.find(o=>o.format===e.format)??i[0]}let r,n;if(Jo.isScalar(e)){n=e.value;let i=t.filter(o=>o.identify?.(n));if(i.length>1){let o=i.filter(s=>s.test);o.length>0&&(i=o)}r=i.find(o=>o.format===e.format)??i.find(o=>!o.format)}else n=e,r=t.find(i=>i.nodeClass&&n instanceof i.nodeClass);if(!r){let i=n?.constructor?.name??(n===null?"null":typeof n);throw new Error(`Tag not resolved for ${i} value`)}return r}function dpe(t,e,{anchors:r,doc:n}){if(!n.directives)return"";let i=[],o=(Jo.isScalar(t)||Jo.isCollection(t))&&t.anchor;o&&spe.anchorIsValid(o)&&(r.add(o),i.push(`&${o}`));let s=t.tag??(e.default?null:e.tag);return s&&i.push(n.directives.tagString(s)),i.join(" ")}function fpe(t,e,r,n){if(Jo.isPair(t))return t.toString(e,r,n);if(Jo.isAlias(t)){if(e.doc.directives)return t.toString(e);if(e.resolvedAliases?.has(t))throw new TypeError("Cannot stringify circular structure without alias nodes");e.resolvedAliases?e.resolvedAliases.add(t):e.resolvedAliases=new Set([t]),t=t.resolve(e.doc)}let i,o=Jo.isNode(t)?t:e.doc.createNode(t,{onTagObj:c=>i=c});i??(i=upe(e.doc.schema.tags,o));let s=dpe(o,i,e);s.length>0&&(e.indentAtStart=(e.indentAtStart??0)+s.length+1);let a=typeof i.stringify=="function"?i.stringify(o,e,r,n):Jo.isScalar(o)?cpe.stringifyString(o,e,r,n):o.toString(e,r,n);return s?Jo.isScalar(o)||a[0]==="{"||a[0]==="["?`${s} ${a}`:`${s} -${e.indent}${a}`:a}dT.createStringifyContext=lpe;dT.stringify=fpe});var a6=v(s6=>{"use strict";var ho=De(),i6=Dt(),o6=vf(),Sf=gf();function ppe({key:t,value:e},r,n,i){let{allNullValues:o,doc:s,indent:a,indentStep:c,options:{commentString:l,indentSeq:u,simpleKeys:d}}=r,f=ho.isNode(t)&&t.comment||null;if(d){if(f)throw new Error("With simple keys, key nodes cannot have comments");if(ho.isCollection(t)||!ho.isNode(t)&&typeof t=="object"){let T="With simple keys, collection cannot be used as a key value";throw new Error(T)}}let p=!d&&(!t||f&&e==null&&!r.inFlow||ho.isCollection(t)||(ho.isScalar(t)?t.type===i6.Scalar.BLOCK_FOLDED||t.type===i6.Scalar.BLOCK_LITERAL:typeof t=="object"));r=Object.assign({},r,{allNullValues:!1,implicitKey:!p&&(d||!o),indent:a+c});let m=!1,h=!1,g=o6.stringify(t,r,()=>m=!0,()=>h=!0);if(!p&&!r.inFlow&&g.length>1024){if(d)throw new Error("With simple keys, single line scalar must not span more than 1024 characters");p=!0}if(r.inFlow){if(o||e==null)return m&&n&&n(),g===""?"?":p?`? ${g}`:g}else if(o&&!d||e==null&&p)return g=`? ${g}`,f&&!m?g+=Sf.lineComment(g,r.indent,l(f)):h&&i&&i(),g;m&&(f=null),p?(f&&(g+=Sf.lineComment(g,r.indent,l(f))),g=`? ${g} -${a}:`):(g=`${g}:`,f&&(g+=Sf.lineComment(g,r.indent,l(f))));let b,_,S;ho.isNode(e)?(b=!!e.spaceBefore,_=e.commentBefore,S=e.comment):(b=!1,_=null,S=null,e&&typeof e=="object"&&(e=s.createNode(e))),r.implicitKey=!1,!p&&!f&&ho.isScalar(e)&&(r.indentAtStart=g.length+1),h=!1,!u&&c.length>=2&&!r.inFlow&&!p&&ho.isSeq(e)&&!e.flow&&!e.tag&&!e.anchor&&(r.indent=r.indent.substring(2));let x=!1,w=o6.stringify(e,r,()=>x=!0,()=>h=!0),O=" ";if(f||b||_){if(O=b?` -`:"",_){let T=l(_);O+=` -${Sf.indentComment(T,r.indent)}`}w===""&&!r.inFlow?O===` -`&&S&&(O=` - -`):O+=` -${r.indent}`}else if(!p&&ho.isCollection(e)){let T=w[0],A=w.indexOf(` -`),D=A!==-1,$=r.inFlow??e.flow??e.items.length===0;if(D||!$){let re=!1;if(D&&(T==="&"||T==="!")){let K=w.indexOf(" ");T==="&"&&K!==-1&&K{R=!0});let O=Jo.foldFlowLines(`${_}${w}${p}`,l,Jo.FOLD_BLOCK,A);if(!R)return`>${x} +${l}${O}`}return r=r.replace(/\n+/g,`$&${l}`),`|${x} +${l}${_}${r}${p}`}function Hpe(t,e,r,n){let{type:i,value:o}=t,{actualString:s,implicitKey:a,indent:c,indentStep:l,inFlow:u}=e;if(a&&o.includes(` +`)||u&&/[[\]{},]/.test(o))return al(o,e);if(/^[\n\t ,[\]{}#&*!|>'"%@`]|^[?-]$|^[?-][ \t]|[\n:][ \t]|[ \t]\n|[\n\t ]#|[\n\t :]$/.test(o))return a||u||!o.includes(` +`)?al(o,e):qy(t,e,r,n);if(!a&&!u&&i!==Xn.Scalar.PLAIN&&o.includes(` +`))return qy(t,e,r,n);if(By(o)){if(c==="")return e.forceBlockIndent=!0,qy(t,e,r,n);if(a&&c===l)return al(o,e)}let d=o.replace(/\n+/g,`$& +${c}`);if(s){let f=h=>h.default&&h.tag!=="tag:yaml.org,2002:str"&&h.test?.test(d),{compat:p,tags:m}=e.doc.schema;if(m.some(f)||p?.some(f))return al(o,e)}return a?d:Jo.foldFlowLines(d,c,Jo.FOLD_FLOW,Hy(e,!1))}function Bpe(t,e,r,n){let{implicitKey:i,inFlow:o}=e,s=typeof t.value=="string"?t:Object.assign({},t,{value:String(t.value)}),{type:a}=t;a!==Xn.Scalar.QUOTE_DOUBLE&&/[\x00-\x08\x0b-\x1f\x7f-\x9f\u{D800}-\u{DFFF}]/u.test(s.value)&&(a=Xn.Scalar.QUOTE_DOUBLE);let c=u=>{switch(u){case Xn.Scalar.BLOCK_FOLDED:case Xn.Scalar.BLOCK_LITERAL:return i||o?al(s.value,e):qy(s,e,r,n);case Xn.Scalar.QUOTE_DOUBLE:return Sf(s.value,e);case Xn.Scalar.QUOTE_SINGLE:return yO(s.value,e);case Xn.Scalar.PLAIN:return Hpe(s,e,r,n);default:return null}},l=c(a);if(l===null){let{defaultKeyType:u,defaultStringType:d}=e.options,f=i&&u||d;if(l=c(f),l===null)throw new Error(`Unsupported default string type ${f}`)}return l}_H.stringifyString=Bpe});var xf=v(bO=>{"use strict";var Gpe=Ny(),Yo=De(),Zpe=bf(),Vpe=wf();function Wpe(t,e){let r=Object.assign({blockQuote:!0,commentString:Zpe.stringifyComment,defaultKeyType:null,defaultStringType:"PLAIN",directives:null,doubleQuotedAsJSON:!1,doubleQuotedMinMultiLineLength:40,falseStr:"false",flowCollectionPadding:!0,indentSeq:!0,lineWidth:80,minContentWidth:20,nullStr:"null",simpleKeys:!1,singleQuote:null,trailingComma:!1,trueStr:"true",verifyAliasOrder:!0},t.schema.toStringOptions,e),n;switch(r.collectionStyle){case"block":n=!1;break;case"flow":n=!0;break;default:n=null}return{anchors:new Set,doc:t,flowCollectionPadding:r.flowCollectionPadding?" ":"",indent:"",indentStep:typeof r.indent=="number"?" ".repeat(r.indent):" ",inFlow:n,options:r}}function Kpe(t,e){if(e.tag){let i=t.filter(o=>o.tag===e.tag);if(i.length>0)return i.find(o=>o.format===e.format)??i[0]}let r,n;if(Yo.isScalar(e)){n=e.value;let i=t.filter(o=>o.identify?.(n));if(i.length>1){let o=i.filter(s=>s.test);o.length>0&&(i=o)}r=i.find(o=>o.format===e.format)??i.find(o=>!o.format)}else n=e,r=t.find(i=>i.nodeClass&&n instanceof i.nodeClass);if(!r){let i=n?.constructor?.name??(n===null?"null":typeof n);throw new Error(`Tag not resolved for ${i} value`)}return r}function Jpe(t,e,{anchors:r,doc:n}){if(!n.directives)return"";let i=[],o=(Yo.isScalar(t)||Yo.isCollection(t))&&t.anchor;o&&Gpe.anchorIsValid(o)&&(r.add(o),i.push(`&${o}`));let s=t.tag??(e.default?null:e.tag);return s&&i.push(n.directives.tagString(s)),i.join(" ")}function Ype(t,e,r,n){if(Yo.isPair(t))return t.toString(e,r,n);if(Yo.isAlias(t)){if(e.doc.directives)return t.toString(e);if(e.resolvedAliases?.has(t))throw new TypeError("Cannot stringify circular structure without alias nodes");e.resolvedAliases?e.resolvedAliases.add(t):e.resolvedAliases=new Set([t]),t=t.resolve(e.doc)}let i,o=Yo.isNode(t)?t:e.doc.createNode(t,{onTagObj:c=>i=c});i??(i=Kpe(e.doc.schema.tags,o));let s=Jpe(o,i,e);s.length>0&&(e.indentAtStart=(e.indentAtStart??0)+s.length+1);let a=typeof i.stringify=="function"?i.stringify(o,e,r,n):Yo.isScalar(o)?Vpe.stringifyString(o,e,r,n):o.toString(e,r,n);return s?Yo.isScalar(o)||a[0]==="{"||a[0]==="["?`${s} ${a}`:`${s} +${e.indent}${a}`:a}bO.createStringifyContext=Wpe;bO.stringify=Ype});var wH=v(SH=>{"use strict";var go=De(),bH=Dt(),vH=xf(),$f=bf();function Xpe({key:t,value:e},r,n,i){let{allNullValues:o,doc:s,indent:a,indentStep:c,options:{commentString:l,indentSeq:u,simpleKeys:d}}=r,f=go.isNode(t)&&t.comment||null;if(d){if(f)throw new Error("With simple keys, key nodes cannot have comments");if(go.isCollection(t)||!go.isNode(t)&&typeof t=="object"){let A="With simple keys, collection cannot be used as a key value";throw new Error(A)}}let p=!d&&(!t||f&&e==null&&!r.inFlow||go.isCollection(t)||(go.isScalar(t)?t.type===bH.Scalar.BLOCK_FOLDED||t.type===bH.Scalar.BLOCK_LITERAL:typeof t=="object"));r=Object.assign({},r,{allNullValues:!1,implicitKey:!p&&(d||!o),indent:a+c});let m=!1,h=!1,g=vH.stringify(t,r,()=>m=!0,()=>h=!0);if(!p&&!r.inFlow&&g.length>1024){if(d)throw new Error("With simple keys, single line scalar must not span more than 1024 characters");p=!0}if(r.inFlow){if(o||e==null)return m&&n&&n(),g===""?"?":p?`? ${g}`:g}else if(o&&!d||e==null&&p)return g=`? ${g}`,f&&!m?g+=$f.lineComment(g,r.indent,l(f)):h&&i&&i(),g;m&&(f=null),p?(f&&(g+=$f.lineComment(g,r.indent,l(f))),g=`? ${g} +${a}:`):(g=`${g}:`,f&&(g+=$f.lineComment(g,r.indent,l(f))));let b,_,S;go.isNode(e)?(b=!!e.spaceBefore,_=e.commentBefore,S=e.comment):(b=!1,_=null,S=null,e&&typeof e=="object"&&(e=s.createNode(e))),r.implicitKey=!1,!p&&!f&&go.isScalar(e)&&(r.indentAtStart=g.length+1),h=!1,!u&&c.length>=2&&!r.inFlow&&!p&&go.isSeq(e)&&!e.flow&&!e.tag&&!e.anchor&&(r.indent=r.indent.substring(2));let x=!1,w=vH.stringify(e,r,()=>x=!0,()=>h=!0),R=" ";if(f||b||_){if(R=b?` +`:"",_){let A=l(_);R+=` +${$f.indentComment(A,r.indent)}`}w===""&&!r.inFlow?R===` +`&&S&&(R=` + +`):R+=` +${r.indent}`}else if(!p&&go.isCollection(e)){let A=w[0],O=w.indexOf(` +`),D=O!==-1,E=r.inFlow??e.flow??e.items.length===0;if(D||!E){let ae=!1;if(D&&(A==="&"||A==="!")){let X=w.indexOf(" ");A==="&"&&X!==-1&&X{"use strict";var c6=Ge("process");function mpe(t,...e){t==="debug"&&console.log(...e)}function hpe(t,e){(t==="debug"||t==="warn")&&(typeof c6.emitWarning=="function"?c6.emitWarning(e):console.warn(e))}fT.debug=mpe;fT.warn=hpe});var Zy=v(Gy=>{"use strict";var Hy=De(),l6=Dt(),qy="<<",By={identify:t=>t===qy||typeof t=="symbol"&&t.description===qy,default:"key",tag:"tag:yaml.org,2002:merge",test:/^<<$/,resolve:()=>Object.assign(new l6.Scalar(Symbol(qy)),{addToJSMap:u6}),stringify:()=>qy},gpe=(t,e)=>(By.identify(e)||Hy.isScalar(e)&&(!e.type||e.type===l6.Scalar.PLAIN)&&By.identify(e.value))&&t?.doc.schema.tags.some(r=>r.tag===By.tag&&r.default);function u6(t,e,r){let n=d6(t,r);if(Hy.isSeq(n))for(let i of n.items)mT(t,e,i);else if(Array.isArray(n))for(let i of n)mT(t,e,i);else mT(t,e,n)}function mT(t,e,r){let n=d6(t,r);if(!Hy.isMap(n))throw new Error("Merge sources must be maps or map aliases");let i=n.toJSON(null,t,Map);for(let[o,s]of i)e instanceof Map?e.has(o)||e.set(o,s):e instanceof Set?e.add(o):Object.prototype.hasOwnProperty.call(e,o)||Object.defineProperty(e,o,{value:s,writable:!0,enumerable:!0,configurable:!0});return e}function d6(t,e){return t&&Hy.isAlias(e)?e.resolve(t.doc,t):e}Gy.addMergeToJSMap=u6;Gy.isMergeKey=gpe;Gy.merge=By});var gT=v(m6=>{"use strict";var ype=pT(),f6=Zy(),_pe=vf(),p6=De(),hT=Vo();function bpe(t,e,{key:r,value:n}){if(p6.isNode(r)&&r.addToJSMap)r.addToJSMap(t,e,n);else if(f6.isMergeKey(t,r))f6.addMergeToJSMap(t,e,n);else{let i=hT.toJS(r,"",t);if(e instanceof Map)e.set(i,hT.toJS(n,i,t));else if(e instanceof Set)e.add(i);else{let o=vpe(r,i,t),s=hT.toJS(n,o,t);o in e?Object.defineProperty(e,o,{value:s,writable:!0,enumerable:!0,configurable:!0}):e[o]=s}}return e}function vpe(t,e,r){if(e===null)return"";if(typeof e!="object")return String(e);if(p6.isNode(t)&&r?.doc){let n=_pe.createStringifyContext(r.doc,{});n.anchors=new Set;for(let o of r.anchors.keys())n.anchors.add(o.anchor);n.inFlow=!0,n.inStringifyKey=!0;let i=t.toString(n);if(!r.mapKeyWarned){let o=JSON.stringify(i);o.length>40&&(o=o.substring(0,36)+'..."'),ype.warn(r.doc.options.logLevel,`Keys with collection values will be stringified due to JS Object restrictions: ${o}. Set mapAsMap: true to use object keys.`),r.mapKeyWarned=!0}return i}return JSON.stringify(e)}m6.addPairToJSMap=bpe});var Yo=v(yT=>{"use strict";var h6=hf(),Spe=a6(),wpe=gT(),Vy=De();function xpe(t,e,r){let n=h6.createNode(t,void 0,r),i=h6.createNode(e,void 0,r);return new Wy(n,i)}var Wy=class t{constructor(e,r=null){Object.defineProperty(this,Vy.NODE_TYPE,{value:Vy.PAIR}),this.key=e,this.value=r}clone(e){let{key:r,value:n}=this;return Vy.isNode(r)&&(r=r.clone(e)),Vy.isNode(n)&&(n=n.clone(e)),new t(r,n)}toJSON(e,r){let n=r?.mapAsMap?new Map:{};return wpe.addPairToJSMap(r,n,this)}toString(e,r,n){return e?.doc?Spe.stringifyPair(this,e,r,n):JSON.stringify(this)}};yT.Pair=Wy;yT.createPair=xpe});var _T=v(y6=>{"use strict";var pa=De(),g6=vf(),Ky=gf();function $pe(t,e,r){return(e.inFlow??t.flow?Epe:kpe)(t,e,r)}function kpe({comment:t,items:e},r,{blockItemPrefix:n,flowChars:i,itemIndent:o,onChompKeep:s,onComment:a}){let{indent:c,options:{commentString:l}}=r,u=Object.assign({},r,{indent:o,type:null}),d=!1,f=[];for(let m=0;mg=null,()=>d=!0);g&&(b+=Ky.lineComment(b,o,l(g))),d&&g&&(d=!1),f.push(n+b)}let p;if(f.length===0)p=i.start+i.end;else{p=f[0];for(let m=1;m{"use strict";var xH=Ze("process");function Qpe(t,...e){t==="debug"&&console.log(...e)}function eme(t,e){(t==="debug"||t==="warn")&&(typeof xH.emitWarning=="function"?xH.emitWarning(e):console.warn(e))}vO.debug=Qpe;vO.warn=eme});var Ky=v(Wy=>{"use strict";var Vy=De(),$H=Dt(),Gy="<<",Zy={identify:t=>t===Gy||typeof t=="symbol"&&t.description===Gy,default:"key",tag:"tag:yaml.org,2002:merge",test:/^<<$/,resolve:()=>Object.assign(new $H.Scalar(Symbol(Gy)),{addToJSMap:kH}),stringify:()=>Gy},tme=(t,e)=>(Zy.identify(e)||Vy.isScalar(e)&&(!e.type||e.type===$H.Scalar.PLAIN)&&Zy.identify(e.value))&&t?.doc.schema.tags.some(r=>r.tag===Zy.tag&&r.default);function kH(t,e,r){let n=EH(t,r);if(Vy.isSeq(n))for(let i of n.items)wO(t,e,i);else if(Array.isArray(n))for(let i of n)wO(t,e,i);else wO(t,e,n)}function wO(t,e,r){let n=EH(t,r);if(!Vy.isMap(n))throw new Error("Merge sources must be maps or map aliases");let i=n.toJSON(null,t,Map);for(let[o,s]of i)e instanceof Map?e.has(o)||e.set(o,s):e instanceof Set?e.add(o):Object.prototype.hasOwnProperty.call(e,o)||Object.defineProperty(e,o,{value:s,writable:!0,enumerable:!0,configurable:!0});return e}function EH(t,e){return t&&Vy.isAlias(e)?e.resolve(t.doc,t):e}Wy.addMergeToJSMap=kH;Wy.isMergeKey=tme;Wy.merge=Zy});var $O=v(TH=>{"use strict";var rme=SO(),AH=Ky(),nme=xf(),OH=De(),xO=Wo();function ime(t,e,{key:r,value:n}){if(OH.isNode(r)&&r.addToJSMap)r.addToJSMap(t,e,n);else if(AH.isMergeKey(t,r))AH.addMergeToJSMap(t,e,n);else{let i=xO.toJS(r,"",t);if(e instanceof Map)e.set(i,xO.toJS(n,i,t));else if(e instanceof Set)e.add(i);else{let o=ome(r,i,t),s=xO.toJS(n,o,t);o in e?Object.defineProperty(e,o,{value:s,writable:!0,enumerable:!0,configurable:!0}):e[o]=s}}return e}function ome(t,e,r){if(e===null)return"";if(typeof e!="object")return String(e);if(OH.isNode(t)&&r?.doc){let n=nme.createStringifyContext(r.doc,{});n.anchors=new Set;for(let o of r.anchors.keys())n.anchors.add(o.anchor);n.inFlow=!0,n.inStringifyKey=!0;let i=t.toString(n);if(!r.mapKeyWarned){let o=JSON.stringify(i);o.length>40&&(o=o.substring(0,36)+'..."'),rme.warn(r.doc.options.logLevel,`Keys with collection values will be stringified due to JS Object restrictions: ${o}. Set mapAsMap: true to use object keys.`),r.mapKeyWarned=!0}return i}return JSON.stringify(e)}TH.addPairToJSMap=ime});var Xo=v(kO=>{"use strict";var RH=_f(),sme=wH(),ame=$O(),Jy=De();function cme(t,e,r){let n=RH.createNode(t,void 0,r),i=RH.createNode(e,void 0,r);return new Yy(n,i)}var Yy=class t{constructor(e,r=null){Object.defineProperty(this,Jy.NODE_TYPE,{value:Jy.PAIR}),this.key=e,this.value=r}clone(e){let{key:r,value:n}=this;return Jy.isNode(r)&&(r=r.clone(e)),Jy.isNode(n)&&(n=n.clone(e)),new t(r,n)}toJSON(e,r){let n=r?.mapAsMap?new Map:{};return ame.addPairToJSMap(r,n,this)}toString(e,r,n){return e?.doc?sme.stringifyPair(this,e,r,n):JSON.stringify(this)}};kO.Pair=Yy;kO.createPair=cme});var EO=v(PH=>{"use strict";var ga=De(),IH=xf(),Xy=bf();function lme(t,e,r){return(e.inFlow??t.flow?dme:ume)(t,e,r)}function ume({comment:t,items:e},r,{blockItemPrefix:n,flowChars:i,itemIndent:o,onChompKeep:s,onComment:a}){let{indent:c,options:{commentString:l}}=r,u=Object.assign({},r,{indent:o,type:null}),d=!1,f=[];for(let m=0;mg=null,()=>d=!0);g&&(b+=Xy.lineComment(b,o,l(g))),d&&g&&(d=!1),f.push(n+b)}let p;if(f.length===0)p=i.start+i.end;else{p=f[0];for(let m=1;mg=null);l||(l=d.length>u||b.includes(` -`)),m0&&(l||(l=d.reduce((_,S)=>_+S.length+2,2)+(b.length+2)>e.options.lineWidth)),l&&(b+=",")),g&&(b+=Ky.lineComment(b,n,a(g))),d.push(b),u=d.length}let{start:f,end:p}=r;if(d.length===0)return f+p;if(!l){let m=d.reduce((h,g)=>h+g.length+2,2);l=e.options.lineWidth>0&&m>e.options.lineWidth}if(l){let m=f;for(let h of d)m+=h?` +`+Xy.indentComment(l(t),c),a&&a()):d&&s&&s(),p}function dme({items:t},e,{flowChars:r,itemIndent:n}){let{indent:i,indentStep:o,flowCollectionPadding:s,options:{commentString:a}}=e;n+=o;let c=Object.assign({},e,{indent:n,inFlow:!0,type:null}),l=!1,u=0,d=[];for(let m=0;mg=null);l||(l=d.length>u||b.includes(` +`)),m0&&(l||(l=d.reduce((_,S)=>_+S.length+2,2)+(b.length+2)>e.options.lineWidth)),l&&(b+=",")),g&&(b+=Xy.lineComment(b,n,a(g))),d.push(b),u=d.length}let{start:f,end:p}=r;if(d.length===0)return f+p;if(!l){let m=d.reduce((h,g)=>h+g.length+2,2);l=e.options.lineWidth>0&&m>e.options.lineWidth}if(l){let m=f;for(let h of d)m+=h?` ${o}${i}${h}`:` `;return`${m} -${i}${p}`}else return`${f}${s}${d.join(" ")}${s}${p}`}function Jy({indent:t,options:{commentString:e}},r,n,i){if(n&&i&&(n=n.replace(/^\n+/,"")),n){let o=Ky.indentComment(e(n),t);r.push(o.trimStart())}}y6.stringifyCollection=$pe});var Qo=v(vT=>{"use strict";var Ape=_T(),Tpe=gT(),Ope=jy(),Xo=De(),Yy=Yo(),Rpe=Dt();function wf(t,e){let r=Xo.isScalar(e)?e.value:e;for(let n of t)if(Xo.isPair(n)&&(n.key===e||n.key===r||Xo.isScalar(n.key)&&n.key.value===r))return n}var bT=class extends Ope.Collection{static get tagName(){return"tag:yaml.org,2002:map"}constructor(e){super(Xo.MAP,e),this.items=[]}static from(e,r,n){let{keepUndefined:i,replacer:o}=n,s=new this(e),a=(c,l)=>{if(typeof o=="function")l=o.call(r,c,l);else if(Array.isArray(o)&&!o.includes(c))return;(l!==void 0||i)&&s.items.push(Yy.createPair(c,l,n))};if(r instanceof Map)for(let[c,l]of r)a(c,l);else if(r&&typeof r=="object")for(let c of Object.keys(r))a(c,r[c]);return typeof e.sortMapEntries=="function"&&s.items.sort(e.sortMapEntries),s}add(e,r){let n;Xo.isPair(e)?n=e:!e||typeof e!="object"||!("key"in e)?n=new Yy.Pair(e,e?.value):n=new Yy.Pair(e.key,e.value);let i=wf(this.items,n.key),o=this.schema?.sortMapEntries;if(i){if(!r)throw new Error(`Key ${n.key} already set`);Xo.isScalar(i.value)&&Rpe.isScalarValue(n.value)?i.value.value=n.value:i.value=n.value}else if(o){let s=this.items.findIndex(a=>o(n,a)<0);s===-1?this.items.push(n):this.items.splice(s,0,n)}else this.items.push(n)}delete(e){let r=wf(this.items,e);return r?this.items.splice(this.items.indexOf(r),1).length>0:!1}get(e,r){let i=wf(this.items,e)?.value;return(!r&&Xo.isScalar(i)?i.value:i)??void 0}has(e){return!!wf(this.items,e)}set(e,r){this.add(new Yy.Pair(e,r),!0)}toJSON(e,r,n){let i=n?new n:r?.mapAsMap?new Map:{};r?.onCreate&&r.onCreate(i);for(let o of this.items)Tpe.addPairToJSMap(r,i,o);return i}toString(e,r,n){if(!e)return JSON.stringify(this);for(let i of this.items)if(!Xo.isPair(i))throw new Error(`Map items must all be pairs; found ${JSON.stringify(i)} instead`);return!e.allNullValues&&this.hasAllNullValues(!1)&&(e=Object.assign({},e,{allNullValues:!0})),Ape.stringifyCollection(this,e,{blockItemPrefix:"",flowChars:{start:"{",end:"}"},itemIndent:e.indent||"",onChompKeep:n,onComment:r})}};vT.YAMLMap=bT;vT.findPair=wf});var ol=v(b6=>{"use strict";var Ipe=De(),_6=Qo(),Ppe={collection:"map",default:!0,nodeClass:_6.YAMLMap,tag:"tag:yaml.org,2002:map",resolve(t,e){return Ipe.isMap(t)||e("Expected a mapping for this tag"),t},createNode:(t,e,r)=>_6.YAMLMap.from(t,e,r)};b6.map=Ppe});var es=v(v6=>{"use strict";var Cpe=hf(),Dpe=_T(),Npe=jy(),Qy=De(),jpe=Dt(),Mpe=Vo(),ST=class extends Npe.Collection{static get tagName(){return"tag:yaml.org,2002:seq"}constructor(e){super(Qy.SEQ,e),this.items=[]}add(e){this.items.push(e)}delete(e){let r=Xy(e);return typeof r!="number"?!1:this.items.splice(r,1).length>0}get(e,r){let n=Xy(e);if(typeof n!="number")return;let i=this.items[n];return!r&&Qy.isScalar(i)?i.value:i}has(e){let r=Xy(e);return typeof r=="number"&&r=0?e:null}v6.YAMLSeq=ST});var sl=v(w6=>{"use strict";var Fpe=De(),S6=es(),Lpe={collection:"seq",default:!0,nodeClass:S6.YAMLSeq,tag:"tag:yaml.org,2002:seq",resolve(t,e){return Fpe.isSeq(t)||e("Expected a sequence for this tag"),t},createNode:(t,e,r)=>S6.YAMLSeq.from(t,e,r)};w6.seq=Lpe});var xf=v(x6=>{"use strict";var zpe=bf(),Upe={identify:t=>typeof t=="string",default:!0,tag:"tag:yaml.org,2002:str",resolve:t=>t,stringify(t,e,r,n){return e=Object.assign({actualString:!0},e),zpe.stringifyString(t,e,r,n)}};x6.string=Upe});var e_=v(E6=>{"use strict";var $6=Dt(),k6={identify:t=>t==null,createNode:()=>new $6.Scalar(null),default:!0,tag:"tag:yaml.org,2002:null",test:/^(?:~|[Nn]ull|NULL)?$/,resolve:()=>new $6.Scalar(null),stringify:({source:t},e)=>typeof t=="string"&&k6.test.test(t)?t:e.options.nullStr};E6.nullTag=k6});var wT=v(T6=>{"use strict";var qpe=Dt(),A6={identify:t=>typeof t=="boolean",default:!0,tag:"tag:yaml.org,2002:bool",test:/^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,resolve:t=>new qpe.Scalar(t[0]==="t"||t[0]==="T"),stringify({source:t,value:e},r){if(t&&A6.test.test(t)){let n=t[0]==="t"||t[0]==="T";if(e===n)return t}return e?r.options.trueStr:r.options.falseStr}};T6.boolTag=A6});var al=v(O6=>{"use strict";function Bpe({format:t,minFractionDigits:e,tag:r,value:n}){if(typeof n=="bigint")return String(n);let i=typeof n=="number"?n:Number(n);if(!isFinite(i))return isNaN(i)?".nan":i<0?"-.inf":".inf";let o=Object.is(n,-0)?"-0":JSON.stringify(n);if(!t&&e&&(!r||r==="tag:yaml.org,2002:float")&&/^-?\d/.test(o)&&!o.includes("e")){let s=o.indexOf(".");s<0&&(s=o.length,o+=".");let a=e-(o.length-s-1);for(;a-- >0;)o+="0"}return o}O6.stringifyNumber=Bpe});var $T=v(t_=>{"use strict";var Hpe=Dt(),xT=al(),Gpe={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,resolve:t=>t.slice(-3).toLowerCase()==="nan"?NaN:t[0]==="-"?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY,stringify:xT.stringifyNumber},Zpe={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",format:"EXP",test:/^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,resolve:t=>parseFloat(t),stringify(t){let e=Number(t.value);return isFinite(e)?e.toExponential():xT.stringifyNumber(t)}},Vpe={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,resolve(t){let e=new Hpe.Scalar(parseFloat(t)),r=t.indexOf(".");return r!==-1&&t[t.length-1]==="0"&&(e.minFractionDigits=t.length-r-1),e},stringify:xT.stringifyNumber};t_.float=Vpe;t_.floatExp=Zpe;t_.floatNaN=Gpe});var ET=v(n_=>{"use strict";var R6=al(),r_=t=>typeof t=="bigint"||Number.isInteger(t),kT=(t,e,r,{intAsBigInt:n})=>n?BigInt(t):parseInt(t.substring(e),r);function I6(t,e,r){let{value:n}=t;return r_(n)&&n>=0?r+n.toString(e):R6.stringifyNumber(t)}var Wpe={identify:t=>r_(t)&&t>=0,default:!0,tag:"tag:yaml.org,2002:int",format:"OCT",test:/^0o[0-7]+$/,resolve:(t,e,r)=>kT(t,2,8,r),stringify:t=>I6(t,8,"0o")},Kpe={identify:r_,default:!0,tag:"tag:yaml.org,2002:int",test:/^[-+]?[0-9]+$/,resolve:(t,e,r)=>kT(t,0,10,r),stringify:R6.stringifyNumber},Jpe={identify:t=>r_(t)&&t>=0,default:!0,tag:"tag:yaml.org,2002:int",format:"HEX",test:/^0x[0-9a-fA-F]+$/,resolve:(t,e,r)=>kT(t,2,16,r),stringify:t=>I6(t,16,"0x")};n_.int=Kpe;n_.intHex=Jpe;n_.intOct=Wpe});var C6=v(P6=>{"use strict";var Ype=ol(),Xpe=e_(),Qpe=sl(),eme=xf(),tme=wT(),AT=$T(),TT=ET(),rme=[Ype.map,Qpe.seq,eme.string,Xpe.nullTag,tme.boolTag,TT.intOct,TT.int,TT.intHex,AT.floatNaN,AT.floatExp,AT.float];P6.schema=rme});var j6=v(N6=>{"use strict";var nme=Dt(),ime=ol(),ome=sl();function D6(t){return typeof t=="bigint"||Number.isInteger(t)}var i_=({value:t})=>JSON.stringify(t),sme=[{identify:t=>typeof t=="string",default:!0,tag:"tag:yaml.org,2002:str",resolve:t=>t,stringify:i_},{identify:t=>t==null,createNode:()=>new nme.Scalar(null),default:!0,tag:"tag:yaml.org,2002:null",test:/^null$/,resolve:()=>null,stringify:i_},{identify:t=>typeof t=="boolean",default:!0,tag:"tag:yaml.org,2002:bool",test:/^true$|^false$/,resolve:t=>t==="true",stringify:i_},{identify:D6,default:!0,tag:"tag:yaml.org,2002:int",test:/^-?(?:0|[1-9][0-9]*)$/,resolve:(t,e,{intAsBigInt:r})=>r?BigInt(t):parseInt(t,10),stringify:({value:t})=>D6(t)?t.toString():JSON.stringify(t)},{identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/,resolve:t=>parseFloat(t),stringify:i_}],ame={default:!0,tag:"",test:/^/,resolve(t,e){return e(`Unresolved plain scalar ${JSON.stringify(t)}`),t}},cme=[ime.map,ome.seq].concat(sme,ame);N6.schema=cme});var RT=v(M6=>{"use strict";var $f=Ge("buffer"),OT=Dt(),lme=bf(),ume={identify:t=>t instanceof Uint8Array,default:!1,tag:"tag:yaml.org,2002:binary",resolve(t,e){if(typeof $f.Buffer=="function")return $f.Buffer.from(t,"base64");if(typeof atob=="function"){let r=atob(t.replace(/[\n\r]/g,"")),n=new Uint8Array(r.length);for(let i=0;i{"use strict";var o_=De(),IT=Yo(),dme=Dt(),fme=es();function F6(t,e){if(o_.isSeq(t))for(let r=0;r1&&e("Each pair must have its own sequence indicator");let i=n.items[0]||new IT.Pair(new dme.Scalar(null));if(n.commentBefore&&(i.key.commentBefore=i.key.commentBefore?`${n.commentBefore} +${i}${p}`}else return`${f}${s}${d.join(" ")}${s}${p}`}function Qy({indent:t,options:{commentString:e}},r,n,i){if(n&&i&&(n=n.replace(/^\n+/,"")),n){let o=Xy.indentComment(e(n),t);r.push(o.trimStart())}}PH.stringifyCollection=lme});var es=v(OO=>{"use strict";var fme=EO(),pme=$O(),mme=Ly(),Qo=De(),e_=Xo(),hme=Dt();function kf(t,e){let r=Qo.isScalar(e)?e.value:e;for(let n of t)if(Qo.isPair(n)&&(n.key===e||n.key===r||Qo.isScalar(n.key)&&n.key.value===r))return n}var AO=class extends mme.Collection{static get tagName(){return"tag:yaml.org,2002:map"}constructor(e){super(Qo.MAP,e),this.items=[]}static from(e,r,n){let{keepUndefined:i,replacer:o}=n,s=new this(e),a=(c,l)=>{if(typeof o=="function")l=o.call(r,c,l);else if(Array.isArray(o)&&!o.includes(c))return;(l!==void 0||i)&&s.items.push(e_.createPair(c,l,n))};if(r instanceof Map)for(let[c,l]of r)a(c,l);else if(r&&typeof r=="object")for(let c of Object.keys(r))a(c,r[c]);return typeof e.sortMapEntries=="function"&&s.items.sort(e.sortMapEntries),s}add(e,r){let n;Qo.isPair(e)?n=e:!e||typeof e!="object"||!("key"in e)?n=new e_.Pair(e,e?.value):n=new e_.Pair(e.key,e.value);let i=kf(this.items,n.key),o=this.schema?.sortMapEntries;if(i){if(!r)throw new Error(`Key ${n.key} already set`);Qo.isScalar(i.value)&&hme.isScalarValue(n.value)?i.value.value=n.value:i.value=n.value}else if(o){let s=this.items.findIndex(a=>o(n,a)<0);s===-1?this.items.push(n):this.items.splice(s,0,n)}else this.items.push(n)}delete(e){let r=kf(this.items,e);return r?this.items.splice(this.items.indexOf(r),1).length>0:!1}get(e,r){let i=kf(this.items,e)?.value;return(!r&&Qo.isScalar(i)?i.value:i)??void 0}has(e){return!!kf(this.items,e)}set(e,r){this.add(new e_.Pair(e,r),!0)}toJSON(e,r,n){let i=n?new n:r?.mapAsMap?new Map:{};r?.onCreate&&r.onCreate(i);for(let o of this.items)pme.addPairToJSMap(r,i,o);return i}toString(e,r,n){if(!e)return JSON.stringify(this);for(let i of this.items)if(!Qo.isPair(i))throw new Error(`Map items must all be pairs; found ${JSON.stringify(i)} instead`);return!e.allNullValues&&this.hasAllNullValues(!1)&&(e=Object.assign({},e,{allNullValues:!0})),fme.stringifyCollection(this,e,{blockItemPrefix:"",flowChars:{start:"{",end:"}"},itemIndent:e.indent||"",onChompKeep:n,onComment:r})}};OO.YAMLMap=AO;OO.findPair=kf});var cl=v(DH=>{"use strict";var gme=De(),CH=es(),yme={collection:"map",default:!0,nodeClass:CH.YAMLMap,tag:"tag:yaml.org,2002:map",resolve(t,e){return gme.isMap(t)||e("Expected a mapping for this tag"),t},createNode:(t,e,r)=>CH.YAMLMap.from(t,e,r)};DH.map=yme});var ts=v(NH=>{"use strict";var _me=_f(),bme=EO(),vme=Ly(),r_=De(),Sme=Dt(),wme=Wo(),TO=class extends vme.Collection{static get tagName(){return"tag:yaml.org,2002:seq"}constructor(e){super(r_.SEQ,e),this.items=[]}add(e){this.items.push(e)}delete(e){let r=t_(e);return typeof r!="number"?!1:this.items.splice(r,1).length>0}get(e,r){let n=t_(e);if(typeof n!="number")return;let i=this.items[n];return!r&&r_.isScalar(i)?i.value:i}has(e){let r=t_(e);return typeof r=="number"&&r=0?e:null}NH.YAMLSeq=TO});var ll=v(MH=>{"use strict";var xme=De(),jH=ts(),$me={collection:"seq",default:!0,nodeClass:jH.YAMLSeq,tag:"tag:yaml.org,2002:seq",resolve(t,e){return xme.isSeq(t)||e("Expected a sequence for this tag"),t},createNode:(t,e,r)=>jH.YAMLSeq.from(t,e,r)};MH.seq=$me});var Ef=v(FH=>{"use strict";var kme=wf(),Eme={identify:t=>typeof t=="string",default:!0,tag:"tag:yaml.org,2002:str",resolve:t=>t,stringify(t,e,r,n){return e=Object.assign({actualString:!0},e),kme.stringifyString(t,e,r,n)}};FH.string=Eme});var n_=v(UH=>{"use strict";var LH=Dt(),zH={identify:t=>t==null,createNode:()=>new LH.Scalar(null),default:!0,tag:"tag:yaml.org,2002:null",test:/^(?:~|[Nn]ull|NULL)?$/,resolve:()=>new LH.Scalar(null),stringify:({source:t},e)=>typeof t=="string"&&zH.test.test(t)?t:e.options.nullStr};UH.nullTag=zH});var RO=v(HH=>{"use strict";var Ame=Dt(),qH={identify:t=>typeof t=="boolean",default:!0,tag:"tag:yaml.org,2002:bool",test:/^(?:[Tt]rue|TRUE|[Ff]alse|FALSE)$/,resolve:t=>new Ame.Scalar(t[0]==="t"||t[0]==="T"),stringify({source:t,value:e},r){if(t&&qH.test.test(t)){let n=t[0]==="t"||t[0]==="T";if(e===n)return t}return e?r.options.trueStr:r.options.falseStr}};HH.boolTag=qH});var ul=v(BH=>{"use strict";function Ome({format:t,minFractionDigits:e,tag:r,value:n}){if(typeof n=="bigint")return String(n);let i=typeof n=="number"?n:Number(n);if(!isFinite(i))return isNaN(i)?".nan":i<0?"-.inf":".inf";let o=Object.is(n,-0)?"-0":JSON.stringify(n);if(!t&&e&&(!r||r==="tag:yaml.org,2002:float")&&/^-?\d/.test(o)&&!o.includes("e")){let s=o.indexOf(".");s<0&&(s=o.length,o+=".");let a=e-(o.length-s-1);for(;a-- >0;)o+="0"}return o}BH.stringifyNumber=Ome});var PO=v(i_=>{"use strict";var Tme=Dt(),IO=ul(),Rme={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,resolve:t=>t.slice(-3).toLowerCase()==="nan"?NaN:t[0]==="-"?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY,stringify:IO.stringifyNumber},Ime={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",format:"EXP",test:/^[-+]?(?:\.[0-9]+|[0-9]+(?:\.[0-9]*)?)[eE][-+]?[0-9]+$/,resolve:t=>parseFloat(t),stringify(t){let e=Number(t.value);return isFinite(e)?e.toExponential():IO.stringifyNumber(t)}},Pme={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^[-+]?(?:\.[0-9]+|[0-9]+\.[0-9]*)$/,resolve(t){let e=new Tme.Scalar(parseFloat(t)),r=t.indexOf(".");return r!==-1&&t[t.length-1]==="0"&&(e.minFractionDigits=t.length-r-1),e},stringify:IO.stringifyNumber};i_.float=Pme;i_.floatExp=Ime;i_.floatNaN=Rme});var DO=v(s_=>{"use strict";var GH=ul(),o_=t=>typeof t=="bigint"||Number.isInteger(t),CO=(t,e,r,{intAsBigInt:n})=>n?BigInt(t):parseInt(t.substring(e),r);function ZH(t,e,r){let{value:n}=t;return o_(n)&&n>=0?r+n.toString(e):GH.stringifyNumber(t)}var Cme={identify:t=>o_(t)&&t>=0,default:!0,tag:"tag:yaml.org,2002:int",format:"OCT",test:/^0o[0-7]+$/,resolve:(t,e,r)=>CO(t,2,8,r),stringify:t=>ZH(t,8,"0o")},Dme={identify:o_,default:!0,tag:"tag:yaml.org,2002:int",test:/^[-+]?[0-9]+$/,resolve:(t,e,r)=>CO(t,0,10,r),stringify:GH.stringifyNumber},Nme={identify:t=>o_(t)&&t>=0,default:!0,tag:"tag:yaml.org,2002:int",format:"HEX",test:/^0x[0-9a-fA-F]+$/,resolve:(t,e,r)=>CO(t,2,16,r),stringify:t=>ZH(t,16,"0x")};s_.int=Dme;s_.intHex=Nme;s_.intOct=Cme});var WH=v(VH=>{"use strict";var jme=cl(),Mme=n_(),Fme=ll(),Lme=Ef(),zme=RO(),NO=PO(),jO=DO(),Ume=[jme.map,Fme.seq,Lme.string,Mme.nullTag,zme.boolTag,jO.intOct,jO.int,jO.intHex,NO.floatNaN,NO.floatExp,NO.float];VH.schema=Ume});var YH=v(JH=>{"use strict";var qme=Dt(),Hme=cl(),Bme=ll();function KH(t){return typeof t=="bigint"||Number.isInteger(t)}var a_=({value:t})=>JSON.stringify(t),Gme=[{identify:t=>typeof t=="string",default:!0,tag:"tag:yaml.org,2002:str",resolve:t=>t,stringify:a_},{identify:t=>t==null,createNode:()=>new qme.Scalar(null),default:!0,tag:"tag:yaml.org,2002:null",test:/^null$/,resolve:()=>null,stringify:a_},{identify:t=>typeof t=="boolean",default:!0,tag:"tag:yaml.org,2002:bool",test:/^true$|^false$/,resolve:t=>t==="true",stringify:a_},{identify:KH,default:!0,tag:"tag:yaml.org,2002:int",test:/^-?(?:0|[1-9][0-9]*)$/,resolve:(t,e,{intAsBigInt:r})=>r?BigInt(t):parseInt(t,10),stringify:({value:t})=>KH(t)?t.toString():JSON.stringify(t)},{identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^-?(?:0|[1-9][0-9]*)(?:\.[0-9]*)?(?:[eE][-+]?[0-9]+)?$/,resolve:t=>parseFloat(t),stringify:a_}],Zme={default:!0,tag:"",test:/^/,resolve(t,e){return e(`Unresolved plain scalar ${JSON.stringify(t)}`),t}},Vme=[Hme.map,Bme.seq].concat(Gme,Zme);JH.schema=Vme});var FO=v(XH=>{"use strict";var Af=Ze("buffer"),MO=Dt(),Wme=wf(),Kme={identify:t=>t instanceof Uint8Array,default:!1,tag:"tag:yaml.org,2002:binary",resolve(t,e){if(typeof Af.Buffer=="function")return Af.Buffer.from(t,"base64");if(typeof atob=="function"){let r=atob(t.replace(/[\n\r]/g,"")),n=new Uint8Array(r.length);for(let i=0;i{"use strict";var c_=De(),LO=Xo(),Jme=Dt(),Yme=ts();function QH(t,e){if(c_.isSeq(t))for(let r=0;r1&&e("Each pair must have its own sequence indicator");let i=n.items[0]||new LO.Pair(new Jme.Scalar(null));if(n.commentBefore&&(i.key.commentBefore=i.key.commentBefore?`${n.commentBefore} ${i.key.commentBefore}`:n.commentBefore),n.comment){let o=i.value??i.key;o.comment=o.comment?`${n.comment} -${o.comment}`:n.comment}n=i}t.items[r]=o_.isPair(n)?n:new IT.Pair(n)}}else e("Expected a sequence for this tag");return t}function L6(t,e,r){let{replacer:n}=r,i=new fme.YAMLSeq(t);i.tag="tag:yaml.org,2002:pairs";let o=0;if(e&&Symbol.iterator in Object(e))for(let s of e){typeof n=="function"&&(s=n.call(e,String(o++),s));let a,c;if(Array.isArray(s))if(s.length===2)a=s[0],c=s[1];else throw new TypeError(`Expected [key, value] tuple: ${s}`);else if(s&&s instanceof Object){let l=Object.keys(s);if(l.length===1)a=l[0],c=s[a];else throw new TypeError(`Expected tuple with one key, not ${l.length} keys`)}else a=s;i.items.push(IT.createPair(a,c,r))}return i}var pme={collection:"seq",default:!1,tag:"tag:yaml.org,2002:pairs",resolve:F6,createNode:L6};s_.createPairs=L6;s_.pairs=pme;s_.resolvePairs=F6});var DT=v(CT=>{"use strict";var z6=De(),PT=Vo(),kf=Qo(),mme=es(),U6=a_(),ma=class t extends mme.YAMLSeq{constructor(){super(),this.add=kf.YAMLMap.prototype.add.bind(this),this.delete=kf.YAMLMap.prototype.delete.bind(this),this.get=kf.YAMLMap.prototype.get.bind(this),this.has=kf.YAMLMap.prototype.has.bind(this),this.set=kf.YAMLMap.prototype.set.bind(this),this.tag=t.tag}toJSON(e,r){if(!r)return super.toJSON(e);let n=new Map;r?.onCreate&&r.onCreate(n);for(let i of this.items){let o,s;if(z6.isPair(i)?(o=PT.toJS(i.key,"",r),s=PT.toJS(i.value,o,r)):o=PT.toJS(i,"",r),n.has(o))throw new Error("Ordered maps must not include duplicate keys");n.set(o,s)}return n}static from(e,r,n){let i=U6.createPairs(e,r,n),o=new this;return o.items=i.items,o}};ma.tag="tag:yaml.org,2002:omap";var hme={collection:"seq",identify:t=>t instanceof Map,nodeClass:ma,default:!1,tag:"tag:yaml.org,2002:omap",resolve(t,e){let r=U6.resolvePairs(t,e),n=[];for(let{key:i}of r.items)z6.isScalar(i)&&(n.includes(i.value)?e(`Ordered maps must not include duplicate keys: ${i.value}`):n.push(i.value));return Object.assign(new ma,r)},createNode:(t,e,r)=>ma.from(t,e,r)};CT.YAMLOMap=ma;CT.omap=hme});var Z6=v(NT=>{"use strict";var q6=Dt();function B6({value:t,source:e},r){return e&&(t?H6:G6).test.test(e)?e:t?r.options.trueStr:r.options.falseStr}var H6={identify:t=>t===!0,default:!0,tag:"tag:yaml.org,2002:bool",test:/^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/,resolve:()=>new q6.Scalar(!0),stringify:B6},G6={identify:t=>t===!1,default:!0,tag:"tag:yaml.org,2002:bool",test:/^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/,resolve:()=>new q6.Scalar(!1),stringify:B6};NT.falseTag=G6;NT.trueTag=H6});var V6=v(c_=>{"use strict";var gme=Dt(),jT=al(),yme={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,resolve:t=>t.slice(-3).toLowerCase()==="nan"?NaN:t[0]==="-"?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY,stringify:jT.stringifyNumber},_me={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",format:"EXP",test:/^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,resolve:t=>parseFloat(t.replace(/_/g,"")),stringify(t){let e=Number(t.value);return isFinite(e)?e.toExponential():jT.stringifyNumber(t)}},bme={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,resolve(t){let e=new gme.Scalar(parseFloat(t.replace(/_/g,""))),r=t.indexOf(".");if(r!==-1){let n=t.substring(r+1).replace(/_/g,"");n[n.length-1]==="0"&&(e.minFractionDigits=n.length)}return e},stringify:jT.stringifyNumber};c_.float=bme;c_.floatExp=_me;c_.floatNaN=yme});var K6=v(Af=>{"use strict";var W6=al(),Ef=t=>typeof t=="bigint"||Number.isInteger(t);function l_(t,e,r,{intAsBigInt:n}){let i=t[0];if((i==="-"||i==="+")&&(e+=1),t=t.substring(e).replace(/_/g,""),n){switch(r){case 2:t=`0b${t}`;break;case 8:t=`0o${t}`;break;case 16:t=`0x${t}`;break}let s=BigInt(t);return i==="-"?BigInt(-1)*s:s}let o=parseInt(t,r);return i==="-"?-1*o:o}function MT(t,e,r){let{value:n}=t;if(Ef(n)){let i=n.toString(e);return n<0?"-"+r+i.substr(1):r+i}return W6.stringifyNumber(t)}var vme={identify:Ef,default:!0,tag:"tag:yaml.org,2002:int",format:"BIN",test:/^[-+]?0b[0-1_]+$/,resolve:(t,e,r)=>l_(t,2,2,r),stringify:t=>MT(t,2,"0b")},Sme={identify:Ef,default:!0,tag:"tag:yaml.org,2002:int",format:"OCT",test:/^[-+]?0[0-7_]+$/,resolve:(t,e,r)=>l_(t,1,8,r),stringify:t=>MT(t,8,"0")},wme={identify:Ef,default:!0,tag:"tag:yaml.org,2002:int",test:/^[-+]?[0-9][0-9_]*$/,resolve:(t,e,r)=>l_(t,0,10,r),stringify:W6.stringifyNumber},xme={identify:Ef,default:!0,tag:"tag:yaml.org,2002:int",format:"HEX",test:/^[-+]?0x[0-9a-fA-F_]+$/,resolve:(t,e,r)=>l_(t,2,16,r),stringify:t=>MT(t,16,"0x")};Af.int=wme;Af.intBin=vme;Af.intHex=xme;Af.intOct=Sme});var LT=v(FT=>{"use strict";var f_=De(),u_=Yo(),d_=Qo(),ha=class t extends d_.YAMLMap{constructor(e){super(e),this.tag=t.tag}add(e){let r;f_.isPair(e)?r=e:e&&typeof e=="object"&&"key"in e&&"value"in e&&e.value===null?r=new u_.Pair(e.key,null):r=new u_.Pair(e,null),d_.findPair(this.items,r.key)||this.items.push(r)}get(e,r){let n=d_.findPair(this.items,e);return!r&&f_.isPair(n)?f_.isScalar(n.key)?n.key.value:n.key:n}set(e,r){if(typeof r!="boolean")throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof r}`);let n=d_.findPair(this.items,e);n&&!r?this.items.splice(this.items.indexOf(n),1):!n&&r&&this.items.push(new u_.Pair(e))}toJSON(e,r){return super.toJSON(e,r,Set)}toString(e,r,n){if(!e)return JSON.stringify(this);if(this.hasAllNullValues(!0))return super.toString(Object.assign({},e,{allNullValues:!0}),r,n);throw new Error("Set items must all have null values")}static from(e,r,n){let{replacer:i}=n,o=new this(e);if(r&&Symbol.iterator in Object(r))for(let s of r)typeof i=="function"&&(s=i.call(r,s,s)),o.items.push(u_.createPair(s,null,n));return o}};ha.tag="tag:yaml.org,2002:set";var $me={collection:"map",identify:t=>t instanceof Set,nodeClass:ha,default:!1,tag:"tag:yaml.org,2002:set",createNode:(t,e,r)=>ha.from(t,e,r),resolve(t,e){if(f_.isMap(t)){if(t.hasAllNullValues(!0))return Object.assign(new ha,t);e("Set items must all have null values")}else e("Expected a mapping for this tag");return t}};FT.YAMLSet=ha;FT.set=$me});var UT=v(p_=>{"use strict";var kme=al();function zT(t,e){let r=t[0],n=r==="-"||r==="+"?t.substring(1):t,i=s=>e?BigInt(s):Number(s),o=n.replace(/_/g,"").split(":").reduce((s,a)=>s*i(60)+i(a),i(0));return r==="-"?i(-1)*o:o}function J6(t){let{value:e}=t,r=s=>s;if(typeof e=="bigint")r=s=>BigInt(s);else if(isNaN(e)||!isFinite(e))return kme.stringifyNumber(t);let n="";e<0&&(n="-",e*=r(-1));let i=r(60),o=[e%i];return e<60?o.unshift(0):(e=(e-o[0])/i,o.unshift(e%i),e>=60&&(e=(e-o[0])/i,o.unshift(e))),n+o.map(s=>String(s).padStart(2,"0")).join(":").replace(/000000\d*$/,"")}var Eme={identify:t=>typeof t=="bigint"||Number.isInteger(t),default:!0,tag:"tag:yaml.org,2002:int",format:"TIME",test:/^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,resolve:(t,e,{intAsBigInt:r})=>zT(t,r),stringify:J6},Ame={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",format:"TIME",test:/^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,resolve:t=>zT(t,!1),stringify:J6},Y6={identify:t=>t instanceof Date,default:!0,tag:"tag:yaml.org,2002:timestamp",test:RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"),resolve(t){let e=t.match(Y6.test);if(!e)throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");let[,r,n,i,o,s,a]=e.map(Number),c=e[7]?Number((e[7]+"00").substr(1,3)):0,l=Date.UTC(r,n-1,i,o||0,s||0,a||0,c),u=e[8];if(u&&u!=="Z"){let d=zT(u,!1);Math.abs(d)<30&&(d*=60),l-=6e4*d}return new Date(l)},stringify:({value:t})=>t?.toISOString().replace(/(T00:00:00)?\.000Z$/,"")??""};p_.floatTime=Ame;p_.intTime=Eme;p_.timestamp=Y6});var eB=v(Q6=>{"use strict";var Tme=ol(),Ome=e_(),Rme=sl(),Ime=xf(),Pme=RT(),X6=Z6(),qT=V6(),m_=K6(),Cme=Zy(),Dme=DT(),Nme=a_(),jme=LT(),BT=UT(),Mme=[Tme.map,Rme.seq,Ime.string,Ome.nullTag,X6.trueTag,X6.falseTag,m_.intBin,m_.intOct,m_.int,m_.intHex,qT.floatNaN,qT.floatExp,qT.float,Pme.binary,Cme.merge,Dme.omap,Nme.pairs,jme.set,BT.intTime,BT.floatTime,BT.timestamp];Q6.schema=Mme});var uB=v(ZT=>{"use strict";var iB=ol(),Fme=e_(),oB=sl(),Lme=xf(),zme=wT(),HT=$T(),GT=ET(),Ume=C6(),qme=j6(),sB=RT(),Tf=Zy(),aB=DT(),cB=a_(),tB=eB(),lB=LT(),h_=UT(),rB=new Map([["core",Ume.schema],["failsafe",[iB.map,oB.seq,Lme.string]],["json",qme.schema],["yaml11",tB.schema],["yaml-1.1",tB.schema]]),nB={binary:sB.binary,bool:zme.boolTag,float:HT.float,floatExp:HT.floatExp,floatNaN:HT.floatNaN,floatTime:h_.floatTime,int:GT.int,intHex:GT.intHex,intOct:GT.intOct,intTime:h_.intTime,map:iB.map,merge:Tf.merge,null:Fme.nullTag,omap:aB.omap,pairs:cB.pairs,seq:oB.seq,set:lB.set,timestamp:h_.timestamp},Bme={"tag:yaml.org,2002:binary":sB.binary,"tag:yaml.org,2002:merge":Tf.merge,"tag:yaml.org,2002:omap":aB.omap,"tag:yaml.org,2002:pairs":cB.pairs,"tag:yaml.org,2002:set":lB.set,"tag:yaml.org,2002:timestamp":h_.timestamp};function Hme(t,e,r){let n=rB.get(e);if(n&&!t)return r&&!n.includes(Tf.merge)?n.concat(Tf.merge):n.slice();let i=n;if(!i)if(Array.isArray(t))i=[];else{let o=Array.from(rB.keys()).filter(s=>s!=="yaml11").map(s=>JSON.stringify(s)).join(", ");throw new Error(`Unknown schema "${e}"; use one of ${o} or define customTags array`)}if(Array.isArray(t))for(let o of t)i=i.concat(o);else typeof t=="function"&&(i=t(i.slice()));return r&&(i=i.concat(Tf.merge)),i.reduce((o,s)=>{let a=typeof s=="string"?nB[s]:s;if(!a){let c=JSON.stringify(s),l=Object.keys(nB).map(u=>JSON.stringify(u)).join(", ");throw new Error(`Unknown custom tag ${c}; use one of ${l}`)}return o.includes(a)||o.push(a),o},[])}ZT.coreKnownTags=Bme;ZT.getTags=Hme});var KT=v(dB=>{"use strict";var VT=De(),Gme=ol(),Zme=sl(),Vme=xf(),g_=uB(),Wme=(t,e)=>t.keye.key?1:0,WT=class t{constructor({compat:e,customTags:r,merge:n,resolveKnownTags:i,schema:o,sortMapEntries:s,toStringDefaults:a}){this.compat=Array.isArray(e)?g_.getTags(e,"compat"):e?g_.getTags(null,e):null,this.name=typeof o=="string"&&o||"core",this.knownTags=i?g_.coreKnownTags:{},this.tags=g_.getTags(r,this.name,n),this.toStringOptions=a??null,Object.defineProperty(this,VT.MAP,{value:Gme.map}),Object.defineProperty(this,VT.SCALAR,{value:Vme.string}),Object.defineProperty(this,VT.SEQ,{value:Zme.seq}),this.sortMapEntries=typeof s=="function"?s:s===!0?Wme:null}clone(){let e=Object.create(t.prototype,Object.getOwnPropertyDescriptors(this));return e.tags=this.tags.slice(),e}};dB.Schema=WT});var pB=v(fB=>{"use strict";var Kme=De(),JT=vf(),Of=gf();function Jme(t,e){let r=[],n=e.directives===!0;if(e.directives!==!1&&t.directives){let c=t.directives.toString(t);c?(r.push(c),n=!0):t.directives.docStart&&(n=!0)}n&&r.push("---");let i=JT.createStringifyContext(t,e),{commentString:o}=i.options;if(t.commentBefore){r.length!==1&&r.unshift("");let c=o(t.commentBefore);r.unshift(Of.indentComment(c,""))}let s=!1,a=null;if(t.contents){if(Kme.isNode(t.contents)){if(t.contents.spaceBefore&&n&&r.push(""),t.contents.commentBefore){let u=o(t.contents.commentBefore);r.push(Of.indentComment(u,""))}i.forceBlockIndent=!!t.comment,a=t.contents.comment}let c=a?void 0:()=>s=!0,l=JT.stringify(t.contents,i,()=>a=null,c);a&&(l+=Of.lineComment(l,"",o(a))),(l[0]==="|"||l[0]===">")&&r[r.length-1]==="---"?r[r.length-1]=`--- ${l}`:r.push(l)}else r.push(JT.stringify(t.contents,i));if(t.directives?.docEnd)if(t.comment){let c=o(t.comment);c.includes(` -`)?(r.push("..."),r.push(Of.indentComment(c,""))):r.push(`... ${c}`)}else r.push("...");else{let c=t.comment;c&&s&&(c=c.replace(/^\n+/,"")),c&&((!s||a)&&r[r.length-1]!==""&&r.push(""),r.push(Of.indentComment(o(c),"")))}return r.join(` +${o.comment}`:n.comment}n=i}t.items[r]=c_.isPair(n)?n:new LO.Pair(n)}}else e("Expected a sequence for this tag");return t}function e6(t,e,r){let{replacer:n}=r,i=new Yme.YAMLSeq(t);i.tag="tag:yaml.org,2002:pairs";let o=0;if(e&&Symbol.iterator in Object(e))for(let s of e){typeof n=="function"&&(s=n.call(e,String(o++),s));let a,c;if(Array.isArray(s))if(s.length===2)a=s[0],c=s[1];else throw new TypeError(`Expected [key, value] tuple: ${s}`);else if(s&&s instanceof Object){let l=Object.keys(s);if(l.length===1)a=l[0],c=s[a];else throw new TypeError(`Expected tuple with one key, not ${l.length} keys`)}else a=s;i.items.push(LO.createPair(a,c,r))}return i}var Xme={collection:"seq",default:!1,tag:"tag:yaml.org,2002:pairs",resolve:QH,createNode:e6};l_.createPairs=e6;l_.pairs=Xme;l_.resolvePairs=QH});var qO=v(UO=>{"use strict";var t6=De(),zO=Wo(),Of=es(),Qme=ts(),r6=u_(),ya=class t extends Qme.YAMLSeq{constructor(){super(),this.add=Of.YAMLMap.prototype.add.bind(this),this.delete=Of.YAMLMap.prototype.delete.bind(this),this.get=Of.YAMLMap.prototype.get.bind(this),this.has=Of.YAMLMap.prototype.has.bind(this),this.set=Of.YAMLMap.prototype.set.bind(this),this.tag=t.tag}toJSON(e,r){if(!r)return super.toJSON(e);let n=new Map;r?.onCreate&&r.onCreate(n);for(let i of this.items){let o,s;if(t6.isPair(i)?(o=zO.toJS(i.key,"",r),s=zO.toJS(i.value,o,r)):o=zO.toJS(i,"",r),n.has(o))throw new Error("Ordered maps must not include duplicate keys");n.set(o,s)}return n}static from(e,r,n){let i=r6.createPairs(e,r,n),o=new this;return o.items=i.items,o}};ya.tag="tag:yaml.org,2002:omap";var ehe={collection:"seq",identify:t=>t instanceof Map,nodeClass:ya,default:!1,tag:"tag:yaml.org,2002:omap",resolve(t,e){let r=r6.resolvePairs(t,e),n=[];for(let{key:i}of r.items)t6.isScalar(i)&&(n.includes(i.value)?e(`Ordered maps must not include duplicate keys: ${i.value}`):n.push(i.value));return Object.assign(new ya,r)},createNode:(t,e,r)=>ya.from(t,e,r)};UO.YAMLOMap=ya;UO.omap=ehe});var a6=v(HO=>{"use strict";var n6=Dt();function i6({value:t,source:e},r){return e&&(t?o6:s6).test.test(e)?e:t?r.options.trueStr:r.options.falseStr}var o6={identify:t=>t===!0,default:!0,tag:"tag:yaml.org,2002:bool",test:/^(?:Y|y|[Yy]es|YES|[Tt]rue|TRUE|[Oo]n|ON)$/,resolve:()=>new n6.Scalar(!0),stringify:i6},s6={identify:t=>t===!1,default:!0,tag:"tag:yaml.org,2002:bool",test:/^(?:N|n|[Nn]o|NO|[Ff]alse|FALSE|[Oo]ff|OFF)$/,resolve:()=>new n6.Scalar(!1),stringify:i6};HO.falseTag=s6;HO.trueTag=o6});var c6=v(d_=>{"use strict";var the=Dt(),BO=ul(),rhe={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^(?:[-+]?\.(?:inf|Inf|INF)|\.nan|\.NaN|\.NAN)$/,resolve:t=>t.slice(-3).toLowerCase()==="nan"?NaN:t[0]==="-"?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY,stringify:BO.stringifyNumber},nhe={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",format:"EXP",test:/^[-+]?(?:[0-9][0-9_]*)?(?:\.[0-9_]*)?[eE][-+]?[0-9]+$/,resolve:t=>parseFloat(t.replace(/_/g,"")),stringify(t){let e=Number(t.value);return isFinite(e)?e.toExponential():BO.stringifyNumber(t)}},ihe={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",test:/^[-+]?(?:[0-9][0-9_]*)?\.[0-9_]*$/,resolve(t){let e=new the.Scalar(parseFloat(t.replace(/_/g,""))),r=t.indexOf(".");if(r!==-1){let n=t.substring(r+1).replace(/_/g,"");n[n.length-1]==="0"&&(e.minFractionDigits=n.length)}return e},stringify:BO.stringifyNumber};d_.float=ihe;d_.floatExp=nhe;d_.floatNaN=rhe});var u6=v(Rf=>{"use strict";var l6=ul(),Tf=t=>typeof t=="bigint"||Number.isInteger(t);function f_(t,e,r,{intAsBigInt:n}){let i=t[0];if((i==="-"||i==="+")&&(e+=1),t=t.substring(e).replace(/_/g,""),n){switch(r){case 2:t=`0b${t}`;break;case 8:t=`0o${t}`;break;case 16:t=`0x${t}`;break}let s=BigInt(t);return i==="-"?BigInt(-1)*s:s}let o=parseInt(t,r);return i==="-"?-1*o:o}function GO(t,e,r){let{value:n}=t;if(Tf(n)){let i=n.toString(e);return n<0?"-"+r+i.substr(1):r+i}return l6.stringifyNumber(t)}var ohe={identify:Tf,default:!0,tag:"tag:yaml.org,2002:int",format:"BIN",test:/^[-+]?0b[0-1_]+$/,resolve:(t,e,r)=>f_(t,2,2,r),stringify:t=>GO(t,2,"0b")},she={identify:Tf,default:!0,tag:"tag:yaml.org,2002:int",format:"OCT",test:/^[-+]?0[0-7_]+$/,resolve:(t,e,r)=>f_(t,1,8,r),stringify:t=>GO(t,8,"0")},ahe={identify:Tf,default:!0,tag:"tag:yaml.org,2002:int",test:/^[-+]?[0-9][0-9_]*$/,resolve:(t,e,r)=>f_(t,0,10,r),stringify:l6.stringifyNumber},che={identify:Tf,default:!0,tag:"tag:yaml.org,2002:int",format:"HEX",test:/^[-+]?0x[0-9a-fA-F_]+$/,resolve:(t,e,r)=>f_(t,2,16,r),stringify:t=>GO(t,16,"0x")};Rf.int=ahe;Rf.intBin=ohe;Rf.intHex=che;Rf.intOct=she});var VO=v(ZO=>{"use strict";var h_=De(),p_=Xo(),m_=es(),_a=class t extends m_.YAMLMap{constructor(e){super(e),this.tag=t.tag}add(e){let r;h_.isPair(e)?r=e:e&&typeof e=="object"&&"key"in e&&"value"in e&&e.value===null?r=new p_.Pair(e.key,null):r=new p_.Pair(e,null),m_.findPair(this.items,r.key)||this.items.push(r)}get(e,r){let n=m_.findPair(this.items,e);return!r&&h_.isPair(n)?h_.isScalar(n.key)?n.key.value:n.key:n}set(e,r){if(typeof r!="boolean")throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof r}`);let n=m_.findPair(this.items,e);n&&!r?this.items.splice(this.items.indexOf(n),1):!n&&r&&this.items.push(new p_.Pair(e))}toJSON(e,r){return super.toJSON(e,r,Set)}toString(e,r,n){if(!e)return JSON.stringify(this);if(this.hasAllNullValues(!0))return super.toString(Object.assign({},e,{allNullValues:!0}),r,n);throw new Error("Set items must all have null values")}static from(e,r,n){let{replacer:i}=n,o=new this(e);if(r&&Symbol.iterator in Object(r))for(let s of r)typeof i=="function"&&(s=i.call(r,s,s)),o.items.push(p_.createPair(s,null,n));return o}};_a.tag="tag:yaml.org,2002:set";var lhe={collection:"map",identify:t=>t instanceof Set,nodeClass:_a,default:!1,tag:"tag:yaml.org,2002:set",createNode:(t,e,r)=>_a.from(t,e,r),resolve(t,e){if(h_.isMap(t)){if(t.hasAllNullValues(!0))return Object.assign(new _a,t);e("Set items must all have null values")}else e("Expected a mapping for this tag");return t}};ZO.YAMLSet=_a;ZO.set=lhe});var KO=v(g_=>{"use strict";var uhe=ul();function WO(t,e){let r=t[0],n=r==="-"||r==="+"?t.substring(1):t,i=s=>e?BigInt(s):Number(s),o=n.replace(/_/g,"").split(":").reduce((s,a)=>s*i(60)+i(a),i(0));return r==="-"?i(-1)*o:o}function d6(t){let{value:e}=t,r=s=>s;if(typeof e=="bigint")r=s=>BigInt(s);else if(isNaN(e)||!isFinite(e))return uhe.stringifyNumber(t);let n="";e<0&&(n="-",e*=r(-1));let i=r(60),o=[e%i];return e<60?o.unshift(0):(e=(e-o[0])/i,o.unshift(e%i),e>=60&&(e=(e-o[0])/i,o.unshift(e))),n+o.map(s=>String(s).padStart(2,"0")).join(":").replace(/000000\d*$/,"")}var dhe={identify:t=>typeof t=="bigint"||Number.isInteger(t),default:!0,tag:"tag:yaml.org,2002:int",format:"TIME",test:/^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+$/,resolve:(t,e,{intAsBigInt:r})=>WO(t,r),stringify:d6},fhe={identify:t=>typeof t=="number",default:!0,tag:"tag:yaml.org,2002:float",format:"TIME",test:/^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\.[0-9_]*$/,resolve:t=>WO(t,!1),stringify:d6},f6={identify:t=>t instanceof Date,default:!0,tag:"tag:yaml.org,2002:timestamp",test:RegExp("^([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})(?:(?:t|T|[ \\t]+)([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2}(\\.[0-9]+)?)(?:[ \\t]*(Z|[-+][012]?[0-9](?::[0-9]{2})?))?)?$"),resolve(t){let e=t.match(f6.test);if(!e)throw new Error("!!timestamp expects a date, starting with yyyy-mm-dd");let[,r,n,i,o,s,a]=e.map(Number),c=e[7]?Number((e[7]+"00").substr(1,3)):0,l=Date.UTC(r,n-1,i,o||0,s||0,a||0,c),u=e[8];if(u&&u!=="Z"){let d=WO(u,!1);Math.abs(d)<30&&(d*=60),l-=6e4*d}return new Date(l)},stringify:({value:t})=>t?.toISOString().replace(/(T00:00:00)?\.000Z$/,"")??""};g_.floatTime=fhe;g_.intTime=dhe;g_.timestamp=f6});var h6=v(m6=>{"use strict";var phe=cl(),mhe=n_(),hhe=ll(),ghe=Ef(),yhe=FO(),p6=a6(),JO=c6(),y_=u6(),_he=Ky(),bhe=qO(),vhe=u_(),She=VO(),YO=KO(),whe=[phe.map,hhe.seq,ghe.string,mhe.nullTag,p6.trueTag,p6.falseTag,y_.intBin,y_.intOct,y_.int,y_.intHex,JO.floatNaN,JO.floatExp,JO.float,yhe.binary,_he.merge,bhe.omap,vhe.pairs,She.set,YO.intTime,YO.floatTime,YO.timestamp];m6.schema=whe});var k6=v(eT=>{"use strict";var b6=cl(),xhe=n_(),v6=ll(),$he=Ef(),khe=RO(),XO=PO(),QO=DO(),Ehe=WH(),Ahe=YH(),S6=FO(),If=Ky(),w6=qO(),x6=u_(),g6=h6(),$6=VO(),__=KO(),y6=new Map([["core",Ehe.schema],["failsafe",[b6.map,v6.seq,$he.string]],["json",Ahe.schema],["yaml11",g6.schema],["yaml-1.1",g6.schema]]),_6={binary:S6.binary,bool:khe.boolTag,float:XO.float,floatExp:XO.floatExp,floatNaN:XO.floatNaN,floatTime:__.floatTime,int:QO.int,intHex:QO.intHex,intOct:QO.intOct,intTime:__.intTime,map:b6.map,merge:If.merge,null:xhe.nullTag,omap:w6.omap,pairs:x6.pairs,seq:v6.seq,set:$6.set,timestamp:__.timestamp},Ohe={"tag:yaml.org,2002:binary":S6.binary,"tag:yaml.org,2002:merge":If.merge,"tag:yaml.org,2002:omap":w6.omap,"tag:yaml.org,2002:pairs":x6.pairs,"tag:yaml.org,2002:set":$6.set,"tag:yaml.org,2002:timestamp":__.timestamp};function The(t,e,r){let n=y6.get(e);if(n&&!t)return r&&!n.includes(If.merge)?n.concat(If.merge):n.slice();let i=n;if(!i)if(Array.isArray(t))i=[];else{let o=Array.from(y6.keys()).filter(s=>s!=="yaml11").map(s=>JSON.stringify(s)).join(", ");throw new Error(`Unknown schema "${e}"; use one of ${o} or define customTags array`)}if(Array.isArray(t))for(let o of t)i=i.concat(o);else typeof t=="function"&&(i=t(i.slice()));return r&&(i=i.concat(If.merge)),i.reduce((o,s)=>{let a=typeof s=="string"?_6[s]:s;if(!a){let c=JSON.stringify(s),l=Object.keys(_6).map(u=>JSON.stringify(u)).join(", ");throw new Error(`Unknown custom tag ${c}; use one of ${l}`)}return o.includes(a)||o.push(a),o},[])}eT.coreKnownTags=Ohe;eT.getTags=The});var nT=v(E6=>{"use strict";var tT=De(),Rhe=cl(),Ihe=ll(),Phe=Ef(),b_=k6(),Che=(t,e)=>t.keye.key?1:0,rT=class t{constructor({compat:e,customTags:r,merge:n,resolveKnownTags:i,schema:o,sortMapEntries:s,toStringDefaults:a}){this.compat=Array.isArray(e)?b_.getTags(e,"compat"):e?b_.getTags(null,e):null,this.name=typeof o=="string"&&o||"core",this.knownTags=i?b_.coreKnownTags:{},this.tags=b_.getTags(r,this.name,n),this.toStringOptions=a??null,Object.defineProperty(this,tT.MAP,{value:Rhe.map}),Object.defineProperty(this,tT.SCALAR,{value:Phe.string}),Object.defineProperty(this,tT.SEQ,{value:Ihe.seq}),this.sortMapEntries=typeof s=="function"?s:s===!0?Che:null}clone(){let e=Object.create(t.prototype,Object.getOwnPropertyDescriptors(this));return e.tags=this.tags.slice(),e}};E6.Schema=rT});var O6=v(A6=>{"use strict";var Dhe=De(),iT=xf(),Pf=bf();function Nhe(t,e){let r=[],n=e.directives===!0;if(e.directives!==!1&&t.directives){let c=t.directives.toString(t);c?(r.push(c),n=!0):t.directives.docStart&&(n=!0)}n&&r.push("---");let i=iT.createStringifyContext(t,e),{commentString:o}=i.options;if(t.commentBefore){r.length!==1&&r.unshift("");let c=o(t.commentBefore);r.unshift(Pf.indentComment(c,""))}let s=!1,a=null;if(t.contents){if(Dhe.isNode(t.contents)){if(t.contents.spaceBefore&&n&&r.push(""),t.contents.commentBefore){let u=o(t.contents.commentBefore);r.push(Pf.indentComment(u,""))}i.forceBlockIndent=!!t.comment,a=t.contents.comment}let c=a?void 0:()=>s=!0,l=iT.stringify(t.contents,i,()=>a=null,c);a&&(l+=Pf.lineComment(l,"",o(a))),(l[0]==="|"||l[0]===">")&&r[r.length-1]==="---"?r[r.length-1]=`--- ${l}`:r.push(l)}else r.push(iT.stringify(t.contents,i));if(t.directives?.docEnd)if(t.comment){let c=o(t.comment);c.includes(` +`)?(r.push("..."),r.push(Pf.indentComment(c,""))):r.push(`... ${c}`)}else r.push("...");else{let c=t.comment;c&&s&&(c=c.replace(/^\n+/,"")),c&&((!s||a)&&r[r.length-1]!==""&&r.push(""),r.push(Pf.indentComment(o(c),"")))}return r.join(` `)+` -`}fB.stringifyDocument=Jme});var Rf=v(mB=>{"use strict";var Yme=mf(),cl=jy(),On=De(),Xme=Yo(),Qme=Vo(),ehe=KT(),the=pB(),YT=Py(),rhe=tT(),nhe=hf(),XT=eT(),QT=class t{constructor(e,r,n){this.commentBefore=null,this.comment=null,this.errors=[],this.warnings=[],Object.defineProperty(this,On.NODE_TYPE,{value:On.DOC});let i=null;typeof r=="function"||Array.isArray(r)?i=r:n===void 0&&r&&(n=r,r=void 0);let o=Object.assign({intAsBigInt:!1,keepSourceTokens:!1,logLevel:"warn",prettyErrors:!0,strict:!0,stringKeys:!1,uniqueKeys:!0,version:"1.2"},n);this.options=o;let{version:s}=o;n?._directives?(this.directives=n._directives.atDocument(),this.directives.yaml.explicit&&(s=this.directives.yaml.version)):this.directives=new XT.Directives({version:s}),this.setSchema(s,n),this.contents=e===void 0?null:this.createNode(e,i,n)}clone(){let e=Object.create(t.prototype,{[On.NODE_TYPE]:{value:On.DOC}});return e.commentBefore=this.commentBefore,e.comment=this.comment,e.errors=this.errors.slice(),e.warnings=this.warnings.slice(),e.options=Object.assign({},this.options),this.directives&&(e.directives=this.directives.clone()),e.schema=this.schema.clone(),e.contents=On.isNode(this.contents)?this.contents.clone(e.schema):this.contents,this.range&&(e.range=this.range.slice()),e}add(e){ll(this.contents)&&this.contents.add(e)}addIn(e,r){ll(this.contents)&&this.contents.addIn(e,r)}createAlias(e,r){if(!e.anchor){let n=YT.anchorNames(this);e.anchor=!r||n.has(r)?YT.findNewAnchor(r||"a",n):r}return new Yme.Alias(e.anchor)}createNode(e,r,n){let i;if(typeof r=="function")e=r.call({"":e},"",e),i=r;else if(Array.isArray(r)){let g=_=>typeof _=="number"||_ instanceof String||_ instanceof Number,b=r.filter(g).map(String);b.length>0&&(r=r.concat(b)),i=r}else n===void 0&&r&&(n=r,r=void 0);let{aliasDuplicateObjects:o,anchorPrefix:s,flow:a,keepUndefined:c,onTagObj:l,tag:u}=n??{},{onAnchor:d,setAnchors:f,sourceObjects:p}=YT.createNodeAnchors(this,s||"a"),m={aliasDuplicateObjects:o??!0,keepUndefined:c??!1,onAnchor:d,onTagObj:l,replacer:i,schema:this.schema,sourceObjects:p},h=nhe.createNode(e,u,m);return a&&On.isCollection(h)&&(h.flow=!0),f(),h}createPair(e,r,n={}){let i=this.createNode(e,null,n),o=this.createNode(r,null,n);return new Xme.Pair(i,o)}delete(e){return ll(this.contents)?this.contents.delete(e):!1}deleteIn(e){return cl.isEmptyPath(e)?this.contents==null?!1:(this.contents=null,!0):ll(this.contents)?this.contents.deleteIn(e):!1}get(e,r){return On.isCollection(this.contents)?this.contents.get(e,r):void 0}getIn(e,r){return cl.isEmptyPath(e)?!r&&On.isScalar(this.contents)?this.contents.value:this.contents:On.isCollection(this.contents)?this.contents.getIn(e,r):void 0}has(e){return On.isCollection(this.contents)?this.contents.has(e):!1}hasIn(e){return cl.isEmptyPath(e)?this.contents!==void 0:On.isCollection(this.contents)?this.contents.hasIn(e):!1}set(e,r){this.contents==null?this.contents=cl.collectionFromPath(this.schema,[e],r):ll(this.contents)&&this.contents.set(e,r)}setIn(e,r){cl.isEmptyPath(e)?this.contents=r:this.contents==null?this.contents=cl.collectionFromPath(this.schema,Array.from(e),r):ll(this.contents)&&this.contents.setIn(e,r)}setSchema(e,r={}){typeof e=="number"&&(e=String(e));let n;switch(e){case"1.1":this.directives?this.directives.yaml.version="1.1":this.directives=new XT.Directives({version:"1.1"}),n={resolveKnownTags:!1,schema:"yaml-1.1"};break;case"1.2":case"next":this.directives?this.directives.yaml.version=e:this.directives=new XT.Directives({version:e}),n={resolveKnownTags:!0,schema:"core"};break;case null:this.directives&&delete this.directives,n=null;break;default:{let i=JSON.stringify(e);throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${i}`)}}if(r.schema instanceof Object)this.schema=r.schema;else if(n)this.schema=new ehe.Schema(Object.assign(n,r));else throw new Error("With a null YAML version, the { schema: Schema } option is required")}toJS({json:e,jsonArg:r,mapAsMap:n,maxAliasCount:i,onAnchor:o,reviver:s}={}){let a={anchors:new Map,doc:this,keep:!e,mapAsMap:n===!0,mapKeyWarned:!1,maxAliasCount:typeof i=="number"?i:100},c=Qme.toJS(this.contents,r??"",a);if(typeof o=="function")for(let{count:l,res:u}of a.anchors.values())o(u,l);return typeof s=="function"?rhe.applyReviver(s,{"":c},"",c):c}toJSON(e,r){return this.toJS({json:!0,jsonArg:e,mapAsMap:!1,onAnchor:r})}toString(e={}){if(this.errors.length>0)throw new Error("Document with errors cannot be stringified");if("indent"in e&&(!Number.isInteger(e.indent)||Number(e.indent)<=0)){let r=JSON.stringify(e.indent);throw new Error(`"indent" option must be a positive integer, not ${r}`)}return the.stringifyDocument(this,e)}};function ll(t){if(On.isCollection(t))return!0;throw new Error("Expected a YAML collection as document contents")}mB.Document=QT});var Cf=v(Pf=>{"use strict";var If=class extends Error{constructor(e,r,n,i){super(),this.name=e,this.code=n,this.message=i,this.pos=r}},eO=class extends If{constructor(e,r,n){super("YAMLParseError",e,r,n)}},tO=class extends If{constructor(e,r,n){super("YAMLWarning",e,r,n)}},ihe=(t,e)=>r=>{if(r.pos[0]===-1)return;r.linePos=r.pos.map(a=>e.linePos(a));let{line:n,col:i}=r.linePos[0];r.message+=` at line ${n}, column ${i}`;let o=i-1,s=t.substring(e.lineStarts[n-1],e.lineStarts[n]).replace(/[\n\r]+$/,"");if(o>=60&&s.length>80){let a=Math.min(o-39,s.length-79);s="\u2026"+s.substring(a),o-=a-1}if(s.length>80&&(s=s.substring(0,79)+"\u2026"),n>1&&/^ *$/.test(s.substring(0,o))){let a=t.substring(e.lineStarts[n-2],e.lineStarts[n-1]);a.length>80&&(a=a.substring(0,79)+`\u2026 +`}A6.stringifyDocument=Nhe});var Cf=v(T6=>{"use strict";var jhe=yf(),dl=Ly(),Rn=De(),Mhe=Xo(),Fhe=Wo(),Lhe=nT(),zhe=O6(),oT=Ny(),Uhe=lO(),qhe=_f(),sT=cO(),aT=class t{constructor(e,r,n){this.commentBefore=null,this.comment=null,this.errors=[],this.warnings=[],Object.defineProperty(this,Rn.NODE_TYPE,{value:Rn.DOC});let i=null;typeof r=="function"||Array.isArray(r)?i=r:n===void 0&&r&&(n=r,r=void 0);let o=Object.assign({intAsBigInt:!1,keepSourceTokens:!1,logLevel:"warn",prettyErrors:!0,strict:!0,stringKeys:!1,uniqueKeys:!0,version:"1.2"},n);this.options=o;let{version:s}=o;n?._directives?(this.directives=n._directives.atDocument(),this.directives.yaml.explicit&&(s=this.directives.yaml.version)):this.directives=new sT.Directives({version:s}),this.setSchema(s,n),this.contents=e===void 0?null:this.createNode(e,i,n)}clone(){let e=Object.create(t.prototype,{[Rn.NODE_TYPE]:{value:Rn.DOC}});return e.commentBefore=this.commentBefore,e.comment=this.comment,e.errors=this.errors.slice(),e.warnings=this.warnings.slice(),e.options=Object.assign({},this.options),this.directives&&(e.directives=this.directives.clone()),e.schema=this.schema.clone(),e.contents=Rn.isNode(this.contents)?this.contents.clone(e.schema):this.contents,this.range&&(e.range=this.range.slice()),e}add(e){fl(this.contents)&&this.contents.add(e)}addIn(e,r){fl(this.contents)&&this.contents.addIn(e,r)}createAlias(e,r){if(!e.anchor){let n=oT.anchorNames(this);e.anchor=!r||n.has(r)?oT.findNewAnchor(r||"a",n):r}return new jhe.Alias(e.anchor)}createNode(e,r,n){let i;if(typeof r=="function")e=r.call({"":e},"",e),i=r;else if(Array.isArray(r)){let g=_=>typeof _=="number"||_ instanceof String||_ instanceof Number,b=r.filter(g).map(String);b.length>0&&(r=r.concat(b)),i=r}else n===void 0&&r&&(n=r,r=void 0);let{aliasDuplicateObjects:o,anchorPrefix:s,flow:a,keepUndefined:c,onTagObj:l,tag:u}=n??{},{onAnchor:d,setAnchors:f,sourceObjects:p}=oT.createNodeAnchors(this,s||"a"),m={aliasDuplicateObjects:o??!0,keepUndefined:c??!1,onAnchor:d,onTagObj:l,replacer:i,schema:this.schema,sourceObjects:p},h=qhe.createNode(e,u,m);return a&&Rn.isCollection(h)&&(h.flow=!0),f(),h}createPair(e,r,n={}){let i=this.createNode(e,null,n),o=this.createNode(r,null,n);return new Mhe.Pair(i,o)}delete(e){return fl(this.contents)?this.contents.delete(e):!1}deleteIn(e){return dl.isEmptyPath(e)?this.contents==null?!1:(this.contents=null,!0):fl(this.contents)?this.contents.deleteIn(e):!1}get(e,r){return Rn.isCollection(this.contents)?this.contents.get(e,r):void 0}getIn(e,r){return dl.isEmptyPath(e)?!r&&Rn.isScalar(this.contents)?this.contents.value:this.contents:Rn.isCollection(this.contents)?this.contents.getIn(e,r):void 0}has(e){return Rn.isCollection(this.contents)?this.contents.has(e):!1}hasIn(e){return dl.isEmptyPath(e)?this.contents!==void 0:Rn.isCollection(this.contents)?this.contents.hasIn(e):!1}set(e,r){this.contents==null?this.contents=dl.collectionFromPath(this.schema,[e],r):fl(this.contents)&&this.contents.set(e,r)}setIn(e,r){dl.isEmptyPath(e)?this.contents=r:this.contents==null?this.contents=dl.collectionFromPath(this.schema,Array.from(e),r):fl(this.contents)&&this.contents.setIn(e,r)}setSchema(e,r={}){typeof e=="number"&&(e=String(e));let n;switch(e){case"1.1":this.directives?this.directives.yaml.version="1.1":this.directives=new sT.Directives({version:"1.1"}),n={resolveKnownTags:!1,schema:"yaml-1.1"};break;case"1.2":case"next":this.directives?this.directives.yaml.version=e:this.directives=new sT.Directives({version:e}),n={resolveKnownTags:!0,schema:"core"};break;case null:this.directives&&delete this.directives,n=null;break;default:{let i=JSON.stringify(e);throw new Error(`Expected '1.1', '1.2' or null as first argument, but found: ${i}`)}}if(r.schema instanceof Object)this.schema=r.schema;else if(n)this.schema=new Lhe.Schema(Object.assign(n,r));else throw new Error("With a null YAML version, the { schema: Schema } option is required")}toJS({json:e,jsonArg:r,mapAsMap:n,maxAliasCount:i,onAnchor:o,reviver:s}={}){let a={anchors:new Map,doc:this,keep:!e,mapAsMap:n===!0,mapKeyWarned:!1,maxAliasCount:typeof i=="number"?i:100},c=Fhe.toJS(this.contents,r??"",a);if(typeof o=="function")for(let{count:l,res:u}of a.anchors.values())o(u,l);return typeof s=="function"?Uhe.applyReviver(s,{"":c},"",c):c}toJSON(e,r){return this.toJS({json:!0,jsonArg:e,mapAsMap:!1,onAnchor:r})}toString(e={}){if(this.errors.length>0)throw new Error("Document with errors cannot be stringified");if("indent"in e&&(!Number.isInteger(e.indent)||Number(e.indent)<=0)){let r=JSON.stringify(e.indent);throw new Error(`"indent" option must be a positive integer, not ${r}`)}return zhe.stringifyDocument(this,e)}};function fl(t){if(Rn.isCollection(t))return!0;throw new Error("Expected a YAML collection as document contents")}T6.Document=aT});var jf=v(Nf=>{"use strict";var Df=class extends Error{constructor(e,r,n,i){super(),this.name=e,this.code=n,this.message=i,this.pos=r}},cT=class extends Df{constructor(e,r,n){super("YAMLParseError",e,r,n)}},lT=class extends Df{constructor(e,r,n){super("YAMLWarning",e,r,n)}},Hhe=(t,e)=>r=>{if(r.pos[0]===-1)return;r.linePos=r.pos.map(a=>e.linePos(a));let{line:n,col:i}=r.linePos[0];r.message+=` at line ${n}, column ${i}`;let o=i-1,s=t.substring(e.lineStarts[n-1],e.lineStarts[n]).replace(/[\n\r]+$/,"");if(o>=60&&s.length>80){let a=Math.min(o-39,s.length-79);s="\u2026"+s.substring(a),o-=a-1}if(s.length>80&&(s=s.substring(0,79)+"\u2026"),n>1&&/^ *$/.test(s.substring(0,o))){let a=t.substring(e.lineStarts[n-2],e.lineStarts[n-1]);a.length>80&&(a=a.substring(0,79)+`\u2026 `),s=a+s}if(/[^ ]/.test(s)){let a=1,c=r.linePos[1];c?.line===n&&c.col>i&&(a=Math.max(1,Math.min(c.col-i,80-o)));let l=" ".repeat(o)+"^".repeat(a);r.message+=`: ${s} ${l} -`}};Pf.YAMLError=If;Pf.YAMLParseError=eO;Pf.YAMLWarning=tO;Pf.prettifyError=ihe});var Df=v(hB=>{"use strict";function ohe(t,{flow:e,indicator:r,next:n,offset:i,onError:o,parentIndent:s,startOnNewline:a}){let c=!1,l=a,u=a,d="",f="",p=!1,m=!1,h=null,g=null,b=null,_=null,S=null,x=null,w=null;for(let A of t)switch(m&&(A.type!=="space"&&A.type!=="newline"&&A.type!=="comma"&&o(A.offset,"MISSING_CHAR","Tags and anchors must be separated from the next token by white space"),m=!1),h&&(l&&A.type!=="comment"&&A.type!=="newline"&&o(h,"TAB_AS_INDENT","Tabs are not allowed as indentation"),h=null),A.type){case"space":!e&&(r!=="doc-start"||n?.type!=="flow-collection")&&A.source.includes(" ")&&(h=A),u=!0;break;case"comment":{u||o(A,"MISSING_CHAR","Comments must be separated from other tokens by white space characters");let D=A.source.substring(1)||" ";d?d+=f+D:d=D,f="",l=!1;break}case"newline":l?d?d+=A.source:(!x||r!=="seq-item-ind")&&(c=!0):f+=A.source,l=!0,p=!0,(g||b)&&(_=A),u=!0;break;case"anchor":g&&o(A,"MULTIPLE_ANCHORS","A node can have at most one anchor"),A.source.endsWith(":")&&o(A.offset+A.source.length-1,"BAD_ALIAS","Anchor ending in : is ambiguous",!0),g=A,w??(w=A.offset),l=!1,u=!1,m=!0;break;case"tag":{b&&o(A,"MULTIPLE_TAGS","A node can have at most one tag"),b=A,w??(w=A.offset),l=!1,u=!1,m=!0;break}case r:(g||b)&&o(A,"BAD_PROP_ORDER",`Anchors and tags must be after the ${A.source} indicator`),x&&o(A,"UNEXPECTED_TOKEN",`Unexpected ${A.source} in ${e??"collection"}`),x=A,l=r==="seq-item-ind"||r==="explicit-key-ind",u=!1;break;case"comma":if(e){S&&o(A,"UNEXPECTED_TOKEN",`Unexpected , in ${e}`),S=A,l=!1,u=!1;break}default:o(A,"UNEXPECTED_TOKEN",`Unexpected ${A.type} token`),l=!1,u=!1}let O=t[t.length-1],T=O?O.offset+O.source.length:i;return m&&n&&n.type!=="space"&&n.type!=="newline"&&n.type!=="comma"&&(n.type!=="scalar"||n.source!=="")&&o(n.offset,"MISSING_CHAR","Tags and anchors must be separated from the next token by white space"),h&&(l&&h.indent<=s||n?.type==="block-map"||n?.type==="block-seq")&&o(h,"TAB_AS_INDENT","Tabs are not allowed as indentation"),{comma:S,found:x,spaceBefore:c,comment:d,hasNewline:p,anchor:g,tag:b,newlineAfterProp:_,end:T,start:w??T}}hB.resolveProps=ohe});var y_=v(gB=>{"use strict";function rO(t){if(!t)return null;switch(t.type){case"alias":case"scalar":case"double-quoted-scalar":case"single-quoted-scalar":if(t.source.includes(` -`))return!0;if(t.end){for(let e of t.end)if(e.type==="newline")return!0}return!1;case"flow-collection":for(let e of t.items){for(let r of e.start)if(r.type==="newline")return!0;if(e.sep){for(let r of e.sep)if(r.type==="newline")return!0}if(rO(e.key)||rO(e.value))return!0}return!1;default:return!0}}gB.containsNewline=rO});var nO=v(yB=>{"use strict";var she=y_();function ahe(t,e,r){if(e?.type==="flow-collection"){let n=e.end[0];n.indent===t&&(n.source==="]"||n.source==="}")&&she.containsNewline(e)&&r(n,"BAD_INDENT","Flow end indicator should be more indented than parent",!0)}}yB.flowIndentCheck=ahe});var iO=v(bB=>{"use strict";var _B=De();function che(t,e,r){let{uniqueKeys:n}=t.options;if(n===!1)return!1;let i=typeof n=="function"?n:(o,s)=>o===s||_B.isScalar(o)&&_B.isScalar(s)&&o.value===s.value;return e.some(o=>i(o.key,r))}bB.mapIncludes=che});var kB=v($B=>{"use strict";var vB=Yo(),lhe=Qo(),SB=Df(),uhe=y_(),wB=nO(),dhe=iO(),xB="All mapping items must start at the same column";function fhe({composeNode:t,composeEmptyNode:e},r,n,i,o){let s=o?.nodeClass??lhe.YAMLMap,a=new s(r.schema);r.atRoot&&(r.atRoot=!1);let c=n.offset,l=null;for(let u of n.items){let{start:d,key:f,sep:p,value:m}=u,h=SB.resolveProps(d,{indicator:"explicit-key-ind",next:f??p?.[0],offset:c,onError:i,parentIndent:n.indent,startOnNewline:!0}),g=!h.found;if(g){if(f&&(f.type==="block-seq"?i(c,"BLOCK_AS_IMPLICIT_KEY","A block sequence may not be used as an implicit map key"):"indent"in f&&f.indent!==n.indent&&i(c,"BAD_INDENT",xB)),!h.anchor&&!h.tag&&!p){l=h.end,h.comment&&(a.comment?a.comment+=` -`+h.comment:a.comment=h.comment);continue}(h.newlineAfterProp||uhe.containsNewline(f))&&i(f??d[d.length-1],"MULTILINE_IMPLICIT_KEY","Implicit keys need to be on a single line")}else h.found?.indent!==n.indent&&i(c,"BAD_INDENT",xB);r.atKey=!0;let b=h.end,_=f?t(r,f,h,i):e(r,b,d,null,h,i);r.schema.compat&&wB.flowIndentCheck(n.indent,f,i),r.atKey=!1,dhe.mapIncludes(r,a.items,_)&&i(b,"DUPLICATE_KEY","Map keys must be unique");let S=SB.resolveProps(p??[],{indicator:"map-value-ind",next:m,offset:_.range[2],onError:i,parentIndent:n.indent,startOnNewline:!f||f.type==="block-scalar"});if(c=S.end,S.found){g&&(m?.type==="block-map"&&!S.hasNewline&&i(c,"BLOCK_AS_IMPLICIT_KEY","Nested mappings are not allowed in compact mappings"),r.options.strict&&h.start{"use strict";var phe=es(),mhe=Df(),hhe=nO();function ghe({composeNode:t,composeEmptyNode:e},r,n,i,o){let s=o?.nodeClass??phe.YAMLSeq,a=new s(r.schema);r.atRoot&&(r.atRoot=!1),r.atKey&&(r.atKey=!1);let c=n.offset,l=null;for(let{start:u,value:d}of n.items){let f=mhe.resolveProps(u,{indicator:"seq-item-ind",next:d,offset:c,onError:i,parentIndent:n.indent,startOnNewline:!0});if(!f.found)if(f.anchor||f.tag||d)d?.type==="block-seq"?i(f.end,"BAD_INDENT","All sequence items must start at the same column"):i(c,"MISSING_CHAR","Sequence item without - indicator");else{l=f.end,f.comment&&(a.comment=f.comment);continue}let p=d?t(r,d,f,i):e(r,f.end,u,null,f,i);r.schema.compat&&hhe.flowIndentCheck(n.indent,d,i),c=p.range[2],a.items.push(p)}return a.range=[n.offset,c,l??c],a}EB.resolveBlockSeq=ghe});var ul=v(TB=>{"use strict";function yhe(t,e,r,n){let i="";if(t){let o=!1,s="";for(let a of t){let{source:c,type:l}=a;switch(l){case"space":o=!0;break;case"comment":{r&&!o&&n(a,"MISSING_CHAR","Comments must be separated from other tokens by white space characters");let u=c.substring(1)||" ";i?i+=s+u:i=u,s="";break}case"newline":i&&(s+=c),o=!0;break;default:n(a,"UNEXPECTED_TOKEN",`Unexpected ${l} at node end`)}e+=c.length}}return{comment:i,offset:e}}TB.resolveEnd=yhe});var PB=v(IB=>{"use strict";var _he=De(),bhe=Yo(),OB=Qo(),vhe=es(),She=ul(),RB=Df(),whe=y_(),xhe=iO(),oO="Block collections are not allowed within flow collections",sO=t=>t&&(t.type==="block-map"||t.type==="block-seq");function $he({composeNode:t,composeEmptyNode:e},r,n,i,o){let s=n.start.source==="{",a=s?"flow map":"flow sequence",c=o?.nodeClass??(s?OB.YAMLMap:vhe.YAMLSeq),l=new c(r.schema);l.flow=!0;let u=r.atRoot;u&&(r.atRoot=!1),r.atKey&&(r.atKey=!1);let d=n.offset+n.start.source.length;for(let g=0;g0){let g=She.resolveEnd(m,h,r.options.strict,i);g.comment&&(l.comment?l.comment+=` -`+g.comment:l.comment=g.comment),l.range=[n.offset,h,g.offset]}else l.range=[n.offset,h,h];return l}IB.resolveFlowCollection=$he});var DB=v(CB=>{"use strict";var khe=De(),Ehe=Dt(),Ahe=Qo(),The=es(),Ohe=kB(),Rhe=AB(),Ihe=PB();function aO(t,e,r,n,i,o){let s=r.type==="block-map"?Ohe.resolveBlockMap(t,e,r,n,o):r.type==="block-seq"?Rhe.resolveBlockSeq(t,e,r,n,o):Ihe.resolveFlowCollection(t,e,r,n,o),a=s.constructor;return i==="!"||i===a.tagName?(s.tag=a.tagName,s):(i&&(s.tag=i),s)}function Phe(t,e,r,n,i){let o=n.tag,s=o?e.directives.tagName(o.source,f=>i(o,"TAG_RESOLVE_FAILED",f)):null;if(r.type==="block-seq"){let{anchor:f,newlineAfterProp:p}=n,m=f&&o?f.offset>o.offset?f:o:f??o;m&&(!p||p.offsetf.tag===s&&f.collection===a);if(!c){let f=e.schema.knownTags[s];if(f?.collection===a)e.schema.tags.push(Object.assign({},f,{default:!1})),c=f;else return f?i(o,"BAD_COLLECTION_TYPE",`${f.tag} used for ${a} collection, but expects ${f.collection??"scalar"}`,!0):i(o,"TAG_RESOLVE_FAILED",`Unresolved tag: ${s}`,!0),aO(t,e,r,i,s)}let l=aO(t,e,r,i,s,c),u=c.resolve?.(l,f=>i(o,"TAG_RESOLVE_FAILED",f),e.options)??l,d=khe.isNode(u)?u:new Ehe.Scalar(u);return d.range=l.range,d.tag=s,c?.format&&(d.format=c.format),d}CB.composeCollection=Phe});var lO=v(NB=>{"use strict";var cO=Dt();function Che(t,e,r){let n=e.offset,i=Dhe(e,t.options.strict,r);if(!i)return{value:"",type:null,comment:"",range:[n,n,n]};let o=i.mode===">"?cO.Scalar.BLOCK_FOLDED:cO.Scalar.BLOCK_LITERAL,s=e.source?Nhe(e.source):[],a=s.length;for(let h=s.length-1;h>=0;--h){let g=s[h][1];if(g===""||g==="\r")a=h;else break}if(a===0){let h=i.chomp==="+"&&s.length>0?` +`}};Nf.YAMLError=Df;Nf.YAMLParseError=cT;Nf.YAMLWarning=lT;Nf.prettifyError=Hhe});var Mf=v(R6=>{"use strict";function Bhe(t,{flow:e,indicator:r,next:n,offset:i,onError:o,parentIndent:s,startOnNewline:a}){let c=!1,l=a,u=a,d="",f="",p=!1,m=!1,h=null,g=null,b=null,_=null,S=null,x=null,w=null;for(let O of t)switch(m&&(O.type!=="space"&&O.type!=="newline"&&O.type!=="comma"&&o(O.offset,"MISSING_CHAR","Tags and anchors must be separated from the next token by white space"),m=!1),h&&(l&&O.type!=="comment"&&O.type!=="newline"&&o(h,"TAB_AS_INDENT","Tabs are not allowed as indentation"),h=null),O.type){case"space":!e&&(r!=="doc-start"||n?.type!=="flow-collection")&&O.source.includes(" ")&&(h=O),u=!0;break;case"comment":{u||o(O,"MISSING_CHAR","Comments must be separated from other tokens by white space characters");let D=O.source.substring(1)||" ";d?d+=f+D:d=D,f="",l=!1;break}case"newline":l?d?d+=O.source:(!x||r!=="seq-item-ind")&&(c=!0):f+=O.source,l=!0,p=!0,(g||b)&&(_=O),u=!0;break;case"anchor":g&&o(O,"MULTIPLE_ANCHORS","A node can have at most one anchor"),O.source.endsWith(":")&&o(O.offset+O.source.length-1,"BAD_ALIAS","Anchor ending in : is ambiguous",!0),g=O,w??(w=O.offset),l=!1,u=!1,m=!0;break;case"tag":{b&&o(O,"MULTIPLE_TAGS","A node can have at most one tag"),b=O,w??(w=O.offset),l=!1,u=!1,m=!0;break}case r:(g||b)&&o(O,"BAD_PROP_ORDER",`Anchors and tags must be after the ${O.source} indicator`),x&&o(O,"UNEXPECTED_TOKEN",`Unexpected ${O.source} in ${e??"collection"}`),x=O,l=r==="seq-item-ind"||r==="explicit-key-ind",u=!1;break;case"comma":if(e){S&&o(O,"UNEXPECTED_TOKEN",`Unexpected , in ${e}`),S=O,l=!1,u=!1;break}default:o(O,"UNEXPECTED_TOKEN",`Unexpected ${O.type} token`),l=!1,u=!1}let R=t[t.length-1],A=R?R.offset+R.source.length:i;return m&&n&&n.type!=="space"&&n.type!=="newline"&&n.type!=="comma"&&(n.type!=="scalar"||n.source!=="")&&o(n.offset,"MISSING_CHAR","Tags and anchors must be separated from the next token by white space"),h&&(l&&h.indent<=s||n?.type==="block-map"||n?.type==="block-seq")&&o(h,"TAB_AS_INDENT","Tabs are not allowed as indentation"),{comma:S,found:x,spaceBefore:c,comment:d,hasNewline:p,anchor:g,tag:b,newlineAfterProp:_,end:A,start:w??A}}R6.resolveProps=Bhe});var v_=v(I6=>{"use strict";function uT(t){if(!t)return null;switch(t.type){case"alias":case"scalar":case"double-quoted-scalar":case"single-quoted-scalar":if(t.source.includes(` +`))return!0;if(t.end){for(let e of t.end)if(e.type==="newline")return!0}return!1;case"flow-collection":for(let e of t.items){for(let r of e.start)if(r.type==="newline")return!0;if(e.sep){for(let r of e.sep)if(r.type==="newline")return!0}if(uT(e.key)||uT(e.value))return!0}return!1;default:return!0}}I6.containsNewline=uT});var dT=v(P6=>{"use strict";var Ghe=v_();function Zhe(t,e,r){if(e?.type==="flow-collection"){let n=e.end[0];n.indent===t&&(n.source==="]"||n.source==="}")&&Ghe.containsNewline(e)&&r(n,"BAD_INDENT","Flow end indicator should be more indented than parent",!0)}}P6.flowIndentCheck=Zhe});var fT=v(D6=>{"use strict";var C6=De();function Vhe(t,e,r){let{uniqueKeys:n}=t.options;if(n===!1)return!1;let i=typeof n=="function"?n:(o,s)=>o===s||C6.isScalar(o)&&C6.isScalar(s)&&o.value===s.value;return e.some(o=>i(o.key,r))}D6.mapIncludes=Vhe});var z6=v(L6=>{"use strict";var N6=Xo(),Whe=es(),j6=Mf(),Khe=v_(),M6=dT(),Jhe=fT(),F6="All mapping items must start at the same column";function Yhe({composeNode:t,composeEmptyNode:e},r,n,i,o){let s=o?.nodeClass??Whe.YAMLMap,a=new s(r.schema);r.atRoot&&(r.atRoot=!1);let c=n.offset,l=null;for(let u of n.items){let{start:d,key:f,sep:p,value:m}=u,h=j6.resolveProps(d,{indicator:"explicit-key-ind",next:f??p?.[0],offset:c,onError:i,parentIndent:n.indent,startOnNewline:!0}),g=!h.found;if(g){if(f&&(f.type==="block-seq"?i(c,"BLOCK_AS_IMPLICIT_KEY","A block sequence may not be used as an implicit map key"):"indent"in f&&f.indent!==n.indent&&i(c,"BAD_INDENT",F6)),!h.anchor&&!h.tag&&!p){l=h.end,h.comment&&(a.comment?a.comment+=` +`+h.comment:a.comment=h.comment);continue}(h.newlineAfterProp||Khe.containsNewline(f))&&i(f??d[d.length-1],"MULTILINE_IMPLICIT_KEY","Implicit keys need to be on a single line")}else h.found?.indent!==n.indent&&i(c,"BAD_INDENT",F6);r.atKey=!0;let b=h.end,_=f?t(r,f,h,i):e(r,b,d,null,h,i);r.schema.compat&&M6.flowIndentCheck(n.indent,f,i),r.atKey=!1,Jhe.mapIncludes(r,a.items,_)&&i(b,"DUPLICATE_KEY","Map keys must be unique");let S=j6.resolveProps(p??[],{indicator:"map-value-ind",next:m,offset:_.range[2],onError:i,parentIndent:n.indent,startOnNewline:!f||f.type==="block-scalar"});if(c=S.end,S.found){g&&(m?.type==="block-map"&&!S.hasNewline&&i(c,"BLOCK_AS_IMPLICIT_KEY","Nested mappings are not allowed in compact mappings"),r.options.strict&&h.start{"use strict";var Xhe=ts(),Qhe=Mf(),ege=dT();function tge({composeNode:t,composeEmptyNode:e},r,n,i,o){let s=o?.nodeClass??Xhe.YAMLSeq,a=new s(r.schema);r.atRoot&&(r.atRoot=!1),r.atKey&&(r.atKey=!1);let c=n.offset,l=null;for(let{start:u,value:d}of n.items){let f=Qhe.resolveProps(u,{indicator:"seq-item-ind",next:d,offset:c,onError:i,parentIndent:n.indent,startOnNewline:!0});if(!f.found)if(f.anchor||f.tag||d)d?.type==="block-seq"?i(f.end,"BAD_INDENT","All sequence items must start at the same column"):i(c,"MISSING_CHAR","Sequence item without - indicator");else{l=f.end,f.comment&&(a.comment=f.comment);continue}let p=d?t(r,d,f,i):e(r,f.end,u,null,f,i);r.schema.compat&&ege.flowIndentCheck(n.indent,d,i),c=p.range[2],a.items.push(p)}return a.range=[n.offset,c,l??c],a}U6.resolveBlockSeq=tge});var pl=v(H6=>{"use strict";function rge(t,e,r,n){let i="";if(t){let o=!1,s="";for(let a of t){let{source:c,type:l}=a;switch(l){case"space":o=!0;break;case"comment":{r&&!o&&n(a,"MISSING_CHAR","Comments must be separated from other tokens by white space characters");let u=c.substring(1)||" ";i?i+=s+u:i=u,s="";break}case"newline":i&&(s+=c),o=!0;break;default:n(a,"UNEXPECTED_TOKEN",`Unexpected ${l} at node end`)}e+=c.length}}return{comment:i,offset:e}}H6.resolveEnd=rge});var V6=v(Z6=>{"use strict";var nge=De(),ige=Xo(),B6=es(),oge=ts(),sge=pl(),G6=Mf(),age=v_(),cge=fT(),pT="Block collections are not allowed within flow collections",mT=t=>t&&(t.type==="block-map"||t.type==="block-seq");function lge({composeNode:t,composeEmptyNode:e},r,n,i,o){let s=n.start.source==="{",a=s?"flow map":"flow sequence",c=o?.nodeClass??(s?B6.YAMLMap:oge.YAMLSeq),l=new c(r.schema);l.flow=!0;let u=r.atRoot;u&&(r.atRoot=!1),r.atKey&&(r.atKey=!1);let d=n.offset+n.start.source.length;for(let g=0;g0){let g=sge.resolveEnd(m,h,r.options.strict,i);g.comment&&(l.comment?l.comment+=` +`+g.comment:l.comment=g.comment),l.range=[n.offset,h,g.offset]}else l.range=[n.offset,h,h];return l}Z6.resolveFlowCollection=lge});var K6=v(W6=>{"use strict";var uge=De(),dge=Dt(),fge=es(),pge=ts(),mge=z6(),hge=q6(),gge=V6();function hT(t,e,r,n,i,o){let s=r.type==="block-map"?mge.resolveBlockMap(t,e,r,n,o):r.type==="block-seq"?hge.resolveBlockSeq(t,e,r,n,o):gge.resolveFlowCollection(t,e,r,n,o),a=s.constructor;return i==="!"||i===a.tagName?(s.tag=a.tagName,s):(i&&(s.tag=i),s)}function yge(t,e,r,n,i){let o=n.tag,s=o?e.directives.tagName(o.source,f=>i(o,"TAG_RESOLVE_FAILED",f)):null;if(r.type==="block-seq"){let{anchor:f,newlineAfterProp:p}=n,m=f&&o?f.offset>o.offset?f:o:f??o;m&&(!p||p.offsetf.tag===s&&f.collection===a);if(!c){let f=e.schema.knownTags[s];if(f?.collection===a)e.schema.tags.push(Object.assign({},f,{default:!1})),c=f;else return f?i(o,"BAD_COLLECTION_TYPE",`${f.tag} used for ${a} collection, but expects ${f.collection??"scalar"}`,!0):i(o,"TAG_RESOLVE_FAILED",`Unresolved tag: ${s}`,!0),hT(t,e,r,i,s)}let l=hT(t,e,r,i,s,c),u=c.resolve?.(l,f=>i(o,"TAG_RESOLVE_FAILED",f),e.options)??l,d=uge.isNode(u)?u:new dge.Scalar(u);return d.range=l.range,d.tag=s,c?.format&&(d.format=c.format),d}W6.composeCollection=yge});var yT=v(J6=>{"use strict";var gT=Dt();function _ge(t,e,r){let n=e.offset,i=bge(e,t.options.strict,r);if(!i)return{value:"",type:null,comment:"",range:[n,n,n]};let o=i.mode===">"?gT.Scalar.BLOCK_FOLDED:gT.Scalar.BLOCK_LITERAL,s=e.source?vge(e.source):[],a=s.length;for(let h=s.length-1;h>=0;--h){let g=s[h][1];if(g===""||g==="\r")a=h;else break}if(a===0){let h=i.chomp==="+"&&s.length>0?` `.repeat(Math.max(1,s.length-1)):"",g=n+i.length;return e.source&&(g+=e.source.length),{value:h,type:o,comment:i.comment,range:[n,g,g]}}let c=e.indent+i.indent,l=e.offset+i.length,u=0;for(let h=0;hc&&(c=g.length);else{g.length=a;--h)s[h][0].length>c&&(a=h+1);let d="",f="",p=!1;for(let h=0;hc||b[0]===" "?(f===" "?f=` `:!p&&f===` `&&(f=` @@ -112,95 +112,102 @@ ${l} `+s[h][0].slice(c);d[d.length-1]!==` `&&(d+=` `);break;default:d+=` -`}let m=n+i.length+e.source.length;return{value:d,type:o,comment:i.comment,range:[n,m,m]}}function Dhe({offset:t,props:e},r,n){if(e[0].type!=="block-scalar-header")return n(e[0],"IMPOSSIBLE","Block scalar header not found"),null;let{source:i}=e[0],o=i[0],s=0,a="",c=-1;for(let f=1;f{"use strict";var uO=Dt(),jhe=ul();function Mhe(t,e,r){let{offset:n,type:i,source:o,end:s}=t,a,c,l=(f,p,m)=>r(n+f,p,m);switch(i){case"scalar":a=uO.Scalar.PLAIN,c=Fhe(o,l);break;case"single-quoted-scalar":a=uO.Scalar.QUOTE_SINGLE,c=Lhe(o,l);break;case"double-quoted-scalar":a=uO.Scalar.QUOTE_DOUBLE,c=zhe(o,l);break;default:return r(t,"UNEXPECTED_TOKEN",`Expected a flow scalar value, but found: ${i}`),{value:"",type:null,comment:"",range:[n,n+o.length,n+o.length]}}let u=n+o.length,d=jhe.resolveEnd(s,u,e,r);return{value:c,type:a,comment:d.comment,range:[n,u,d.offset]}}function Fhe(t,e){let r="";switch(t[0]){case" ":r="a tab character";break;case",":r="flow indicator character ,";break;case"%":r="directive indicator character %";break;case"|":case">":{r=`block scalar indicator ${t[0]}`;break}case"@":case"`":{r=`reserved character ${t[0]}`;break}}return r&&e(0,"BAD_SCALAR_START",`Plain value cannot start with ${r}`),jB(t)}function Lhe(t,e){return(t[t.length-1]!=="'"||t.length===1)&&e(t.length,"MISSING_CHAR","Missing closing 'quote"),jB(t.slice(1,-1)).replace(/''/g,"'")}function jB(t){let e,r;try{e=new RegExp(`(.*?)(?{"use strict";var _T=Dt(),Sge=pl();function wge(t,e,r){let{offset:n,type:i,source:o,end:s}=t,a,c,l=(f,p,m)=>r(n+f,p,m);switch(i){case"scalar":a=_T.Scalar.PLAIN,c=xge(o,l);break;case"single-quoted-scalar":a=_T.Scalar.QUOTE_SINGLE,c=$ge(o,l);break;case"double-quoted-scalar":a=_T.Scalar.QUOTE_DOUBLE,c=kge(o,l);break;default:return r(t,"UNEXPECTED_TOKEN",`Expected a flow scalar value, but found: ${i}`),{value:"",type:null,comment:"",range:[n,n+o.length,n+o.length]}}let u=n+o.length,d=Sge.resolveEnd(s,u,e,r);return{value:c,type:a,comment:d.comment,range:[n,u,d.offset]}}function xge(t,e){let r="";switch(t[0]){case" ":r="a tab character";break;case",":r="flow indicator character ,";break;case"%":r="directive indicator character %";break;case"|":case">":{r=`block scalar indicator ${t[0]}`;break}case"@":case"`":{r=`reserved character ${t[0]}`;break}}return r&&e(0,"BAD_SCALAR_START",`Plain value cannot start with ${r}`),Y6(t)}function $ge(t,e){return(t[t.length-1]!=="'"||t.length===1)&&e(t.length,"MISSING_CHAR","Missing closing 'quote"),Y6(t.slice(1,-1)).replace(/''/g,"'")}function Y6(t){let e,r;try{e=new RegExp(`(.*?)(?o?t.slice(o,n+1):i)}else r+=i}return(t[t.length-1]!=='"'||t.length===1)&&e(t.length,"MISSING_CHAR",'Missing closing "quote'),r}function Uhe(t,e){let r="",n=t[e+1];for(;(n===" "||n===" "||n===` +`)&&(r+=n>o?t.slice(o,n+1):i)}else r+=i}return(t[t.length-1]!=='"'||t.length===1)&&e(t.length,"MISSING_CHAR",'Missing closing "quote'),r}function Ege(t,e){let r="",n=t[e+1];for(;(n===" "||n===" "||n===` `||n==="\r")&&!(n==="\r"&&t[e+2]!==` `);)n===` `&&(r+=` -`),e+=1,n=t[e+1];return r||(r=" "),{fold:r,offset:e}}var qhe={0:"\0",a:"\x07",b:"\b",e:"\x1B",f:"\f",n:` -`,r:"\r",t:" ",v:"\v",N:"\x85",_:"\xA0",L:"\u2028",P:"\u2029"," ":" ",'"':'"',"/":"/","\\":"\\"," ":" "};function Bhe(t,e,r,n){let i=t.substr(e,r),s=i.length===r&&/^[0-9a-fA-F]+$/.test(i)?parseInt(i,16):NaN;try{return String.fromCodePoint(s)}catch{let a=t.substr(e-2,r+2);return n(e-2,"BAD_DQ_ESCAPE",`Invalid escape sequence ${a}`),a}}MB.resolveFlowScalar=Mhe});var zB=v(LB=>{"use strict";var ga=De(),FB=Dt(),Hhe=lO(),Ghe=dO();function Zhe(t,e,r,n){let{value:i,type:o,comment:s,range:a}=e.type==="block-scalar"?Hhe.resolveBlockScalar(t,e,n):Ghe.resolveFlowScalar(e,t.options.strict,n),c=r?t.directives.tagName(r.source,d=>n(r,"TAG_RESOLVE_FAILED",d)):null,l;t.options.stringKeys&&t.atKey?l=t.schema[ga.SCALAR]:c?l=Vhe(t.schema,i,c,r,n):e.type==="scalar"?l=Whe(t,i,e,n):l=t.schema[ga.SCALAR];let u;try{let d=l.resolve(i,f=>n(r??e,"TAG_RESOLVE_FAILED",f),t.options);u=ga.isScalar(d)?d:new FB.Scalar(d)}catch(d){let f=d instanceof Error?d.message:String(d);n(r??e,"TAG_RESOLVE_FAILED",f),u=new FB.Scalar(i)}return u.range=a,u.source=i,o&&(u.type=o),c&&(u.tag=c),l.format&&(u.format=l.format),s&&(u.comment=s),u}function Vhe(t,e,r,n,i){if(r==="!")return t[ga.SCALAR];let o=[];for(let a of t.tags)if(!a.collection&&a.tag===r)if(a.default&&a.test)o.push(a);else return a;for(let a of o)if(a.test?.test(e))return a;let s=t.knownTags[r];return s&&!s.collection?(t.tags.push(Object.assign({},s,{default:!1,test:void 0})),s):(i(n,"TAG_RESOLVE_FAILED",`Unresolved tag: ${r}`,r!=="tag:yaml.org,2002:str"),t[ga.SCALAR])}function Whe({atKey:t,directives:e,schema:r},n,i,o){let s=r.tags.find(a=>(a.default===!0||t&&a.default==="key")&&a.test?.test(n))||r[ga.SCALAR];if(r.compat){let a=r.compat.find(c=>c.default&&c.test?.test(n))??r[ga.SCALAR];if(s.tag!==a.tag){let c=e.tagString(s.tag),l=e.tagString(a.tag),u=`Value may be parsed as either ${c} or ${l}`;o(i,"TAG_RESOLVE_FAILED",u,!0)}}return s}LB.composeScalar=Zhe});var qB=v(UB=>{"use strict";function Khe(t,e,r){if(e){r??(r=e.length);for(let n=r-1;n>=0;--n){let i=e[n];switch(i.type){case"space":case"comment":case"newline":t-=i.source.length;continue}for(i=e[++n];i?.type==="space";)t+=i.source.length,i=e[++n];break}}return t}UB.emptyScalarPosition=Khe});var GB=v(pO=>{"use strict";var Jhe=mf(),Yhe=De(),Xhe=DB(),BB=zB(),Qhe=ul(),ege=qB(),tge={composeNode:HB,composeEmptyNode:fO};function HB(t,e,r,n){let i=t.atKey,{spaceBefore:o,comment:s,anchor:a,tag:c}=r,l,u=!0;switch(e.type){case"alias":l=rge(t,e,n),(a||c)&&n(e,"ALIAS_PROPS","An alias node must not specify any properties");break;case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":case"block-scalar":l=BB.composeScalar(t,e,c,n),a&&(l.anchor=a.source.substring(1));break;case"block-map":case"block-seq":case"flow-collection":try{l=Xhe.composeCollection(tge,t,e,r,n),a&&(l.anchor=a.source.substring(1))}catch(d){let f=d instanceof Error?d.message:String(d);n(e,"RESOURCE_EXHAUSTION",f)}break;default:{let d=e.type==="error"?e.message:`Unsupported token (type: ${e.type})`;n(e,"UNEXPECTED_TOKEN",d),u=!1}}return l??(l=fO(t,e.offset,void 0,null,r,n)),a&&l.anchor===""&&n(a,"BAD_ALIAS","Anchor cannot be an empty string"),i&&t.options.stringKeys&&(!Yhe.isScalar(l)||typeof l.value!="string"||l.tag&&l.tag!=="tag:yaml.org,2002:str")&&n(c??e,"NON_STRING_KEY","With stringKeys, all keys must be strings"),o&&(l.spaceBefore=!0),s&&(e.type==="scalar"&&e.source===""?l.comment=s:l.commentBefore=s),t.options.keepSourceTokens&&u&&(l.srcToken=e),l}function fO(t,e,r,n,{spaceBefore:i,comment:o,anchor:s,tag:a,end:c},l){let u={type:"scalar",offset:ege.emptyScalarPosition(e,r,n),indent:-1,source:""},d=BB.composeScalar(t,u,a,l);return s&&(d.anchor=s.source.substring(1),d.anchor===""&&l(s,"BAD_ALIAS","Anchor cannot be an empty string")),i&&(d.spaceBefore=!0),o&&(d.comment=o,d.range[2]=c),d}function rge({options:t},{offset:e,source:r,end:n},i){let o=new Jhe.Alias(r.substring(1));o.source===""&&i(e,"BAD_ALIAS","Alias cannot be an empty string"),o.source.endsWith(":")&&i(e+r.length-1,"BAD_ALIAS","Alias ending in : is ambiguous",!0);let s=e+r.length,a=Qhe.resolveEnd(n,s,t.strict,i);return o.range=[e,s,a.offset],a.comment&&(o.comment=a.comment),o}pO.composeEmptyNode=fO;pO.composeNode=HB});var WB=v(VB=>{"use strict";var nge=Rf(),ZB=GB(),ige=ul(),oge=Df();function sge(t,e,{offset:r,start:n,value:i,end:o},s){let a=Object.assign({_directives:e},t),c=new nge.Document(void 0,a),l={atKey:!1,atRoot:!0,directives:c.directives,options:c.options,schema:c.schema},u=oge.resolveProps(n,{indicator:"doc-start",next:i??o?.[0],offset:r,onError:s,parentIndent:0,startOnNewline:!0});u.found&&(c.directives.docStart=!0,i&&(i.type==="block-map"||i.type==="block-seq")&&!u.hasNewline&&s(u.end,"MISSING_CHAR","Block collection cannot start on same line with directives-end marker")),c.contents=i?ZB.composeNode(l,i,u,s):ZB.composeEmptyNode(l,u.end,n,null,u,s);let d=c.contents.range[2],f=ige.resolveEnd(o,d,!1,s);return f.comment&&(c.comment=f.comment),c.range=[r,d,f.offset],c}VB.composeDoc=sge});var hO=v(YB=>{"use strict";var age=Ge("process"),cge=eT(),lge=Rf(),Nf=Cf(),KB=De(),uge=WB(),dge=ul();function jf(t){if(typeof t=="number")return[t,t+1];if(Array.isArray(t))return t.length===2?t:[t[0],t[1]];let{offset:e,source:r}=t;return[e,e+(typeof r=="string"?r.length:1)]}function JB(t){let e="",r=!1,n=!1;for(let i=0;i{"use strict";var ba=De(),Q6=Dt(),Tge=yT(),Rge=bT();function Ige(t,e,r,n){let{value:i,type:o,comment:s,range:a}=e.type==="block-scalar"?Tge.resolveBlockScalar(t,e,n):Rge.resolveFlowScalar(e,t.options.strict,n),c=r?t.directives.tagName(r.source,d=>n(r,"TAG_RESOLVE_FAILED",d)):null,l;t.options.stringKeys&&t.atKey?l=t.schema[ba.SCALAR]:c?l=Pge(t.schema,i,c,r,n):e.type==="scalar"?l=Cge(t,i,e,n):l=t.schema[ba.SCALAR];let u;try{let d=l.resolve(i,f=>n(r??e,"TAG_RESOLVE_FAILED",f),t.options);u=ba.isScalar(d)?d:new Q6.Scalar(d)}catch(d){let f=d instanceof Error?d.message:String(d);n(r??e,"TAG_RESOLVE_FAILED",f),u=new Q6.Scalar(i)}return u.range=a,u.source=i,o&&(u.type=o),c&&(u.tag=c),l.format&&(u.format=l.format),s&&(u.comment=s),u}function Pge(t,e,r,n,i){if(r==="!")return t[ba.SCALAR];let o=[];for(let a of t.tags)if(!a.collection&&a.tag===r)if(a.default&&a.test)o.push(a);else return a;for(let a of o)if(a.test?.test(e))return a;let s=t.knownTags[r];return s&&!s.collection?(t.tags.push(Object.assign({},s,{default:!1,test:void 0})),s):(i(n,"TAG_RESOLVE_FAILED",`Unresolved tag: ${r}`,r!=="tag:yaml.org,2002:str"),t[ba.SCALAR])}function Cge({atKey:t,directives:e,schema:r},n,i,o){let s=r.tags.find(a=>(a.default===!0||t&&a.default==="key")&&a.test?.test(n))||r[ba.SCALAR];if(r.compat){let a=r.compat.find(c=>c.default&&c.test?.test(n))??r[ba.SCALAR];if(s.tag!==a.tag){let c=e.tagString(s.tag),l=e.tagString(a.tag),u=`Value may be parsed as either ${c} or ${l}`;o(i,"TAG_RESOLVE_FAILED",u,!0)}}return s}eB.composeScalar=Ige});var nB=v(rB=>{"use strict";function Dge(t,e,r){if(e){r??(r=e.length);for(let n=r-1;n>=0;--n){let i=e[n];switch(i.type){case"space":case"comment":case"newline":t-=i.source.length;continue}for(i=e[++n];i?.type==="space";)t+=i.source.length,i=e[++n];break}}return t}rB.emptyScalarPosition=Dge});var sB=v(ST=>{"use strict";var Nge=yf(),jge=De(),Mge=K6(),iB=tB(),Fge=pl(),Lge=nB(),zge={composeNode:oB,composeEmptyNode:vT};function oB(t,e,r,n){let i=t.atKey,{spaceBefore:o,comment:s,anchor:a,tag:c}=r,l,u=!0;switch(e.type){case"alias":l=Uge(t,e,n),(a||c)&&n(e,"ALIAS_PROPS","An alias node must not specify any properties");break;case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":case"block-scalar":l=iB.composeScalar(t,e,c,n),a&&(l.anchor=a.source.substring(1));break;case"block-map":case"block-seq":case"flow-collection":try{l=Mge.composeCollection(zge,t,e,r,n),a&&(l.anchor=a.source.substring(1))}catch(d){let f=d instanceof Error?d.message:String(d);n(e,"RESOURCE_EXHAUSTION",f)}break;default:{let d=e.type==="error"?e.message:`Unsupported token (type: ${e.type})`;n(e,"UNEXPECTED_TOKEN",d),u=!1}}return l??(l=vT(t,e.offset,void 0,null,r,n)),a&&l.anchor===""&&n(a,"BAD_ALIAS","Anchor cannot be an empty string"),i&&t.options.stringKeys&&(!jge.isScalar(l)||typeof l.value!="string"||l.tag&&l.tag!=="tag:yaml.org,2002:str")&&n(c??e,"NON_STRING_KEY","With stringKeys, all keys must be strings"),o&&(l.spaceBefore=!0),s&&(e.type==="scalar"&&e.source===""?l.comment=s:l.commentBefore=s),t.options.keepSourceTokens&&u&&(l.srcToken=e),l}function vT(t,e,r,n,{spaceBefore:i,comment:o,anchor:s,tag:a,end:c},l){let u={type:"scalar",offset:Lge.emptyScalarPosition(e,r,n),indent:-1,source:""},d=iB.composeScalar(t,u,a,l);return s&&(d.anchor=s.source.substring(1),d.anchor===""&&l(s,"BAD_ALIAS","Anchor cannot be an empty string")),i&&(d.spaceBefore=!0),o&&(d.comment=o,d.range[2]=c),d}function Uge({options:t},{offset:e,source:r,end:n},i){let o=new Nge.Alias(r.substring(1));o.source===""&&i(e,"BAD_ALIAS","Alias cannot be an empty string"),o.source.endsWith(":")&&i(e+r.length-1,"BAD_ALIAS","Alias ending in : is ambiguous",!0);let s=e+r.length,a=Fge.resolveEnd(n,s,t.strict,i);return o.range=[e,s,a.offset],a.comment&&(o.comment=a.comment),o}ST.composeEmptyNode=vT;ST.composeNode=oB});var lB=v(cB=>{"use strict";var qge=Cf(),aB=sB(),Hge=pl(),Bge=Mf();function Gge(t,e,{offset:r,start:n,value:i,end:o},s){let a=Object.assign({_directives:e},t),c=new qge.Document(void 0,a),l={atKey:!1,atRoot:!0,directives:c.directives,options:c.options,schema:c.schema},u=Bge.resolveProps(n,{indicator:"doc-start",next:i??o?.[0],offset:r,onError:s,parentIndent:0,startOnNewline:!0});u.found&&(c.directives.docStart=!0,i&&(i.type==="block-map"||i.type==="block-seq")&&!u.hasNewline&&s(u.end,"MISSING_CHAR","Block collection cannot start on same line with directives-end marker")),c.contents=i?aB.composeNode(l,i,u,s):aB.composeEmptyNode(l,u.end,n,null,u,s);let d=c.contents.range[2],f=Hge.resolveEnd(o,d,!1,s);return f.comment&&(c.comment=f.comment),c.range=[r,d,f.offset],c}cB.composeDoc=Gge});var xT=v(fB=>{"use strict";var Zge=Ze("process"),Vge=cO(),Wge=Cf(),Ff=jf(),uB=De(),Kge=lB(),Jge=pl();function Lf(t){if(typeof t=="number")return[t,t+1];if(Array.isArray(t))return t.length===2?t:[t[0],t[1]];let{offset:e,source:r}=t;return[e,e+(typeof r=="string"?r.length:1)]}function dB(t){let e="",r=!1,n=!1;for(let i=0;i{let s=jf(r);o?this.warnings.push(new Nf.YAMLWarning(s,n,i)):this.errors.push(new Nf.YAMLParseError(s,n,i))},this.directives=new cge.Directives({version:e.version||"1.2"}),this.options=e}decorate(e,r){let{comment:n,afterEmptyLine:i}=JB(this.prelude);if(n){let o=e.contents;if(r)e.comment=e.comment?`${e.comment} -${n}`:n;else if(i||e.directives.docStart||!o)e.commentBefore=n;else if(KB.isCollection(o)&&!o.flow&&o.items.length>0){let s=o.items[0];KB.isPair(s)&&(s=s.key);let a=s.commentBefore;s.commentBefore=a?`${n} +`)+(o.substring(1)||" "),r=!0,n=!1;break;case"%":t[i+1]?.[0]!=="#"&&(i+=1),r=!1;break;default:r||(n=!0),r=!1}}return{comment:e,afterEmptyLine:n}}var wT=class{constructor(e={}){this.doc=null,this.atDirectives=!1,this.prelude=[],this.errors=[],this.warnings=[],this.onError=(r,n,i,o)=>{let s=Lf(r);o?this.warnings.push(new Ff.YAMLWarning(s,n,i)):this.errors.push(new Ff.YAMLParseError(s,n,i))},this.directives=new Vge.Directives({version:e.version||"1.2"}),this.options=e}decorate(e,r){let{comment:n,afterEmptyLine:i}=dB(this.prelude);if(n){let o=e.contents;if(r)e.comment=e.comment?`${e.comment} +${n}`:n;else if(i||e.directives.docStart||!o)e.commentBefore=n;else if(uB.isCollection(o)&&!o.flow&&o.items.length>0){let s=o.items[0];uB.isPair(s)&&(s=s.key);let a=s.commentBefore;s.commentBefore=a?`${n} ${a}`:n}else{let s=o.commentBefore;o.commentBefore=s?`${n} -${s}`:n}}if(r){for(let o=0;o{let o=jf(e);o[0]+=r,this.onError(o,"BAD_DIRECTIVE",n,i)}),this.prelude.push(e.source),this.atDirectives=!0;break;case"document":{let r=uge.composeDoc(this.options,this.directives,e,this.onError);this.atDirectives&&!r.directives.docStart&&this.onError(e,"MISSING_CHAR","Missing directives-end/doc-start indicator line"),this.decorate(r,!1),this.doc&&(yield this.doc),this.doc=r,this.atDirectives=!1;break}case"byte-order-mark":case"space":break;case"comment":case"newline":this.prelude.push(e.source);break;case"error":{let r=e.source?`${e.message}: ${JSON.stringify(e.source)}`:e.message,n=new Nf.YAMLParseError(jf(e),"UNEXPECTED_TOKEN",r);this.atDirectives||!this.doc?this.errors.push(n):this.doc.errors.push(n);break}case"doc-end":{if(!this.doc){let n="Unexpected doc-end without preceding document";this.errors.push(new Nf.YAMLParseError(jf(e),"UNEXPECTED_TOKEN",n));break}this.doc.directives.docEnd=!0;let r=dge.resolveEnd(e.end,e.offset+e.source.length,this.doc.options.strict,this.onError);if(this.decorate(this.doc,!0),r.comment){let n=this.doc.comment;this.doc.comment=n?`${n} -${r.comment}`:r.comment}this.doc.range[2]=r.offset;break}default:this.errors.push(new Nf.YAMLParseError(jf(e),"UNEXPECTED_TOKEN",`Unsupported token ${e.type}`))}}*end(e=!1,r=-1){if(this.doc)this.decorate(this.doc,!0),yield this.doc,this.doc=null;else if(e){let n=Object.assign({_directives:this.directives},this.options),i=new lge.Document(void 0,n);this.atDirectives&&this.onError(r,"MISSING_CHAR","Missing directives-end indicator line"),i.range=[0,r,r],this.decorate(i,!1),yield i}}};YB.Composer=mO});var eH=v(__=>{"use strict";var fge=lO(),pge=dO(),mge=Cf(),XB=bf();function hge(t,e=!0,r){if(t){let n=(i,o,s)=>{let a=typeof i=="number"?i:Array.isArray(i)?i[0]:i.offset;if(r)r(a,o,s);else throw new mge.YAMLParseError([a,a+1],o,s)};switch(t.type){case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return pge.resolveFlowScalar(t,e,n);case"block-scalar":return fge.resolveBlockScalar({options:{strict:e}},t,n)}}return null}function gge(t,e){let{implicitKey:r=!1,indent:n,inFlow:i=!1,offset:o=-1,type:s="PLAIN"}=e,a=XB.stringifyString({type:s,value:t},{implicitKey:r,indent:n>0?" ".repeat(n):"",inFlow:i,options:{blockQuote:!0,lineWidth:-1}}),c=e.end??[{type:"newline",offset:-1,indent:n,source:` +${s}`:n}}if(r){for(let o=0;o{let o=Lf(e);o[0]+=r,this.onError(o,"BAD_DIRECTIVE",n,i)}),this.prelude.push(e.source),this.atDirectives=!0;break;case"document":{let r=Kge.composeDoc(this.options,this.directives,e,this.onError);this.atDirectives&&!r.directives.docStart&&this.onError(e,"MISSING_CHAR","Missing directives-end/doc-start indicator line"),this.decorate(r,!1),this.doc&&(yield this.doc),this.doc=r,this.atDirectives=!1;break}case"byte-order-mark":case"space":break;case"comment":case"newline":this.prelude.push(e.source);break;case"error":{let r=e.source?`${e.message}: ${JSON.stringify(e.source)}`:e.message,n=new Ff.YAMLParseError(Lf(e),"UNEXPECTED_TOKEN",r);this.atDirectives||!this.doc?this.errors.push(n):this.doc.errors.push(n);break}case"doc-end":{if(!this.doc){let n="Unexpected doc-end without preceding document";this.errors.push(new Ff.YAMLParseError(Lf(e),"UNEXPECTED_TOKEN",n));break}this.doc.directives.docEnd=!0;let r=Jge.resolveEnd(e.end,e.offset+e.source.length,this.doc.options.strict,this.onError);if(this.decorate(this.doc,!0),r.comment){let n=this.doc.comment;this.doc.comment=n?`${n} +${r.comment}`:r.comment}this.doc.range[2]=r.offset;break}default:this.errors.push(new Ff.YAMLParseError(Lf(e),"UNEXPECTED_TOKEN",`Unsupported token ${e.type}`))}}*end(e=!1,r=-1){if(this.doc)this.decorate(this.doc,!0),yield this.doc,this.doc=null;else if(e){let n=Object.assign({_directives:this.directives},this.options),i=new Wge.Document(void 0,n);this.atDirectives&&this.onError(r,"MISSING_CHAR","Missing directives-end indicator line"),i.range=[0,r,r],this.decorate(i,!1),yield i}}};fB.Composer=wT});var hB=v(S_=>{"use strict";var Yge=yT(),Xge=bT(),Qge=jf(),pB=wf();function eye(t,e=!0,r){if(t){let n=(i,o,s)=>{let a=typeof i=="number"?i:Array.isArray(i)?i[0]:i.offset;if(r)r(a,o,s);else throw new Qge.YAMLParseError([a,a+1],o,s)};switch(t.type){case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return Xge.resolveFlowScalar(t,e,n);case"block-scalar":return Yge.resolveBlockScalar({options:{strict:e}},t,n)}}return null}function tye(t,e){let{implicitKey:r=!1,indent:n,inFlow:i=!1,offset:o=-1,type:s="PLAIN"}=e,a=pB.stringifyString({type:s,value:t},{implicitKey:r,indent:n>0?" ".repeat(n):"",inFlow:i,options:{blockQuote:!0,lineWidth:-1}}),c=e.end??[{type:"newline",offset:-1,indent:n,source:` `}];switch(a[0]){case"|":case">":{let l=a.indexOf(` `),u=a.substring(0,l),d=a.substring(l+1)+` -`,f=[{type:"block-scalar-header",offset:o,indent:n,source:u}];return QB(f,c)||f.push({type:"newline",offset:-1,indent:n,source:` -`}),{type:"block-scalar",offset:o,indent:n,props:f,source:d}}case'"':return{type:"double-quoted-scalar",offset:o,indent:n,source:a,end:c};case"'":return{type:"single-quoted-scalar",offset:o,indent:n,source:a,end:c};default:return{type:"scalar",offset:o,indent:n,source:a,end:c}}}function yge(t,e,r={}){let{afterKey:n=!1,implicitKey:i=!1,inFlow:o=!1,type:s}=r,a="indent"in t?t.indent:null;if(n&&typeof a=="number"&&(a+=2),!s)switch(t.type){case"single-quoted-scalar":s="QUOTE_SINGLE";break;case"double-quoted-scalar":s="QUOTE_DOUBLE";break;case"block-scalar":{let l=t.props[0];if(l.type!=="block-scalar-header")throw new Error("Invalid block scalar header");s=l.source[0]===">"?"BLOCK_FOLDED":"BLOCK_LITERAL";break}default:s="PLAIN"}let c=XB.stringifyString({type:s,value:e},{implicitKey:i||a===null,indent:a!==null&&a>0?" ".repeat(a):"",inFlow:o,options:{blockQuote:!0,lineWidth:-1}});switch(c[0]){case"|":case">":_ge(t,c);break;case'"':gO(t,c,"double-quoted-scalar");break;case"'":gO(t,c,"single-quoted-scalar");break;default:gO(t,c,"scalar")}}function _ge(t,e){let r=e.indexOf(` +`,f=[{type:"block-scalar-header",offset:o,indent:n,source:u}];return mB(f,c)||f.push({type:"newline",offset:-1,indent:n,source:` +`}),{type:"block-scalar",offset:o,indent:n,props:f,source:d}}case'"':return{type:"double-quoted-scalar",offset:o,indent:n,source:a,end:c};case"'":return{type:"single-quoted-scalar",offset:o,indent:n,source:a,end:c};default:return{type:"scalar",offset:o,indent:n,source:a,end:c}}}function rye(t,e,r={}){let{afterKey:n=!1,implicitKey:i=!1,inFlow:o=!1,type:s}=r,a="indent"in t?t.indent:null;if(n&&typeof a=="number"&&(a+=2),!s)switch(t.type){case"single-quoted-scalar":s="QUOTE_SINGLE";break;case"double-quoted-scalar":s="QUOTE_DOUBLE";break;case"block-scalar":{let l=t.props[0];if(l.type!=="block-scalar-header")throw new Error("Invalid block scalar header");s=l.source[0]===">"?"BLOCK_FOLDED":"BLOCK_LITERAL";break}default:s="PLAIN"}let c=pB.stringifyString({type:s,value:e},{implicitKey:i||a===null,indent:a!==null&&a>0?" ".repeat(a):"",inFlow:o,options:{blockQuote:!0,lineWidth:-1}});switch(c[0]){case"|":case">":nye(t,c);break;case'"':$T(t,c,"double-quoted-scalar");break;case"'":$T(t,c,"single-quoted-scalar");break;default:$T(t,c,"scalar")}}function nye(t,e){let r=e.indexOf(` `),n=e.substring(0,r),i=e.substring(r+1)+` -`;if(t.type==="block-scalar"){let o=t.props[0];if(o.type!=="block-scalar-header")throw new Error("Invalid block scalar header");o.source=n,t.source=i}else{let{offset:o}=t,s="indent"in t?t.indent:-1,a=[{type:"block-scalar-header",offset:o,indent:s,source:n}];QB(a,"end"in t?t.end:void 0)||a.push({type:"newline",offset:-1,indent:s,source:` -`});for(let c of Object.keys(t))c!=="type"&&c!=="offset"&&delete t[c];Object.assign(t,{type:"block-scalar",indent:s,props:a,source:i})}}function QB(t,e){if(e)for(let r of e)switch(r.type){case"space":case"comment":t.push(r);break;case"newline":return t.push(r),!0}return!1}function gO(t,e,r){switch(t.type){case"scalar":case"double-quoted-scalar":case"single-quoted-scalar":t.type=r,t.source=e;break;case"block-scalar":{let n=t.props.slice(1),i=e.length;t.props[0].type==="block-scalar-header"&&(i-=t.props[0].source.length);for(let o of n)o.offset+=i;delete t.props,Object.assign(t,{type:r,source:e,end:n});break}case"block-map":case"block-seq":{let i={type:"newline",offset:t.offset+e.length,indent:t.indent,source:` -`};delete t.items,Object.assign(t,{type:r,source:e,end:[i]});break}default:{let n="indent"in t?t.indent:-1,i="end"in t&&Array.isArray(t.end)?t.end.filter(o=>o.type==="space"||o.type==="comment"||o.type==="newline"):[];for(let o of Object.keys(t))o!=="type"&&o!=="offset"&&delete t[o];Object.assign(t,{type:r,indent:n,source:e,end:i})}}}__.createScalarToken=gge;__.resolveAsScalar=hge;__.setScalarValue=yge});var rH=v(tH=>{"use strict";var bge=t=>"type"in t?v_(t):b_(t);function v_(t){switch(t.type){case"block-scalar":{let e="";for(let r of t.props)e+=v_(r);return e+t.source}case"block-map":case"block-seq":{let e="";for(let r of t.items)e+=b_(r);return e}case"flow-collection":{let e=t.start.source;for(let r of t.items)e+=b_(r);for(let r of t.end)e+=r.source;return e}case"document":{let e=b_(t);if(t.end)for(let r of t.end)e+=r.source;return e}default:{let e=t.source;if("end"in t&&t.end)for(let r of t.end)e+=r.source;return e}}}function b_({start:t,key:e,sep:r,value:n}){let i="";for(let o of t)i+=o.source;if(e&&(i+=v_(e)),r)for(let o of r)i+=o.source;return n&&(i+=v_(n)),i}tH.stringify=bge});var sH=v(oH=>{"use strict";var yO=Symbol("break visit"),vge=Symbol("skip children"),nH=Symbol("remove item");function ya(t,e){"type"in t&&t.type==="document"&&(t={start:t.start,value:t.value}),iH(Object.freeze([]),t,e)}ya.BREAK=yO;ya.SKIP=vge;ya.REMOVE=nH;ya.itemAtPath=(t,e)=>{let r=t;for(let[n,i]of e){let o=r?.[n];if(o&&"items"in o)r=o.items[i];else return}return r};ya.parentCollection=(t,e)=>{let r=ya.itemAtPath(t,e.slice(0,-1)),n=e[e.length-1][0],i=r?.[n];if(i&&"items"in i)return i;throw new Error("Parent collection not found")};function iH(t,e,r){let n=r(e,t);if(typeof n=="symbol")return n;for(let i of["key","value"]){let o=e[i];if(o&&"items"in o){for(let s=0;s{"use strict";var _O=eH(),Sge=rH(),wge=sH(),bO="\uFEFF",vO="",SO="",wO="",xge=t=>!!t&&"items"in t,$ge=t=>!!t&&(t.type==="scalar"||t.type==="single-quoted-scalar"||t.type==="double-quoted-scalar"||t.type==="block-scalar");function kge(t){switch(t){case bO:return"";case vO:return"";case SO:return"";case wO:return"";default:return JSON.stringify(t)}}function Ege(t){switch(t){case bO:return"byte-order-mark";case vO:return"doc-mode";case SO:return"flow-error-end";case wO:return"scalar";case"---":return"doc-start";case"...":return"doc-end";case"":case` +`;if(t.type==="block-scalar"){let o=t.props[0];if(o.type!=="block-scalar-header")throw new Error("Invalid block scalar header");o.source=n,t.source=i}else{let{offset:o}=t,s="indent"in t?t.indent:-1,a=[{type:"block-scalar-header",offset:o,indent:s,source:n}];mB(a,"end"in t?t.end:void 0)||a.push({type:"newline",offset:-1,indent:s,source:` +`});for(let c of Object.keys(t))c!=="type"&&c!=="offset"&&delete t[c];Object.assign(t,{type:"block-scalar",indent:s,props:a,source:i})}}function mB(t,e){if(e)for(let r of e)switch(r.type){case"space":case"comment":t.push(r);break;case"newline":return t.push(r),!0}return!1}function $T(t,e,r){switch(t.type){case"scalar":case"double-quoted-scalar":case"single-quoted-scalar":t.type=r,t.source=e;break;case"block-scalar":{let n=t.props.slice(1),i=e.length;t.props[0].type==="block-scalar-header"&&(i-=t.props[0].source.length);for(let o of n)o.offset+=i;delete t.props,Object.assign(t,{type:r,source:e,end:n});break}case"block-map":case"block-seq":{let i={type:"newline",offset:t.offset+e.length,indent:t.indent,source:` +`};delete t.items,Object.assign(t,{type:r,source:e,end:[i]});break}default:{let n="indent"in t?t.indent:-1,i="end"in t&&Array.isArray(t.end)?t.end.filter(o=>o.type==="space"||o.type==="comment"||o.type==="newline"):[];for(let o of Object.keys(t))o!=="type"&&o!=="offset"&&delete t[o];Object.assign(t,{type:r,indent:n,source:e,end:i})}}}S_.createScalarToken=tye;S_.resolveAsScalar=eye;S_.setScalarValue=rye});var yB=v(gB=>{"use strict";var iye=t=>"type"in t?x_(t):w_(t);function x_(t){switch(t.type){case"block-scalar":{let e="";for(let r of t.props)e+=x_(r);return e+t.source}case"block-map":case"block-seq":{let e="";for(let r of t.items)e+=w_(r);return e}case"flow-collection":{let e=t.start.source;for(let r of t.items)e+=w_(r);for(let r of t.end)e+=r.source;return e}case"document":{let e=w_(t);if(t.end)for(let r of t.end)e+=r.source;return e}default:{let e=t.source;if("end"in t&&t.end)for(let r of t.end)e+=r.source;return e}}}function w_({start:t,key:e,sep:r,value:n}){let i="";for(let o of t)i+=o.source;if(e&&(i+=x_(e)),r)for(let o of r)i+=o.source;return n&&(i+=x_(n)),i}gB.stringify=iye});var SB=v(vB=>{"use strict";var kT=Symbol("break visit"),oye=Symbol("skip children"),_B=Symbol("remove item");function va(t,e){"type"in t&&t.type==="document"&&(t={start:t.start,value:t.value}),bB(Object.freeze([]),t,e)}va.BREAK=kT;va.SKIP=oye;va.REMOVE=_B;va.itemAtPath=(t,e)=>{let r=t;for(let[n,i]of e){let o=r?.[n];if(o&&"items"in o)r=o.items[i];else return}return r};va.parentCollection=(t,e)=>{let r=va.itemAtPath(t,e.slice(0,-1)),n=e[e.length-1][0],i=r?.[n];if(i&&"items"in i)return i;throw new Error("Parent collection not found")};function bB(t,e,r){let n=r(e,t);if(typeof n=="symbol")return n;for(let i of["key","value"]){let o=e[i];if(o&&"items"in o){for(let s=0;s{"use strict";var ET=hB(),sye=yB(),aye=SB(),AT="\uFEFF",OT="",TT="",RT="",cye=t=>!!t&&"items"in t,lye=t=>!!t&&(t.type==="scalar"||t.type==="single-quoted-scalar"||t.type==="double-quoted-scalar"||t.type==="block-scalar");function uye(t){switch(t){case AT:return"";case OT:return"";case TT:return"";case RT:return"";default:return JSON.stringify(t)}}function dye(t){switch(t){case AT:return"byte-order-mark";case OT:return"doc-mode";case TT:return"flow-error-end";case RT:return"scalar";case"---":return"doc-start";case"...":return"doc-end";case"":case` `:case`\r -`:return"newline";case"-":return"seq-item-ind";case"?":return"explicit-key-ind";case":":return"map-value-ind";case"{":return"flow-map-start";case"}":return"flow-map-end";case"[":return"flow-seq-start";case"]":return"flow-seq-end";case",":return"comma"}switch(t[0]){case" ":case" ":return"space";case"#":return"comment";case"%":return"directive-line";case"*":return"alias";case"&":return"anchor";case"!":return"tag";case"'":return"single-quoted-scalar";case'"':return"double-quoted-scalar";case"|":case">":return"block-scalar-header"}return null}jr.createScalarToken=_O.createScalarToken;jr.resolveAsScalar=_O.resolveAsScalar;jr.setScalarValue=_O.setScalarValue;jr.stringify=Sge.stringify;jr.visit=wge.visit;jr.BOM=bO;jr.DOCUMENT=vO;jr.FLOW_END=SO;jr.SCALAR=wO;jr.isCollection=xge;jr.isScalar=$ge;jr.prettyToken=kge;jr.tokenType=Ege});var kO=v(cH=>{"use strict";var Mf=S_();function Xn(t){switch(t){case void 0:case" ":case` -`:case"\r":case" ":return!0;default:return!1}}var aH=new Set("0123456789ABCDEFabcdef"),Age=new Set("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()"),w_=new Set(",[]{}"),Tge=new Set(` ,[]{} -\r `),xO=t=>!t||Tge.has(t),$O=class{constructor(){this.atEnd=!1,this.blockScalarIndent=-1,this.blockScalarKeep=!1,this.buffer="",this.flowKey=!1,this.flowLevel=0,this.indentNext=0,this.indentValue=0,this.lineEndPos=null,this.next=null,this.pos=0}*lex(e,r=!1){if(e){if(typeof e!="string")throw TypeError("source is not a string");this.buffer=this.buffer?this.buffer+e:e,this.lineEndPos=null}this.atEnd=!r;let n=this.next??"stream";for(;n&&(r||this.hasChars(1));)n=yield*this.parseNext(n)}atLineEnd(){let e=this.pos,r=this.buffer[e];for(;r===" "||r===" ";)r=this.buffer[++e];return!r||r==="#"||r===` +`:return"newline";case"-":return"seq-item-ind";case"?":return"explicit-key-ind";case":":return"map-value-ind";case"{":return"flow-map-start";case"}":return"flow-map-end";case"[":return"flow-seq-start";case"]":return"flow-seq-end";case",":return"comma"}switch(t[0]){case" ":case" ":return"space";case"#":return"comment";case"%":return"directive-line";case"*":return"alias";case"&":return"anchor";case"!":return"tag";case"'":return"single-quoted-scalar";case'"':return"double-quoted-scalar";case"|":case">":return"block-scalar-header"}return null}Mr.createScalarToken=ET.createScalarToken;Mr.resolveAsScalar=ET.resolveAsScalar;Mr.setScalarValue=ET.setScalarValue;Mr.stringify=sye.stringify;Mr.visit=aye.visit;Mr.BOM=AT;Mr.DOCUMENT=OT;Mr.FLOW_END=TT;Mr.SCALAR=RT;Mr.isCollection=cye;Mr.isScalar=lye;Mr.prettyToken=uye;Mr.tokenType=dye});var CT=v(xB=>{"use strict";var zf=$_();function Qn(t){switch(t){case void 0:case" ":case` +`:case"\r":case" ":return!0;default:return!1}}var wB=new Set("0123456789ABCDEFabcdef"),fye=new Set("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-#;/?:@&=+$_.!~*'()"),k_=new Set(",[]{}"),pye=new Set(` ,[]{} +\r `),IT=t=>!t||pye.has(t),PT=class{constructor(){this.atEnd=!1,this.blockScalarIndent=-1,this.blockScalarKeep=!1,this.buffer="",this.flowKey=!1,this.flowLevel=0,this.indentNext=0,this.indentValue=0,this.lineEndPos=null,this.next=null,this.pos=0}*lex(e,r=!1){if(e){if(typeof e!="string")throw TypeError("source is not a string");this.buffer=this.buffer?this.buffer+e:e,this.lineEndPos=null}this.atEnd=!r;let n=this.next??"stream";for(;n&&(r||this.hasChars(1));)n=yield*this.parseNext(n)}atLineEnd(){let e=this.pos,r=this.buffer[e];for(;r===" "||r===" ";)r=this.buffer[++e];return!r||r==="#"||r===` `?!0:r==="\r"?this.buffer[e+1]===` `:!1}charAt(e){return this.buffer[this.pos+e]}continueScalar(e){let r=this.buffer[e];if(this.indentNext>0){let n=0;for(;r===" ";)r=this.buffer[++n+e];if(r==="\r"){let i=this.buffer[n+e+1];if(i===` `||!i&&!this.atEnd)return e+n+1}return r===` -`||n>=this.indentNext||!r&&!this.atEnd?e+n:-1}if(r==="-"||r==="."){let n=this.buffer.substr(e,3);if((n==="---"||n==="...")&&Xn(this.buffer[e+3]))return-1}return e}getLine(){let e=this.lineEndPos;return(typeof e!="number"||e!==-1&&ethis.indentValue&&!Xn(this.charAt(1))&&(this.indentNext=this.indentValue),yield*this.parseBlockStart()}*parseBlockStart(){let[e,r]=this.peek(2);if(!r&&!this.atEnd)return this.setNext("block-start");if((e==="-"||e==="?"||e===":")&&Xn(r)){let n=(yield*this.pushCount(1))+(yield*this.pushSpaces(!0));return this.indentNext=this.indentValue+1,this.indentValue+=n,"block-start"}return"doc"}*parseDocument(){yield*this.pushSpaces(!0);let e=this.getLine();if(e===null)return this.setNext("doc");let r=yield*this.pushIndicators();switch(e[r]){case"#":yield*this.pushCount(e.length-r);case void 0:return yield*this.pushNewline(),yield*this.parseLineStart();case"{":case"[":return yield*this.pushCount(1),this.flowKey=!1,this.flowLevel=1,"flow";case"}":case"]":return yield*this.pushCount(1),"doc";case"*":return yield*this.pushUntil(xO),"doc";case'"':case"'":return yield*this.parseQuotedScalar();case"|":case">":return r+=yield*this.parseBlockScalarHeader(),r+=yield*this.pushSpaces(!0),yield*this.pushCount(e.length-r),yield*this.pushNewline(),yield*this.parseBlockScalar();default:return yield*this.parsePlainScalar()}}*parseFlowCollection(){let e,r,n=-1;do e=yield*this.pushNewline(),e>0?(r=yield*this.pushSpaces(!1),this.indentValue=n=r):r=0,r+=yield*this.pushSpaces(!0);while(e+r>0);let i=this.getLine();if(i===null)return this.setNext("flow");if((n!==-1&&n=this.indentNext||!r&&!this.atEnd?e+n:-1}if(r==="-"||r==="."){let n=this.buffer.substr(e,3);if((n==="---"||n==="...")&&Qn(this.buffer[e+3]))return-1}return e}getLine(){let e=this.lineEndPos;return(typeof e!="number"||e!==-1&&ethis.indentValue&&!Qn(this.charAt(1))&&(this.indentNext=this.indentValue),yield*this.parseBlockStart()}*parseBlockStart(){let[e,r]=this.peek(2);if(!r&&!this.atEnd)return this.setNext("block-start");if((e==="-"||e==="?"||e===":")&&Qn(r)){let n=(yield*this.pushCount(1))+(yield*this.pushSpaces(!0));return this.indentNext=this.indentValue+1,this.indentValue+=n,"block-start"}return"doc"}*parseDocument(){yield*this.pushSpaces(!0);let e=this.getLine();if(e===null)return this.setNext("doc");let r=yield*this.pushIndicators();switch(e[r]){case"#":yield*this.pushCount(e.length-r);case void 0:return yield*this.pushNewline(),yield*this.parseLineStart();case"{":case"[":return yield*this.pushCount(1),this.flowKey=!1,this.flowLevel=1,"flow";case"}":case"]":return yield*this.pushCount(1),"doc";case"*":return yield*this.pushUntil(IT),"doc";case'"':case"'":return yield*this.parseQuotedScalar();case"|":case">":return r+=yield*this.parseBlockScalarHeader(),r+=yield*this.pushSpaces(!0),yield*this.pushCount(e.length-r),yield*this.pushNewline(),yield*this.parseBlockScalar();default:return yield*this.parsePlainScalar()}}*parseFlowCollection(){let e,r,n=-1;do e=yield*this.pushNewline(),e>0?(r=yield*this.pushSpaces(!1),this.indentValue=n=r):r=0,r+=yield*this.pushSpaces(!0);while(e+r>0);let i=this.getLine();if(i===null)return this.setNext("flow");if((n!==-1&&n"0"&&r<="9")this.blockScalarIndent=Number(r)-1;else if(r!=="-")break}return yield*this.pushUntil(r=>Xn(r)||r==="#")}*parseBlockScalar(){let e=this.pos-1,r=0,n;e:for(let o=this.pos;n=this.buffer[o];++o)switch(n){case" ":r+=1;break;case` +`,o)}i!==-1&&(r=i-(n[i-1]==="\r"?2:1))}if(r===-1){if(!this.atEnd)return this.setNext("quoted-scalar");r=this.buffer.length}return yield*this.pushToIndex(r+1,!1),this.flowLevel?"flow":"doc"}*parseBlockScalarHeader(){this.blockScalarIndent=-1,this.blockScalarKeep=!1;let e=this.pos;for(;;){let r=this.buffer[++e];if(r==="+")this.blockScalarKeep=!0;else if(r>"0"&&r<="9")this.blockScalarIndent=Number(r)-1;else if(r!=="-")break}return yield*this.pushUntil(r=>Qn(r)||r==="#")}*parseBlockScalar(){let e=this.pos-1,r=0,n;e:for(let o=this.pos;n=this.buffer[o];++o)switch(n){case" ":r+=1;break;case` `:e=o,r=0;break;case"\r":{let s=this.buffer[o+1];if(!s&&!this.atEnd)return this.setNext("block-scalar");if(s===` `)break}default:break e}if(!n&&!this.atEnd)return this.setNext("block-scalar");if(r>=this.indentNext){this.blockScalarIndent===-1?this.indentNext=r:this.indentNext=this.blockScalarIndent+(this.indentNext===0?1:this.indentNext);do{let o=this.continueScalar(e+1);if(o===-1)break;e=this.buffer.indexOf(` `,o)}while(e!==-1);if(e===-1){if(!this.atEnd)return this.setNext("block-scalar");e=this.buffer.length}}let i=e+1;for(n=this.buffer[i];n===" ";)n=this.buffer[++i];if(n===" "){for(;n===" "||n===" "||n==="\r"||n===` `;)n=this.buffer[++i];e=i-1}else if(!this.blockScalarKeep)do{let o=e-1,s=this.buffer[o];s==="\r"&&(s=this.buffer[--o]);let a=o;for(;s===" ";)s=this.buffer[--o];if(s===` -`&&o>=this.pos&&o+1+r>a)e=o;else break}while(!0);return yield Mf.SCALAR,yield*this.pushToIndex(e+1,!0),yield*this.parseLineStart()}*parsePlainScalar(){let e=this.flowLevel>0,r=this.pos-1,n=this.pos-1,i;for(;i=this.buffer[++n];)if(i===":"){let o=this.buffer[n+1];if(Xn(o)||e&&w_.has(o))break;r=n}else if(Xn(i)){let o=this.buffer[n+1];if(i==="\r"&&(o===` +`&&o>=this.pos&&o+1+r>a)e=o;else break}while(!0);return yield zf.SCALAR,yield*this.pushToIndex(e+1,!0),yield*this.parseLineStart()}*parsePlainScalar(){let e=this.flowLevel>0,r=this.pos-1,n=this.pos-1,i;for(;i=this.buffer[++n];)if(i===":"){let o=this.buffer[n+1];if(Qn(o)||e&&k_.has(o))break;r=n}else if(Qn(i)){let o=this.buffer[n+1];if(i==="\r"&&(o===` `?(n+=1,i=` -`,o=this.buffer[n+1]):r=n),o==="#"||e&&w_.has(o))break;if(i===` -`){let s=this.continueScalar(n+1);if(s===-1)break;n=Math.max(n,s-2)}}else{if(e&&w_.has(i))break;r=n}return!i&&!this.atEnd?this.setNext("plain-scalar"):(yield Mf.SCALAR,yield*this.pushToIndex(r+1,!0),e?"flow":"doc")}*pushCount(e){return e>0?(yield this.buffer.substr(this.pos,e),this.pos+=e,e):0}*pushToIndex(e,r){let n=this.buffer.slice(this.pos,e);return n?(yield n,this.pos+=n.length,n.length):(r&&(yield""),0)}*pushIndicators(){let e=0;e:for(;;){switch(this.charAt(0)){case"!":e+=yield*this.pushTag(),e+=yield*this.pushSpaces(!0);continue e;case"&":e+=yield*this.pushUntil(xO),e+=yield*this.pushSpaces(!0);continue e;case"-":case"?":case":":{let r=this.flowLevel>0,n=this.charAt(1);if(Xn(n)||r&&w_.has(n)){r?this.flowKey&&(this.flowKey=!1):this.indentNext=this.indentValue+1,e+=yield*this.pushCount(1),e+=yield*this.pushSpaces(!0);continue e}}}break e}return e}*pushTag(){if(this.charAt(1)==="<"){let e=this.pos+2,r=this.buffer[e];for(;!Xn(r)&&r!==">";)r=this.buffer[++e];return yield*this.pushToIndex(r===">"?e+1:e,!1)}else{let e=this.pos+1,r=this.buffer[e];for(;r;)if(Age.has(r))r=this.buffer[++e];else if(r==="%"&&aH.has(this.buffer[e+1])&&aH.has(this.buffer[e+2]))r=this.buffer[e+=3];else break;return yield*this.pushToIndex(e,!1)}}*pushNewline(){let e=this.buffer[this.pos];return e===` +`,o=this.buffer[n+1]):r=n),o==="#"||e&&k_.has(o))break;if(i===` +`){let s=this.continueScalar(n+1);if(s===-1)break;n=Math.max(n,s-2)}}else{if(e&&k_.has(i))break;r=n}return!i&&!this.atEnd?this.setNext("plain-scalar"):(yield zf.SCALAR,yield*this.pushToIndex(r+1,!0),e?"flow":"doc")}*pushCount(e){return e>0?(yield this.buffer.substr(this.pos,e),this.pos+=e,e):0}*pushToIndex(e,r){let n=this.buffer.slice(this.pos,e);return n?(yield n,this.pos+=n.length,n.length):(r&&(yield""),0)}*pushIndicators(){let e=0;e:for(;;){switch(this.charAt(0)){case"!":e+=yield*this.pushTag(),e+=yield*this.pushSpaces(!0);continue e;case"&":e+=yield*this.pushUntil(IT),e+=yield*this.pushSpaces(!0);continue e;case"-":case"?":case":":{let r=this.flowLevel>0,n=this.charAt(1);if(Qn(n)||r&&k_.has(n)){r?this.flowKey&&(this.flowKey=!1):this.indentNext=this.indentValue+1,e+=yield*this.pushCount(1),e+=yield*this.pushSpaces(!0);continue e}}}break e}return e}*pushTag(){if(this.charAt(1)==="<"){let e=this.pos+2,r=this.buffer[e];for(;!Qn(r)&&r!==">";)r=this.buffer[++e];return yield*this.pushToIndex(r===">"?e+1:e,!1)}else{let e=this.pos+1,r=this.buffer[e];for(;r;)if(fye.has(r))r=this.buffer[++e];else if(r==="%"&&wB.has(this.buffer[e+1])&&wB.has(this.buffer[e+2]))r=this.buffer[e+=3];else break;return yield*this.pushToIndex(e,!1)}}*pushNewline(){let e=this.buffer[this.pos];return e===` `?yield*this.pushCount(1):e==="\r"&&this.charAt(1)===` -`?yield*this.pushCount(2):0}*pushSpaces(e){let r=this.pos-1,n;do n=this.buffer[++r];while(n===" "||e&&n===" ");let i=r-this.pos;return i>0&&(yield this.buffer.substr(this.pos,i),this.pos=r),i}*pushUntil(e){let r=this.pos,n=this.buffer[r];for(;!e(n);)n=this.buffer[++r];return yield*this.pushToIndex(r,!1)}};cH.Lexer=$O});var AO=v(lH=>{"use strict";var EO=class{constructor(){this.lineStarts=[],this.addNewLine=e=>this.lineStarts.push(e),this.linePos=e=>{let r=0,n=this.lineStarts.length;for(;r>1;this.lineStarts[o]{"use strict";var Oge=Ge("process"),uH=S_(),Rge=kO();function ts(t,e){for(let r=0;r=0;)switch(t[e].type){case"doc-start":case"explicit-key-ind":case"map-value-ind":case"seq-item-ind":case"newline":break e}for(;t[++e]?.type==="space";);return t.splice(e,t.length)}function $_(t,e){if(e.length<1e5)Array.prototype.push.apply(t,e);else for(let r=0;r0;)yield*this.pop()}get sourceToken(){return{type:this.type,offset:this.offset,indent:this.indent,source:this.source}}*step(){let e=this.peek(1);if(this.type==="doc-end"&&e?.type!=="doc-end"){for(;this.stack.length>0;)yield*this.pop();this.stack.push({type:"doc-end",offset:this.offset,source:this.source});return}if(!e)return yield*this.stream();switch(e.type){case"document":return yield*this.document(e);case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return yield*this.scalar(e);case"block-scalar":return yield*this.blockScalar(e);case"block-map":return yield*this.blockMap(e);case"block-seq":return yield*this.blockSequence(e);case"flow-collection":return yield*this.flowCollection(e);case"doc-end":return yield*this.documentEnd(e)}yield*this.pop()}peek(e){return this.stack[this.stack.length-e]}*pop(e){let r=e??this.stack.pop();if(!r)yield{type:"error",offset:this.offset,source:"",message:"Tried to pop an empty stack"};else if(this.stack.length===0)yield r;else{let n=this.peek(1);switch(r.type==="block-scalar"?r.indent="indent"in n?n.indent:0:r.type==="flow-collection"&&n.type==="document"&&(r.indent=0),r.type==="flow-collection"&&fH(r),n.type){case"document":n.value=r;break;case"block-scalar":n.props.push(r);break;case"block-map":{let i=n.items[n.items.length-1];if(i.value){n.items.push({start:[],key:r,sep:[]}),this.onKeyLine=!0;return}else if(i.sep)i.value=r;else{Object.assign(i,{key:r,sep:[]}),this.onKeyLine=!i.explicitKey;return}break}case"block-seq":{let i=n.items[n.items.length-1];i.value?n.items.push({start:[],value:r}):i.value=r;break}case"flow-collection":{let i=n.items[n.items.length-1];!i||i.value?n.items.push({start:[],key:r,sep:[]}):i.sep?i.value=r:Object.assign(i,{key:r,sep:[]});return}default:yield*this.pop(),yield*this.pop(r)}if((n.type==="document"||n.type==="block-map"||n.type==="block-seq")&&(r.type==="block-map"||r.type==="block-seq")){let i=r.items[r.items.length-1];i&&!i.sep&&!i.value&&i.start.length>0&&dH(i.start)===-1&&(r.indent===0||i.start.every(o=>o.type!=="comment"||o.indent0&&(yield this.buffer.substr(this.pos,i),this.pos=r),i}*pushUntil(e){let r=this.pos,n=this.buffer[r];for(;!e(n);)n=this.buffer[++r];return yield*this.pushToIndex(r,!1)}};xB.Lexer=PT});var NT=v($B=>{"use strict";var DT=class{constructor(){this.lineStarts=[],this.addNewLine=e=>this.lineStarts.push(e),this.linePos=e=>{let r=0,n=this.lineStarts.length;for(;r>1;this.lineStarts[o]{"use strict";var mye=Ze("process"),kB=$_(),hye=CT();function rs(t,e){for(let r=0;r=0;)switch(t[e].type){case"doc-start":case"explicit-key-ind":case"map-value-ind":case"seq-item-ind":case"newline":break e}for(;t[++e]?.type==="space";);return t.splice(e,t.length)}function A_(t,e){if(e.length<1e5)Array.prototype.push.apply(t,e);else for(let r=0;r0;)yield*this.pop()}get sourceToken(){return{type:this.type,offset:this.offset,indent:this.indent,source:this.source}}*step(){let e=this.peek(1);if(this.type==="doc-end"&&e?.type!=="doc-end"){for(;this.stack.length>0;)yield*this.pop();this.stack.push({type:"doc-end",offset:this.offset,source:this.source});return}if(!e)return yield*this.stream();switch(e.type){case"document":return yield*this.document(e);case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return yield*this.scalar(e);case"block-scalar":return yield*this.blockScalar(e);case"block-map":return yield*this.blockMap(e);case"block-seq":return yield*this.blockSequence(e);case"flow-collection":return yield*this.flowCollection(e);case"doc-end":return yield*this.documentEnd(e)}yield*this.pop()}peek(e){return this.stack[this.stack.length-e]}*pop(e){let r=e??this.stack.pop();if(!r)yield{type:"error",offset:this.offset,source:"",message:"Tried to pop an empty stack"};else if(this.stack.length===0)yield r;else{let n=this.peek(1);switch(r.type==="block-scalar"?r.indent="indent"in n?n.indent:0:r.type==="flow-collection"&&n.type==="document"&&(r.indent=0),r.type==="flow-collection"&&AB(r),n.type){case"document":n.value=r;break;case"block-scalar":n.props.push(r);break;case"block-map":{let i=n.items[n.items.length-1];if(i.value){n.items.push({start:[],key:r,sep:[]}),this.onKeyLine=!0;return}else if(i.sep)i.value=r;else{Object.assign(i,{key:r,sep:[]}),this.onKeyLine=!i.explicitKey;return}break}case"block-seq":{let i=n.items[n.items.length-1];i.value?n.items.push({start:[],value:r}):i.value=r;break}case"flow-collection":{let i=n.items[n.items.length-1];!i||i.value?n.items.push({start:[],key:r,sep:[]}):i.sep?i.value=r:Object.assign(i,{key:r,sep:[]});return}default:yield*this.pop(),yield*this.pop(r)}if((n.type==="document"||n.type==="block-map"||n.type==="block-seq")&&(r.type==="block-map"||r.type==="block-seq")){let i=r.items[r.items.length-1];i&&!i.sep&&!i.value&&i.start.length>0&&EB(i.start)===-1&&(r.indent===0||i.start.every(o=>o.type!=="comment"||o.indent=e.indent){let n=!this.onKeyLine&&this.indent===e.indent,i=n&&(r.sep||r.explicitKey)&&this.type!=="seq-item-ind",o=[];if(i&&r.sep&&!r.value){let s=[];for(let a=0;ae.indent&&(s.length=0);break;default:s.length=0}}s.length>=2&&(o=r.sep.splice(s[1]))}switch(this.type){case"anchor":case"tag":i||r.value?(o.push(this.sourceToken),e.items.push({start:o}),this.onKeyLine=!0):r.sep?r.sep.push(this.sourceToken):r.start.push(this.sourceToken);return;case"explicit-key-ind":!r.sep&&!r.explicitKey?(r.start.push(this.sourceToken),r.explicitKey=!0):i||r.value?(o.push(this.sourceToken),e.items.push({start:o,explicitKey:!0})):this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken],explicitKey:!0}]}),this.onKeyLine=!0;return;case"map-value-ind":if(r.explicitKey)if(r.sep)if(r.value)e.items.push({start:[],key:null,sep:[this.sourceToken]});else if(ts(r.sep,"map-value-ind"))this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:o,key:null,sep:[this.sourceToken]}]});else if(pH(r.key)&&!ts(r.sep,"newline")){let s=dl(r.start),a=r.key,c=r.sep;c.push(this.sourceToken),delete r.key,delete r.sep,this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:s,key:a,sep:c}]})}else o.length>0?r.sep=r.sep.concat(o,this.sourceToken):r.sep.push(this.sourceToken);else if(ts(r.start,"newline"))Object.assign(r,{key:null,sep:[this.sourceToken]});else{let s=dl(r.start);this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:s,key:null,sep:[this.sourceToken]}]})}else r.sep?r.value||i?e.items.push({start:o,key:null,sep:[this.sourceToken]}):ts(r.sep,"map-value-ind")?this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[],key:null,sep:[this.sourceToken]}]}):r.sep.push(this.sourceToken):Object.assign(r,{key:null,sep:[this.sourceToken]});this.onKeyLine=!0;return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{let s=this.flowScalar(this.type);i||r.value?(e.items.push({start:o,key:s,sep:[]}),this.onKeyLine=!0):r.sep?this.stack.push(s):(Object.assign(r,{key:s,sep:[]}),this.onKeyLine=!0);return}default:{let s=this.startBlockValue(e);if(s){if(s.type==="block-seq"){if(!r.explicitKey&&r.sep&&!ts(r.sep,"newline")){yield*this.pop({type:"error",offset:this.offset,message:"Unexpected block-seq-ind on same line with key",source:this.source});return}}else n&&e.items.push({start:o});this.stack.push(s);return}}}}yield*this.pop(),yield*this.step()}*blockSequence(e){let r=e.items[e.items.length-1];switch(this.type){case"newline":if(r.value){let n="end"in r.value?r.value.end:void 0;(Array.isArray(n)?n[n.length-1]:void 0)?.type==="comment"?n?.push(this.sourceToken):e.items.push({start:[this.sourceToken]})}else r.start.push(this.sourceToken);return;case"space":case"comment":if(r.value)e.items.push({start:[this.sourceToken]});else{if(this.atIndentedComment(r.start,e.indent)){let i=e.items[e.items.length-2]?.value?.end;if(Array.isArray(i)){$_(i,r.start),i.push(this.sourceToken),e.items.pop();return}}r.start.push(this.sourceToken)}return;case"anchor":case"tag":if(r.value||this.indent<=e.indent)break;r.start.push(this.sourceToken);return;case"seq-item-ind":if(this.indent!==e.indent)break;r.value||ts(r.start,"seq-item-ind")?e.items.push({start:[this.sourceToken]}):r.start.push(this.sourceToken);return}if(this.indent>e.indent){let n=this.startBlockValue(e);if(n){this.stack.push(n);return}}yield*this.pop(),yield*this.step()}*flowCollection(e){let r=e.items[e.items.length-1];if(this.type==="flow-error-end"){let n;do yield*this.pop(),n=this.peek(1);while(n?.type==="flow-collection")}else if(e.end.length===0){switch(this.type){case"comma":case"explicit-key-ind":!r||r.sep?e.items.push({start:[this.sourceToken]}):r.start.push(this.sourceToken);return;case"map-value-ind":!r||r.value?e.items.push({start:[],key:null,sep:[this.sourceToken]}):r.sep?r.sep.push(this.sourceToken):Object.assign(r,{key:null,sep:[this.sourceToken]});return;case"space":case"comment":case"newline":case"anchor":case"tag":!r||r.value?e.items.push({start:[this.sourceToken]}):r.sep?r.sep.push(this.sourceToken):r.start.push(this.sourceToken);return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{let i=this.flowScalar(this.type);!r||r.value?e.items.push({start:[],key:i,sep:[]}):r.sep?this.stack.push(i):Object.assign(r,{key:i,sep:[]});return}case"flow-map-end":case"flow-seq-end":e.end.push(this.sourceToken);return}let n=this.startBlockValue(e);n?this.stack.push(n):(yield*this.pop(),yield*this.step())}else{let n=this.peek(2);if(n.type==="block-map"&&(this.type==="map-value-ind"&&n.indent===e.indent||this.type==="newline"&&!n.items[n.items.length-1].sep))yield*this.pop(),yield*this.step();else if(this.type==="map-value-ind"&&n.type!=="flow-collection"){let i=x_(n),o=dl(i);fH(e);let s=e.end.splice(1,e.end.length);s.push(this.sourceToken);let a={type:"block-map",offset:e.offset,indent:e.indent,items:[{start:o,key:e,sep:s}]};this.onKeyLine=!0,this.stack[this.stack.length-1]=a}else yield*this.lineEnd(e)}}flowScalar(e){if(this.onNewLine){let r=this.source.indexOf(` +`,r)+1}yield*this.pop();break;default:yield*this.pop(),yield*this.step()}}*blockMap(e){let r=e.items[e.items.length-1];switch(this.type){case"newline":if(this.onKeyLine=!1,r.value){let n="end"in r.value?r.value.end:void 0;(Array.isArray(n)?n[n.length-1]:void 0)?.type==="comment"?n?.push(this.sourceToken):e.items.push({start:[this.sourceToken]})}else r.sep?r.sep.push(this.sourceToken):r.start.push(this.sourceToken);return;case"space":case"comment":if(r.value)e.items.push({start:[this.sourceToken]});else if(r.sep)r.sep.push(this.sourceToken);else{if(this.atIndentedComment(r.start,e.indent)){let i=e.items[e.items.length-2]?.value?.end;if(Array.isArray(i)){A_(i,r.start),i.push(this.sourceToken),e.items.pop();return}}r.start.push(this.sourceToken)}return}if(this.indent>=e.indent){let n=!this.onKeyLine&&this.indent===e.indent,i=n&&(r.sep||r.explicitKey)&&this.type!=="seq-item-ind",o=[];if(i&&r.sep&&!r.value){let s=[];for(let a=0;ae.indent&&(s.length=0);break;default:s.length=0}}s.length>=2&&(o=r.sep.splice(s[1]))}switch(this.type){case"anchor":case"tag":i||r.value?(o.push(this.sourceToken),e.items.push({start:o}),this.onKeyLine=!0):r.sep?r.sep.push(this.sourceToken):r.start.push(this.sourceToken);return;case"explicit-key-ind":!r.sep&&!r.explicitKey?(r.start.push(this.sourceToken),r.explicitKey=!0):i||r.value?(o.push(this.sourceToken),e.items.push({start:o,explicitKey:!0})):this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken],explicitKey:!0}]}),this.onKeyLine=!0;return;case"map-value-ind":if(r.explicitKey)if(r.sep)if(r.value)e.items.push({start:[],key:null,sep:[this.sourceToken]});else if(rs(r.sep,"map-value-ind"))this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:o,key:null,sep:[this.sourceToken]}]});else if(OB(r.key)&&!rs(r.sep,"newline")){let s=ml(r.start),a=r.key,c=r.sep;c.push(this.sourceToken),delete r.key,delete r.sep,this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:s,key:a,sep:c}]})}else o.length>0?r.sep=r.sep.concat(o,this.sourceToken):r.sep.push(this.sourceToken);else if(rs(r.start,"newline"))Object.assign(r,{key:null,sep:[this.sourceToken]});else{let s=ml(r.start);this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:s,key:null,sep:[this.sourceToken]}]})}else r.sep?r.value||i?e.items.push({start:o,key:null,sep:[this.sourceToken]}):rs(r.sep,"map-value-ind")?this.stack.push({type:"block-map",offset:this.offset,indent:this.indent,items:[{start:[],key:null,sep:[this.sourceToken]}]}):r.sep.push(this.sourceToken):Object.assign(r,{key:null,sep:[this.sourceToken]});this.onKeyLine=!0;return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{let s=this.flowScalar(this.type);i||r.value?(e.items.push({start:o,key:s,sep:[]}),this.onKeyLine=!0):r.sep?this.stack.push(s):(Object.assign(r,{key:s,sep:[]}),this.onKeyLine=!0);return}default:{let s=this.startBlockValue(e);if(s){if(s.type==="block-seq"){if(!r.explicitKey&&r.sep&&!rs(r.sep,"newline")){yield*this.pop({type:"error",offset:this.offset,message:"Unexpected block-seq-ind on same line with key",source:this.source});return}}else n&&e.items.push({start:o});this.stack.push(s);return}}}}yield*this.pop(),yield*this.step()}*blockSequence(e){let r=e.items[e.items.length-1];switch(this.type){case"newline":if(r.value){let n="end"in r.value?r.value.end:void 0;(Array.isArray(n)?n[n.length-1]:void 0)?.type==="comment"?n?.push(this.sourceToken):e.items.push({start:[this.sourceToken]})}else r.start.push(this.sourceToken);return;case"space":case"comment":if(r.value)e.items.push({start:[this.sourceToken]});else{if(this.atIndentedComment(r.start,e.indent)){let i=e.items[e.items.length-2]?.value?.end;if(Array.isArray(i)){A_(i,r.start),i.push(this.sourceToken),e.items.pop();return}}r.start.push(this.sourceToken)}return;case"anchor":case"tag":if(r.value||this.indent<=e.indent)break;r.start.push(this.sourceToken);return;case"seq-item-ind":if(this.indent!==e.indent)break;r.value||rs(r.start,"seq-item-ind")?e.items.push({start:[this.sourceToken]}):r.start.push(this.sourceToken);return}if(this.indent>e.indent){let n=this.startBlockValue(e);if(n){this.stack.push(n);return}}yield*this.pop(),yield*this.step()}*flowCollection(e){let r=e.items[e.items.length-1];if(this.type==="flow-error-end"){let n;do yield*this.pop(),n=this.peek(1);while(n?.type==="flow-collection")}else if(e.end.length===0){switch(this.type){case"comma":case"explicit-key-ind":!r||r.sep?e.items.push({start:[this.sourceToken]}):r.start.push(this.sourceToken);return;case"map-value-ind":!r||r.value?e.items.push({start:[],key:null,sep:[this.sourceToken]}):r.sep?r.sep.push(this.sourceToken):Object.assign(r,{key:null,sep:[this.sourceToken]});return;case"space":case"comment":case"newline":case"anchor":case"tag":!r||r.value?e.items.push({start:[this.sourceToken]}):r.sep?r.sep.push(this.sourceToken):r.start.push(this.sourceToken);return;case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":{let i=this.flowScalar(this.type);!r||r.value?e.items.push({start:[],key:i,sep:[]}):r.sep?this.stack.push(i):Object.assign(r,{key:i,sep:[]});return}case"flow-map-end":case"flow-seq-end":e.end.push(this.sourceToken);return}let n=this.startBlockValue(e);n?this.stack.push(n):(yield*this.pop(),yield*this.step())}else{let n=this.peek(2);if(n.type==="block-map"&&(this.type==="map-value-ind"&&n.indent===e.indent||this.type==="newline"&&!n.items[n.items.length-1].sep))yield*this.pop(),yield*this.step();else if(this.type==="map-value-ind"&&n.type!=="flow-collection"){let i=E_(n),o=ml(i);AB(e);let s=e.end.splice(1,e.end.length);s.push(this.sourceToken);let a={type:"block-map",offset:e.offset,indent:e.indent,items:[{start:o,key:e,sep:s}]};this.onKeyLine=!0,this.stack[this.stack.length-1]=a}else yield*this.lineEnd(e)}}flowScalar(e){if(this.onNewLine){let r=this.source.indexOf(` `)+1;for(;r!==0;)this.onNewLine(this.offset+r),r=this.source.indexOf(` -`,r)+1}return{type:e,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(e){switch(this.type){case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return this.flowScalar(this.type);case"block-scalar-header":return{type:"block-scalar",offset:this.offset,indent:this.indent,props:[this.sourceToken],source:""};case"flow-map-start":case"flow-seq-start":return{type:"flow-collection",offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case"seq-item-ind":return{type:"block-seq",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case"explicit-key-ind":{this.onKeyLine=!0;let r=x_(e),n=dl(r);return n.push(this.sourceToken),{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:n,explicitKey:!0}]}}case"map-value-ind":{this.onKeyLine=!0;let r=x_(e),n=dl(r);return{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:n,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(e,r){return this.type!=="comment"||this.indent<=r?!1:e.every(n=>n.type==="newline"||n.type==="space")}*documentEnd(e){this.type!=="doc-mode"&&(e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop()))}*lineEnd(e){switch(this.type){case"comma":case"doc-start":case"doc-end":case"flow-seq-end":case"flow-map-end":case"map-value-ind":yield*this.pop(),yield*this.step();break;case"newline":this.onKeyLine=!1;default:e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop())}}};mH.Parser=TO});var bH=v(Lf=>{"use strict";var hH=hO(),Ige=Rf(),Ff=Cf(),Pge=pT(),Cge=De(),Dge=AO(),gH=OO();function yH(t){let e=t.prettyErrors!==!1;return{lineCounter:t.lineCounter||e&&new Dge.LineCounter||null,prettyErrors:e}}function Nge(t,e={}){let{lineCounter:r,prettyErrors:n}=yH(e),i=new gH.Parser(r?.addNewLine),o=new hH.Composer(e),s=Array.from(o.compose(i.parse(t)));if(n&&r)for(let a of s)a.errors.forEach(Ff.prettifyError(t,r)),a.warnings.forEach(Ff.prettifyError(t,r));return s.length>0?s:Object.assign([],{empty:!0},o.streamInfo())}function _H(t,e={}){let{lineCounter:r,prettyErrors:n}=yH(e),i=new gH.Parser(r?.addNewLine),o=new hH.Composer(e),s=null;for(let a of o.compose(i.parse(t),!0,t.length))if(!s)s=a;else if(s.options.logLevel!=="silent"){s.errors.push(new Ff.YAMLParseError(a.range.slice(0,2),"MULTIPLE_DOCS","Source contains multiple documents; please use YAML.parseAllDocuments()"));break}return n&&r&&(s.errors.forEach(Ff.prettifyError(t,r)),s.warnings.forEach(Ff.prettifyError(t,r))),s}function jge(t,e,r){let n;typeof e=="function"?n=e:r===void 0&&e&&typeof e=="object"&&(r=e);let i=_H(t,r);if(!i)return null;if(i.warnings.forEach(o=>Pge.warn(i.options.logLevel,o)),i.errors.length>0){if(i.options.logLevel!=="silent")throw i.errors[0];i.errors=[]}return i.toJS(Object.assign({reviver:n},r))}function Mge(t,e,r){let n=null;if(typeof e=="function"||Array.isArray(e)?n=e:r===void 0&&e&&(r=e),typeof r=="string"&&(r=r.length),typeof r=="number"){let i=Math.round(r);r=i<1?void 0:i>8?{indent:8}:{indent:i}}if(t===void 0){let{keepUndefined:i}=r??e??{};if(!i)return}return Cge.isDocument(t)&&!n?t.toString(r):new Ige.Document(t,n,r).toString(r)}Lf.parse=jge;Lf.parseAllDocuments=Nge;Lf.parseDocument=_H;Lf.stringify=Mge});var er=v(Ze=>{"use strict";var Fge=hO(),Lge=Rf(),zge=KT(),RO=Cf(),Uge=mf(),rs=De(),qge=Yo(),Bge=Dt(),Hge=Qo(),Gge=es(),Zge=S_(),Vge=kO(),Wge=AO(),Kge=OO(),k_=bH(),vH=uf();Ze.Composer=Fge.Composer;Ze.Document=Lge.Document;Ze.Schema=zge.Schema;Ze.YAMLError=RO.YAMLError;Ze.YAMLParseError=RO.YAMLParseError;Ze.YAMLWarning=RO.YAMLWarning;Ze.Alias=Uge.Alias;Ze.isAlias=rs.isAlias;Ze.isCollection=rs.isCollection;Ze.isDocument=rs.isDocument;Ze.isMap=rs.isMap;Ze.isNode=rs.isNode;Ze.isPair=rs.isPair;Ze.isScalar=rs.isScalar;Ze.isSeq=rs.isSeq;Ze.Pair=qge.Pair;Ze.Scalar=Bge.Scalar;Ze.YAMLMap=Hge.YAMLMap;Ze.YAMLSeq=Gge.YAMLSeq;Ze.CST=Zge;Ze.Lexer=Vge.Lexer;Ze.LineCounter=Wge.LineCounter;Ze.Parser=Kge.Parser;Ze.parse=k_.parse;Ze.parseAllDocuments=k_.parseAllDocuments;Ze.parseDocument=k_.parseDocument;Ze.stringify=k_.stringify;Ze.visit=vH.visit;Ze.visitAsync=vH.visitAsync});import{execFileSync as IO}from"node:child_process";import{existsSync as E_}from"node:fs";import{join as A_,resolve as Jge}from"node:path";function Yge(t){try{let e=IO("git",["rev-parse","--git-dir"],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();return e?Jge(t,e):null}catch{return null}}function PO(t){let e=Yge(t);if(!e)return null;try{if(E_(A_(e,"MERGE_HEAD")))return"merge";if(E_(A_(e,"CHERRY_PICK_HEAD")))return"cherry-pick";if(E_(A_(e,"rebase-merge"))||E_(A_(e,"rebase-apply")))return"rebase"}catch{return null}return null}function _a(t){return PO(t)!==null}function zf(t,e){try{let r=IO("git",["rev-parse","--verify","--quiet",`${e}^{commit}`],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();return r.length>0?r:null}catch{return null}}function T_(t,e){return zf(t,e)!==null}function SH(t,e){try{let r=IO("git",["merge-base",e,"HEAD"],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();return r.length>0?r:e}catch{return e}}var ba=y(()=>{"use strict"});import{execFileSync as Xge}from"node:child_process";import{existsSync as Qge,readFileSync as eye}from"node:fs";import{join as xH}from"node:path";function ml(t,e){return Xge("git",[...e],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","pipe"]})}function ns(t){try{let e=ml(t,["describe","--tags","--abbrev=0"]).trim();if(e.length>0)return e}catch{}throw new Error("changelog: no git tag found to anchor the default range \u2014 pass --since explicitly (e.g. clad changelog --since v1.0.0)")}function is(t,e){$H(t,e);let r=ml(t,["rev-parse","HEAD"]).trim(),n=tye(t,e);return{groups:rye(t,n),head:r,inventory:{after:wH(R_(t,"spec.yaml")),before:wH(Uf(t,e,"spec.yaml"))},since:e,unsharded_commits:sye(t,e)}}function CO(t){if(t.text&&t.text.trim().length>0)return t.text.trim();let e=t.action?.trim();if(!e)return null;let r=t.condition?.trim(),n=t.response?.trim(),i=r?`${r.charAt(0).toUpperCase()}${r.slice(1)}, the system shall ${e}`:`The system shall ${e}`;return n?`${i} \u2014 ${n}.`:`${i}.`}function $H(t,e){let r=(e??"").trim();if(r.length===0)throw new Error("changelog: empty since ref \u2014 pass --since ");if(!T_(t,r))throw new Error(`changelog: '${r}' does not resolve to a commit in this repository \u2014 pass --since that exists. An unknown ref is an error, never a silently empty changelog.`)}function tye(t,e){let r=ml(t,["diff","--name-status",`${e}..HEAD`,"--","spec/"]),n=[];for(let i of r.split(` -`)){if(i.trim().length===0)continue;let o=i.split(" "),s=o[0]??"",a=o[1]??"",c=o.length>2?o[2]:a;if(!(!O_(c)&&!O_(a)))if(s.startsWith("A")){let l=pl(R_(t,c));if(!l)continue;l.status==="done"?n.push(fl(l,"added-as-done")):l.status==="archived"&&n.push(fl(l,"archived"))}else if(s.startsWith("D")){let l=pl(Uf(t,e,a));l&&n.push(fl(l,"archived"))}else{let l=pl(R_(t,c));if(!l)continue;let d=pl(Uf(t,e,a))?.status;l.status==="done"&&d!=="done"?n.push(fl(l,"flipped-to-done")):l.status==="done"&&d==="done"?n.push(fl(l,"modified-while-done")):l.status==="archived"&&d!=="archived"&&n.push(fl(l,"archived"))}}return n.sort((i,o)=>i.id.localeCompare(o.id)),n}function O_(t){return t.startsWith("spec/features/")&&(t.endsWith(".yaml")||t.endsWith(".yml"))}function kH(t,e){$H(t,e);let r=ml(t,["diff","--name-status",`${e}..HEAD`,"--","spec/"]),n=[];for(let i of r.split(` -`)){if(i.trim().length===0)continue;let o=i.split(" "),s=o[0]??"",a=o[1]??"",c=o.length>2?o[2]??"":a;if(!O_(c)&&!O_(a))continue;let l=s.startsWith("A"),u=s.startsWith("D"),d=l||!u?pl(Uf(t,"HEAD",c)):null,f=l?null:pl(Uf(t,e,a)),p=d??f;p&&n.push({path:u?a:c,id:p.id,...p.slug?{slug:p.slug}:{},title:p.title,statusBefore:f?f.status:null,statusAfter:d?d.status:null,baseAcs:f?.acceptance_criteria??[],headAcs:d?.acceptance_criteria??[]})}return n.sort((i,o)=>i.id.localeCompare(o.id)),n}function fl(t,e){return{acceptance:(t.acceptance_criteria??[]).map(n=>CO(n)).filter(n=>n!==null),change:e,id:t.id,...t.slug?{slug:t.slug}:{},title:t.title}}function pl(t){if(t===null)return null;let e;try{e=(0,I_.parse)(t)}catch{return null}let r=e;return!r||typeof r.id!="string"||typeof r.status!="string"?null:{id:r.id,slug:typeof r.slug=="string"?r.slug:void 0,title:typeof r.title=="string"?r.title:r.id,status:r.status,acceptance_criteria:r.acceptance_criteria}}function R_(t,e){let r=xH(t,e);if(!Qge(r))return null;try{return eye(r,"utf8")}catch{return null}}function Uf(t,e,r){try{return ml(t,["show",`${e}:${r}`])}catch{return null}}function rye(t,e){let r=nye(t).filter(s=>typeof s.id=="string"&&s.id.length>0).sort((s,a)=>s.id.localeCompare(a.id)),n=[],i=new Set;for(let s of r){let a=new Set(s.features??[]),c=e.filter(l=>a.has(l.id)&&!i.has(l.id));if(c.length!==0){for(let l of c)i.add(l.id);n.push({capability:s.id,features:c,title:s.title??s.id})}}let o=e.filter(s=>!i.has(s.id));return o.length>0&&n.push({capability:"uncategorized",features:o,title:"Uncategorized"}),n}function nye(t){let e=R_(t,xH("spec","capabilities.yaml"));if(e===null)return[];try{let r=(0,I_.parse)(e);return Array.isArray(r?.capabilities)?r.capabilities:[]}catch{return[]}}function wH(t){let e={};if(t!==null)try{let n=(0,I_.parse)(t);n&&typeof n.inventory=="object"&&n.inventory!==null&&(e=n.inventory)}catch{}let r=n=>typeof e[n]=="number"?e[n]:0;return{capabilities:r("capabilities"),features:r("features"),scenarios:r("scenarios"),test_files:r("test_files")}}function sye(t,e){let r=ml(t,["log",`${e}..HEAD`,"--format=%h%x09%s","--","src/"]),n=[];for(let i of r.split(` -`)){if(i.trim().length===0)continue;let o=i.indexOf(" ");if(o<0)continue;let s=i.slice(0,o),a=i.slice(o+1);iye.test(a)&&(oye.test(a)||n.push({hash:s,subject:a}))}return n}var I_,iye,oye,hl=y(()=>{"use strict";I_=St(er(),1);ba();iye=/^(feat|fix)(\([^)]*\))?!?:/,oye=/\bF-(\d{3,}|[a-f0-9]{6,})\b/});import{execFileSync as EH}from"node:child_process";import{appendFileSync as aye,existsSync as DO,mkdirSync as cye,readFileSync as lye,renameSync as uye,statSync as dye}from"node:fs";import{userInfo as fye}from"node:os";import{dirname as pye,join as jO}from"node:path";function MO(t){return jO(t,AH,mye)}function tn(t,e){let r=MO(t),n=pye(r);DO(n)||cye(n,{recursive:!0});try{DO(r)&&dye(r).size>hye&&uye(r,jO(n,TH))}catch{}aye(r,`${JSON.stringify(e)} -`,"utf8")}function NO(t){if(!DO(t))return[];let e=lye(t,"utf8").trim();return e.length===0?[]:e.split(` -`).filter(r=>r.length>0).map(r=>JSON.parse(r))}function va(t){return NO(MO(t))}function P_(t){return[...NO(jO(t,AH,TH)),...NO(MO(t))]}function rn(t,e){return{id:`ev-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,timestamp:new Date().toISOString(),type:t,payload:e}}function gye(t){let e;try{e=EH("git",["config","user.name"],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{}if(!e)try{e=fye().username}catch{e=void 0}return{author:"human",name:e,timestamp:new Date().toISOString()}}function yye(t){try{return EH("git",["rev-parse","HEAD"],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return}}function qf(t,e){try{let r=va(t);for(let n=r.length-1;n>=0;n--)if(r[n].type===e)return r[n]}catch{}return null}function tr(t,e,r){try{let n=yye(t),i=gye(t),o={...r,head:n,identity:i};if(e==="gate_run"){let s=qf(t,"gate_run");if(s&&s.payload.head===n&&s.payload.tier===r.tier&&s.payload.strict===r.strict&&s.payload.worst===r.worst)return}tn(t,rn(e,o))}catch{}}var AH,mye,TH,hye,Mr=y(()=>{"use strict";AH=".cladding",mye="events.log.jsonl",TH="events.log.1.jsonl",hye=5*1024*1024});import{execFileSync as _ye}from"node:child_process";import{existsSync as OH,readdirSync as bye,readFileSync as vye,statSync as RH}from"node:fs";import{createHash as Sye}from"node:crypto";import{join as FO}from"node:path";function Sa(t){try{return _ye("git",["rev-parse","HEAD"],{cwd:t,stdio:["ignore","pipe","ignore"]}).toString("utf8").trim()||null}catch{return null}}function LO(t){let e=[],r=FO(t,"spec.yaml");OH(r)&&RH(r).isFile()&&e.push(r);for(let i of["features","scenarios"]){let o=FO(t,"spec",i);if(!(!OH(o)||!RH(o).isDirectory()))for(let s of bye(o))s.endsWith(".yaml")&&e.push(FO(o,s))}e.sort();let n=Sye("sha256");for(let i of e){let o=i.slice(t.length+1);n.update(`${o}\0`),n.update(vye(i)),n.update("\0")}return n.digest("hex")}function C_(t,e){let r={featureId:e,gitHead:Sa(t),specDigest:LO(t),timestamp:new Date().toISOString()};return tn(t,rn("feature_checkpoint",{feature:e,git_head:r.gitHead,spec_digest:r.specDigest})),r}function D_(t,e){let r=va(t);for(let n=r.length-1;n>=0;n--){let i=r[n];if(i.type==="feature_checkpoint"&&i.payload.feature===e)return{featureId:e,gitHead:i.payload.git_head??null,specDigest:String(i.payload.spec_digest??""),timestamp:i.timestamp}}return null}function N_(t,e,r,n){let i=rn("feature_rolled_back",{feature:e,to_git_head:r.gitHead,to_spec_digest:r.specDigest,to_checkpoint_at:r.timestamp,reason:n??null});return tn(t,i),i}var Bf=y(()=>{"use strict";Mr()});import{readFileSync as wye,statSync as xye}from"node:fs";import{extname as $ye,resolve as zO,sep as kye}from"node:path";function nn(t){return Math.ceil(t.length/4)}function Tye(t,e){let r=zO(e),n=zO(r,t);return n===r||n.startsWith(r+kye)}function PH(t,e,r,n){if(!Tye(t,e))return{path:t,omitted:"unsafe-path"};if(!Eye.has($ye(t).toLowerCase()))return{path:t,omitted:"unsupported"};let i,o;if(n){let l=n(t);if(l==null)return{path:t,omitted:"missing"};if(i=l,o=Buffer.byteLength(l,"utf8"),o>IH)return{path:t,omitted:"too-large",bytes:o}}else{let l=zO(e,t);try{o=xye(l).size}catch{return{path:t,omitted:"missing"}}if(o>IH)return{path:t,omitted:"too-large",bytes:o};try{i=wye(l,"utf8")}catch{return{path:t,omitted:"missing",bytes:o}}}if(i.includes(Aye))return{path:t,omitted:"binary",bytes:o};let s=Math.max(0,Math.floor(r));if(i.length<=s)return{path:t,text:i,bytes:o};let a=` +`,r)+1}return{type:e,offset:this.offset,indent:this.indent,source:this.source}}startBlockValue(e){switch(this.type){case"alias":case"scalar":case"single-quoted-scalar":case"double-quoted-scalar":return this.flowScalar(this.type);case"block-scalar-header":return{type:"block-scalar",offset:this.offset,indent:this.indent,props:[this.sourceToken],source:""};case"flow-map-start":case"flow-seq-start":return{type:"flow-collection",offset:this.offset,indent:this.indent,start:this.sourceToken,items:[],end:[]};case"seq-item-ind":return{type:"block-seq",offset:this.offset,indent:this.indent,items:[{start:[this.sourceToken]}]};case"explicit-key-ind":{this.onKeyLine=!0;let r=E_(e),n=ml(r);return n.push(this.sourceToken),{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:n,explicitKey:!0}]}}case"map-value-ind":{this.onKeyLine=!0;let r=E_(e),n=ml(r);return{type:"block-map",offset:this.offset,indent:this.indent,items:[{start:n,key:null,sep:[this.sourceToken]}]}}}return null}atIndentedComment(e,r){return this.type!=="comment"||this.indent<=r?!1:e.every(n=>n.type==="newline"||n.type==="space")}*documentEnd(e){this.type!=="doc-mode"&&(e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop()))}*lineEnd(e){switch(this.type){case"comma":case"doc-start":case"doc-end":case"flow-seq-end":case"flow-map-end":case"map-value-ind":yield*this.pop(),yield*this.step();break;case"newline":this.onKeyLine=!1;default:e.end?e.end.push(this.sourceToken):e.end=[this.sourceToken],this.type==="newline"&&(yield*this.pop())}}};TB.Parser=jT});var DB=v(qf=>{"use strict";var RB=xT(),gye=Cf(),Uf=jf(),yye=SO(),_ye=De(),bye=NT(),IB=MT();function PB(t){let e=t.prettyErrors!==!1;return{lineCounter:t.lineCounter||e&&new bye.LineCounter||null,prettyErrors:e}}function vye(t,e={}){let{lineCounter:r,prettyErrors:n}=PB(e),i=new IB.Parser(r?.addNewLine),o=new RB.Composer(e),s=Array.from(o.compose(i.parse(t)));if(n&&r)for(let a of s)a.errors.forEach(Uf.prettifyError(t,r)),a.warnings.forEach(Uf.prettifyError(t,r));return s.length>0?s:Object.assign([],{empty:!0},o.streamInfo())}function CB(t,e={}){let{lineCounter:r,prettyErrors:n}=PB(e),i=new IB.Parser(r?.addNewLine),o=new RB.Composer(e),s=null;for(let a of o.compose(i.parse(t),!0,t.length))if(!s)s=a;else if(s.options.logLevel!=="silent"){s.errors.push(new Uf.YAMLParseError(a.range.slice(0,2),"MULTIPLE_DOCS","Source contains multiple documents; please use YAML.parseAllDocuments()"));break}return n&&r&&(s.errors.forEach(Uf.prettifyError(t,r)),s.warnings.forEach(Uf.prettifyError(t,r))),s}function Sye(t,e,r){let n;typeof e=="function"?n=e:r===void 0&&e&&typeof e=="object"&&(r=e);let i=CB(t,r);if(!i)return null;if(i.warnings.forEach(o=>yye.warn(i.options.logLevel,o)),i.errors.length>0){if(i.options.logLevel!=="silent")throw i.errors[0];i.errors=[]}return i.toJS(Object.assign({reviver:n},r))}function wye(t,e,r){let n=null;if(typeof e=="function"||Array.isArray(e)?n=e:r===void 0&&e&&(r=e),typeof r=="string"&&(r=r.length),typeof r=="number"){let i=Math.round(r);r=i<1?void 0:i>8?{indent:8}:{indent:i}}if(t===void 0){let{keepUndefined:i}=r??e??{};if(!i)return}return _ye.isDocument(t)&&!n?t.toString(r):new gye.Document(t,n,r).toString(r)}qf.parse=Sye;qf.parseAllDocuments=vye;qf.parseDocument=CB;qf.stringify=wye});var tr=v(Ve=>{"use strict";var xye=xT(),$ye=Cf(),kye=nT(),FT=jf(),Eye=yf(),ns=De(),Aye=Xo(),Oye=Dt(),Tye=es(),Rye=ts(),Iye=$_(),Pye=CT(),Cye=NT(),Dye=MT(),O_=DB(),NB=pf();Ve.Composer=xye.Composer;Ve.Document=$ye.Document;Ve.Schema=kye.Schema;Ve.YAMLError=FT.YAMLError;Ve.YAMLParseError=FT.YAMLParseError;Ve.YAMLWarning=FT.YAMLWarning;Ve.Alias=Eye.Alias;Ve.isAlias=ns.isAlias;Ve.isCollection=ns.isCollection;Ve.isDocument=ns.isDocument;Ve.isMap=ns.isMap;Ve.isNode=ns.isNode;Ve.isPair=ns.isPair;Ve.isScalar=ns.isScalar;Ve.isSeq=ns.isSeq;Ve.Pair=Aye.Pair;Ve.Scalar=Oye.Scalar;Ve.YAMLMap=Tye.YAMLMap;Ve.YAMLSeq=Rye.YAMLSeq;Ve.CST=Iye;Ve.Lexer=Pye.Lexer;Ve.LineCounter=Cye.LineCounter;Ve.Parser=Dye.Parser;Ve.parse=O_.parse;Ve.parseAllDocuments=O_.parseAllDocuments;Ve.parseDocument=O_.parseDocument;Ve.stringify=O_.stringify;Ve.visit=NB.visit;Ve.visitAsync=NB.visitAsync});import{execFileSync as LT}from"node:child_process";import{existsSync as T_}from"node:fs";import{join as R_,resolve as Nye}from"node:path";function jye(t){try{let e=LT("git",["rev-parse","--git-dir"],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();return e?Nye(t,e):null}catch{return null}}function zT(t){let e=jye(t);if(!e)return null;try{if(T_(R_(e,"MERGE_HEAD")))return"merge";if(T_(R_(e,"CHERRY_PICK_HEAD")))return"cherry-pick";if(T_(R_(e,"rebase-merge"))||T_(R_(e,"rebase-apply")))return"rebase"}catch{return null}return null}function Sa(t){return zT(t)!==null}function Hf(t,e){try{let r=LT("git",["rev-parse","--verify","--quiet",`${e}^{commit}`],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();return r.length>0?r:null}catch{return null}}function I_(t,e){return Hf(t,e)!==null}function jB(t,e){try{let r=LT("git",["merge-base",e,"HEAD"],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim();return r.length>0?r:e}catch{return e}}var wa=y(()=>{"use strict"});import{execFileSync as Mye}from"node:child_process";import{existsSync as Fye,readFileSync as Lye}from"node:fs";import{join as FB}from"node:path";function yl(t,e){return Mye("git",[...e],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","pipe"]})}function is(t){try{let e=yl(t,["describe","--tags","--abbrev=0"]).trim();if(e.length>0)return e}catch{}throw new Error("changelog: no git tag found to anchor the default range \u2014 pass --since explicitly (e.g. clad changelog --since v1.0.0)")}function os(t,e){LB(t,e);let r=yl(t,["rev-parse","HEAD"]).trim(),n=zye(t,e);return{groups:Uye(t,n),head:r,inventory:{after:MB(C_(t,"spec.yaml")),before:MB(Bf(t,e,"spec.yaml"))},since:e,unsharded_commits:Gye(t,e)}}function UT(t){if(t.text&&t.text.trim().length>0)return t.text.trim();let e=t.action?.trim();if(!e)return null;let r=t.condition?.trim(),n=t.response?.trim(),i=r?`${r.charAt(0).toUpperCase()}${r.slice(1)}, the system shall ${e}`:`The system shall ${e}`;return n?`${i} \u2014 ${n}.`:`${i}.`}function LB(t,e){let r=(e??"").trim();if(r.length===0)throw new Error("changelog: empty since ref \u2014 pass --since ");if(!I_(t,r))throw new Error(`changelog: '${r}' does not resolve to a commit in this repository \u2014 pass --since that exists. An unknown ref is an error, never a silently empty changelog.`)}function zye(t,e){let r=yl(t,["diff","--name-status",`${e}..HEAD`,"--","spec/"]),n=[];for(let i of r.split(` +`)){if(i.trim().length===0)continue;let o=i.split(" "),s=o[0]??"",a=o[1]??"",c=o.length>2?o[2]:a;if(!(!P_(c)&&!P_(a)))if(s.startsWith("A")){let l=gl(C_(t,c));if(!l)continue;l.status==="done"?n.push(hl(l,"added-as-done")):l.status==="archived"&&n.push(hl(l,"archived"))}else if(s.startsWith("D")){let l=gl(Bf(t,e,a));l&&n.push(hl(l,"archived"))}else{let l=gl(C_(t,c));if(!l)continue;let d=gl(Bf(t,e,a))?.status;l.status==="done"&&d!=="done"?n.push(hl(l,"flipped-to-done")):l.status==="done"&&d==="done"?n.push(hl(l,"modified-while-done")):l.status==="archived"&&d!=="archived"&&n.push(hl(l,"archived"))}}return n.sort((i,o)=>i.id.localeCompare(o.id)),n}function P_(t){return t.startsWith("spec/features/")&&(t.endsWith(".yaml")||t.endsWith(".yml"))}function zB(t,e){LB(t,e);let r=yl(t,["diff","--name-status",`${e}..HEAD`,"--","spec/"]),n=[];for(let i of r.split(` +`)){if(i.trim().length===0)continue;let o=i.split(" "),s=o[0]??"",a=o[1]??"",c=o.length>2?o[2]??"":a;if(!P_(c)&&!P_(a))continue;let l=s.startsWith("A"),u=s.startsWith("D"),d=l||!u?gl(Bf(t,"HEAD",c)):null,f=l?null:gl(Bf(t,e,a)),p=d??f;p&&n.push({path:u?a:c,id:p.id,...p.slug?{slug:p.slug}:{},title:p.title,statusBefore:f?f.status:null,statusAfter:d?d.status:null,baseAcs:f?.acceptance_criteria??[],headAcs:d?.acceptance_criteria??[]})}return n.sort((i,o)=>i.id.localeCompare(o.id)),n}function hl(t,e){return{acceptance:(t.acceptance_criteria??[]).map(n=>UT(n)).filter(n=>n!==null),change:e,id:t.id,...t.slug?{slug:t.slug}:{},title:t.title}}function gl(t){if(t===null)return null;let e;try{e=(0,D_.parse)(t)}catch{return null}let r=e;return!r||typeof r.id!="string"||typeof r.status!="string"?null:{id:r.id,slug:typeof r.slug=="string"?r.slug:void 0,title:typeof r.title=="string"?r.title:r.id,status:r.status,acceptance_criteria:r.acceptance_criteria}}function C_(t,e){let r=FB(t,e);if(!Fye(r))return null;try{return Lye(r,"utf8")}catch{return null}}function Bf(t,e,r){try{return yl(t,["show",`${e}:${r}`])}catch{return null}}function Uye(t,e){let r=qye(t).filter(s=>typeof s.id=="string"&&s.id.length>0).sort((s,a)=>s.id.localeCompare(a.id)),n=[],i=new Set;for(let s of r){let a=new Set(s.features??[]),c=e.filter(l=>a.has(l.id)&&!i.has(l.id));if(c.length!==0){for(let l of c)i.add(l.id);n.push({capability:s.id,features:c,title:s.title??s.id})}}let o=e.filter(s=>!i.has(s.id));return o.length>0&&n.push({capability:"uncategorized",features:o,title:"Uncategorized"}),n}function qye(t){let e=C_(t,FB("spec","capabilities.yaml"));if(e===null)return[];try{let r=(0,D_.parse)(e);return Array.isArray(r?.capabilities)?r.capabilities:[]}catch{return[]}}function MB(t){let e={};if(t!==null)try{let n=(0,D_.parse)(t);n&&typeof n.inventory=="object"&&n.inventory!==null&&(e=n.inventory)}catch{}let r=n=>typeof e[n]=="number"?e[n]:0;return{capabilities:r("capabilities"),features:r("features"),scenarios:r("scenarios"),test_files:r("test_files")}}function Gye(t,e){let r=yl(t,["log",`${e}..HEAD`,"--format=%h%x09%s","--","src/"]),n=[];for(let i of r.split(` +`)){if(i.trim().length===0)continue;let o=i.indexOf(" ");if(o<0)continue;let s=i.slice(0,o),a=i.slice(o+1);Hye.test(a)&&(Bye.test(a)||n.push({hash:s,subject:a}))}return n}var D_,Hye,Bye,_l=y(()=>{"use strict";D_=wt(tr(),1);wa();Hye=/^(feat|fix)(\([^)]*\))?!?:/,Bye=/\bF-(\d{3,}|[a-f0-9]{6,})\b/});import{execFileSync as UB}from"node:child_process";import{appendFileSync as Zye,existsSync as qT,mkdirSync as Vye,readFileSync as Wye,renameSync as Kye,statSync as Jye}from"node:fs";import{userInfo as Yye}from"node:os";import{dirname as Xye,join as BT}from"node:path";function GT(t){return BT(t,qB,Qye)}function rn(t,e){let r=GT(t),n=Xye(r);qT(n)||Vye(n,{recursive:!0});try{qT(r)&&Jye(r).size>e_e&&Kye(r,BT(n,HB))}catch{}Zye(r,`${JSON.stringify(e)} +`,"utf8")}function HT(t){if(!qT(t))return[];let e=Wye(t,"utf8").trim();return e.length===0?[]:e.split(` +`).filter(r=>r.length>0).map(r=>JSON.parse(r))}function ss(t){return HT(GT(t))}function N_(t){return[...HT(BT(t,qB,HB)),...HT(GT(t))]}function nn(t,e){return{id:`ev-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,6)}`,timestamp:new Date().toISOString(),type:t,payload:e}}function t_e(t){let e;try{e=UB("git",["config","user.name"],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()||void 0}catch{}if(!e)try{e=Yye().username}catch{e=void 0}return{author:"human",name:e,timestamp:new Date().toISOString()}}function r_e(t){try{return UB("git",["rev-parse","HEAD"],{cwd:t,encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{return}}function Gf(t,e){try{let r=ss(t);for(let n=r.length-1;n>=0;n--)if(r[n].type===e)return r[n]}catch{}return null}function Jt(t,e,r){try{let n=r_e(t),i=t_e(t),o={...r,head:n,identity:i};if(e==="gate_run"){let s=ss(t),a=-1;for(let u=s.length-1;u>=0;u--)if(s[u].type==="gate_run"){a=u;break}let c=a>=0?s[a]:void 0,l=a>=0&&s.slice(a+1).some(u=>u.type==="stop_blocked");if(c&&!l&&c.payload.head===n&&c.payload.tier===r.tier&&c.payload.strict===r.strict&&c.payload.worst===r.worst&&c.payload.stopFingerprint===r.stopFingerprint&&JSON.stringify(c.payload.blockers??[])===JSON.stringify(r.blockers??[]))return}rn(t,nn(e,o))}catch{}}var qB,Qye,HB,e_e,Fr=y(()=>{"use strict";qB=".cladding",Qye="events.log.jsonl",HB="events.log.1.jsonl",e_e=5*1024*1024});import{execFileSync as n_e}from"node:child_process";import{existsSync as BB,readdirSync as i_e,readFileSync as o_e,statSync as GB}from"node:fs";import{createHash as s_e}from"node:crypto";import{join as ZT}from"node:path";function xa(t){try{return n_e("git",["rev-parse","HEAD"],{cwd:t,stdio:["ignore","pipe","ignore"]}).toString("utf8").trim()||null}catch{return null}}function VT(t){let e=[],r=ZT(t,"spec.yaml");BB(r)&&GB(r).isFile()&&e.push(r);for(let i of["features","scenarios"]){let o=ZT(t,"spec",i);if(!(!BB(o)||!GB(o).isDirectory()))for(let s of i_e(o))s.endsWith(".yaml")&&e.push(ZT(o,s))}e.sort();let n=s_e("sha256");for(let i of e){let o=i.slice(t.length+1);n.update(`${o}\0`),n.update(o_e(i)),n.update("\0")}return n.digest("hex")}function j_(t,e){let r={featureId:e,gitHead:xa(t),specDigest:VT(t),timestamp:new Date().toISOString()};return rn(t,nn("feature_checkpoint",{feature:e,git_head:r.gitHead,spec_digest:r.specDigest})),r}function M_(t,e){let r=ss(t);for(let n=r.length-1;n>=0;n--){let i=r[n];if(i.type==="feature_checkpoint"&&i.payload.feature===e)return{featureId:e,gitHead:i.payload.git_head??null,specDigest:String(i.payload.spec_digest??""),timestamp:i.timestamp}}return null}function F_(t,e,r,n){let i=nn("feature_rolled_back",{feature:e,to_git_head:r.gitHead,to_spec_digest:r.specDigest,to_checkpoint_at:r.timestamp,reason:n??null});return rn(t,i),i}var Zf=y(()=>{"use strict";Fr()});import{readFileSync as a_e,statSync as c_e}from"node:fs";import{extname as l_e,resolve as WT,sep as u_e}from"node:path";function on(t){return Math.ceil(t.length/4)}function p_e(t,e){let r=WT(e),n=WT(r,t);return n===r||n.startsWith(r+u_e)}function VB(t,e,r,n){if(!p_e(t,e))return{path:t,omitted:"unsafe-path"};if(!d_e.has(l_e(t).toLowerCase()))return{path:t,omitted:"unsupported"};let i,o;if(n){let l=n(t);if(l==null)return{path:t,omitted:"missing"};if(i=l,o=Buffer.byteLength(l,"utf8"),o>ZB)return{path:t,omitted:"too-large",bytes:o}}else{let l=WT(e,t);try{o=c_e(l).size}catch{return{path:t,omitted:"missing"}}if(o>ZB)return{path:t,omitted:"too-large",bytes:o};try{i=a_e(l,"utf8")}catch{return{path:t,omitted:"missing",bytes:o}}}if(i.includes(f_e))return{path:t,omitted:"binary",bytes:o};let s=Math.max(0,Math.floor(r));if(i.length<=s)return{path:t,text:i,bytes:o};let a=` /* ... clipped (${o} bytes total) ... */ -`,c=Math.max(0,s-a.length);return{path:t,text:i.slice(0,c)+a,truncated:!0,bytes:o}}var Eye,IH,Aye,j_=y(()=>{"use strict";Eye=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rs",".go",".java",".kt",".kts",".cs",".rb",".php",".swift",".c",".h",".cpp",".hpp",".css",".scss",".sql",".sh",".yaml",".yml",".json",".md",".toml"]),IH=2e6,Aye="\0"});function Hf(t){for(let i of Oye)if(t.startsWith(i))return null;let e=t.indexOf("#"),n=(e>=0?t.slice(0,e):t).trim();return n.length>0?n:null}function UO(t,e,r){let n=t.get(e);n||(n=new Set,t.set(e,n)),n.add(r)}function Rye(t){let e=new Map,r=new Map,n=new Map;for(let i of t.features??[]){let o=i.id;for(let s of i.depends_on??[])UO(e,s,o);for(let s of i.modules??[])UO(r,s,o);for(let s of i.acceptance_criteria??[])for(let a of s.test_refs??[]){let c=Hf(a);c&&UO(n,c,o)}}return{dependents:e,moduleOwners:r,testRefCitations:n}}function Rn(t){let e=CH.get(t);return e||(e=Rye(t),CH.set(t,e)),e}var Oye,CH,os=y(()=>{"use strict";Oye=["derived:","fixture:","script:","self-dogfood:"];CH=new WeakMap});function qO(t,e,r=1/0){let n=new Set,i=new Set(t),o=[...i],s=0;for(;o.length>0&&sn.id===e)??r.find(n=>n.slug===e)??null}function Sr(t,e,r={}){let n=r.depth??1/0,i=Rn(t),o=new Map((t.features??[]).map(_=>[_.id,_])),s=[],a,c=Iye(t,e);if(c)s=[c];else{let _=i.moduleOwners.get(e);_&&_.size>0&&(a=e,s=[..._].map(S=>o.get(S)).filter(S=>!!S))}if(s.length===0)return{not_found:e,accepted_forms:["feature id (F-\u2026)","slug","module path (e.g. src/spec/load.ts)"],discovery:"grep spec/index.yaml \u2014 one line per feature (run clad sync if missing); module paths live in each shard\u2019s modules:; if the query is a file, fall back to normal code search \u2014 the graph only knows declared modules"};let l=s.map(_=>_.id),u=qO(l,i.dependents,n),d=[...u].map(_=>o.get(_)).filter(_=>!!_).map(_=>({id:_.id,title:_.title,status:_.status})).sort((_,S)=>_.id.localeCompare(S.id)),f=new Set([...l,...u]),p=[...f].map(_=>o.get(_)).filter(_=>!!_),m=[...new Set(p.flatMap(_=>_.modules??[]))].sort(),h=(t.scenarios??[]).filter(_=>(_.features??[]).some(S=>f.has(S))).map(_=>({id:_.id,title:_.title})).sort((_,S)=>_.id.localeCompare(S.id)),g=[...new Set(p.flatMap(_=>(_.acceptance_criteria??[]).flatMap(S=>S.test_refs??[])))].sort();return{focus:a?{module:a,owners:[...l].sort()}:{id:s[0].id,title:s[0].title,status:s[0].status},impacted:d,impacted_modules:m,scenarios:h,test_refs:g,ledger:BO(i)}}var wa=y(()=>{"use strict";os()});function DH(t){return t.impacted.length}function F_(t,e,r={}){let n=r.initialDepth??M_.initialDepth,i=r.maxDepth??M_.maxDepth,o=r.coverageThreshold??M_.coverageThreshold,s=r.marginYieldThreshold??M_.marginYieldThreshold,a=Rn(t),c=new Map((t.features??[]).map(b=>[b.id,b])),l=[],u=(t.features??[]).find(b=>b.id===e||b.slug===e);if(u)l=[u.id];else{let b=a.moduleOwners.get(e);b&&b.size>0&&(l=[...b].filter(_=>c.has(_)))}if(l.length===0){let b=Sr(t,e,{depth:1});return"not_found"in b,b}let d=qO(l,a.dependents,1/0).size;if(d===0){let b=Sr(t,e,{depth:n});return"not_found"in b?b:{slice:b,depthUsed:n,stoppedBy:"no-known-dependents",analysis:{frontierExhausted:!0,coverage:null,marginalYields:[0],totalKnownDependents:0}}}let f=[],p=0,m=null;for(let b=n;b<=i;b++){let _=Sr(t,e,{depth:b});if("not_found"in _)return _;m=_;let S=DH(_),x=S-p,w=S>0?x/S:0;f.push(w);let O=d>0?S/d:1,T=x===0&&b>n,A={frontierExhausted:T,coverage:O,marginalYields:[...f],totalKnownDependents:d};if(T)return{slice:_,depthUsed:b,stoppedBy:"exhaustion",analysis:A};if(O>=o)return{slice:_,depthUsed:b,stoppedBy:"coverage",analysis:A};if(f.length>=2&&f[f.length-1]0?g/d:1,marginalYields:[...f],totalKnownDependents:d}}}var M_,HO=y(()=>{"use strict";wa();os();M_={initialDepth:1,maxDepth:10,coverageThreshold:.9,marginYieldThreshold:.05}});function Pye(t,e){let r=new Set,n=[t];for(;n.length>0;){let i=n.pop();if(!i||r.has(i))continue;r.add(i);let o=e.get(i);for(let s of o?.depends_on??[])n.push(s)}return r}function NH(t,e){let r=new Map(t.features.map(a=>[a.id,a]));if(!r.has(e))return t;let n=Pye(e,r),i=t.features.filter(a=>n.has(a.id)),o=(t.scenarios??[]).filter(a=>(a.features??[]).some(c=>n.has(c)));return{...t,features:i,scenarios:o}}var jH=y(()=>{"use strict"});function Cye(t,e){let r=t.features??[];return r.find(n=>n.id===e)??r.find(n=>n.slug===e)??r.find(n=>(n.modules??[]).includes(e))??null}function gl(t,e){let r=Cye(t,e);if(!r)return{not_found:e,accepted_forms:["feature id (F-\u2026)","slug","module path (e.g. src/auth/login.ts)"],discovery:"grep spec/index.yaml \u2014 one line per feature (id, slug, status; run clad sync if missing); if the query is a file, fall back to normal code search \u2014 the graph only knows declared modules"};let n=NH(t,r.id),i=(n.features??[]).filter(c=>c.id!==r.id).map(c=>({id:c.id,title:c.title,status:c.status})).sort((c,l)=>c.id.localeCompare(l.id)),o=(n.scenarios??[]).map(c=>({id:c.id,title:c.title})).sort((c,l)=>c.id.localeCompare(l.id)),s=(t.project?.ai_hints?.preferred_patterns??[]).map(c=>({when:c.when,prefer:c.prefer,...c.over!==void 0?{over:c.over}:{}})),a=[...new Set((r.acceptance_criteria??[]).flatMap(c=>c.test_refs??[]))].sort();return{focus:r,ancestors:i,scenarios:o,preferred_patterns:s,test_refs:a}}var L_=y(()=>{"use strict";jH()});import{existsSync as FH,readdirSync as Dye,readFileSync as Nye}from"node:fs";import{join as ZO}from"node:path";function VO(t,e=Mye){let r=t.trim().replace(/\s+/g," ");return r.length<=e?r:`${r.slice(0,e-1)}\u2026`}function Fye(t){let e=t.payload??{};if(t.type==="drift_detected"){let n=typeof e.gate=="string"&&e.gate?e.gate:"drift";return{detector:n,message:VO(`drift detected at gate ${n}`)}}let r=typeof e.worst=="number"?` (worst ${e.worst})`:"";return{detector:"done_attempted",message:VO(`done reverted \u2014 pre-push strict gate red${r}`)}}function MH(t){let e=Date.parse(t.timestamp);return Number.isFinite(e)?e:0}function Lye(t){let e=[];t.lastFailedGate&&e.push(`failed ${t.lastFailedGate}`),typeof t.retryCount=="number"&&e.push(`${t.retryCount} retries`);let r=e.length?` (${e.join(", ")})`:"",n=t.recovery?`recover: ${t.recovery}${r}`:`rolled back${r}`;return VO(n)}function zye(t,e,r,n={}){let i=t.filter(m=>m&&m.payload&&m.payload.feature===r),o=e.filter(m=>m&&m.featureId===r).slice().sort((m,h)=>MH(m)-MH(h)),s=i.filter(m=>m.type==="drift_detected"||m.type==="done_attempted"&&m.payload.kept===!1),a=i.filter(m=>m.type==="feature_rolled_back");if(s.length===0&&a.length===0&&o.length===0)return;let c=o.length?o[o.length-1]:void 0,l;for(let m=s.length-1;m>=0;m--){let h=s[m].payload.gate;if(s[m].type==="drift_detected"&&typeof h=="string"&&h){l=h;break}}!l&&c?.lastFailedGate&&(l=c.lastFailedGate);let u=s.slice(-jye).map(Fye),d;for(let m=a.length-1;m>=0;m--){let h=a[m].payload.to_git_head;if(typeof h=="string"&&h){d=h;break}}let f=typeof c?.retryCount=="number"?c.retryCount:void 0,p=c?Lye(c):void 0;return{attempts:s.length,...l?{last_failed_gate:l}:{},...f!==void 0?{retry_count:f}:{},...u.length?{drift_history:u}:{},...d?{rolled_back_at:d}:{},...p?{recovery_hint:p}:{},...n.truncated?{truncated_history:!0}:{}}}function GO(t,e){let r=t.match(e);return r&&r[1]?r[1].trim():void 0}function Uye(t){let e=t.indexOf("## Recommended recovery");if(e<0)return;let r=t.slice(e).match(/```[^\n]*\n([\s\S]*?)```/);return r&&r[1].split(` -`).map(i=>i.trim()).find(i=>i.length>0)||void 0}function qye(t,e,r){let n=GO(t,/_Rolled back at_\s*`([^`]+)`/),i=GO(t,/Last failed gate:\s*`([^`]+)`/),o=GO(t,/Retry attempts:\s*(\d+)/),s=Uye(t);return{featureId:e,timestamp:n??r,...i?{lastFailedGate:i}:{},...o?{retryCount:Number(o)}:{},...s?{recovery:s}:{}}}function Bye(t,e){let r=ZO(t,".cladding","post-mortems");if(!FH(r))return[];let n=`post-mortem-${e}-`,i=[];for(let o of Dye(r))if(!(!o.startsWith(n)||!o.endsWith(".md")))try{i.push(qye(Nye(ZO(r,o),"utf8"),e,o))}catch{}return i}function LH(t,e){try{let r=P_(t),n=Bye(t,e),i=FH(ZO(t,".cladding","events.log.1.jsonl"));return zye(r,n,e,{truncated:i})}catch{return}}var jye,Mye,zH=y(()=>{"use strict";Mr();jye=5,Mye=120});function z_(t,e,r){return nn(JSON.stringify({...t,needs:e,must_edit:{...t.must_edit,code:r}}))}function xa(t,e,r={}){let n=r.cwd??".",i=r.maxTokens&&r.maxTokens>0?r.maxTokens:Hye,o=e,s,a=Rn(t).moduleOwners.get(e);if(a&&a.size>0){let se=[...a].sort();o=se[0],se.length>1&&(s=se)}let c=gl(t,o);if("not_found"in c)return c;let l=c.focus,u=LH(n,l.id),d=a&&a.size>0?e:l.id,f=F_(t,d),p="not_found"in f?null:f.slice,m=p?p.impacted:[],h=p?p.test_refs:[],g="not_found"in f?null:{depth:f.depthUsed,stopped_by:f.stoppedBy,coverage:f.analysis.coverage===null?null:Math.round(f.analysis.coverage*100)/100,total_known_dependents:f.analysis.totalKnownDependents},b=l.acceptance_criteria??[],_=b.filter(se=>se.ears==="unwanted"||se.ears==="state").map(se=>({id:se.id,ears:String(se.ears)})),S=[...new Set(b.flatMap(se=>se.oracle_refs??[]))].sort(),x=[],w={must_edit:{id:l.id,title:l.title,status:l.status,modules:l.modules??[],acceptance_criteria:b,code:[],...s?{co_owners:s}:{}},needs:c.ancestors,breaks_if_changed:{impacted:m,regression_tests:h,...g?{radius:g}:{}},verify:{scenarios:c.scenarios,test_refs:c.test_refs,oracle_refs:S,high_risk_acs:_},guidance:{preferred_patterns:c.preferred_patterns},budget:{max_tokens:i,used_tokens:0,truncated:x}},O=[...c.ancestors];for(;O.length>Gye&&z_(w,O,[])>i;)O.pop();O.lengthi){x.push(`code: omitted ${se} (budget)`);continue}A.push(Kt),Kt.truncated&&x.push(`code: clipped ${se}`)}T>i&&x.push("must-edit exceeds budget \u2014 retained in full (focus is never dropped)");let D=(se,Ce)=>({impacted:se,regression_tests:Ce,...g?{radius:g}:{},...p?.ledger?{ledger:p.ledger}:{}}),$=(se,Ce,Kt,dr)=>{let Xt=Kt+dr>0?[`breaks: omitted ${Kt} feature(s) / ${dr} test(s)`]:[],uo={...w,needs:O,must_edit:{...w.must_edit,code:A},breaks_if_changed:D(se,Ce),budget:{...w.budget,truncated:[...x,...Xt]}};return nn(JSON.stringify(uo))>i},re=m,K=h;if($(re,K,0,0)){let se=Sr(t,d,{depth:1}),Ce=new Set("not_found"in se?[]:se.impacted.map(de=>de.id)),Kt=new Set("not_found"in se?[]:se.test_refs),Xt=[...m.filter(de=>Ce.has(de.id)),...m.filter(de=>!Ce.has(de.id))],uo=0;for(;Xt.length>Ce.size&&$(Xt,K,uo,0);)Xt=Xt.slice(0,-1),uo++;let ki=[...h],en=0;for(;$(Xt,ki,uo,en);){let de=-1;for(let fo=ki.length-1;fo>=0;fo--)if(!Kt.has(ki[fo])){de=fo;break}if(de<0)break;ki.splice(de,1),en++}re=Xt,K=ki,uo+en>0&&x.push(`breaks: omitted ${uo} feature(s) / ${en} test(s)`),$(re,K,0,0)&&x.push("breaks: direct set retained in full \u2014 exceeds budget")}let xe=D(re,K),C={...w,needs:O,must_edit:{...w.must_edit,code:A},breaks_if_changed:xe},P=C;if(u){let se={...C,prior_attempts:u};nn(JSON.stringify(se))<=i?P=se:x.push("prior_attempts: omitted (budget)")}let Cr=nn(JSON.stringify(P));return{...P,budget:{max_tokens:i,used_tokens:Cr,truncated:x}}}var Hye,Gye,U_=y(()=>{"use strict";j_();L_();HO();zH();wa();os();Hye=3e3,Gye=3});function Qn(t){if(t.length===0)return 0;let e=[...t].sort((n,i)=>n-i),r=Math.floor(e.length/2);return e.length%2?e[r]:(e[r-1]+e[r])/2}function Zye(t,e){if(t.length===0)return 0;let r=[...t].sort((n,i)=>n-i);return r[Math.min(r.length-1,Math.floor(e/100*r.length))]}function UH(t,e,r="."){let n=Rn(t),i=t.features??[],o=[];for(let f of i){let p=xa(t,f.id,{cwd:r,read:e});if("not_found"in p)continue;let m=xa(t,f.id,{cwd:r,read:e,maxTokens:Number.MAX_SAFE_INTEGER}),h=F_(t,f.id),g=!("not_found"in h),b=nn(JSON.stringify(p)),_="not_found"in m?b:nn(JSON.stringify(m)),S=nn(JSON.stringify(f));for(let O of f.modules??[]){let T=e(O);T&&(S+=nn(T))}let x=(f.depends_on??[]).length,w=n.dependents.get(f.id)?.size??0;o.push({id:f.id,sliceTokens:b,structuralTokens:_,naiveTokens:S,contextRatio:S>0?b/S:1,budgetSaturated:p.budget.truncated.length>0,searchDepth:g?h.depthUsed:1,edgesResolved:x+w,stoppedBy:g?h.stoppedBy:"n/a",coverage:g?h.analysis.coverage:1,regressionTests:p.breaks_if_changed.regression_tests.length})}o.sort((f,p)=>f.id.localeCompare(p.id));let s=o.map(f=>f.contextRatio),a=f=>f.filter(p=>p.sliceTokens>0).map(p=>p.naiveTokens/p.sliceTokens),c=o.filter(f=>!f.budgetSaturated),l=o.filter(f=>f.budgetSaturated),u=o.filter(f=>f.naiveTokens>0).map(f=>f.structuralTokens/f.naiveTokens),d={};for(let f of o)d[f.stoppedBy]=(d[f.stoppedBy]??0)+1;return{featureCount:i.length,measured:o.length,context:{medianContextRatio:Math.round(Qn(s)*1e3)/1e3,medianShrinkFactor:Math.round(Qn(a(o))*10)/10,fitsCount:c.length,truncatedCount:l.length,medianShrinkFit:Math.round(Qn(a(c))*10)/10,medianShrinkTruncated:Math.round(Qn(a(l))*10)/10,medianStructuralRatio:Math.round(Qn(u)*100)/100,medianSliceTokens:Math.round(Qn(o.map(f=>f.sliceTokens))),medianNaiveTokens:Math.round(Qn(o.map(f=>f.naiveTokens)))},search:{medianDepth:Qn(o.map(f=>f.searchDepth)),p95Depth:Zye(o.map(f=>f.searchDepth),95),medianEdges:Qn(o.map(f=>f.edgesResolved)),maxEdges:o.reduce((f,p)=>Math.max(f,p.edgesResolved),0)},stability:{byStopReason:d,medianCoverage:Math.round(Qn(o.map(f=>f.coverage).filter(f=>f!==null))*100)/100,medianRegressionTests:Qn(o.map(f=>f.regressionTests))},features:o}}var yl,q_=y(()=>{"use strict";j_();HO();U_();os();yl="(deterministic upper bound vs the shard+all-modules baseline \u2014 not an agent-adoption measurement)"});import{appendFileSync as Vye,existsSync as WO,mkdirSync as Wye,readFileSync as qH}from"node:fs";import{dirname as Kye,join as Jye}from"node:path";function KO(t){return Jye(t,Yye,Xye)}function Qye(t,e){return{timestamp:new Date().toISOString(),head:Sa(t),spec_digest:LO(t),featureCount:e.featureCount,measured:e.measured,context:e.context,search:e.search,stability:e.stability}}function BH(t,e){try{let r=Qye(t,e);if(r.head===null)return{appended:!1,reason:"no_head"};let n=JO(t),i=n[n.length-1];if(i&&i.head===r.head&&i.spec_digest===r.spec_digest)return{appended:!1,reason:"deduped"};let o=KO(t),s=Kye(o);return WO(s)||Wye(s,{recursive:!0}),Vye(o,`${JSON.stringify(r)} -`,"utf8"),{appended:!0,reason:"appended"}}catch{return{appended:!1,reason:"error"}}}function HH(t){let e=[];for(let r of t.split(` -`)){let n=r.trim();if(n.length!==0)try{let i=JSON.parse(n);i&&typeof i=="object"&&i.context&&i.search&&i.stability&&e.push(i)}catch{}}return e}function JO(t,e){let r=KO(t);if(!WO(r))return[];let n;try{n=qH(r,"utf8")}catch{return[]}let i=HH(n);return typeof e=="number"&&e>=0?i.slice(-e):i}function GH(t){let e=KO(t);if(!WO(e))return{snapshots:[],unreadable:!1};let r;try{r=qH(e,"utf8")}catch{return{snapshots:[],unreadable:!0}}let n=HH(r),i=r.trim().length>0;return{snapshots:n,unreadable:i&&n.length===0}}function Gf(t,e=0){let r=e>0?Math.round(t*10**e)/10**e:Math.round(t),n=r.toFixed(e);return r>0?`+${n}`:n}function ZH(t,e=5){let r=Math.max(0,t.length-e),i=[`measure trend \xB7 last ${t.slice(r).length} of ${t.length} snapshot(s)`];for(let o=r;o0?t[o-1]:null,c=(d,f=0)=>a?` (${Gf(d(s)-d(a),f)})`:"",l=s.timestamp.slice(0,19),u=s.head?s.head.slice(0,7):"nogit";i.push(` ${l} ${u} \xB7 ${s.featureCount} feat \xB7 slice ${s.context.medianSliceTokens}${c(d=>d.context.medianSliceTokens)} \xB7 struct ${s.context.medianStructuralRatio.toFixed(2)}${c(d=>d.context.medianStructuralRatio,2)} \xB7 cov ${s.stability.medianCoverage.toFixed(2)}${c(d=>d.stability.medianCoverage,2)} \xB7 p95depth ${s.search.p95Depth}${c(d=>d.search.p95Depth)} \xB7 trunc ${s.context.truncatedCount}${c(d=>d.context.truncatedCount)}`)}return i.push(` ${yl}`),i.join(` -`)}var Yye,Xye,Zf=y(()=>{"use strict";Bf();q_();Yye=".cladding",Xye="measure.jsonl"});import{existsSync as e_e}from"node:fs";import{join as t_e}from"node:path";function _l(t){if(t.groups.reduce((i,o)=>i+o.features.length,0)===0&&t.unsharded_commits.length===0)return`no shipped changes since ${t.since}`;let r=[`# Changes since ${t.since}`,""];for(let i of t.groups){r.push(`## ${i.title}`,"");for(let o of i.features){r.push(`- **${o.title}** (${r_e[o.change]})`);for(let s of o.acceptance)r.push(` - ${s}`)}r.push("")}if(t.unsharded_commits.length>0){r.push("## Other changes (not yet spec-tracked)","");for(let i of t.unsharded_commits)r.push(`- ${i.subject}`);r.push("")}let n=t.inventory;for((n.before.features!==n.after.features||n.before.scenarios!==n.after.scenarios)&&r.push(`_Spec inventory: ${n.before.features} \u2192 ${n.after.features} features, ${n.before.scenarios} \u2192 ${n.after.scenarios} scenarios._`,"");r[r.length-1]==="";)r.pop();return r.join(` -`)}function WH(t){let e=t.snapshot,r=["## Measured (this release)",""];if(!e||!e.head)return r.push("not measured at this commit \u2014 run clad measure before tagging"),r.join(` -`);let n=e.context,i=e.stability;r.push(`- features measured: ${e.measured} of ${e.featureCount}`),r.push(`- median slice tokens: ${n.medianSliceTokens} vs ${n.medianNaiveTokens} naive`),r.push(`- median structural ratio: ${n.medianStructuralRatio.toFixed(2)}`),r.push(`- median coverage: ${i.medianCoverage.toFixed(2)}`),r.push(`- regression tests surfaced: ${i.medianRegressionTests}`);let o=t.sinceSnapshot;if(o){let s=t.sinceRef??(o.head?o.head.slice(0,7):"previous");r.push(`- since ${s}: slice ${Gf(n.medianSliceTokens-o.context.medianSliceTokens)} \xB7 struct ${Gf(n.medianStructuralRatio-o.context.medianStructuralRatio,2)} \xB7 cov ${Gf(i.medianCoverage-o.stability.medianCoverage,2)}`)}return r.push("",`head ${e.head.slice(0,7)} \xB7 spec_digest ${e.spec_digest}`,`reproduce: git checkout ${e.head} && clad measure`,"",yl),r.join(` -`)}function bl(t,e,r){let n=[`# Audit \u2014 shipped changes since ${t.since}`,"","| feature | AC | EARS | verification refs |","|---|---|---|---|"],i=new Map(e.features.map(o=>[o.id,o]));for(let o of t.groups)for(let s of o.features){let a=i.get(s.id);if(!a){n.push(`| ${s.id} | \u2014 | \u2014 | (removed from spec \u2014 see git history at ${t.since}) |`);continue}let c=a.acceptance_criteria??[];if(c.length===0){n.push(`| ${a.id} | \u2014 | \u2014 | (no acceptance criteria) |`);continue}for(let l of c)n.push(`| ${a.id} | ${l.id} | ${l.ears??"\u2014"} | ${i_e(l,r)} |`)}return n.join(` -`)}function i_e(t,e){let r=[...t.test_refs??[],...t.oracle_refs??[],...t.evidence_refs??[]];return r.length===0?"(none)":r.map(n=>{for(let[o,s]of n_e)if(n.startsWith(o))return`${n} (${s})`;let i=n.split("#",1)[0]??n;return`${e_e(t_e(e,i))?"\u2713":"\u2717"} ${n}`}).join("
")}function vl(t){let e=[`# ${t.project.name} \u2014 capability catalog`,""],r=[...t.capabilities??[]].filter(s=>typeof s.id=="string"&&s.id.length>0).sort((s,a)=>s.id.localeCompare(a.id)),n=new Map(t.features.map(s=>[s.id,s])),i=new Set;for(let s of r){e.push(`## ${s.title??s.id}`,""),s.summary&&e.push(s.summary,"");for(let a of s.features??[]){let c=n.get(a);!c||c.status==="archived"||(i.add(a),VH(e,c))}}let o=t.features.filter(s=>!i.has(s.id)&&s.status!=="archived").sort((s,a)=>s.id.localeCompare(a.id));if(o.length>0){e.push("## Uncategorized","");for(let s of o)VH(e,s)}for(;e[e.length-1]==="";)e.pop();return e.join(` -`)}function VH(t,e){t.push(`### ${e.title}`,"");for(let r of e.acceptance_criteria??[]){let n=CO(r);n&&t.push(`- ${n}`)}t.push("")}var r_e,n_e,B_=y(()=>{"use strict";Zf();q_();hl();r_e={"added-as-done":"new","flipped-to-done":"completed","modified-while-done":"updated",archived:"retired"};n_e=[["derived:","machine-suggested \u2014 not author-confirmed"],["self-dogfood:","verified by cladding running on itself"],["fixture:","conformance fixture"],["script:","npm script"]]});import{readFileSync as o_e}from"node:fs";function Ri(t="./spec.yaml"){let e=o_e(t,"utf8");return(0,KH.parse)(e)}var KH,H_=y(()=>{"use strict";KH=St(er(),1)});var ss=v((Fr,eR)=>{"use strict";var YO=Fr.ValidationError=function(e,r,n,i,o,s){if(Array.isArray(i)?(this.path=i,this.property=i.reduce(function(c,l){return c+YH(l)},"instance")):i!==void 0&&(this.property=i),e&&(this.message=e),n){var a=n.$id||n.id;this.schema=a||n}r!==void 0&&(this.instance=r),this.name=o,this.argument=s,this.stack=this.toString()};YO.prototype.toString=function(){return this.property+" "+this.message};var G_=Fr.ValidatorResult=function(e,r,n,i){this.instance=e,this.schema=r,this.options=n,this.path=i.path,this.propertyPath=i.propertyPath,this.errors=[],this.throwError=n&&n.throwError,this.throwFirst=n&&n.throwFirst,this.throwAll=n&&n.throwAll,this.disableFormat=n&&n.disableFormat===!0};G_.prototype.addError=function(e){var r;if(typeof e=="string")r=new YO(e,this.instance,this.schema,this.path);else{if(!e)throw new Error("Missing error detail");if(!e.message)throw new Error("Missing error message");if(!e.name)throw new Error("Missing validator type");r=new YO(e.message,this.instance,this.schema,this.path,e.name,e.argument)}if(this.errors.push(r),this.throwFirst)throw new $a(this);if(this.throwError)throw r;return r};G_.prototype.importErrors=function(e){typeof e=="string"||e&&e.validatorType?this.addError(e):e&&e.errors&&(this.errors=this.errors.concat(e.errors))};function s_e(t,e){return e+": "+t.toString()+` -`}G_.prototype.toString=function(e){return this.errors.map(s_e).join("")};Object.defineProperty(G_.prototype,"valid",{get:function(){return!this.errors.length}});eR.exports.ValidatorResultError=$a;function $a(t){typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,$a),this.instance=t.instance,this.schema=t.schema,this.options=t.options,this.errors=t.errors}$a.prototype=new Error;$a.prototype.constructor=$a;$a.prototype.name="Validation Error";var JH=Fr.SchemaError=function t(e,r){this.message=e,this.schema=r,Error.call(this,e),typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,t)};JH.prototype=Object.create(Error.prototype,{constructor:{value:JH,enumerable:!1},name:{value:"SchemaError",enumerable:!1}});var XO=Fr.SchemaContext=function(e,r,n,i,o){this.schema=e,this.options=r,Array.isArray(n)?(this.path=n,this.propertyPath=n.reduce(function(s,a){return s+YH(a)},"instance")):this.propertyPath=n,this.base=i,this.schemas=o};XO.prototype.resolve=function(e){return XH(this.base,e)};XO.prototype.makeChild=function(e,r){var n=r===void 0?this.path:this.path.concat([r]),i=e.$id||e.id;let o=XH(this.base,i||"");var s=new XO(e,this.options,n,o,Object.create(this.schemas));return i&&!s.schemas[o]&&(s.schemas[o]=e),s};var ei=Fr.FORMAT_REGEXPS={"date-time":/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-(3[01]|0[1-9]|[12][0-9])[tT ](2[0-4]|[01][0-9]):([0-5][0-9]):(60|[0-5][0-9])(\.\d+)?([zZ]|[+-]([0-5][0-9]):(60|[0-5][0-9]))$/,date:/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-(3[01]|0[1-9]|[12][0-9])$/,time:/^(2[0-4]|[01][0-9]):([0-5][0-9]):(60|[0-5][0-9])$/,duration:/P(T\d+(H(\d+M(\d+S)?)?|M(\d+S)?|S)|\d+(D|M(\d+D)?|Y(\d+M(\d+D)?)?)(T\d+(H(\d+M(\d+S)?)?|M(\d+S)?|S))?|\d+W)/i,email:/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/,"idn-email":/^("(?:[!#-\[\]-\u{10FFFF}]|\\[\t -\u{10FFFF}])*"|[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}](?:\.?[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}])*)@([!#-'*+\-/-9=?A-Z\^-\u{10FFFF}](?:\.?[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}])*|\[[!-Z\^-\u{10FFFF}]*\])$/u,"ip-address":/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,ipv6:/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,uri:/^[a-zA-Z][a-zA-Z0-9+.-]*:[^\s]*$/,"uri-reference":/^(((([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|([A-Za-z][+\-.0-9A-Za-z]*:?)?)|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|(\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?)?))#(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|(([A-Za-z][+\-.0-9A-Za-z]*)?%[0-9A-Fa-f]{2}|[!$&-.0-9;=@_~]|[A-Za-z][+\-.0-9A-Za-z]*[!$&-*,;=@_~])(%[0-9A-Fa-f]{2}|[!$&-.0-9;=@-Z_a-z~])*((([/?](%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*)?#|[/?])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*)?|([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+(:\d*)?|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?:\d*|\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)?|[A-Za-z][+\-.0-9A-Za-z]*:?)?$/,iri:/^[a-zA-Z][a-zA-Z0-9+.-]*:[^\s]*$/,"iri-reference":/^(((([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~-\u{10FFFF}]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|([A-Za-z][+\-.0-9A-Za-z]*:?)?)|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~-\u{10FFFF}])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~-\u{10FFFF}])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|(\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~-\u{10FFFF}])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?)?))#(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|(([A-Za-z][+\-.0-9A-Za-z]*)?%[0-9A-Fa-f]{2}|[!$&-.0-9;=@_~-\u{10FFFF}]|[A-Za-z][+\-.0-9A-Za-z]*[!$&-*,;=@_~-\u{10FFFF}])(%[0-9A-Fa-f]{2}|[!$&-.0-9;=@-Z_a-z~-\u{10FFFF}])*((([/?](%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*)?#|[/?])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*)?|([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~-\u{10FFFF}]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~-\u{10FFFF}])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~-\u{10FFFF}])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~-\u{10FFFF}])+(:\d*)?|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?:\d*|\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?)?|[A-Za-z][+\-.0-9A-Za-z]*:?)?$/u,uuid:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i,"uri-template":/(%[0-9a-f]{2}|[!#$&(-;=?@\[\]_a-z~]|\{[!#&+,./;=?@|]?(%[0-9a-f]{2}|[0-9_a-z])(\.?(%[0-9a-f]{2}|[0-9_a-z]))*(:[1-9]\d{0,3}|\*)?(,(%[0-9a-f]{2}|[0-9_a-z])(\.?(%[0-9a-f]{2}|[0-9_a-z]))*(:[1-9]\d{0,3}|\*)?)*\})*/iu,"json-pointer":/^(\/([\x00-\x2e0-@\[-}\x7f]|~[01])*)*$/iu,"relative-json-pointer":/^\d+(#|(\/([\x00-\x2e0-@\[-}\x7f]|~[01])*)*)$/iu,hostname:/^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/,"host-name":/^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/,"utc-millisec":function(t){return typeof t=="string"&&parseFloat(t)===parseInt(t,10)&&!isNaN(t)},regex:function(t){var e=!0;try{new RegExp(t)}catch{e=!1}return e},style:/[\r\n\t ]*[^\r\n\t ][^:]*:[\r\n\t ]*[^\r\n\t ;]*[\r\n\t ]*;?/,color:/^(#?([0-9A-Fa-f]{3}){1,2}\b|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/,phone:/^\+(?:[0-9] ?){6,14}[0-9]$/,alpha:/^[a-zA-Z]+$/,alphanumeric:/^[a-zA-Z0-9]+$/};ei.regexp=ei.regex;ei.pattern=ei.regex;ei.ipv4=ei["ip-address"];Fr.isFormat=function(e,r,n){if(typeof e=="string"&&ei[r]!==void 0){if(ei[r]instanceof RegExp)return ei[r].test(e);if(typeof ei[r]=="function")return ei[r](e)}else if(n&&n.customFormats&&typeof n.customFormats[r]=="function")return n.customFormats[r](e);return!0};var YH=Fr.makeSuffix=function(e){return e=e.toString(),!e.match(/[.\s\[\]]/)&&!e.match(/^[\d]/)?"."+e:e.match(/^\d+$/)?"["+e+"]":"["+JSON.stringify(e)+"]"};Fr.deepCompareStrict=function t(e,r){if(typeof e!=typeof r)return!1;if(Array.isArray(e))return!Array.isArray(r)||e.length!==r.length?!1:e.every(function(o,s){return t(e[s],r[s])});if(typeof e=="object"){if(!e||!r)return e===r;var n=Object.keys(e),i=Object.keys(r);return n.length!==i.length?!1:n.every(function(o){return t(e[o],r[o])})}return e===r};function a_e(t,e,r,n){typeof r=="object"?e[n]=QO(t[n],r):t.indexOf(r)===-1&&e.push(r)}function c_e(t,e,r){e[r]=t[r]}function l_e(t,e,r,n){typeof e[n]!="object"||!e[n]?r[n]=e[n]:t[n]?r[n]=QO(t[n],e[n]):r[n]=e[n]}function QO(t,e){var r=Array.isArray(e),n=r&&[]||{};return r?(t=t||[],n=n.concat(t),e.forEach(a_e.bind(null,t,n))):(t&&typeof t=="object"&&Object.keys(t).forEach(c_e.bind(null,t,n)),Object.keys(e).forEach(l_e.bind(null,t,e,n))),n}eR.exports.deepMerge=QO;Fr.objectGetPath=function(e,r){for(var n=r.split("/").slice(1),i;typeof(i=n.shift())=="string";){var o=decodeURIComponent(i.replace(/~0/,"~").replace(/~1/g,"/"));if(!(o in e))return;e=e[o]}return e};function u_e(t){return"/"+encodeURIComponent(t).replace(/~/g,"%7E")}Fr.encodePath=function(e){return e.map(u_e).join("")};Fr.getDecimalPlaces=function(e){var r=0;if(isNaN(e))return r;typeof e!="number"&&(e=Number(e));var n=e.toString().split("e");if(n.length===2){if(n[1][0]!=="-")return r;r=Number(n[1].slice(1))}var i=n[0].split(".");return i.length===2&&(r+=i[1].length),r};Fr.isSchema=function(e){return typeof e=="object"&&e||typeof e=="boolean"};var XH=Fr.resolveUrl=function(e,r){let n=new URL(r,new URL(e,"resolve://"));if(n.protocol==="resolve:"){let{pathname:i,search:o,hash:s}=n;return i+o+s}return n.toString()}});var rG=v((G7e,tG)=>{"use strict";var on=ss(),Le=on.ValidatorResult,as=on.SchemaError,tR={};tR.ignoreProperties={id:!0,default:!0,description:!0,title:!0,additionalItems:!0,then:!0,else:!0,$schema:!0,$ref:!0,extends:!0};var ze=tR.validators={};ze.type=function(e,r,n,i){if(e===void 0)return null;var o=new Le(e,r,n,i),s=Array.isArray(r.type)?r.type:[r.type];if(!s.some(this.testType.bind(this,e,r,n,i))){var a=s.map(function(c){if(c){var l=c.$id||c.id;return l?"<"+l+">":c+""}});o.addError({name:"type",argument:a,message:"is not of a type(s) "+a})}return o};function rR(t,e,r,n,i){var o=e.throwError,s=e.throwAll;e.throwError=!1,e.throwAll=!1;var a=this.validateSchema(t,i,e,r);return e.throwError=o,e.throwAll=s,!a.valid&&n instanceof Function&&n(a),a.valid}ze.anyOf=function(e,r,n,i){if(e===void 0)return null;var o=new Le(e,r,n,i),s=new Le(e,r,n,i);if(!Array.isArray(r.anyOf))throw new as("anyOf must be an array");if(!r.anyOf.some(rR.bind(this,e,n,i,function(c){s.importErrors(c)}))){var a=r.anyOf.map(function(c,l){var u=c.$id||c.id;return u?"<"+u+">":c.title&&JSON.stringify(c.title)||c.$ref&&"<"+c.$ref+">"||"[subschema "+l+"]"});n.nestedErrors&&o.importErrors(s),o.addError({name:"anyOf",argument:a,message:"is not any of "+a.join(",")})}return o};ze.allOf=function(e,r,n,i){if(e===void 0)return null;if(!Array.isArray(r.allOf))throw new as("allOf must be an array");var o=new Le(e,r,n,i),s=this;return r.allOf.forEach(function(a,c){var l=s.validateSchema(e,a,n,i);if(!l.valid){var u=a.$id||a.id,d=u||a.title&&JSON.stringify(a.title)||a.$ref&&"<"+a.$ref+">"||"[subschema "+c+"]";o.addError({name:"allOf",argument:{id:d,length:l.errors.length,valid:l},message:"does not match allOf schema "+d+" with "+l.errors.length+" error[s]:"}),o.importErrors(l)}}),o};ze.oneOf=function(e,r,n,i){if(e===void 0)return null;if(!Array.isArray(r.oneOf))throw new as("oneOf must be an array");var o=new Le(e,r,n,i),s=new Le(e,r,n,i),a=r.oneOf.filter(rR.bind(this,e,n,i,function(l){s.importErrors(l)})).length,c=r.oneOf.map(function(l,u){var d=l.$id||l.id;return d||l.title&&JSON.stringify(l.title)||l.$ref&&"<"+l.$ref+">"||"[subschema "+u+"]"});return a!==1&&(n.nestedErrors&&o.importErrors(s),o.addError({name:"oneOf",argument:c,message:"is not exactly one from "+c.join(",")})),o};ze.if=function(e,r,n,i){if(e===void 0)return null;if(!on.isSchema(r.if))throw new Error('Expected "if" keyword to be a schema');var o=rR.call(this,e,n,i,null,r.if),s=new Le(e,r,n,i),a;if(o){if(r.then===void 0)return;if(!on.isSchema(r.then))throw new Error('Expected "then" keyword to be a schema');a=this.validateSchema(e,r.then,n,i.makeChild(r.then)),s.importErrors(a)}else{if(r.else===void 0)return;if(!on.isSchema(r.else))throw new Error('Expected "else" keyword to be a schema');a=this.validateSchema(e,r.else,n,i.makeChild(r.else)),s.importErrors(a)}return s};function nR(t,e){if(Object.hasOwnProperty.call(t,e))return t[e];if(e in t){for(;t=Object.getPrototypeOf(t);)if(Object.propertyIsEnumerable.call(t,e))return t[e]}}ze.propertyNames=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=r.propertyNames!==void 0?r.propertyNames:{};if(!on.isSchema(s))throw new as('Expected "propertyNames" to be a schema (object or boolean)');for(var a in e)if(nR(e,a)!==void 0){var c=this.validateSchema(a,s,n,i.makeChild(s));o.importErrors(c)}return o}};ze.properties=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=r.properties||{};for(var a in s){var c=s[a];if(c!==void 0){if(c===null)throw new as('Unexpected null, expected schema in "properties"');typeof n.preValidateProperty=="function"&&n.preValidateProperty(e,a,c,n,i);var l=nR(e,a),u=this.validateSchema(l,c,n,i.makeChild(c,a));u.instance!==o.instance[a]&&(o.instance[a]=u.instance),o.importErrors(u)}}return o}};function QH(t,e,r,n,i,o){if(this.types.object(t)&&!(e.properties&&e.properties[i]!==void 0))if(e.additionalProperties===!1)o.addError({name:"additionalProperties",argument:i,message:"is not allowed to have the additional property "+JSON.stringify(i)});else{var s=e.additionalProperties||{};typeof r.preValidateProperty=="function"&&r.preValidateProperty(t,i,s,r,n);var a=this.validateSchema(t[i],s,r,n.makeChild(s,i));a.instance!==o.instance[i]&&(o.instance[i]=a.instance),o.importErrors(a)}}ze.patternProperties=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=r.patternProperties||{};for(var a in e){var c=!0;for(var l in s){var u=s[l];if(u!==void 0){if(u===null)throw new as('Unexpected null, expected schema in "patternProperties"');try{var d=new RegExp(l,"u")}catch{d=new RegExp(l)}if(d.test(a)){c=!1,typeof n.preValidateProperty=="function"&&n.preValidateProperty(e,a,u,n,i);var f=this.validateSchema(e[a],u,n,i.makeChild(u,a));f.instance!==o.instance[a]&&(o.instance[a]=f.instance),o.importErrors(f)}}}c&&QH.call(this,e,r,n,i,a,o)}return o}};ze.additionalProperties=function(e,r,n,i){if(this.types.object(e)){if(r.patternProperties)return null;var o=new Le(e,r,n,i);for(var s in e)QH.call(this,e,r,n,i,s,o);return o}};ze.minProperties=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=Object.keys(e);return s.length>=r.minProperties||o.addError({name:"minProperties",argument:r.minProperties,message:"does not meet minimum property length of "+r.minProperties}),o}};ze.maxProperties=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=Object.keys(e);return s.length<=r.maxProperties||o.addError({name:"maxProperties",argument:r.maxProperties,message:"does not meet maximum property length of "+r.maxProperties}),o}};ze.items=function(e,r,n,i){var o=this;if(this.types.array(e)&&r.items!==void 0){var s=new Le(e,r,n,i);return e.every(function(a,c){if(Array.isArray(r.items))var l=r.items[c]===void 0?r.additionalItems:r.items[c];else var l=r.items;if(l===void 0)return!0;if(l===!1)return s.addError({name:"items",message:"additionalItems not permitted"}),!1;var u=o.validateSchema(a,l,n,i.makeChild(l,c));return u.instance!==s.instance[c]&&(s.instance[c]=u.instance),s.importErrors(u),!0}),s}};ze.contains=function(e,r,n,i){var o=this;if(this.types.array(e)&&r.contains!==void 0){if(!on.isSchema(r.contains))throw new Error('Expected "contains" keyword to be a schema');var s=new Le(e,r,n,i),a=e.some(function(c,l){var u=o.validateSchema(c,r.contains,n,i.makeChild(r.contains,l));return u.errors.length===0});return a===!1&&s.addError({name:"contains",argument:r.contains,message:"must contain an item matching given schema"}),s}};ze.minimum=function(e,r,n,i){if(this.types.number(e)){var o=new Le(e,r,n,i);return r.exclusiveMinimum&&r.exclusiveMinimum===!0?e>r.minimum||o.addError({name:"minimum",argument:r.minimum,message:"must be greater than "+r.minimum}):e>=r.minimum||o.addError({name:"minimum",argument:r.minimum,message:"must be greater than or equal to "+r.minimum}),o}};ze.maximum=function(e,r,n,i){if(this.types.number(e)){var o=new Le(e,r,n,i);return r.exclusiveMaximum&&r.exclusiveMaximum===!0?er.exclusiveMinimum;return s||o.addError({name:"exclusiveMinimum",argument:r.exclusiveMinimum,message:"must be strictly greater than "+r.exclusiveMinimum}),o}};ze.exclusiveMaximum=function(e,r,n,i){if(typeof r.exclusiveMaximum!="boolean"&&this.types.number(e)){var o=new Le(e,r,n,i),s=e=r.minLength||o.addError({name:"minLength",argument:r.minLength,message:"does not meet minimum length of "+r.minLength}),o}};ze.maxLength=function(e,r,n,i){if(this.types.string(e)){var o=new Le(e,r,n,i),s=e.match(/[\uDC00-\uDFFF]/g),a=e.length-(s?s.length:0);return a<=r.maxLength||o.addError({name:"maxLength",argument:r.maxLength,message:"does not meet maximum length of "+r.maxLength}),o}};ze.minItems=function(e,r,n,i){if(this.types.array(e)){var o=new Le(e,r,n,i);return e.length>=r.minItems||o.addError({name:"minItems",argument:r.minItems,message:"does not meet minimum length of "+r.minItems}),o}};ze.maxItems=function(e,r,n,i){if(this.types.array(e)){var o=new Le(e,r,n,i);return e.length<=r.maxItems||o.addError({name:"maxItems",argument:r.maxItems,message:"does not meet maximum length of "+r.maxItems}),o}};function d_e(t,e,r){var n,i=r.length;for(n=e+1,i;n{"use strict";var iR=ss();oR.exports.SchemaScanResult=nG;function nG(t,e){this.id=t,this.ref=e}oR.exports.scan=function(e,r){function n(c,l){if(!l||typeof l!="object")return;if(l.$ref){let p=iR.resolveUrl(c,l.$ref);a[p]=a[p]?a[p]+1:0;return}var u=l.$id||l.id;let d=iR.resolveUrl(c,u);var f=u?d:c;if(f){if(f.indexOf("#")<0&&(f+="#"),s[f]){if(!iR.deepCompareStrict(s[f],l))throw new Error("Schema <"+f+"> already exists with different definition");return s[f]}s[f]=l,f[f.length-1]=="#"&&(s[f.substring(0,f.length-1)]=l)}i(f+"/items",Array.isArray(l.items)?l.items:[l.items]),i(f+"/extends",Array.isArray(l.extends)?l.extends:[l.extends]),n(f+"/additionalItems",l.additionalItems),o(f+"/properties",l.properties),n(f+"/additionalProperties",l.additionalProperties),o(f+"/definitions",l.definitions),o(f+"/patternProperties",l.patternProperties),o(f+"/dependencies",l.dependencies),i(f+"/disallow",l.disallow),i(f+"/allOf",l.allOf),i(f+"/anyOf",l.anyOf),i(f+"/oneOf",l.oneOf),n(f+"/not",l.not)}function i(c,l){if(Array.isArray(l))for(var u=0;u{"use strict";var iG=rG(),cs=ss(),oG=Z_().scan,sG=cs.ValidatorResult,f_e=cs.ValidatorResultError,Vf=cs.SchemaError,aG=cs.SchemaContext,p_e="/",Jt=function t(){this.customFormats=Object.create(t.prototype.customFormats),this.schemas={},this.unresolvedRefs=[],this.types=Object.create(Ii),this.attributes=Object.create(iG.validators)};Jt.prototype.customFormats={};Jt.prototype.schemas=null;Jt.prototype.types=null;Jt.prototype.attributes=null;Jt.prototype.unresolvedRefs=null;Jt.prototype.addSchema=function(e,r){var n=this;if(!e)return null;var i=oG(r||p_e,e),o=r||e.$id||e.id;for(var s in i.id)this.schemas[s]=i.id[s];for(var s in i.ref)this.unresolvedRefs.push(s);return this.unresolvedRefs=this.unresolvedRefs.filter(function(a){return typeof n.schemas[a]>"u"}),this.schemas[o]};Jt.prototype.addSubSchemaArray=function(e,r){if(Array.isArray(r))for(var n=0;n",e);var a=cs.objectGetPath(n.schemas[s],o.substr(1));if(a===void 0)throw new Vf("no such schema "+o+" located in <"+s+">",e);return{subschema:a,switchSchema:r}};Jt.prototype.testType=function(e,r,n,i,o){if(o!==void 0){if(o===null)throw new Vf('Unexpected null in "type" keyword');if(typeof this.types[o]=="function")return this.types[o].call(this,e);if(o&&typeof o=="object"){var s=this.validateSchema(e,o,n,i);return s===void 0||!(s&&s.errors.length)}return!0}};var Ii=Jt.prototype.types={};Ii.string=function(e){return typeof e=="string"};Ii.number=function(e){return typeof e=="number"&&isFinite(e)};Ii.integer=function(e){return typeof e=="number"&&e%1===0};Ii.boolean=function(e){return typeof e=="boolean"};Ii.array=function(e){return Array.isArray(e)};Ii.null=function(e){return e===null};Ii.date=function(e){return e instanceof Date};Ii.any=function(e){return!0};Ii.object=function(e){return e&&typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Date)};lG.exports=Jt});var dG=v((W7e,go)=>{"use strict";var m_e=go.exports.Validator=uG();go.exports.ValidatorResult=ss().ValidatorResult;go.exports.ValidatorResultError=ss().ValidatorResultError;go.exports.ValidationError=ss().ValidationError;go.exports.SchemaError=ss().SchemaError;go.exports.SchemaScanResult=Z_().SchemaScanResult;go.exports.scan=Z_().scan;go.exports.validate=function(t,e,r){var n=new m_e;return n.validate(t,e,r)}});import{readFileSync as h_e}from"node:fs";import{dirname as g_e,join as y_e}from"node:path";import{fileURLToPath as __e}from"node:url";function x_e(t){let e=w_e.validate(t,S_e);return e.valid?{valid:!0,errors:[]}:{valid:!1,errors:e.errors.map(n=>`${n.property}: ${n.message}`)}}function pG(t){let e=x_e(t);if(!e.valid)throw new Error(`spec.yaml invalid: +`,c=Math.max(0,s-a.length);return{path:t,text:i.slice(0,c)+a,truncated:!0,bytes:o}}var d_e,ZB,f_e,L_=y(()=>{"use strict";d_e=new Set([".ts",".tsx",".js",".jsx",".mjs",".cjs",".py",".rs",".go",".java",".kt",".kts",".cs",".rb",".php",".swift",".c",".h",".cpp",".hpp",".css",".scss",".sql",".sh",".yaml",".yml",".json",".md",".toml"]),ZB=2e6,f_e="\0"});function Vf(t){for(let i of m_e)if(t.startsWith(i))return null;let e=t.indexOf("#"),n=(e>=0?t.slice(0,e):t).trim();return n.length>0?n:null}function KT(t,e,r){let n=t.get(e);n||(n=new Set,t.set(e,n)),n.add(r)}function h_e(t){let e=new Map,r=new Map,n=new Map;for(let i of t.features??[]){let o=i.id;for(let s of i.depends_on??[])KT(e,s,o);for(let s of i.modules??[])KT(r,s,o);for(let s of i.acceptance_criteria??[])for(let a of s.test_refs??[]){let c=Vf(a);c&&KT(n,c,o)}}return{dependents:e,moduleOwners:r,testRefCitations:n}}function In(t){let e=WB.get(t);return e||(e=h_e(t),WB.set(t,e)),e}var m_e,WB,as=y(()=>{"use strict";m_e=["derived:","fixture:","script:","self-dogfood:"];WB=new WeakMap});function JT(t,e,r=1/0){let n=new Set,i=new Set(t),o=[...i],s=0;for(;o.length>0&&sn.id===e)??r.find(n=>n.slug===e)??null}function xr(t,e,r={}){let n=r.depth??1/0,i=In(t),o=new Map((t.features??[]).map(_=>[_.id,_])),s=[],a,c=g_e(t,e);if(c)s=[c];else{let _=i.moduleOwners.get(e);_&&_.size>0&&(a=e,s=[..._].map(S=>o.get(S)).filter(S=>!!S))}if(s.length===0)return{not_found:e,accepted_forms:["feature id (F-\u2026)","slug","module path (e.g. src/spec/load.ts)"],discovery:"grep spec/index.yaml \u2014 one line per feature (run clad sync if missing); module paths live in each shard\u2019s modules:; if the query is a file, fall back to normal code search \u2014 the graph only knows declared modules"};let l=s.map(_=>_.id),u=JT(l,i.dependents,n),d=[...u].map(_=>o.get(_)).filter(_=>!!_).map(_=>({id:_.id,title:_.title,status:_.status})).sort((_,S)=>_.id.localeCompare(S.id)),f=new Set([...l,...u]),p=[...f].map(_=>o.get(_)).filter(_=>!!_),m=[...new Set(p.flatMap(_=>_.modules??[]))].sort(),h=(t.scenarios??[]).filter(_=>(_.features??[]).some(S=>f.has(S))).map(_=>({id:_.id,title:_.title})).sort((_,S)=>_.id.localeCompare(S.id)),g=[...new Set(p.flatMap(_=>(_.acceptance_criteria??[]).flatMap(S=>S.test_refs??[])))].sort();return{focus:a?{module:a,owners:[...l].sort()}:{id:s[0].id,title:s[0].title,status:s[0].status},impacted:d,impacted_modules:m,scenarios:h,test_refs:g,ledger:YT(i)}}var $a=y(()=>{"use strict";as()});function KB(t){return t.impacted.length}function U_(t,e,r={}){let n=r.initialDepth??z_.initialDepth,i=r.maxDepth??z_.maxDepth,o=r.coverageThreshold??z_.coverageThreshold,s=r.marginYieldThreshold??z_.marginYieldThreshold,a=In(t),c=new Map((t.features??[]).map(b=>[b.id,b])),l=[],u=(t.features??[]).find(b=>b.id===e||b.slug===e);if(u)l=[u.id];else{let b=a.moduleOwners.get(e);b&&b.size>0&&(l=[...b].filter(_=>c.has(_)))}if(l.length===0){let b=xr(t,e,{depth:1});return"not_found"in b,b}let d=JT(l,a.dependents,1/0).size;if(d===0){let b=xr(t,e,{depth:n});return"not_found"in b?b:{slice:b,depthUsed:n,stoppedBy:"no-known-dependents",analysis:{frontierExhausted:!0,coverage:null,marginalYields:[0],totalKnownDependents:0}}}let f=[],p=0,m=null;for(let b=n;b<=i;b++){let _=xr(t,e,{depth:b});if("not_found"in _)return _;m=_;let S=KB(_),x=S-p,w=S>0?x/S:0;f.push(w);let R=d>0?S/d:1,A=x===0&&b>n,O={frontierExhausted:A,coverage:R,marginalYields:[...f],totalKnownDependents:d};if(A)return{slice:_,depthUsed:b,stoppedBy:"exhaustion",analysis:O};if(R>=o)return{slice:_,depthUsed:b,stoppedBy:"coverage",analysis:O};if(f.length>=2&&f[f.length-1]0?g/d:1,marginalYields:[...f],totalKnownDependents:d}}}var z_,XT=y(()=>{"use strict";$a();as();z_={initialDepth:1,maxDepth:10,coverageThreshold:.9,marginYieldThreshold:.05}});function y_e(t,e){let r=new Set,n=[t];for(;n.length>0;){let i=n.pop();if(!i||r.has(i))continue;r.add(i);let o=e.get(i);for(let s of o?.depends_on??[])n.push(s)}return r}function JB(t,e){let r=new Map(t.features.map(a=>[a.id,a]));if(!r.has(e))return t;let n=y_e(e,r),i=t.features.filter(a=>n.has(a.id)),o=(t.scenarios??[]).filter(a=>(a.features??[]).some(c=>n.has(c)));return{...t,features:i,scenarios:o}}var YB=y(()=>{"use strict"});function __e(t,e){let r=t.features??[];return r.find(n=>n.id===e)??r.find(n=>n.slug===e)??r.find(n=>(n.modules??[]).includes(e))??null}function bl(t,e){let r=__e(t,e);if(!r)return{not_found:e,accepted_forms:["feature id (F-\u2026)","slug","module path (e.g. src/auth/login.ts)"],discovery:"grep spec/index.yaml \u2014 one line per feature (id, slug, status; run clad sync if missing); if the query is a file, fall back to normal code search \u2014 the graph only knows declared modules"};let n=JB(t,r.id),i=(n.features??[]).filter(c=>c.id!==r.id).map(c=>({id:c.id,title:c.title,status:c.status})).sort((c,l)=>c.id.localeCompare(l.id)),o=(n.scenarios??[]).map(c=>({id:c.id,title:c.title})).sort((c,l)=>c.id.localeCompare(l.id)),s=(t.project?.ai_hints?.preferred_patterns??[]).map(c=>({when:c.when,prefer:c.prefer,...c.over!==void 0?{over:c.over}:{}})),a=[...new Set((r.acceptance_criteria??[]).flatMap(c=>c.test_refs??[]))].sort();return{focus:r,ancestors:i,scenarios:o,preferred_patterns:s,test_refs:a}}var q_=y(()=>{"use strict";YB()});import{existsSync as QB,readdirSync as b_e,readFileSync as v_e}from"node:fs";import{join as eR}from"node:path";function tR(t,e=w_e){let r=t.trim().replace(/\s+/g," ");return r.length<=e?r:`${r.slice(0,e-1)}\u2026`}function x_e(t){let e=t.payload??{};if(t.type==="drift_detected"){let n=typeof e.gate=="string"&&e.gate?e.gate:"drift";return{detector:n,message:tR(`drift detected at gate ${n}`)}}let r=typeof e.worst=="number"?` (worst ${e.worst})`:"";return{detector:"done_attempted",message:tR(`done reverted \u2014 pre-push strict gate red${r}`)}}function XB(t){let e=Date.parse(t.timestamp);return Number.isFinite(e)?e:0}function $_e(t){let e=[];t.lastFailedGate&&e.push(`failed ${t.lastFailedGate}`),typeof t.retryCount=="number"&&e.push(`${t.retryCount} retries`);let r=e.length?` (${e.join(", ")})`:"",n=t.recovery?`recover: ${t.recovery}${r}`:`rolled back${r}`;return tR(n)}function k_e(t,e,r,n={}){let i=t.filter(m=>m&&m.payload&&m.payload.feature===r),o=e.filter(m=>m&&m.featureId===r).slice().sort((m,h)=>XB(m)-XB(h)),s=i.filter(m=>m.type==="drift_detected"||m.type==="done_attempted"&&m.payload.kept===!1),a=i.filter(m=>m.type==="feature_rolled_back");if(s.length===0&&a.length===0&&o.length===0)return;let c=o.length?o[o.length-1]:void 0,l;for(let m=s.length-1;m>=0;m--){let h=s[m].payload.gate;if(s[m].type==="drift_detected"&&typeof h=="string"&&h){l=h;break}}!l&&c?.lastFailedGate&&(l=c.lastFailedGate);let u=s.slice(-S_e).map(x_e),d;for(let m=a.length-1;m>=0;m--){let h=a[m].payload.to_git_head;if(typeof h=="string"&&h){d=h;break}}let f=typeof c?.retryCount=="number"?c.retryCount:void 0,p=c?$_e(c):void 0;return{attempts:s.length,...l?{last_failed_gate:l}:{},...f!==void 0?{retry_count:f}:{},...u.length?{drift_history:u}:{},...d?{rolled_back_at:d}:{},...p?{recovery_hint:p}:{},...n.truncated?{truncated_history:!0}:{}}}function QT(t,e){let r=t.match(e);return r&&r[1]?r[1].trim():void 0}function E_e(t){let e=t.indexOf("## Recommended recovery");if(e<0)return;let r=t.slice(e).match(/```[^\n]*\n([\s\S]*?)```/);return r&&r[1].split(` +`).map(i=>i.trim()).find(i=>i.length>0)||void 0}function A_e(t,e,r){let n=QT(t,/_Rolled back at_\s*`([^`]+)`/),i=QT(t,/Last failed gate:\s*`([^`]+)`/),o=QT(t,/Retry attempts:\s*(\d+)/),s=E_e(t);return{featureId:e,timestamp:n??r,...i?{lastFailedGate:i}:{},...o?{retryCount:Number(o)}:{},...s?{recovery:s}:{}}}function O_e(t,e){let r=eR(t,".cladding","post-mortems");if(!QB(r))return[];let n=`post-mortem-${e}-`,i=[];for(let o of b_e(r))if(!(!o.startsWith(n)||!o.endsWith(".md")))try{i.push(A_e(v_e(eR(r,o),"utf8"),e,o))}catch{}return i}function eG(t,e){try{let r=N_(t),n=O_e(t,e),i=QB(eR(t,".cladding","events.log.1.jsonl"));return k_e(r,n,e,{truncated:i})}catch{return}}var S_e,w_e,tG=y(()=>{"use strict";Fr();S_e=5,w_e=120});function H_(t,e,r){return on(JSON.stringify({...t,needs:e,must_edit:{...t.must_edit,code:r}}))}function ka(t,e,r={}){let n=r.cwd??".",i=r.maxTokens&&r.maxTokens>0?r.maxTokens:T_e,o=e,s,a=In(t).moduleOwners.get(e);if(a&&a.size>0){let se=[...a].sort();o=se[0],se.length>1&&(s=se)}let c=bl(t,o);if("not_found"in c)return c;let l=c.focus,u=eG(n,l.id),d=a&&a.size>0?e:l.id,f=U_(t,d),p="not_found"in f?null:f.slice,m=p?p.impacted:[],h=p?p.test_refs:[],g="not_found"in f?null:{depth:f.depthUsed,stopped_by:f.stoppedBy,coverage:f.analysis.coverage===null?null:Math.round(f.analysis.coverage*100)/100,total_known_dependents:f.analysis.totalKnownDependents},b=l.acceptance_criteria??[],_=b.filter(se=>se.ears==="unwanted"||se.ears==="state").map(se=>({id:se.id,ears:String(se.ears)})),S=[...new Set(b.flatMap(se=>se.oracle_refs??[]))].sort(),x=[],w={must_edit:{id:l.id,title:l.title,status:l.status,modules:l.modules??[],acceptance_criteria:b,code:[],...s?{co_owners:s}:{}},needs:c.ancestors,breaks_if_changed:{impacted:m,regression_tests:h,...g?{radius:g}:{}},verify:{scenarios:c.scenarios,test_refs:c.test_refs,oracle_refs:S,high_risk_acs:_},guidance:{preferred_patterns:c.preferred_patterns},budget:{max_tokens:i,used_tokens:0,truncated:x}},R=[...c.ancestors];for(;R.length>R_e&&H_(w,R,[])>i;)R.pop();R.lengthi){x.push(`code: omitted ${se} (budget)`);continue}O.push(Kt),Kt.truncated&&x.push(`code: clipped ${se}`)}A>i&&x.push("must-edit exceeds budget \u2014 retained in full (focus is never dropped)");let D=(se,Ce)=>({impacted:se,regression_tests:Ce,...g?{radius:g}:{},...p?.ledger?{ledger:p.ledger}:{}}),E=(se,Ce,Kt,fr)=>{let Qt=Kt+fr>0?[`breaks: omitted ${Kt} feature(s) / ${fr} test(s)`]:[],fo={...w,needs:R,must_edit:{...w.must_edit,code:O},breaks_if_changed:D(se,Ce),budget:{...w.budget,truncated:[...x,...Qt]}};return on(JSON.stringify(fo))>i},ae=m,X=h;if(E(ae,X,0,0)){let se=xr(t,d,{depth:1}),Ce=new Set("not_found"in se?[]:se.impacted.map(fe=>fe.id)),Kt=new Set("not_found"in se?[]:se.test_refs),Qt=[...m.filter(fe=>Ce.has(fe.id)),...m.filter(fe=>!Ce.has(fe.id))],fo=0;for(;Qt.length>Ce.size&&E(Qt,X,fo,0);)Qt=Qt.slice(0,-1),fo++;let ki=[...h],tn=0;for(;E(Qt,ki,fo,tn);){let fe=-1;for(let po=ki.length-1;po>=0;po--)if(!Kt.has(ki[po])){fe=po;break}if(fe<0)break;ki.splice(fe,1),tn++}ae=Qt,X=ki,fo+tn>0&&x.push(`breaks: omitted ${fo} feature(s) / ${tn} test(s)`),E(ae,X,0,0)&&x.push("breaks: direct set retained in full \u2014 exceeds budget")}let J=D(ae,X),P={...w,needs:R,must_edit:{...w.must_edit,code:O},breaks_if_changed:J},C=P;if(u){let se={...P,prior_attempts:u};on(JSON.stringify(se))<=i?C=se:x.push("prior_attempts: omitted (budget)")}let dr=on(JSON.stringify(C));return{...C,budget:{max_tokens:i,used_tokens:dr,truncated:x}}}var T_e,R_e,B_=y(()=>{"use strict";L_();q_();XT();tG();$a();as();T_e=3e3,R_e=3});function ei(t){if(t.length===0)return 0;let e=[...t].sort((n,i)=>n-i),r=Math.floor(e.length/2);return e.length%2?e[r]:(e[r-1]+e[r])/2}function I_e(t,e){if(t.length===0)return 0;let r=[...t].sort((n,i)=>n-i);return r[Math.min(r.length-1,Math.floor(e/100*r.length))]}function rG(t,e,r="."){let n=In(t),i=t.features??[],o=[];for(let f of i){let p=ka(t,f.id,{cwd:r,read:e});if("not_found"in p)continue;let m=ka(t,f.id,{cwd:r,read:e,maxTokens:Number.MAX_SAFE_INTEGER}),h=U_(t,f.id),g=!("not_found"in h),b=on(JSON.stringify(p)),_="not_found"in m?b:on(JSON.stringify(m)),S=on(JSON.stringify(f));for(let R of f.modules??[]){let A=e(R);A&&(S+=on(A))}let x=(f.depends_on??[]).length,w=n.dependents.get(f.id)?.size??0;o.push({id:f.id,sliceTokens:b,structuralTokens:_,naiveTokens:S,contextRatio:S>0?b/S:1,budgetSaturated:p.budget.truncated.length>0,searchDepth:g?h.depthUsed:1,edgesResolved:x+w,stoppedBy:g?h.stoppedBy:"n/a",coverage:g?h.analysis.coverage:1,regressionTests:p.breaks_if_changed.regression_tests.length})}o.sort((f,p)=>f.id.localeCompare(p.id));let s=o.map(f=>f.contextRatio),a=f=>f.filter(p=>p.sliceTokens>0).map(p=>p.naiveTokens/p.sliceTokens),c=o.filter(f=>!f.budgetSaturated),l=o.filter(f=>f.budgetSaturated),u=o.filter(f=>f.naiveTokens>0).map(f=>f.structuralTokens/f.naiveTokens),d={};for(let f of o)d[f.stoppedBy]=(d[f.stoppedBy]??0)+1;return{featureCount:i.length,measured:o.length,context:{medianContextRatio:Math.round(ei(s)*1e3)/1e3,medianShrinkFactor:Math.round(ei(a(o))*10)/10,fitsCount:c.length,truncatedCount:l.length,medianShrinkFit:Math.round(ei(a(c))*10)/10,medianShrinkTruncated:Math.round(ei(a(l))*10)/10,medianStructuralRatio:Math.round(ei(u)*100)/100,medianSliceTokens:Math.round(ei(o.map(f=>f.sliceTokens))),medianNaiveTokens:Math.round(ei(o.map(f=>f.naiveTokens)))},search:{medianDepth:ei(o.map(f=>f.searchDepth)),p95Depth:I_e(o.map(f=>f.searchDepth),95),medianEdges:ei(o.map(f=>f.edgesResolved)),maxEdges:o.reduce((f,p)=>Math.max(f,p.edgesResolved),0)},stability:{byStopReason:d,medianCoverage:Math.round(ei(o.map(f=>f.coverage).filter(f=>f!==null))*100)/100,medianRegressionTests:ei(o.map(f=>f.regressionTests))},features:o}}var vl,G_=y(()=>{"use strict";L_();XT();B_();as();vl="(deterministic upper bound vs the shard+all-modules baseline \u2014 not an agent-adoption measurement)"});import{appendFileSync as P_e,existsSync as rR,mkdirSync as C_e,readFileSync as nG}from"node:fs";import{dirname as D_e,join as N_e}from"node:path";function nR(t){return N_e(t,j_e,M_e)}function F_e(t,e){return{timestamp:new Date().toISOString(),head:xa(t),spec_digest:VT(t),featureCount:e.featureCount,measured:e.measured,context:e.context,search:e.search,stability:e.stability}}function iG(t,e){try{let r=F_e(t,e);if(r.head===null)return{appended:!1,reason:"no_head"};let n=iR(t),i=n[n.length-1];if(i&&i.head===r.head&&i.spec_digest===r.spec_digest)return{appended:!1,reason:"deduped"};let o=nR(t),s=D_e(o);return rR(s)||C_e(s,{recursive:!0}),P_e(o,`${JSON.stringify(r)} +`,"utf8"),{appended:!0,reason:"appended"}}catch{return{appended:!1,reason:"error"}}}function oG(t){let e=[];for(let r of t.split(` +`)){let n=r.trim();if(n.length!==0)try{let i=JSON.parse(n);i&&typeof i=="object"&&i.context&&i.search&&i.stability&&e.push(i)}catch{}}return e}function iR(t,e){let r=nR(t);if(!rR(r))return[];let n;try{n=nG(r,"utf8")}catch{return[]}let i=oG(n);return typeof e=="number"&&e>=0?i.slice(-e):i}function sG(t){let e=nR(t);if(!rR(e))return{snapshots:[],unreadable:!1};let r;try{r=nG(e,"utf8")}catch{return{snapshots:[],unreadable:!0}}let n=oG(r),i=r.trim().length>0;return{snapshots:n,unreadable:i&&n.length===0}}function Wf(t,e=0){let r=e>0?Math.round(t*10**e)/10**e:Math.round(t),n=r.toFixed(e);return r>0?`+${n}`:n}function aG(t,e=5){let r=Math.max(0,t.length-e),i=[`measure trend \xB7 last ${t.slice(r).length} of ${t.length} snapshot(s)`];for(let o=r;o0?t[o-1]:null,c=(d,f=0)=>a?` (${Wf(d(s)-d(a),f)})`:"",l=s.timestamp.slice(0,19),u=s.head?s.head.slice(0,7):"nogit";i.push(` ${l} ${u} \xB7 ${s.featureCount} feat \xB7 slice ${s.context.medianSliceTokens}${c(d=>d.context.medianSliceTokens)} \xB7 struct ${s.context.medianStructuralRatio.toFixed(2)}${c(d=>d.context.medianStructuralRatio,2)} \xB7 cov ${s.stability.medianCoverage.toFixed(2)}${c(d=>d.stability.medianCoverage,2)} \xB7 p95depth ${s.search.p95Depth}${c(d=>d.search.p95Depth)} \xB7 trunc ${s.context.truncatedCount}${c(d=>d.context.truncatedCount)}`)}return i.push(` ${vl}`),i.join(` +`)}var j_e,M_e,Kf=y(()=>{"use strict";Zf();G_();j_e=".cladding",M_e="measure.jsonl"});import{existsSync as L_e}from"node:fs";import{join as z_e}from"node:path";function Sl(t){if(t.groups.reduce((i,o)=>i+o.features.length,0)===0&&t.unsharded_commits.length===0)return`no shipped changes since ${t.since}`;let r=[`# Changes since ${t.since}`,""];for(let i of t.groups){r.push(`## ${i.title}`,"");for(let o of i.features){r.push(`- **${o.title}** (${U_e[o.change]})`);for(let s of o.acceptance)r.push(` - ${s}`)}r.push("")}if(t.unsharded_commits.length>0){r.push("## Other changes (not yet spec-tracked)","");for(let i of t.unsharded_commits)r.push(`- ${i.subject}`);r.push("")}let n=t.inventory;for((n.before.features!==n.after.features||n.before.scenarios!==n.after.scenarios)&&r.push(`_Spec inventory: ${n.before.features} \u2192 ${n.after.features} features, ${n.before.scenarios} \u2192 ${n.after.scenarios} scenarios._`,"");r[r.length-1]==="";)r.pop();return r.join(` +`)}function lG(t){let e=t.snapshot,r=["## Measured (this release)",""];if(!e||!e.head)return r.push("not measured at this commit \u2014 run clad measure before tagging"),r.join(` +`);let n=e.context,i=e.stability;r.push(`- features measured: ${e.measured} of ${e.featureCount}`),r.push(`- median slice tokens: ${n.medianSliceTokens} vs ${n.medianNaiveTokens} naive`),r.push(`- median structural ratio: ${n.medianStructuralRatio.toFixed(2)}`),r.push(`- median coverage: ${i.medianCoverage.toFixed(2)}`),r.push(`- regression tests surfaced: ${i.medianRegressionTests}`);let o=t.sinceSnapshot;if(o){let s=t.sinceRef??(o.head?o.head.slice(0,7):"previous");r.push(`- since ${s}: slice ${Wf(n.medianSliceTokens-o.context.medianSliceTokens)} \xB7 struct ${Wf(n.medianStructuralRatio-o.context.medianStructuralRatio,2)} \xB7 cov ${Wf(i.medianCoverage-o.stability.medianCoverage,2)}`)}return r.push("",`head ${e.head.slice(0,7)} \xB7 spec_digest ${e.spec_digest}`,`reproduce: git checkout ${e.head} && clad measure`,"",vl),r.join(` +`)}function wl(t,e,r){let n=[`# Audit \u2014 shipped changes since ${t.since}`,"","| feature | AC | EARS | verification refs |","|---|---|---|---|"],i=new Map(e.features.map(o=>[o.id,o]));for(let o of t.groups)for(let s of o.features){let a=i.get(s.id);if(!a){n.push(`| ${s.id} | \u2014 | \u2014 | (removed from spec \u2014 see git history at ${t.since}) |`);continue}let c=a.acceptance_criteria??[];if(c.length===0){n.push(`| ${a.id} | \u2014 | \u2014 | (no acceptance criteria) |`);continue}for(let l of c)n.push(`| ${a.id} | ${l.id} | ${l.ears??"\u2014"} | ${H_e(l,r)} |`)}return n.join(` +`)}function H_e(t,e){let r=[...t.test_refs??[],...t.oracle_refs??[],...t.evidence_refs??[]];return r.length===0?"(none)":r.map(n=>{for(let[o,s]of q_e)if(n.startsWith(o))return`${n} (${s})`;let i=n.split("#",1)[0]??n;return`${L_e(z_e(e,i))?"\u2713":"\u2717"} ${n}`}).join("
")}function xl(t){let e=[`# ${t.project.name} \u2014 capability catalog`,""],r=[...t.capabilities??[]].filter(s=>typeof s.id=="string"&&s.id.length>0).sort((s,a)=>s.id.localeCompare(a.id)),n=new Map(t.features.map(s=>[s.id,s])),i=new Set;for(let s of r){e.push(`## ${s.title??s.id}`,""),s.summary&&e.push(s.summary,"");for(let a of s.features??[]){let c=n.get(a);!c||c.status==="archived"||(i.add(a),cG(e,c))}}let o=t.features.filter(s=>!i.has(s.id)&&s.status!=="archived").sort((s,a)=>s.id.localeCompare(a.id));if(o.length>0){e.push("## Uncategorized","");for(let s of o)cG(e,s)}for(;e[e.length-1]==="";)e.pop();return e.join(` +`)}function cG(t,e){t.push(`### ${e.title}`,"");for(let r of e.acceptance_criteria??[]){let n=UT(r);n&&t.push(`- ${n}`)}t.push("")}var U_e,q_e,Z_=y(()=>{"use strict";Kf();G_();_l();U_e={"added-as-done":"new","flipped-to-done":"completed","modified-while-done":"updated",archived:"retired"};q_e=[["derived:","machine-suggested \u2014 not author-confirmed"],["self-dogfood:","verified by cladding running on itself"],["fixture:","conformance fixture"],["script:","npm script"]]});import{readFileSync as B_e}from"node:fs";function Ri(t="./spec.yaml"){let e=B_e(t,"utf8");return(0,uG.parse)(e)}var uG,V_=y(()=>{"use strict";uG=wt(tr(),1)});var cs=v((Lr,cR)=>{"use strict";var oR=Lr.ValidationError=function(e,r,n,i,o,s){if(Array.isArray(i)?(this.path=i,this.property=i.reduce(function(c,l){return c+fG(l)},"instance")):i!==void 0&&(this.property=i),e&&(this.message=e),n){var a=n.$id||n.id;this.schema=a||n}r!==void 0&&(this.instance=r),this.name=o,this.argument=s,this.stack=this.toString()};oR.prototype.toString=function(){return this.property+" "+this.message};var W_=Lr.ValidatorResult=function(e,r,n,i){this.instance=e,this.schema=r,this.options=n,this.path=i.path,this.propertyPath=i.propertyPath,this.errors=[],this.throwError=n&&n.throwError,this.throwFirst=n&&n.throwFirst,this.throwAll=n&&n.throwAll,this.disableFormat=n&&n.disableFormat===!0};W_.prototype.addError=function(e){var r;if(typeof e=="string")r=new oR(e,this.instance,this.schema,this.path);else{if(!e)throw new Error("Missing error detail");if(!e.message)throw new Error("Missing error message");if(!e.name)throw new Error("Missing validator type");r=new oR(e.message,this.instance,this.schema,this.path,e.name,e.argument)}if(this.errors.push(r),this.throwFirst)throw new Ea(this);if(this.throwError)throw r;return r};W_.prototype.importErrors=function(e){typeof e=="string"||e&&e.validatorType?this.addError(e):e&&e.errors&&(this.errors=this.errors.concat(e.errors))};function G_e(t,e){return e+": "+t.toString()+` +`}W_.prototype.toString=function(e){return this.errors.map(G_e).join("")};Object.defineProperty(W_.prototype,"valid",{get:function(){return!this.errors.length}});cR.exports.ValidatorResultError=Ea;function Ea(t){typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,Ea),this.instance=t.instance,this.schema=t.schema,this.options=t.options,this.errors=t.errors}Ea.prototype=new Error;Ea.prototype.constructor=Ea;Ea.prototype.name="Validation Error";var dG=Lr.SchemaError=function t(e,r){this.message=e,this.schema=r,Error.call(this,e),typeof Error.captureStackTrace=="function"&&Error.captureStackTrace(this,t)};dG.prototype=Object.create(Error.prototype,{constructor:{value:dG,enumerable:!1},name:{value:"SchemaError",enumerable:!1}});var sR=Lr.SchemaContext=function(e,r,n,i,o){this.schema=e,this.options=r,Array.isArray(n)?(this.path=n,this.propertyPath=n.reduce(function(s,a){return s+fG(a)},"instance")):this.propertyPath=n,this.base=i,this.schemas=o};sR.prototype.resolve=function(e){return pG(this.base,e)};sR.prototype.makeChild=function(e,r){var n=r===void 0?this.path:this.path.concat([r]),i=e.$id||e.id;let o=pG(this.base,i||"");var s=new sR(e,this.options,n,o,Object.create(this.schemas));return i&&!s.schemas[o]&&(s.schemas[o]=e),s};var ti=Lr.FORMAT_REGEXPS={"date-time":/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-(3[01]|0[1-9]|[12][0-9])[tT ](2[0-4]|[01][0-9]):([0-5][0-9]):(60|[0-5][0-9])(\.\d+)?([zZ]|[+-]([0-5][0-9]):(60|[0-5][0-9]))$/,date:/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-(3[01]|0[1-9]|[12][0-9])$/,time:/^(2[0-4]|[01][0-9]):([0-5][0-9]):(60|[0-5][0-9])$/,duration:/P(T\d+(H(\d+M(\d+S)?)?|M(\d+S)?|S)|\d+(D|M(\d+D)?|Y(\d+M(\d+D)?)?)(T\d+(H(\d+M(\d+S)?)?|M(\d+S)?|S))?|\d+W)/i,email:/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/,"idn-email":/^("(?:[!#-\[\]-\u{10FFFF}]|\\[\t -\u{10FFFF}])*"|[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}](?:\.?[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}])*)@([!#-'*+\-/-9=?A-Z\^-\u{10FFFF}](?:\.?[!#-'*+\-/-9=?A-Z\^-\u{10FFFF}])*|\[[!-Z\^-\u{10FFFF}]*\])$/u,"ip-address":/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,ipv6:/^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,uri:/^[a-zA-Z][a-zA-Z0-9+.-]*:[^\s]*$/,"uri-reference":/^(((([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|([A-Za-z][+\-.0-9A-Za-z]*:?)?)|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|(\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?)?))#(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|(([A-Za-z][+\-.0-9A-Za-z]*)?%[0-9A-Fa-f]{2}|[!$&-.0-9;=@_~]|[A-Za-z][+\-.0-9A-Za-z]*[!$&-*,;=@_~])(%[0-9A-Fa-f]{2}|[!$&-.0-9;=@-Z_a-z~])*((([/?](%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*)?#|[/?])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*)?|([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~])*|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~])+(:\d*)?|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?:\d*|\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~]+)?|[.0-:A-Fa-f]+)\])?)?|[A-Za-z][+\-.0-9A-Za-z]*:?)?$/,iri:/^[a-zA-Z][a-zA-Z0-9+.-]*:[^\s]*$/,"iri-reference":/^(((([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~-\u{10FFFF}]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|([A-Za-z][+\-.0-9A-Za-z]*:?)?)|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~-\u{10FFFF}])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~-\u{10FFFF}])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|(\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~-\u{10FFFF}])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?)?))#(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|(([A-Za-z][+\-.0-9A-Za-z]*)?%[0-9A-Fa-f]{2}|[!$&-.0-9;=@_~-\u{10FFFF}]|[A-Za-z][+\-.0-9A-Za-z]*[!$&-*,;=@_~-\u{10FFFF}])(%[0-9A-Fa-f]{2}|[!$&-.0-9;=@-Z_a-z~-\u{10FFFF}])*((([/?](%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*)?#|[/?])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*)?|([A-Za-z][+\-.0-9A-Za-z]*(:%[0-9A-Fa-f]{2}|:[!$&-.0-;=?-Z_a-z~-\u{10FFFF}]|[/?])|\?)(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|([A-Za-z][+\-.0-9A-Za-z]*:)?\/((%[0-9A-Fa-f]{2}|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~-\u{10FFFF}])+|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?)(:\d*)?[/?]|[!$&-.0-;=?-Z_a-z~-\u{10FFFF}])(%[0-9A-Fa-f]{2}|[!$&-;=?-Z_a-z~-\u{10FFFF}])*|\/((%[0-9A-Fa-f]{2}|[!$&-.0-9;=A-Z_a-z~-\u{10FFFF}])+(:\d*)?|(\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?:\d*|\[(([Vv][0-9A-Fa-f]+\.[!$&-.0-;=A-Z_a-z~-\u{10FFFF}]+)?|[.0-:A-Fa-f]+)\])?)?|[A-Za-z][+\-.0-9A-Za-z]*:?)?$/u,uuid:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i,"uri-template":/(%[0-9a-f]{2}|[!#$&(-;=?@\[\]_a-z~]|\{[!#&+,./;=?@|]?(%[0-9a-f]{2}|[0-9_a-z])(\.?(%[0-9a-f]{2}|[0-9_a-z]))*(:[1-9]\d{0,3}|\*)?(,(%[0-9a-f]{2}|[0-9_a-z])(\.?(%[0-9a-f]{2}|[0-9_a-z]))*(:[1-9]\d{0,3}|\*)?)*\})*/iu,"json-pointer":/^(\/([\x00-\x2e0-@\[-}\x7f]|~[01])*)*$/iu,"relative-json-pointer":/^\d+(#|(\/([\x00-\x2e0-@\[-}\x7f]|~[01])*)*)$/iu,hostname:/^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/,"host-name":/^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/,"utc-millisec":function(t){return typeof t=="string"&&parseFloat(t)===parseInt(t,10)&&!isNaN(t)},regex:function(t){var e=!0;try{new RegExp(t)}catch{e=!1}return e},style:/[\r\n\t ]*[^\r\n\t ][^:]*:[\r\n\t ]*[^\r\n\t ;]*[\r\n\t ]*;?/,color:/^(#?([0-9A-Fa-f]{3}){1,2}\b|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/,phone:/^\+(?:[0-9] ?){6,14}[0-9]$/,alpha:/^[a-zA-Z]+$/,alphanumeric:/^[a-zA-Z0-9]+$/};ti.regexp=ti.regex;ti.pattern=ti.regex;ti.ipv4=ti["ip-address"];Lr.isFormat=function(e,r,n){if(typeof e=="string"&&ti[r]!==void 0){if(ti[r]instanceof RegExp)return ti[r].test(e);if(typeof ti[r]=="function")return ti[r](e)}else if(n&&n.customFormats&&typeof n.customFormats[r]=="function")return n.customFormats[r](e);return!0};var fG=Lr.makeSuffix=function(e){return e=e.toString(),!e.match(/[.\s\[\]]/)&&!e.match(/^[\d]/)?"."+e:e.match(/^\d+$/)?"["+e+"]":"["+JSON.stringify(e)+"]"};Lr.deepCompareStrict=function t(e,r){if(typeof e!=typeof r)return!1;if(Array.isArray(e))return!Array.isArray(r)||e.length!==r.length?!1:e.every(function(o,s){return t(e[s],r[s])});if(typeof e=="object"){if(!e||!r)return e===r;var n=Object.keys(e),i=Object.keys(r);return n.length!==i.length?!1:n.every(function(o){return t(e[o],r[o])})}return e===r};function Z_e(t,e,r,n){typeof r=="object"?e[n]=aR(t[n],r):t.indexOf(r)===-1&&e.push(r)}function V_e(t,e,r){e[r]=t[r]}function W_e(t,e,r,n){typeof e[n]!="object"||!e[n]?r[n]=e[n]:t[n]?r[n]=aR(t[n],e[n]):r[n]=e[n]}function aR(t,e){var r=Array.isArray(e),n=r&&[]||{};return r?(t=t||[],n=n.concat(t),e.forEach(Z_e.bind(null,t,n))):(t&&typeof t=="object"&&Object.keys(t).forEach(V_e.bind(null,t,n)),Object.keys(e).forEach(W_e.bind(null,t,e,n))),n}cR.exports.deepMerge=aR;Lr.objectGetPath=function(e,r){for(var n=r.split("/").slice(1),i;typeof(i=n.shift())=="string";){var o=decodeURIComponent(i.replace(/~0/,"~").replace(/~1/g,"/"));if(!(o in e))return;e=e[o]}return e};function K_e(t){return"/"+encodeURIComponent(t).replace(/~/g,"%7E")}Lr.encodePath=function(e){return e.map(K_e).join("")};Lr.getDecimalPlaces=function(e){var r=0;if(isNaN(e))return r;typeof e!="number"&&(e=Number(e));var n=e.toString().split("e");if(n.length===2){if(n[1][0]!=="-")return r;r=Number(n[1].slice(1))}var i=n[0].split(".");return i.length===2&&(r+=i[1].length),r};Lr.isSchema=function(e){return typeof e=="object"&&e||typeof e=="boolean"};var pG=Lr.resolveUrl=function(e,r){let n=new URL(r,new URL(e,"resolve://"));if(n.protocol==="resolve:"){let{pathname:i,search:o,hash:s}=n;return i+o+s}return n.toString()}});var yG=v(($et,gG)=>{"use strict";var sn=cs(),Le=sn.ValidatorResult,ls=sn.SchemaError,lR={};lR.ignoreProperties={id:!0,default:!0,description:!0,title:!0,additionalItems:!0,then:!0,else:!0,$schema:!0,$ref:!0,extends:!0};var ze=lR.validators={};ze.type=function(e,r,n,i){if(e===void 0)return null;var o=new Le(e,r,n,i),s=Array.isArray(r.type)?r.type:[r.type];if(!s.some(this.testType.bind(this,e,r,n,i))){var a=s.map(function(c){if(c){var l=c.$id||c.id;return l?"<"+l+">":c+""}});o.addError({name:"type",argument:a,message:"is not of a type(s) "+a})}return o};function uR(t,e,r,n,i){var o=e.throwError,s=e.throwAll;e.throwError=!1,e.throwAll=!1;var a=this.validateSchema(t,i,e,r);return e.throwError=o,e.throwAll=s,!a.valid&&n instanceof Function&&n(a),a.valid}ze.anyOf=function(e,r,n,i){if(e===void 0)return null;var o=new Le(e,r,n,i),s=new Le(e,r,n,i);if(!Array.isArray(r.anyOf))throw new ls("anyOf must be an array");if(!r.anyOf.some(uR.bind(this,e,n,i,function(c){s.importErrors(c)}))){var a=r.anyOf.map(function(c,l){var u=c.$id||c.id;return u?"<"+u+">":c.title&&JSON.stringify(c.title)||c.$ref&&"<"+c.$ref+">"||"[subschema "+l+"]"});n.nestedErrors&&o.importErrors(s),o.addError({name:"anyOf",argument:a,message:"is not any of "+a.join(",")})}return o};ze.allOf=function(e,r,n,i){if(e===void 0)return null;if(!Array.isArray(r.allOf))throw new ls("allOf must be an array");var o=new Le(e,r,n,i),s=this;return r.allOf.forEach(function(a,c){var l=s.validateSchema(e,a,n,i);if(!l.valid){var u=a.$id||a.id,d=u||a.title&&JSON.stringify(a.title)||a.$ref&&"<"+a.$ref+">"||"[subschema "+c+"]";o.addError({name:"allOf",argument:{id:d,length:l.errors.length,valid:l},message:"does not match allOf schema "+d+" with "+l.errors.length+" error[s]:"}),o.importErrors(l)}}),o};ze.oneOf=function(e,r,n,i){if(e===void 0)return null;if(!Array.isArray(r.oneOf))throw new ls("oneOf must be an array");var o=new Le(e,r,n,i),s=new Le(e,r,n,i),a=r.oneOf.filter(uR.bind(this,e,n,i,function(l){s.importErrors(l)})).length,c=r.oneOf.map(function(l,u){var d=l.$id||l.id;return d||l.title&&JSON.stringify(l.title)||l.$ref&&"<"+l.$ref+">"||"[subschema "+u+"]"});return a!==1&&(n.nestedErrors&&o.importErrors(s),o.addError({name:"oneOf",argument:c,message:"is not exactly one from "+c.join(",")})),o};ze.if=function(e,r,n,i){if(e===void 0)return null;if(!sn.isSchema(r.if))throw new Error('Expected "if" keyword to be a schema');var o=uR.call(this,e,n,i,null,r.if),s=new Le(e,r,n,i),a;if(o){if(r.then===void 0)return;if(!sn.isSchema(r.then))throw new Error('Expected "then" keyword to be a schema');a=this.validateSchema(e,r.then,n,i.makeChild(r.then)),s.importErrors(a)}else{if(r.else===void 0)return;if(!sn.isSchema(r.else))throw new Error('Expected "else" keyword to be a schema');a=this.validateSchema(e,r.else,n,i.makeChild(r.else)),s.importErrors(a)}return s};function dR(t,e){if(Object.hasOwnProperty.call(t,e))return t[e];if(e in t){for(;t=Object.getPrototypeOf(t);)if(Object.propertyIsEnumerable.call(t,e))return t[e]}}ze.propertyNames=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=r.propertyNames!==void 0?r.propertyNames:{};if(!sn.isSchema(s))throw new ls('Expected "propertyNames" to be a schema (object or boolean)');for(var a in e)if(dR(e,a)!==void 0){var c=this.validateSchema(a,s,n,i.makeChild(s));o.importErrors(c)}return o}};ze.properties=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=r.properties||{};for(var a in s){var c=s[a];if(c!==void 0){if(c===null)throw new ls('Unexpected null, expected schema in "properties"');typeof n.preValidateProperty=="function"&&n.preValidateProperty(e,a,c,n,i);var l=dR(e,a),u=this.validateSchema(l,c,n,i.makeChild(c,a));u.instance!==o.instance[a]&&(o.instance[a]=u.instance),o.importErrors(u)}}return o}};function mG(t,e,r,n,i,o){if(this.types.object(t)&&!(e.properties&&e.properties[i]!==void 0))if(e.additionalProperties===!1)o.addError({name:"additionalProperties",argument:i,message:"is not allowed to have the additional property "+JSON.stringify(i)});else{var s=e.additionalProperties||{};typeof r.preValidateProperty=="function"&&r.preValidateProperty(t,i,s,r,n);var a=this.validateSchema(t[i],s,r,n.makeChild(s,i));a.instance!==o.instance[i]&&(o.instance[i]=a.instance),o.importErrors(a)}}ze.patternProperties=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=r.patternProperties||{};for(var a in e){var c=!0;for(var l in s){var u=s[l];if(u!==void 0){if(u===null)throw new ls('Unexpected null, expected schema in "patternProperties"');try{var d=new RegExp(l,"u")}catch{d=new RegExp(l)}if(d.test(a)){c=!1,typeof n.preValidateProperty=="function"&&n.preValidateProperty(e,a,u,n,i);var f=this.validateSchema(e[a],u,n,i.makeChild(u,a));f.instance!==o.instance[a]&&(o.instance[a]=f.instance),o.importErrors(f)}}}c&&mG.call(this,e,r,n,i,a,o)}return o}};ze.additionalProperties=function(e,r,n,i){if(this.types.object(e)){if(r.patternProperties)return null;var o=new Le(e,r,n,i);for(var s in e)mG.call(this,e,r,n,i,s,o);return o}};ze.minProperties=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=Object.keys(e);return s.length>=r.minProperties||o.addError({name:"minProperties",argument:r.minProperties,message:"does not meet minimum property length of "+r.minProperties}),o}};ze.maxProperties=function(e,r,n,i){if(this.types.object(e)){var o=new Le(e,r,n,i),s=Object.keys(e);return s.length<=r.maxProperties||o.addError({name:"maxProperties",argument:r.maxProperties,message:"does not meet maximum property length of "+r.maxProperties}),o}};ze.items=function(e,r,n,i){var o=this;if(this.types.array(e)&&r.items!==void 0){var s=new Le(e,r,n,i);return e.every(function(a,c){if(Array.isArray(r.items))var l=r.items[c]===void 0?r.additionalItems:r.items[c];else var l=r.items;if(l===void 0)return!0;if(l===!1)return s.addError({name:"items",message:"additionalItems not permitted"}),!1;var u=o.validateSchema(a,l,n,i.makeChild(l,c));return u.instance!==s.instance[c]&&(s.instance[c]=u.instance),s.importErrors(u),!0}),s}};ze.contains=function(e,r,n,i){var o=this;if(this.types.array(e)&&r.contains!==void 0){if(!sn.isSchema(r.contains))throw new Error('Expected "contains" keyword to be a schema');var s=new Le(e,r,n,i),a=e.some(function(c,l){var u=o.validateSchema(c,r.contains,n,i.makeChild(r.contains,l));return u.errors.length===0});return a===!1&&s.addError({name:"contains",argument:r.contains,message:"must contain an item matching given schema"}),s}};ze.minimum=function(e,r,n,i){if(this.types.number(e)){var o=new Le(e,r,n,i);return r.exclusiveMinimum&&r.exclusiveMinimum===!0?e>r.minimum||o.addError({name:"minimum",argument:r.minimum,message:"must be greater than "+r.minimum}):e>=r.minimum||o.addError({name:"minimum",argument:r.minimum,message:"must be greater than or equal to "+r.minimum}),o}};ze.maximum=function(e,r,n,i){if(this.types.number(e)){var o=new Le(e,r,n,i);return r.exclusiveMaximum&&r.exclusiveMaximum===!0?er.exclusiveMinimum;return s||o.addError({name:"exclusiveMinimum",argument:r.exclusiveMinimum,message:"must be strictly greater than "+r.exclusiveMinimum}),o}};ze.exclusiveMaximum=function(e,r,n,i){if(typeof r.exclusiveMaximum!="boolean"&&this.types.number(e)){var o=new Le(e,r,n,i),s=e=r.minLength||o.addError({name:"minLength",argument:r.minLength,message:"does not meet minimum length of "+r.minLength}),o}};ze.maxLength=function(e,r,n,i){if(this.types.string(e)){var o=new Le(e,r,n,i),s=e.match(/[\uDC00-\uDFFF]/g),a=e.length-(s?s.length:0);return a<=r.maxLength||o.addError({name:"maxLength",argument:r.maxLength,message:"does not meet maximum length of "+r.maxLength}),o}};ze.minItems=function(e,r,n,i){if(this.types.array(e)){var o=new Le(e,r,n,i);return e.length>=r.minItems||o.addError({name:"minItems",argument:r.minItems,message:"does not meet minimum length of "+r.minItems}),o}};ze.maxItems=function(e,r,n,i){if(this.types.array(e)){var o=new Le(e,r,n,i);return e.length<=r.maxItems||o.addError({name:"maxItems",argument:r.maxItems,message:"does not meet maximum length of "+r.maxItems}),o}};function J_e(t,e,r){var n,i=r.length;for(n=e+1,i;n{"use strict";var fR=cs();pR.exports.SchemaScanResult=_G;function _G(t,e){this.id=t,this.ref=e}pR.exports.scan=function(e,r){function n(c,l){if(!l||typeof l!="object")return;if(l.$ref){let p=fR.resolveUrl(c,l.$ref);a[p]=a[p]?a[p]+1:0;return}var u=l.$id||l.id;let d=fR.resolveUrl(c,u);var f=u?d:c;if(f){if(f.indexOf("#")<0&&(f+="#"),s[f]){if(!fR.deepCompareStrict(s[f],l))throw new Error("Schema <"+f+"> already exists with different definition");return s[f]}s[f]=l,f[f.length-1]=="#"&&(s[f.substring(0,f.length-1)]=l)}i(f+"/items",Array.isArray(l.items)?l.items:[l.items]),i(f+"/extends",Array.isArray(l.extends)?l.extends:[l.extends]),n(f+"/additionalItems",l.additionalItems),o(f+"/properties",l.properties),n(f+"/additionalProperties",l.additionalProperties),o(f+"/definitions",l.definitions),o(f+"/patternProperties",l.patternProperties),o(f+"/dependencies",l.dependencies),i(f+"/disallow",l.disallow),i(f+"/allOf",l.allOf),i(f+"/anyOf",l.anyOf),i(f+"/oneOf",l.oneOf),n(f+"/not",l.not)}function i(c,l){if(Array.isArray(l))for(var u=0;u{"use strict";var bG=yG(),us=cs(),vG=K_().scan,SG=us.ValidatorResult,Y_e=us.ValidatorResultError,Jf=us.SchemaError,wG=us.SchemaContext,X_e="/",Yt=function t(){this.customFormats=Object.create(t.prototype.customFormats),this.schemas={},this.unresolvedRefs=[],this.types=Object.create(Ii),this.attributes=Object.create(bG.validators)};Yt.prototype.customFormats={};Yt.prototype.schemas=null;Yt.prototype.types=null;Yt.prototype.attributes=null;Yt.prototype.unresolvedRefs=null;Yt.prototype.addSchema=function(e,r){var n=this;if(!e)return null;var i=vG(r||X_e,e),o=r||e.$id||e.id;for(var s in i.id)this.schemas[s]=i.id[s];for(var s in i.ref)this.unresolvedRefs.push(s);return this.unresolvedRefs=this.unresolvedRefs.filter(function(a){return typeof n.schemas[a]>"u"}),this.schemas[o]};Yt.prototype.addSubSchemaArray=function(e,r){if(Array.isArray(r))for(var n=0;n",e);var a=us.objectGetPath(n.schemas[s],o.substr(1));if(a===void 0)throw new Jf("no such schema "+o+" located in <"+s+">",e);return{subschema:a,switchSchema:r}};Yt.prototype.testType=function(e,r,n,i,o){if(o!==void 0){if(o===null)throw new Jf('Unexpected null in "type" keyword');if(typeof this.types[o]=="function")return this.types[o].call(this,e);if(o&&typeof o=="object"){var s=this.validateSchema(e,o,n,i);return s===void 0||!(s&&s.errors.length)}return!0}};var Ii=Yt.prototype.types={};Ii.string=function(e){return typeof e=="string"};Ii.number=function(e){return typeof e=="number"&&isFinite(e)};Ii.integer=function(e){return typeof e=="number"&&e%1===0};Ii.boolean=function(e){return typeof e=="boolean"};Ii.array=function(e){return Array.isArray(e)};Ii.null=function(e){return e===null};Ii.date=function(e){return e instanceof Date};Ii.any=function(e){return!0};Ii.object=function(e){return e&&typeof e=="object"&&!Array.isArray(e)&&!(e instanceof Date)};$G.exports=Yt});var EG=v((Aet,yo)=>{"use strict";var Q_e=yo.exports.Validator=kG();yo.exports.ValidatorResult=cs().ValidatorResult;yo.exports.ValidatorResultError=cs().ValidatorResultError;yo.exports.ValidationError=cs().ValidationError;yo.exports.SchemaError=cs().SchemaError;yo.exports.SchemaScanResult=K_().SchemaScanResult;yo.exports.scan=K_().scan;yo.exports.validate=function(t,e,r){var n=new Q_e;return n.validate(t,e,r)}});import{readFileSync as ebe}from"node:fs";import{dirname as tbe,join as rbe}from"node:path";import{fileURLToPath as nbe}from"node:url";function cbe(t){let e=abe.validate(t,sbe);return e.valid?{valid:!0,errors:[]}:{valid:!1,errors:e.errors.map(n=>`${n.property}: ${n.message}`)}}function OG(t){let e=cbe(t);if(!e.valid)throw new Error(`spec.yaml invalid: ${e.errors.join(` - `)}`)}var fG,b_e,v_e,S_e,w_e,mG=y(()=>{"use strict";fG=St(dG(),1),b_e=g_e(__e(import.meta.url)),v_e=y_e(b_e,"schema.json"),S_e=JSON.parse(h_e(v_e,"utf8")),w_e=new fG.Validator});import{existsSync as sR,readdirSync as $_e}from"node:fs";import{dirname as k_e,join as ka,resolve as gG}from"node:path";function hG(t){return sR(t)?$_e(t).filter(r=>r.endsWith(".yaml")||r.endsWith(".yml")).map(r=>Ri(ka(t,r))):[]}function Ea(t,e){V_=e?{cwd:gG(t),spec:e}:null}function q(t=".",e="spec.yaml"){return V_&&e==="spec.yaml"&&gG(t)===V_.cwd?V_.spec:E_e(t,e)}function E_e(t,e){let r=ka(t,e),n=Ri(r),i=ka(t,k_e(e),"spec");if(!n.features||n.features.length===0){let o=hG(ka(i,"features"));o.length>0&&(n.features=o)}if(!n.scenarios||n.scenarios.length===0){let o=hG(ka(i,"scenarios"));o.length>0&&(n.scenarios=o)}if(!n.architecture){let o=ka(i,"architecture.yaml");sR(o)&&(n.architecture=Ri(o))}if(!n.capabilities||n.capabilities.length===0){let o=ka(i,"capabilities.yaml");if(sR(o)){let s=Ri(o);s&&Array.isArray(s.capabilities)&&(n.capabilities=s.capabilities)}}return pG(n),n}var V_,Ue=y(()=>{"use strict";H_();mG();V_=null});import Sl from"node:process";function lR(){return!!Sl.stdout.isTTY}function L(t,e,r=""){let n=yG[t],i=r?` ${r}`:"";lR()?Sl.stdout.write(`${aR[t]}${n}${cR} ${e}${i} -`):Sl.stdout.write(`${n} ${e}${i} -`)}function Wf(t,e,r=""){if(!lR())return;let n=r?` ${r}`:"";Sl.stdout.write(`${_G}${aR.start}\xB7${cR} ${t} \xB7 ${e}${n}`)}function Aa(t,e,r=""){let n=yG[t],i=r?` ${r}`:"";lR()?Sl.stdout.write(`${_G}${aR[t]}${n}${cR} ${e}${i} -`):Sl.stdout.write(`${n} ${e}${i} -`)}var yG,aR,cR,_G,Pi=y(()=>{"use strict";yG={start:"\xB7",pass:"\u2713",fail:"\u2717",skip:"\xB7",note:"\u2139"},aR={start:"\x1B[90m",pass:"\x1B[32m",fail:"\x1B[31m",skip:"\x1B[90m",note:"\x1B[36m"},cR="\x1B[0m",_G="\r\x1B[K"});import{createHash as BG}from"node:crypto";import{existsSync as ube,readFileSync as fR,writeFileSync as dbe}from"node:fs";import{join as W_}from"node:path";function fbe(t,e){let r=BG("sha256");for(let n of[...e].sort()){r.update(n),r.update("\0");try{r.update(fR(W_(t,n)))}catch{r.update("")}r.update("\0")}return r.digest("hex").slice(0,16)}function GG(t,e){let r=BG("sha256");try{r.update(fR(W_(t,e)))}catch{r.update("")}return r.digest("hex").slice(0,16)}function ls(t){let e=W_(t,...HG);if(!ube(e))return null;let r;try{r=fR(e,"utf8")}catch{return null}let n=null,i=null,o=null,s="other";for(let a of r.split(` -`)){if(a==="attested:"){s="v1",n??=new Map;continue}if(a==="attested_modules:"){s="modules",i??=new Map;continue}if(a==="attested_features:"){s="features",o??=new Set;continue}if(!(a.startsWith("#")||a.trim()==="")){if(s==="v1"){let c=a.match(/^ {2}(F-[\w-]+): ([0-9a-f]{16})$/);c&&n.set(c[1],c[2])}else if(s==="modules"){let c=a.match(/^ {2}(.+): ([0-9a-f]{16})$/);c&&i.set(c[1],c[2])}else if(s==="features"){let c=a.match(/^ {2}(F-[\w-]+): ok$/);c&&o.add(c[1])}}}return{v1:n,modules:i,features:o}}function K_(t){return t.features?.size??t.v1?.size??0}function J_(t,e,r){let n=r.modules??[];if(t.modules!==null||t.features!==null){if(!t.features?.has(r.id))return{state:"unattested"};let o=t.modules??new Map;for(let s of[...n].sort())if(o.get(s)!==GG(e,s))return{state:"stale",module:s};return{state:"fresh"}}let i=t.v1?.get(r.id);return i===void 0?{state:"unattested"}:i===fbe(e,n)?{state:"fresh"}:{state:"stale"}}function ZG(t,e){let r=(e.features??[]).filter(a=>a.status==="done"&&(a.modules??[]).length>0);if(r.length===0)return!1;let n=new Set;for(let a of r)for(let c of a.modules??[])n.add(c);let i=[...n].sort().map(a=>` ${a}: ${GG(t,a)}`),o=r.map(a=>` ${a.id}: ok`).sort(),s=pbe+`attested_modules: -`+i.join(` + `)}`)}var AG,ibe,obe,sbe,abe,TG=y(()=>{"use strict";AG=wt(EG(),1),ibe=tbe(nbe(import.meta.url)),obe=rbe(ibe,"schema.json"),sbe=JSON.parse(ebe(obe,"utf8")),abe=new AG.Validator});import{existsSync as mR,readdirSync as lbe}from"node:fs";import{dirname as ube,join as Aa,resolve as IG}from"node:path";function RG(t){return mR(t)?lbe(t).filter(r=>r.endsWith(".yaml")||r.endsWith(".yml")).map(r=>Ri(Aa(t,r))):[]}function Oa(t,e){J_=e?{cwd:IG(t),spec:e}:null}function q(t=".",e="spec.yaml"){return J_&&e==="spec.yaml"&&IG(t)===J_.cwd?J_.spec:dbe(t,e)}function dbe(t,e){let r=Aa(t,e),n=Ri(r),i=Aa(t,ube(e),"spec");if(!n.features||n.features.length===0){let o=RG(Aa(i,"features"));o.length>0&&(n.features=o)}if(!n.scenarios||n.scenarios.length===0){let o=RG(Aa(i,"scenarios"));o.length>0&&(n.scenarios=o)}if(!n.architecture){let o=Aa(i,"architecture.yaml");mR(o)&&(n.architecture=Ri(o))}if(!n.capabilities||n.capabilities.length===0){let o=Aa(i,"capabilities.yaml");if(mR(o)){let s=Ri(o);s&&Array.isArray(s.capabilities)&&(n.capabilities=s.capabilities)}}return OG(n),n}var J_,Ue=y(()=>{"use strict";V_();TG();J_=null});import $l from"node:process";function yR(){return!!$l.stdout.isTTY}function L(t,e,r=""){let n=PG[t],i=r?` ${r}`:"";yR()?$l.stdout.write(`${hR[t]}${n}${gR} ${e}${i} +`):$l.stdout.write(`${n} ${e}${i} +`)}function Yf(t,e,r=""){if(!yR())return;let n=r?` ${r}`:"";$l.stdout.write(`${CG}${hR.start}\xB7${gR} ${t} \xB7 ${e}${n}`)}function Ta(t,e,r=""){let n=PG[t],i=r?` ${r}`:"";yR()?$l.stdout.write(`${CG}${hR[t]}${n}${gR} ${e}${i} +`):$l.stdout.write(`${n} ${e}${i} +`)}var PG,hR,gR,CG,Pi=y(()=>{"use strict";PG={start:"\xB7",pass:"\u2713",fail:"\u2717",skip:"\xB7",note:"\u2139"},hR={start:"\x1B[90m",pass:"\x1B[32m",fail:"\x1B[31m",skip:"\x1B[90m",note:"\x1B[36m"},gR="\x1B[0m",CG="\r\x1B[K"});import{createHash as vR}from"node:crypto";import{existsSync as Kbe,readFileSync as SR,writeFileSync as Jbe}from"node:fs";import{join as Y_}from"node:path";function oZ(t){let e=vR("sha256");return t.forEach((r,n)=>{e.update(`${n}\0${r.name}\0${r.subprocess===!0?"subprocess":"pure"} +`)}),e.digest("hex")}function Ybe(t,e){let r=vR("sha256");for(let n of[...e].sort()){r.update(n),r.update("\0");try{r.update(SR(Y_(t,n)))}catch{r.update("")}r.update("\0")}return r.digest("hex").slice(0,16)}function sZ(t,e){let r=vR("sha256");try{r.update(SR(Y_(t,e)))}catch{r.update("")}return r.digest("hex").slice(0,16)}function ds(t){let e=Y_(t,...iZ);if(!Kbe(e))return null;let r;try{r=SR(e,"utf8")}catch{return null}let n=null,i=null,o=null,s={},a="other";for(let l of r.split(` +`)){if(l==="policy:"){a="policy";continue}if(l==="attested:"){a="v1",n??=new Map;continue}if(l==="attested_modules:"){a="modules",i??=new Map;continue}if(l==="attested_features:"){a="features",o??=new Set;continue}if(!(l.startsWith("#")||l.trim()==="")){if(a==="policy"){let u=l.match(/^ {2}cladding: "([^"]+)"$/),d=l.match(/^ {2}blocking: (strict)$/),f=l.match(/^ {2}detectors_sha256: ([0-9a-f]{64})$/);u&&(s.cladding=u[1]),d&&(s.blocking=d[1]),f&&(s.detectorsSha256=f[1])}else if(a==="v1"){let u=l.match(/^ {2}(F-[\w-]+): ([0-9a-f]{16})$/);u&&n.set(u[1],u[2])}else if(a==="modules"){let u=l.match(/^ {2}(.+): ([0-9a-f]{16})$/);u&&i.set(u[1],u[2])}else if(a==="features"){let u=l.match(/^ {2}(F-[\w-]+): ok$/);u&&o.add(u[1])}}}return{policy:s.cladding!==void 0&&s.blocking==="strict"&&s.detectorsSha256!==void 0?{cladding:s.cladding,blocking:s.blocking,detectorsSha256:s.detectorsSha256}:null,v1:n,modules:i,features:o}}function X_(t){return t.features?.size??t.v1?.size??0}function Q_(t,e,r){let n=r.modules??[];if(t.modules!==null||t.features!==null){if(!t.features?.has(r.id))return{state:"unattested"};let o=t.modules??new Map;for(let s of[...n].sort())if(o.get(s)!==sZ(e,s))return{state:"stale",module:s};return{state:"fresh"}}let i=t.v1?.get(r.id);return i===void 0?{state:"unattested"}:i===Ybe(e,n)?{state:"fresh"}:{state:"stale"}}function aZ(t,e,r){let n=(e.features??[]).filter(c=>c.status==="done"&&(c.modules??[]).length>0);if(n.length===0)return!1;let i=new Set;for(let c of n)for(let l of c.modules??[])i.add(l);let o=[...i].sort().map(c=>` ${c}: ${sZ(t,c)}`),s=n.map(c=>` ${c.id}: ok`).sort(),a=Xbe+(r?`policy: + cladding: ${JSON.stringify(r.cladding)} + blocking: ${r.blocking} + detectors_sha256: ${r.detectorsSha256} +`:"")+`attested_modules: +`+o.join(` `)+` attested_features: -`+o.join(` +`+s.join(` `)+` -`;return dbe(W_(t,...HG),s,"utf8"),!0}var HG,pbe,xl=y(()=>{"use strict";HG=["spec","attestation.yaml"];pbe=`# Cladding \xB7 Tier C \u2014 verification attestation (v2). Written ONLY by a GREEN +`;return Jbe(Y_(t,...iZ),a,"utf8"),!0}var iZ,Xbe,El=y(()=>{"use strict";iZ=["spec","attestation.yaml"];Xbe=`# Cladding \xB7 Tier C \u2014 verification attestation (v2). Written ONLY by a GREEN # \`clad check --tier=pre-push --strict\` gate \u2014 the file's one honest author. # Do not edit by hand. # +# policy: verifier identity: Cladding version, strict blocking, +# and SHA-256 of the ordered detector catalog. # attested_modules: one line per module file across all done features, # value = sha256 of that file's bytes (16 hex). Editing a # file moves exactly its own line \u2014 not every co-owning @@ -212,55 +219,105 @@ attested_features: # Merge conflict here? NEVER hand-resolve the hashes \u2014 keep either side and run # \`clad check --tier=pre-push --strict\`; the GREEN gate rewrites the truth. # Content-anchored: survives fresh clones and squash/rebase. -`});import{resolve as pR}from"node:path";function Y_(t){us={cwd:pR(t),results:new Map}}function VG(t,e,r){!us||us.cwd!==pR(e)||us.results.set(t,r)}function X_(t,e){return!us||us.cwd!==pR(e)?null:us.results.get(t)??null}function Q_(){us=null}var us,$l=y(()=>{"use strict";us=null});function Ot(t){if(typeof t!="object"||t===null)return!1;let e=Object.getPrototypeOf(t);return(e===null||e===Object.prototype||Object.getPrototypeOf(e)===null)&&!(Symbol.toStringTag in t)&&!(Symbol.iterator in t)}var _o=y(()=>{});import{fileURLToPath as mbe}from"node:url";var kl,hbe,mR,hR,El=y(()=>{kl=(t,e)=>{let r=hR(hbe(t));if(typeof r!="string")throw new TypeError(`${e} must be a string or a file URL: ${r}.`);return r},hbe=t=>mR(t)?t.toString():t,mR=t=>typeof t!="string"&&t&&Object.getPrototypeOf(t)===String.prototype,hR=t=>t instanceof URL?mbe(t):t});var eb,gR=y(()=>{_o();El();eb=(t,e=[],r={})=>{let n=kl(t,"First argument"),[i,o]=Ot(e)?[[],e]:[e,r];if(!Array.isArray(i))throw new TypeError(`Second argument must be either an array of arguments or an options object: ${i}`);if(i.some(c=>typeof c=="object"&&c!==null))throw new TypeError(`Second argument must be an array of strings: ${i}`);let s=i.map(String),a=s.find(c=>c.includes("\0"));if(a!==void 0)throw new TypeError(`Arguments cannot contain null bytes ("\\0"): ${a}`);if(!Ot(o))throw new TypeError(`Last argument must be an options object: ${o}`);return[n,s,o]}});import{StringDecoder as gbe}from"node:string_decoder";var WG,KG,qt,bo,ybe,JG,_be,tb,YG,bbe,Jf,vbe,yR,Sbe,sn=y(()=>{({toString:WG}=Object.prototype),KG=t=>WG.call(t)==="[object ArrayBuffer]",qt=t=>WG.call(t)==="[object Uint8Array]",bo=t=>new Uint8Array(t.buffer,t.byteOffset,t.byteLength),ybe=new TextEncoder,JG=t=>ybe.encode(t),_be=new TextDecoder,tb=t=>_be.decode(t),YG=(t,e)=>bbe(t,e).join(""),bbe=(t,e)=>{if(e==="utf8"&&t.every(o=>typeof o=="string"))return t;let r=new gbe(e),n=t.map(o=>typeof o=="string"?JG(o):o).map(o=>r.write(o)),i=r.end();return i===""?n:[...n,i]},Jf=t=>t.length===1&&qt(t[0])?t[0]:yR(vbe(t)),vbe=t=>t.map(e=>typeof e=="string"?JG(e):e),yR=t=>{let e=new Uint8Array(Sbe(t)),r=0;for(let n of t)e.set(n,r),r+=n.length;return e},Sbe=t=>{let e=0;for(let r of t)e+=r.length;return e}});import{ChildProcess as wbe}from"node:child_process";var tZ,rZ,xbe,$be,XG,kbe,QG,eZ,Ebe,nZ=y(()=>{_o();sn();tZ=t=>Array.isArray(t)&&Array.isArray(t.raw),rZ=(t,e)=>{let r=[];for(let[o,s]of t.entries())r=xbe({templates:t,expressions:e,tokens:r,index:o,template:s});if(r.length===0)throw new TypeError("Template script must not be empty");let[n,...i]=r;return[n,i,{}]},xbe=({templates:t,expressions:e,tokens:r,index:n,template:i})=>{if(i===void 0)throw new TypeError(`Invalid backslash sequence: ${t.raw[n]}`);let{nextTokens:o,leadingWhitespaces:s,trailingWhitespaces:a}=$be(i,t.raw[n]),c=QG(r,o,s);if(n===e.length)return c;let l=e[n],u=Array.isArray(l)?l.map(d=>eZ(d)):[eZ(l)];return QG(c,u,a)},$be=(t,e)=>{if(e.length===0)return{nextTokens:[],leadingWhitespaces:!1,trailingWhitespaces:!1};let r=[],n=0,i=XG.has(e[0]);for(let s=0,a=0;sr||t.length===0||e.length===0?[...t,...e]:[...t.slice(0,-1),`${t.at(-1)}${e[0]}`,...e.slice(1)],eZ=t=>{let e=typeof t;if(e==="string")return t;if(e==="number")return String(t);if(Ot(t)&&("stdout"in t||"isMaxBuffer"in t))return Ebe(t);throw t instanceof wbe||Object.prototype.toString.call(t)==="[object Promise]"?new TypeError("Unexpected subprocess in template expression. Please use ${await subprocess} instead of ${subprocess}."):new TypeError(`Unexpected "${e}" in template expression`)},Ebe=({stdout:t})=>{if(typeof t=="string")return t;if(qt(t))return tb(t);throw t===void 0?new TypeError(`Missing result.stdout in template expression. This is probably due to the previous subprocess' "stdout" option.`):new TypeError(`Unexpected "${typeof t}" stdout in template expression`)}});import _R from"node:process";var ti,rb,In,nb,vo=y(()=>{ti=t=>rb.includes(t),rb=[_R.stdin,_R.stdout,_R.stderr],In=["stdin","stdout","stderr"],nb=t=>In[t]??`stdio[${t}]`});import{debuglog as Abe}from"node:util";var oZ,bR,Tbe,Obe,Rbe,Ibe,iZ,Pbe,vR,Cbe,Dbe,Nbe,jbe,SR,So,wo=y(()=>{_o();vo();oZ=t=>{let e={...t};for(let r of SR)e[r]=bR(t,r);return e},bR=(t,e)=>{let r=Array.from({length:Tbe(t)+1}),n=Obe(t[e],r,e);return Dbe(n,e)},Tbe=({stdio:t})=>Array.isArray(t)?Math.max(t.length,In.length):In.length,Obe=(t,e,r)=>Ot(t)?Rbe(t,e,r):e.fill(t),Rbe=(t,e,r)=>{for(let n of Object.keys(t).sort(Ibe))for(let i of Pbe(n,r,e))e[i]=t[n];return e},Ibe=(t,e)=>iZ(t)t==="stdout"||t==="stderr"?0:t==="all"?2:1,Pbe=(t,e,r)=>{if(t==="ipc")return[r.length-1];let n=vR(t);if(n===void 0||n===0)throw new TypeError(`"${e}.${t}" is invalid. +`});import{resolve as wR}from"node:path";function eb(t){fs={cwd:wR(t),results:new Map}}function cZ(t,e,r){!fs||fs.cwd!==wR(e)||fs.results.set(t,r)}function tb(t,e){return!fs||fs.cwd!==wR(e)?null:fs.results.get(t)??null}function rb(){fs=null}var fs,Al=y(()=>{"use strict";fs=null});function Tt(t){if(typeof t!="object"||t===null)return!1;let e=Object.getPrototypeOf(t);return(e===null||e===Object.prototype||Object.getPrototypeOf(e)===null)&&!(Symbol.toStringTag in t)&&!(Symbol.iterator in t)}var bo=y(()=>{});import{fileURLToPath as Qbe}from"node:url";var Ol,eve,xR,$R,Tl=y(()=>{Ol=(t,e)=>{let r=$R(eve(t));if(typeof r!="string")throw new TypeError(`${e} must be a string or a file URL: ${r}.`);return r},eve=t=>xR(t)?t.toString():t,xR=t=>typeof t!="string"&&t&&Object.getPrototypeOf(t)===String.prototype,$R=t=>t instanceof URL?Qbe(t):t});var nb,kR=y(()=>{bo();Tl();nb=(t,e=[],r={})=>{let n=Ol(t,"First argument"),[i,o]=Tt(e)?[[],e]:[e,r];if(!Array.isArray(i))throw new TypeError(`Second argument must be either an array of arguments or an options object: ${i}`);if(i.some(c=>typeof c=="object"&&c!==null))throw new TypeError(`Second argument must be an array of strings: ${i}`);let s=i.map(String),a=s.find(c=>c.includes("\0"));if(a!==void 0)throw new TypeError(`Arguments cannot contain null bytes ("\\0"): ${a}`);if(!Tt(o))throw new TypeError(`Last argument must be an options object: ${o}`);return[n,s,o]}});import{StringDecoder as tve}from"node:string_decoder";var lZ,uZ,qt,vo,rve,dZ,nve,ib,fZ,ive,Qf,ove,ER,sve,an=y(()=>{({toString:lZ}=Object.prototype),uZ=t=>lZ.call(t)==="[object ArrayBuffer]",qt=t=>lZ.call(t)==="[object Uint8Array]",vo=t=>new Uint8Array(t.buffer,t.byteOffset,t.byteLength),rve=new TextEncoder,dZ=t=>rve.encode(t),nve=new TextDecoder,ib=t=>nve.decode(t),fZ=(t,e)=>ive(t,e).join(""),ive=(t,e)=>{if(e==="utf8"&&t.every(o=>typeof o=="string"))return t;let r=new tve(e),n=t.map(o=>typeof o=="string"?dZ(o):o).map(o=>r.write(o)),i=r.end();return i===""?n:[...n,i]},Qf=t=>t.length===1&&qt(t[0])?t[0]:ER(ove(t)),ove=t=>t.map(e=>typeof e=="string"?dZ(e):e),ER=t=>{let e=new Uint8Array(sve(t)),r=0;for(let n of t)e.set(n,r),r+=n.length;return e},sve=t=>{let e=0;for(let r of t)e+=r.length;return e}});import{ChildProcess as ave}from"node:child_process";var gZ,yZ,cve,lve,pZ,uve,mZ,hZ,dve,_Z=y(()=>{bo();an();gZ=t=>Array.isArray(t)&&Array.isArray(t.raw),yZ=(t,e)=>{let r=[];for(let[o,s]of t.entries())r=cve({templates:t,expressions:e,tokens:r,index:o,template:s});if(r.length===0)throw new TypeError("Template script must not be empty");let[n,...i]=r;return[n,i,{}]},cve=({templates:t,expressions:e,tokens:r,index:n,template:i})=>{if(i===void 0)throw new TypeError(`Invalid backslash sequence: ${t.raw[n]}`);let{nextTokens:o,leadingWhitespaces:s,trailingWhitespaces:a}=lve(i,t.raw[n]),c=mZ(r,o,s);if(n===e.length)return c;let l=e[n],u=Array.isArray(l)?l.map(d=>hZ(d)):[hZ(l)];return mZ(c,u,a)},lve=(t,e)=>{if(e.length===0)return{nextTokens:[],leadingWhitespaces:!1,trailingWhitespaces:!1};let r=[],n=0,i=pZ.has(e[0]);for(let s=0,a=0;sr||t.length===0||e.length===0?[...t,...e]:[...t.slice(0,-1),`${t.at(-1)}${e[0]}`,...e.slice(1)],hZ=t=>{let e=typeof t;if(e==="string")return t;if(e==="number")return String(t);if(Tt(t)&&("stdout"in t||"isMaxBuffer"in t))return dve(t);throw t instanceof ave||Object.prototype.toString.call(t)==="[object Promise]"?new TypeError("Unexpected subprocess in template expression. Please use ${await subprocess} instead of ${subprocess}."):new TypeError(`Unexpected "${e}" in template expression`)},dve=({stdout:t})=>{if(typeof t=="string")return t;if(qt(t))return ib(t);throw t===void 0?new TypeError(`Missing result.stdout in template expression. This is probably due to the previous subprocess' "stdout" option.`):new TypeError(`Unexpected "${typeof t}" stdout in template expression`)}});import AR from"node:process";var ri,ob,Pn,sb,So=y(()=>{ri=t=>ob.includes(t),ob=[AR.stdin,AR.stdout,AR.stderr],Pn=["stdin","stdout","stderr"],sb=t=>Pn[t]??`stdio[${t}]`});import{debuglog as fve}from"node:util";var vZ,OR,pve,mve,hve,gve,bZ,yve,TR,_ve,bve,vve,Sve,RR,wo,xo=y(()=>{bo();So();vZ=t=>{let e={...t};for(let r of RR)e[r]=OR(t,r);return e},OR=(t,e)=>{let r=Array.from({length:pve(t)+1}),n=mve(t[e],r,e);return bve(n,e)},pve=({stdio:t})=>Array.isArray(t)?Math.max(t.length,Pn.length):Pn.length,mve=(t,e,r)=>Tt(t)?hve(t,e,r):e.fill(t),hve=(t,e,r)=>{for(let n of Object.keys(t).sort(gve))for(let i of yve(n,r,e))e[i]=t[n];return e},gve=(t,e)=>bZ(t)t==="stdout"||t==="stderr"?0:t==="all"?2:1,yve=(t,e,r)=>{if(t==="ipc")return[r.length-1];let n=TR(t);if(n===void 0||n===0)throw new TypeError(`"${e}.${t}" is invalid. It must be "${e}.stdout", "${e}.stderr", "${e}.all", "${e}.ipc", or "${e}.fd3", "${e}.fd4" (and so on).`);if(n>=r.length)throw new TypeError(`"${e}.${t}" is invalid: that file descriptor does not exist. -Please set the "stdio" option to ensure that file descriptor exists.`);return n==="all"?[1,2]:[n]},vR=t=>{if(t==="all")return t;if(In.includes(t))return In.indexOf(t);let e=Cbe.exec(t);if(e!==null)return Number(e[1])},Cbe=/^fd(\d+)$/,Dbe=(t,e)=>t.map(r=>r===void 0?jbe[e]:r),Nbe=Abe("execa").enabled?"full":"none",jbe={lines:!1,buffer:!0,maxBuffer:1e3*1e3*100,verbose:Nbe,stripFinalNewline:!0},SR=["lines","buffer","maxBuffer","verbose","stripFinalNewline"],So=(t,e)=>e==="ipc"?t.at(-1):t[e]});var Al,Tl,sZ,wR,Mbe,ib,ob,ds=y(()=>{wo();Al=({verbose:t},e)=>wR(t,e)!=="none",Tl=({verbose:t},e)=>!["none","short"].includes(wR(t,e)),sZ=({verbose:t},e)=>{let r=wR(t,e);return ib(r)?r:void 0},wR=(t,e)=>e===void 0?Mbe(t):So(t,e),Mbe=t=>t.find(e=>ib(e))??ob.findLast(e=>t.includes(e)),ib=t=>typeof t=="function",ob=["none","short","full"]});import{platform as Fbe}from"node:process";import{stripVTControlCharacters as Lbe}from"node:util";var aZ,Yf,cZ,zbe,Ube,qbe,Bbe,Hbe,Gbe,Zbe,sb=y(()=>{aZ=(t,e)=>{let r=[t,...e],n=r.join(" "),i=r.map(o=>Gbe(cZ(o))).join(" ");return{command:n,escapedCommand:i}},Yf=t=>Lbe(t).split(` -`).map(e=>cZ(e)).join(` -`),cZ=t=>t.replaceAll(qbe,e=>zbe(e)),zbe=t=>{let e=Bbe[t];if(e!==void 0)return e;let r=t.codePointAt(0),n=r.toString(16);return r<=Hbe?`\\u${n.padStart(4,"0")}`:`\\U${n}`},Ube=()=>{try{return new RegExp("\\p{Separator}|\\p{Other}","gu")}catch{return/[\s\u0000-\u001F\u007F-\u009F\u00AD]/g}},qbe=Ube(),Bbe={" ":" ","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r"," ":"\\t"},Hbe=65535,Gbe=t=>Zbe.test(t)?t:Fbe==="win32"?`"${t.replaceAll('"','""')}"`:`'${t.replaceAll("'","'\\''")}'`,Zbe=/^[\w./-]+$/});import lZ from"node:process";function xR(){let{env:t}=lZ,{TERM:e,TERM_PROGRAM:r}=t;return lZ.platform!=="win32"?e!=="linux":!!t.WT_SESSION||!!t.TERMINUS_SUBLIME||t.ConEmuTask==="{cmd::Cmder}"||r==="Terminus-Sublime"||r==="vscode"||e==="xterm-256color"||e==="alacritty"||e==="rxvt-unicode"||e==="rxvt-unicode-256color"||t.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var uZ=y(()=>{});var dZ,fZ,Vbe,Wbe,Kbe,Jbe,Ybe,ab,tet,pZ=y(()=>{uZ();dZ={circleQuestionMark:"(?)",questionMarkPrefix:"(?)",square:"\u2588",squareDarkShade:"\u2593",squareMediumShade:"\u2592",squareLightShade:"\u2591",squareTop:"\u2580",squareBottom:"\u2584",squareLeft:"\u258C",squareRight:"\u2590",squareCenter:"\u25A0",bullet:"\u25CF",dot:"\u2024",ellipsis:"\u2026",pointerSmall:"\u203A",triangleUp:"\u25B2",triangleUpSmall:"\u25B4",triangleDown:"\u25BC",triangleDownSmall:"\u25BE",triangleLeftSmall:"\u25C2",triangleRightSmall:"\u25B8",home:"\u2302",heart:"\u2665",musicNote:"\u266A",musicNoteBeamed:"\u266B",arrowUp:"\u2191",arrowDown:"\u2193",arrowLeft:"\u2190",arrowRight:"\u2192",arrowLeftRight:"\u2194",arrowUpDown:"\u2195",almostEqual:"\u2248",notEqual:"\u2260",lessOrEqual:"\u2264",greaterOrEqual:"\u2265",identical:"\u2261",infinity:"\u221E",subscriptZero:"\u2080",subscriptOne:"\u2081",subscriptTwo:"\u2082",subscriptThree:"\u2083",subscriptFour:"\u2084",subscriptFive:"\u2085",subscriptSix:"\u2086",subscriptSeven:"\u2087",subscriptEight:"\u2088",subscriptNine:"\u2089",oneHalf:"\xBD",oneThird:"\u2153",oneQuarter:"\xBC",oneFifth:"\u2155",oneSixth:"\u2159",oneEighth:"\u215B",twoThirds:"\u2154",twoFifths:"\u2156",threeQuarters:"\xBE",threeFifths:"\u2157",threeEighths:"\u215C",fourFifths:"\u2158",fiveSixths:"\u215A",fiveEighths:"\u215D",sevenEighths:"\u215E",line:"\u2500",lineBold:"\u2501",lineDouble:"\u2550",lineDashed0:"\u2504",lineDashed1:"\u2505",lineDashed2:"\u2508",lineDashed3:"\u2509",lineDashed4:"\u254C",lineDashed5:"\u254D",lineDashed6:"\u2574",lineDashed7:"\u2576",lineDashed8:"\u2578",lineDashed9:"\u257A",lineDashed10:"\u257C",lineDashed11:"\u257E",lineDashed12:"\u2212",lineDashed13:"\u2013",lineDashed14:"\u2010",lineDashed15:"\u2043",lineVertical:"\u2502",lineVerticalBold:"\u2503",lineVerticalDouble:"\u2551",lineVerticalDashed0:"\u2506",lineVerticalDashed1:"\u2507",lineVerticalDashed2:"\u250A",lineVerticalDashed3:"\u250B",lineVerticalDashed4:"\u254E",lineVerticalDashed5:"\u254F",lineVerticalDashed6:"\u2575",lineVerticalDashed7:"\u2577",lineVerticalDashed8:"\u2579",lineVerticalDashed9:"\u257B",lineVerticalDashed10:"\u257D",lineVerticalDashed11:"\u257F",lineDownLeft:"\u2510",lineDownLeftArc:"\u256E",lineDownBoldLeftBold:"\u2513",lineDownBoldLeft:"\u2512",lineDownLeftBold:"\u2511",lineDownDoubleLeftDouble:"\u2557",lineDownDoubleLeft:"\u2556",lineDownLeftDouble:"\u2555",lineDownRight:"\u250C",lineDownRightArc:"\u256D",lineDownBoldRightBold:"\u250F",lineDownBoldRight:"\u250E",lineDownRightBold:"\u250D",lineDownDoubleRightDouble:"\u2554",lineDownDoubleRight:"\u2553",lineDownRightDouble:"\u2552",lineUpLeft:"\u2518",lineUpLeftArc:"\u256F",lineUpBoldLeftBold:"\u251B",lineUpBoldLeft:"\u251A",lineUpLeftBold:"\u2519",lineUpDoubleLeftDouble:"\u255D",lineUpDoubleLeft:"\u255C",lineUpLeftDouble:"\u255B",lineUpRight:"\u2514",lineUpRightArc:"\u2570",lineUpBoldRightBold:"\u2517",lineUpBoldRight:"\u2516",lineUpRightBold:"\u2515",lineUpDoubleRightDouble:"\u255A",lineUpDoubleRight:"\u2559",lineUpRightDouble:"\u2558",lineUpDownLeft:"\u2524",lineUpBoldDownBoldLeftBold:"\u252B",lineUpBoldDownBoldLeft:"\u2528",lineUpDownLeftBold:"\u2525",lineUpBoldDownLeftBold:"\u2529",lineUpDownBoldLeftBold:"\u252A",lineUpDownBoldLeft:"\u2527",lineUpBoldDownLeft:"\u2526",lineUpDoubleDownDoubleLeftDouble:"\u2563",lineUpDoubleDownDoubleLeft:"\u2562",lineUpDownLeftDouble:"\u2561",lineUpDownRight:"\u251C",lineUpBoldDownBoldRightBold:"\u2523",lineUpBoldDownBoldRight:"\u2520",lineUpDownRightBold:"\u251D",lineUpBoldDownRightBold:"\u2521",lineUpDownBoldRightBold:"\u2522",lineUpDownBoldRight:"\u251F",lineUpBoldDownRight:"\u251E",lineUpDoubleDownDoubleRightDouble:"\u2560",lineUpDoubleDownDoubleRight:"\u255F",lineUpDownRightDouble:"\u255E",lineDownLeftRight:"\u252C",lineDownBoldLeftBoldRightBold:"\u2533",lineDownLeftBoldRightBold:"\u252F",lineDownBoldLeftRight:"\u2530",lineDownBoldLeftBoldRight:"\u2531",lineDownBoldLeftRightBold:"\u2532",lineDownLeftRightBold:"\u252E",lineDownLeftBoldRight:"\u252D",lineDownDoubleLeftDoubleRightDouble:"\u2566",lineDownDoubleLeftRight:"\u2565",lineDownLeftDoubleRightDouble:"\u2564",lineUpLeftRight:"\u2534",lineUpBoldLeftBoldRightBold:"\u253B",lineUpLeftBoldRightBold:"\u2537",lineUpBoldLeftRight:"\u2538",lineUpBoldLeftBoldRight:"\u2539",lineUpBoldLeftRightBold:"\u253A",lineUpLeftRightBold:"\u2536",lineUpLeftBoldRight:"\u2535",lineUpDoubleLeftDoubleRightDouble:"\u2569",lineUpDoubleLeftRight:"\u2568",lineUpLeftDoubleRightDouble:"\u2567",lineUpDownLeftRight:"\u253C",lineUpBoldDownBoldLeftBoldRightBold:"\u254B",lineUpDownBoldLeftBoldRightBold:"\u2548",lineUpBoldDownLeftBoldRightBold:"\u2547",lineUpBoldDownBoldLeftRightBold:"\u254A",lineUpBoldDownBoldLeftBoldRight:"\u2549",lineUpBoldDownLeftRight:"\u2540",lineUpDownBoldLeftRight:"\u2541",lineUpDownLeftBoldRight:"\u253D",lineUpDownLeftRightBold:"\u253E",lineUpBoldDownBoldLeftRight:"\u2542",lineUpDownLeftBoldRightBold:"\u253F",lineUpBoldDownLeftBoldRight:"\u2543",lineUpBoldDownLeftRightBold:"\u2544",lineUpDownBoldLeftBoldRight:"\u2545",lineUpDownBoldLeftRightBold:"\u2546",lineUpDoubleDownDoubleLeftDoubleRightDouble:"\u256C",lineUpDoubleDownDoubleLeftRight:"\u256B",lineUpDownLeftDoubleRightDouble:"\u256A",lineCross:"\u2573",lineBackslash:"\u2572",lineSlash:"\u2571"},fZ={tick:"\u2714",info:"\u2139",warning:"\u26A0",cross:"\u2718",squareSmall:"\u25FB",squareSmallFilled:"\u25FC",circle:"\u25EF",circleFilled:"\u25C9",circleDotted:"\u25CC",circleDouble:"\u25CE",circleCircle:"\u24DE",circleCross:"\u24E7",circlePipe:"\u24BE",radioOn:"\u25C9",radioOff:"\u25EF",checkboxOn:"\u2612",checkboxOff:"\u2610",checkboxCircleOn:"\u24E7",checkboxCircleOff:"\u24BE",pointer:"\u276F",triangleUpOutline:"\u25B3",triangleLeft:"\u25C0",triangleRight:"\u25B6",lozenge:"\u25C6",lozengeOutline:"\u25C7",hamburger:"\u2630",smiley:"\u32E1",mustache:"\u0DF4",star:"\u2605",play:"\u25B6",nodejs:"\u2B22",oneSeventh:"\u2150",oneNinth:"\u2151",oneTenth:"\u2152"},Vbe={tick:"\u221A",info:"i",warning:"\u203C",cross:"\xD7",squareSmall:"\u25A1",squareSmallFilled:"\u25A0",circle:"( )",circleFilled:"(*)",circleDotted:"( )",circleDouble:"( )",circleCircle:"(\u25CB)",circleCross:"(\xD7)",circlePipe:"(\u2502)",radioOn:"(*)",radioOff:"( )",checkboxOn:"[\xD7]",checkboxOff:"[ ]",checkboxCircleOn:"(\xD7)",checkboxCircleOff:"( )",pointer:">",triangleUpOutline:"\u2206",triangleLeft:"\u25C4",triangleRight:"\u25BA",lozenge:"\u2666",lozengeOutline:"\u25CA",hamburger:"\u2261",smiley:"\u263A",mustache:"\u250C\u2500\u2510",star:"\u2736",play:"\u25BA",nodejs:"\u2666",oneSeventh:"1/7",oneNinth:"1/9",oneTenth:"1/10"},Wbe={...dZ,...fZ},Kbe={...dZ,...Vbe},Jbe=xR(),Ybe=Jbe?Wbe:Kbe,ab=Ybe,tet=Object.entries(fZ)});import Xbe from"node:tty";var Qbe,be,iet,mZ,oet,set,aet,cet,uet,det,fet,pet,met,het,get,yet,_et,bet,vet,cb,wet,xet,$et,ket,Eet,Aet,Tet,Oet,Ret,hZ,Iet,gZ,Pet,Cet,Det,Net,jet,Met,Fet,Let,zet,Uet,qet,$R=y(()=>{Qbe=Xbe?.WriteStream?.prototype?.hasColors?.()??!1,be=(t,e)=>{if(!Qbe)return i=>i;let r=`\x1B[${t}m`,n=`\x1B[${e}m`;return i=>{let o=i+"",s=o.indexOf(n);if(s===-1)return r+o+n;let a=r,c=0,u=(e===22?n:"")+r;for(;s!==-1;)a+=o.slice(c,s)+u,c=s+n.length,s=o.indexOf(n,c);return a+=o.slice(c)+n,a}},iet=be(0,0),mZ=be(1,22),oet=be(2,22),set=be(3,23),aet=be(4,24),cet=be(53,55),uet=be(7,27),det=be(8,28),fet=be(9,29),pet=be(30,39),met=be(31,39),het=be(32,39),get=be(33,39),yet=be(34,39),_et=be(35,39),bet=be(36,39),vet=be(37,39),cb=be(90,39),wet=be(40,49),xet=be(41,49),$et=be(42,49),ket=be(43,49),Eet=be(44,49),Aet=be(45,49),Tet=be(46,49),Oet=be(47,49),Ret=be(100,49),hZ=be(91,39),Iet=be(92,39),gZ=be(93,39),Pet=be(94,39),Cet=be(95,39),Det=be(96,39),Net=be(97,39),jet=be(101,49),Met=be(102,49),Fet=be(103,49),Let=be(104,49),zet=be(105,49),Uet=be(106,49),qet=be(107,49)});var yZ=y(()=>{$R();$R()});var vZ,tve,lb,_Z,rve,bZ,nve,SZ=y(()=>{pZ();yZ();vZ=({type:t,message:e,timestamp:r,piped:n,commandId:i,result:{failed:o=!1}={},options:{reject:s=!0}})=>{let a=tve(r),c=rve[t]({failed:o,reject:s,piped:n}),l=nve[t]({reject:s});return`${cb(`[${a}]`)} ${cb(`[${i}]`)} ${l(c)} ${l(e)}`},tve=t=>`${lb(t.getHours(),2)}:${lb(t.getMinutes(),2)}:${lb(t.getSeconds(),2)}.${lb(t.getMilliseconds(),3)}`,lb=(t,e)=>String(t).padStart(e,"0"),_Z=({failed:t,reject:e})=>t?e?ab.cross:ab.warning:ab.tick,rve={command:({piped:t})=>t?"|":"$",output:()=>" ",ipc:()=>"*",error:_Z,duration:_Z},bZ=t=>t,nve={command:()=>mZ,output:()=>bZ,ipc:()=>bZ,error:({reject:t})=>t?hZ:gZ,duration:()=>cb}});var wZ,ive,ove,xZ=y(()=>{ds();wZ=(t,e,r)=>{let n=sZ(e,r);return t.map(({verboseLine:i,verboseObject:o})=>ive(i,o,n)).filter(i=>i!==void 0).map(i=>ove(i)).join("")},ive=(t,e,r)=>{if(r===void 0)return t;let n=r(t,e);if(typeof n=="string")return n},ove=t=>t.endsWith(` +Please set the "stdio" option to ensure that file descriptor exists.`);return n==="all"?[1,2]:[n]},TR=t=>{if(t==="all")return t;if(Pn.includes(t))return Pn.indexOf(t);let e=_ve.exec(t);if(e!==null)return Number(e[1])},_ve=/^fd(\d+)$/,bve=(t,e)=>t.map(r=>r===void 0?Sve[e]:r),vve=fve("execa").enabled?"full":"none",Sve={lines:!1,buffer:!0,maxBuffer:1e3*1e3*100,verbose:vve,stripFinalNewline:!0},RR=["lines","buffer","maxBuffer","verbose","stripFinalNewline"],wo=(t,e)=>e==="ipc"?t.at(-1):t[e]});var Rl,Il,SZ,IR,wve,ab,cb,ps=y(()=>{xo();Rl=({verbose:t},e)=>IR(t,e)!=="none",Il=({verbose:t},e)=>!["none","short"].includes(IR(t,e)),SZ=({verbose:t},e)=>{let r=IR(t,e);return ab(r)?r:void 0},IR=(t,e)=>e===void 0?wve(t):wo(t,e),wve=t=>t.find(e=>ab(e))??cb.findLast(e=>t.includes(e)),ab=t=>typeof t=="function",cb=["none","short","full"]});import{platform as xve}from"node:process";import{stripVTControlCharacters as $ve}from"node:util";var wZ,ep,xZ,kve,Eve,Ave,Ove,Tve,Rve,Ive,lb=y(()=>{wZ=(t,e)=>{let r=[t,...e],n=r.join(" "),i=r.map(o=>Rve(xZ(o))).join(" ");return{command:n,escapedCommand:i}},ep=t=>$ve(t).split(` +`).map(e=>xZ(e)).join(` +`),xZ=t=>t.replaceAll(Ave,e=>kve(e)),kve=t=>{let e=Ove[t];if(e!==void 0)return e;let r=t.codePointAt(0),n=r.toString(16);return r<=Tve?`\\u${n.padStart(4,"0")}`:`\\U${n}`},Eve=()=>{try{return new RegExp("\\p{Separator}|\\p{Other}","gu")}catch{return/[\s\u0000-\u001F\u007F-\u009F\u00AD]/g}},Ave=Eve(),Ove={" ":" ","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r"," ":"\\t"},Tve=65535,Rve=t=>Ive.test(t)?t:xve==="win32"?`"${t.replaceAll('"','""')}"`:`'${t.replaceAll("'","'\\''")}'`,Ive=/^[\w./-]+$/});import $Z from"node:process";function PR(){let{env:t}=$Z,{TERM:e,TERM_PROGRAM:r}=t;return $Z.platform!=="win32"?e!=="linux":!!t.WT_SESSION||!!t.TERMINUS_SUBLIME||t.ConEmuTask==="{cmd::Cmder}"||r==="Terminus-Sublime"||r==="vscode"||e==="xterm-256color"||e==="alacritty"||e==="rxvt-unicode"||e==="rxvt-unicode-256color"||t.TERMINAL_EMULATOR==="JetBrains-JediTerm"}var kZ=y(()=>{});var EZ,AZ,Pve,Cve,Dve,Nve,jve,ub,Dtt,OZ=y(()=>{kZ();EZ={circleQuestionMark:"(?)",questionMarkPrefix:"(?)",square:"\u2588",squareDarkShade:"\u2593",squareMediumShade:"\u2592",squareLightShade:"\u2591",squareTop:"\u2580",squareBottom:"\u2584",squareLeft:"\u258C",squareRight:"\u2590",squareCenter:"\u25A0",bullet:"\u25CF",dot:"\u2024",ellipsis:"\u2026",pointerSmall:"\u203A",triangleUp:"\u25B2",triangleUpSmall:"\u25B4",triangleDown:"\u25BC",triangleDownSmall:"\u25BE",triangleLeftSmall:"\u25C2",triangleRightSmall:"\u25B8",home:"\u2302",heart:"\u2665",musicNote:"\u266A",musicNoteBeamed:"\u266B",arrowUp:"\u2191",arrowDown:"\u2193",arrowLeft:"\u2190",arrowRight:"\u2192",arrowLeftRight:"\u2194",arrowUpDown:"\u2195",almostEqual:"\u2248",notEqual:"\u2260",lessOrEqual:"\u2264",greaterOrEqual:"\u2265",identical:"\u2261",infinity:"\u221E",subscriptZero:"\u2080",subscriptOne:"\u2081",subscriptTwo:"\u2082",subscriptThree:"\u2083",subscriptFour:"\u2084",subscriptFive:"\u2085",subscriptSix:"\u2086",subscriptSeven:"\u2087",subscriptEight:"\u2088",subscriptNine:"\u2089",oneHalf:"\xBD",oneThird:"\u2153",oneQuarter:"\xBC",oneFifth:"\u2155",oneSixth:"\u2159",oneEighth:"\u215B",twoThirds:"\u2154",twoFifths:"\u2156",threeQuarters:"\xBE",threeFifths:"\u2157",threeEighths:"\u215C",fourFifths:"\u2158",fiveSixths:"\u215A",fiveEighths:"\u215D",sevenEighths:"\u215E",line:"\u2500",lineBold:"\u2501",lineDouble:"\u2550",lineDashed0:"\u2504",lineDashed1:"\u2505",lineDashed2:"\u2508",lineDashed3:"\u2509",lineDashed4:"\u254C",lineDashed5:"\u254D",lineDashed6:"\u2574",lineDashed7:"\u2576",lineDashed8:"\u2578",lineDashed9:"\u257A",lineDashed10:"\u257C",lineDashed11:"\u257E",lineDashed12:"\u2212",lineDashed13:"\u2013",lineDashed14:"\u2010",lineDashed15:"\u2043",lineVertical:"\u2502",lineVerticalBold:"\u2503",lineVerticalDouble:"\u2551",lineVerticalDashed0:"\u2506",lineVerticalDashed1:"\u2507",lineVerticalDashed2:"\u250A",lineVerticalDashed3:"\u250B",lineVerticalDashed4:"\u254E",lineVerticalDashed5:"\u254F",lineVerticalDashed6:"\u2575",lineVerticalDashed7:"\u2577",lineVerticalDashed8:"\u2579",lineVerticalDashed9:"\u257B",lineVerticalDashed10:"\u257D",lineVerticalDashed11:"\u257F",lineDownLeft:"\u2510",lineDownLeftArc:"\u256E",lineDownBoldLeftBold:"\u2513",lineDownBoldLeft:"\u2512",lineDownLeftBold:"\u2511",lineDownDoubleLeftDouble:"\u2557",lineDownDoubleLeft:"\u2556",lineDownLeftDouble:"\u2555",lineDownRight:"\u250C",lineDownRightArc:"\u256D",lineDownBoldRightBold:"\u250F",lineDownBoldRight:"\u250E",lineDownRightBold:"\u250D",lineDownDoubleRightDouble:"\u2554",lineDownDoubleRight:"\u2553",lineDownRightDouble:"\u2552",lineUpLeft:"\u2518",lineUpLeftArc:"\u256F",lineUpBoldLeftBold:"\u251B",lineUpBoldLeft:"\u251A",lineUpLeftBold:"\u2519",lineUpDoubleLeftDouble:"\u255D",lineUpDoubleLeft:"\u255C",lineUpLeftDouble:"\u255B",lineUpRight:"\u2514",lineUpRightArc:"\u2570",lineUpBoldRightBold:"\u2517",lineUpBoldRight:"\u2516",lineUpRightBold:"\u2515",lineUpDoubleRightDouble:"\u255A",lineUpDoubleRight:"\u2559",lineUpRightDouble:"\u2558",lineUpDownLeft:"\u2524",lineUpBoldDownBoldLeftBold:"\u252B",lineUpBoldDownBoldLeft:"\u2528",lineUpDownLeftBold:"\u2525",lineUpBoldDownLeftBold:"\u2529",lineUpDownBoldLeftBold:"\u252A",lineUpDownBoldLeft:"\u2527",lineUpBoldDownLeft:"\u2526",lineUpDoubleDownDoubleLeftDouble:"\u2563",lineUpDoubleDownDoubleLeft:"\u2562",lineUpDownLeftDouble:"\u2561",lineUpDownRight:"\u251C",lineUpBoldDownBoldRightBold:"\u2523",lineUpBoldDownBoldRight:"\u2520",lineUpDownRightBold:"\u251D",lineUpBoldDownRightBold:"\u2521",lineUpDownBoldRightBold:"\u2522",lineUpDownBoldRight:"\u251F",lineUpBoldDownRight:"\u251E",lineUpDoubleDownDoubleRightDouble:"\u2560",lineUpDoubleDownDoubleRight:"\u255F",lineUpDownRightDouble:"\u255E",lineDownLeftRight:"\u252C",lineDownBoldLeftBoldRightBold:"\u2533",lineDownLeftBoldRightBold:"\u252F",lineDownBoldLeftRight:"\u2530",lineDownBoldLeftBoldRight:"\u2531",lineDownBoldLeftRightBold:"\u2532",lineDownLeftRightBold:"\u252E",lineDownLeftBoldRight:"\u252D",lineDownDoubleLeftDoubleRightDouble:"\u2566",lineDownDoubleLeftRight:"\u2565",lineDownLeftDoubleRightDouble:"\u2564",lineUpLeftRight:"\u2534",lineUpBoldLeftBoldRightBold:"\u253B",lineUpLeftBoldRightBold:"\u2537",lineUpBoldLeftRight:"\u2538",lineUpBoldLeftBoldRight:"\u2539",lineUpBoldLeftRightBold:"\u253A",lineUpLeftRightBold:"\u2536",lineUpLeftBoldRight:"\u2535",lineUpDoubleLeftDoubleRightDouble:"\u2569",lineUpDoubleLeftRight:"\u2568",lineUpLeftDoubleRightDouble:"\u2567",lineUpDownLeftRight:"\u253C",lineUpBoldDownBoldLeftBoldRightBold:"\u254B",lineUpDownBoldLeftBoldRightBold:"\u2548",lineUpBoldDownLeftBoldRightBold:"\u2547",lineUpBoldDownBoldLeftRightBold:"\u254A",lineUpBoldDownBoldLeftBoldRight:"\u2549",lineUpBoldDownLeftRight:"\u2540",lineUpDownBoldLeftRight:"\u2541",lineUpDownLeftBoldRight:"\u253D",lineUpDownLeftRightBold:"\u253E",lineUpBoldDownBoldLeftRight:"\u2542",lineUpDownLeftBoldRightBold:"\u253F",lineUpBoldDownLeftBoldRight:"\u2543",lineUpBoldDownLeftRightBold:"\u2544",lineUpDownBoldLeftBoldRight:"\u2545",lineUpDownBoldLeftRightBold:"\u2546",lineUpDoubleDownDoubleLeftDoubleRightDouble:"\u256C",lineUpDoubleDownDoubleLeftRight:"\u256B",lineUpDownLeftDoubleRightDouble:"\u256A",lineCross:"\u2573",lineBackslash:"\u2572",lineSlash:"\u2571"},AZ={tick:"\u2714",info:"\u2139",warning:"\u26A0",cross:"\u2718",squareSmall:"\u25FB",squareSmallFilled:"\u25FC",circle:"\u25EF",circleFilled:"\u25C9",circleDotted:"\u25CC",circleDouble:"\u25CE",circleCircle:"\u24DE",circleCross:"\u24E7",circlePipe:"\u24BE",radioOn:"\u25C9",radioOff:"\u25EF",checkboxOn:"\u2612",checkboxOff:"\u2610",checkboxCircleOn:"\u24E7",checkboxCircleOff:"\u24BE",pointer:"\u276F",triangleUpOutline:"\u25B3",triangleLeft:"\u25C0",triangleRight:"\u25B6",lozenge:"\u25C6",lozengeOutline:"\u25C7",hamburger:"\u2630",smiley:"\u32E1",mustache:"\u0DF4",star:"\u2605",play:"\u25B6",nodejs:"\u2B22",oneSeventh:"\u2150",oneNinth:"\u2151",oneTenth:"\u2152"},Pve={tick:"\u221A",info:"i",warning:"\u203C",cross:"\xD7",squareSmall:"\u25A1",squareSmallFilled:"\u25A0",circle:"( )",circleFilled:"(*)",circleDotted:"( )",circleDouble:"( )",circleCircle:"(\u25CB)",circleCross:"(\xD7)",circlePipe:"(\u2502)",radioOn:"(*)",radioOff:"( )",checkboxOn:"[\xD7]",checkboxOff:"[ ]",checkboxCircleOn:"(\xD7)",checkboxCircleOff:"( )",pointer:">",triangleUpOutline:"\u2206",triangleLeft:"\u25C4",triangleRight:"\u25BA",lozenge:"\u2666",lozengeOutline:"\u25CA",hamburger:"\u2261",smiley:"\u263A",mustache:"\u250C\u2500\u2510",star:"\u2736",play:"\u25BA",nodejs:"\u2666",oneSeventh:"1/7",oneNinth:"1/9",oneTenth:"1/10"},Cve={...EZ,...AZ},Dve={...EZ,...Pve},Nve=PR(),jve=Nve?Cve:Dve,ub=jve,Dtt=Object.entries(AZ)});import Mve from"node:tty";var Fve,ve,Mtt,TZ,Ftt,Ltt,ztt,Utt,qtt,Htt,Btt,Gtt,Ztt,Vtt,Wtt,Ktt,Jtt,Ytt,Xtt,db,Qtt,ert,trt,rrt,nrt,irt,ort,srt,art,RZ,crt,IZ,lrt,urt,drt,frt,prt,mrt,hrt,grt,yrt,_rt,brt,CR=y(()=>{Fve=Mve?.WriteStream?.prototype?.hasColors?.()??!1,ve=(t,e)=>{if(!Fve)return i=>i;let r=`\x1B[${t}m`,n=`\x1B[${e}m`;return i=>{let o=i+"",s=o.indexOf(n);if(s===-1)return r+o+n;let a=r,c=0,u=(e===22?n:"")+r;for(;s!==-1;)a+=o.slice(c,s)+u,c=s+n.length,s=o.indexOf(n,c);return a+=o.slice(c)+n,a}},Mtt=ve(0,0),TZ=ve(1,22),Ftt=ve(2,22),Ltt=ve(3,23),ztt=ve(4,24),Utt=ve(53,55),qtt=ve(7,27),Htt=ve(8,28),Btt=ve(9,29),Gtt=ve(30,39),Ztt=ve(31,39),Vtt=ve(32,39),Wtt=ve(33,39),Ktt=ve(34,39),Jtt=ve(35,39),Ytt=ve(36,39),Xtt=ve(37,39),db=ve(90,39),Qtt=ve(40,49),ert=ve(41,49),trt=ve(42,49),rrt=ve(43,49),nrt=ve(44,49),irt=ve(45,49),ort=ve(46,49),srt=ve(47,49),art=ve(100,49),RZ=ve(91,39),crt=ve(92,39),IZ=ve(93,39),lrt=ve(94,39),urt=ve(95,39),drt=ve(96,39),frt=ve(97,39),prt=ve(101,49),mrt=ve(102,49),hrt=ve(103,49),grt=ve(104,49),yrt=ve(105,49),_rt=ve(106,49),brt=ve(107,49)});var PZ=y(()=>{CR();CR()});var NZ,zve,fb,CZ,Uve,DZ,qve,jZ=y(()=>{OZ();PZ();NZ=({type:t,message:e,timestamp:r,piped:n,commandId:i,result:{failed:o=!1}={},options:{reject:s=!0}})=>{let a=zve(r),c=Uve[t]({failed:o,reject:s,piped:n}),l=qve[t]({reject:s});return`${db(`[${a}]`)} ${db(`[${i}]`)} ${l(c)} ${l(e)}`},zve=t=>`${fb(t.getHours(),2)}:${fb(t.getMinutes(),2)}:${fb(t.getSeconds(),2)}.${fb(t.getMilliseconds(),3)}`,fb=(t,e)=>String(t).padStart(e,"0"),CZ=({failed:t,reject:e})=>t?e?ub.cross:ub.warning:ub.tick,Uve={command:({piped:t})=>t?"|":"$",output:()=>" ",ipc:()=>"*",error:CZ,duration:CZ},DZ=t=>t,qve={command:()=>TZ,output:()=>DZ,ipc:()=>DZ,error:({reject:t})=>t?RZ:IZ,duration:()=>db}});var MZ,Hve,Bve,FZ=y(()=>{ps();MZ=(t,e,r)=>{let n=SZ(e,r);return t.map(({verboseLine:i,verboseObject:o})=>Hve(i,o,n)).filter(i=>i!==void 0).map(i=>Bve(i)).join("")},Hve=(t,e,r)=>{if(r===void 0)return t;let n=r(t,e);if(typeof n=="string")return n},Bve=t=>t.endsWith(` `)?t:`${t} -`});import{inspect as sve}from"node:util";var Ci,ave,cve,lve,ub,uve,Ol=y(()=>{sb();SZ();xZ();Ci=({type:t,verboseMessage:e,fdNumber:r,verboseInfo:n,result:i})=>{let o=ave({type:t,result:i,verboseInfo:n}),s=cve(e,o),a=wZ(s,n,r);a!==""&&console.warn(a.slice(0,-1))},ave=({type:t,result:e,verboseInfo:{escapedCommand:r,commandId:n,rawOptions:{piped:i=!1,...o}}})=>({type:t,escapedCommand:r,commandId:`${n}`,timestamp:new Date,piped:i,result:e,options:o}),cve=(t,e)=>t.split(` -`).map(r=>lve({...e,message:r})),lve=t=>({verboseLine:vZ(t),verboseObject:t}),ub=t=>{let e=typeof t=="string"?t:sve(t);return Yf(e).replaceAll(" "," ".repeat(uve))},uve=2});var $Z,kZ=y(()=>{ds();Ol();$Z=(t,e)=>{Al(e)&&Ci({type:"command",verboseMessage:t,verboseInfo:e})}});var EZ,dve,fve,pve,AZ=y(()=>{ds();EZ=(t,e,r)=>{pve(t);let n=dve(t);return{verbose:t,escapedCommand:e,commandId:n,rawOptions:r}},dve=t=>Al({verbose:t})?fve++:void 0,fve=0n,pve=t=>{for(let e of t){if(e===!1)throw new TypeError(`The "verbose: false" option was renamed to "verbose: 'none'".`);if(e===!0)throw new TypeError(`The "verbose: true" option was renamed to "verbose: 'short'".`);if(!ob.includes(e)&&!ib(e)){let r=ob.map(n=>`'${n}'`).join(", ");throw new TypeError(`The "verbose" option must not be ${e}. Allowed values are: ${r} or a function.`)}}}});import{hrtime as TZ}from"node:process";var db,kR,fb=y(()=>{db=()=>TZ.bigint(),kR=t=>Number(TZ.bigint()-t)/1e6});var pb,ER=y(()=>{kZ();AZ();fb();sb();wo();pb=(t,e,r)=>{let n=db(),{command:i,escapedCommand:o}=aZ(t,e),s=bR(r,"verbose"),a=EZ(s,o,{...r});return $Z(o,a),{command:i,escapedCommand:o,startTime:n,verboseInfo:a}}});var CZ=v((mtt,PZ)=>{PZ.exports=IZ;IZ.sync=hve;var OZ=Ge("fs");function mve(t,e){var r=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!r||(r=r.split(";"),r.indexOf("")!==-1))return!0;for(var n=0;n{MZ.exports=NZ;NZ.sync=gve;var DZ=Ge("fs");function NZ(t,e,r){DZ.stat(t,function(n,i){r(n,n?!1:jZ(i,e))})}function gve(t,e){return jZ(DZ.statSync(t),e)}function jZ(t,e){return t.isFile()&&yve(t,e)}function yve(t,e){var r=t.mode,n=t.uid,i=t.gid,o=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),s=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),a=parseInt("100",8),c=parseInt("010",8),l=parseInt("001",8),u=a|c,d=r&l||r&c&&i===s||r&a&&n===o||r&u&&o===0;return d}});var zZ=v((ytt,LZ)=>{var gtt=Ge("fs"),mb;process.platform==="win32"||global.TESTING_WINDOWS?mb=CZ():mb=FZ();LZ.exports=AR;AR.sync=_ve;function AR(t,e,r){if(typeof e=="function"&&(r=e,e={}),!r){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(n,i){AR(t,e||{},function(o,s){o?i(o):n(s)})})}mb(t,e||{},function(n,i){n&&(n.code==="EACCES"||e&&e.ignoreErrors)&&(n=null,i=!1),r(n,i)})}function _ve(t,e){try{return mb.sync(t,e||{})}catch(r){if(e&&e.ignoreErrors||r.code==="EACCES")return!1;throw r}}});var VZ=v((_tt,ZZ)=>{var Rl=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",UZ=Ge("path"),bve=Rl?";":":",qZ=zZ(),BZ=t=>Object.assign(new Error(`not found: ${t}`),{code:"ENOENT"}),HZ=(t,e)=>{let r=e.colon||bve,n=t.match(/\//)||Rl&&t.match(/\\/)?[""]:[...Rl?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(r)],i=Rl?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",o=Rl?i.split(r):[""];return Rl&&t.indexOf(".")!==-1&&o[0]!==""&&o.unshift(""),{pathEnv:n,pathExt:o,pathExtExe:i}},GZ=(t,e,r)=>{typeof e=="function"&&(r=e,e={}),e||(e={});let{pathEnv:n,pathExt:i,pathExtExe:o}=HZ(t,e),s=[],a=l=>new Promise((u,d)=>{if(l===n.length)return e.all&&s.length?u(s):d(BZ(t));let f=n[l],p=/^".*"$/.test(f)?f.slice(1,-1):f,m=UZ.join(p,t),h=!p&&/^\.[\\\/]/.test(t)?t.slice(0,2)+m:m;u(c(h,l,0))}),c=(l,u,d)=>new Promise((f,p)=>{if(d===i.length)return f(a(u+1));let m=i[d];qZ(l+m,{pathExt:o},(h,g)=>{if(!h&&g)if(e.all)s.push(l+m);else return f(l+m);return f(c(l,u,d+1))})});return r?a(0).then(l=>r(null,l),r):a(0)},vve=(t,e)=>{e=e||{};let{pathEnv:r,pathExt:n,pathExtExe:i}=HZ(t,e),o=[];for(let s=0;s{"use strict";var WZ=(t={})=>{let e=t.env||process.env;return(t.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(n=>n.toUpperCase()==="PATH")||"Path"};TR.exports=WZ;TR.exports.default=WZ});var QZ=v((vtt,XZ)=>{"use strict";var JZ=Ge("path"),Sve=VZ(),wve=KZ();function YZ(t,e){let r=t.options.env||process.env,n=process.cwd(),i=t.options.cwd!=null,o=i&&process.chdir!==void 0&&!process.chdir.disabled;if(o)try{process.chdir(t.options.cwd)}catch{}let s;try{s=Sve.sync(t.command,{path:r[wve({env:r})],pathExt:e?JZ.delimiter:void 0})}catch{}finally{o&&process.chdir(n)}return s&&(s=JZ.resolve(i?t.options.cwd:"",s)),s}function xve(t){return YZ(t)||YZ(t,!0)}XZ.exports=xve});var e9=v((Stt,RR)=>{"use strict";var OR=/([()\][%!^"`<>&|;, *?])/g;function $ve(t){return t=t.replace(OR,"^$1"),t}function kve(t,e){return t=`${t}`,t=t.replace(/(?=(\\+?)?)\1"/g,'$1$1\\"'),t=t.replace(/(?=(\\+?)?)\1$/,"$1$1"),t=`"${t}"`,t=t.replace(OR,"^$1"),e&&(t=t.replace(OR,"^$1")),t}RR.exports.command=$ve;RR.exports.argument=kve});var r9=v((wtt,t9)=>{"use strict";t9.exports=/^#!(.*)/});var i9=v((xtt,n9)=>{"use strict";var Eve=r9();n9.exports=(t="")=>{let e=t.match(Eve);if(!e)return null;let[r,n]=e[0].replace(/#! ?/,"").split(" "),i=r.split("/").pop();return i==="env"?n:n?`${i} ${n}`:i}});var s9=v(($tt,o9)=>{"use strict";var IR=Ge("fs"),Ave=i9();function Tve(t){let r=Buffer.alloc(150),n;try{n=IR.openSync(t,"r"),IR.readSync(n,r,0,150,0),IR.closeSync(n)}catch{}return Ave(r.toString())}o9.exports=Tve});var u9=v((ktt,l9)=>{"use strict";var Ove=Ge("path"),a9=QZ(),c9=e9(),Rve=s9(),Ive=process.platform==="win32",Pve=/\.(?:com|exe)$/i,Cve=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function Dve(t){t.file=a9(t);let e=t.file&&Rve(t.file);return e?(t.args.unshift(t.file),t.command=e,a9(t)):t.file}function Nve(t){if(!Ive)return t;let e=Dve(t),r=!Pve.test(e);if(t.options.forceShell||r){let n=Cve.test(e);t.command=Ove.normalize(t.command),t.command=c9.command(t.command),t.args=t.args.map(o=>c9.argument(o,n));let i=[t.command].concat(t.args).join(" ");t.args=["/d","/s","/c",`"${i}"`],t.command=process.env.comspec||"cmd.exe",t.options.windowsVerbatimArguments=!0}return t}function jve(t,e,r){e&&!Array.isArray(e)&&(r=e,e=null),e=e?e.slice(0):[],r=Object.assign({},r);let n={command:t,args:e,options:r,file:void 0,original:{command:t,args:e}};return r.shell?n:Nve(n)}l9.exports=jve});var p9=v((Ett,f9)=>{"use strict";var PR=process.platform==="win32";function CR(t,e){return Object.assign(new Error(`${e} ${t.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${t.command}`,path:t.command,spawnargs:t.args})}function Mve(t,e){if(!PR)return;let r=t.emit;t.emit=function(n,i){if(n==="exit"){let o=d9(i,e);if(o)return r.call(t,"error",o)}return r.apply(t,arguments)}}function d9(t,e){return PR&&t===1&&!e.file?CR(e.original,"spawn"):null}function Fve(t,e){return PR&&t===1&&!e.file?CR(e.original,"spawnSync"):null}f9.exports={hookChildProcess:Mve,verifyENOENT:d9,verifyENOENTSync:Fve,notFoundError:CR}});var g9=v((Att,Il)=>{"use strict";var m9=Ge("child_process"),DR=u9(),NR=p9();function h9(t,e,r){let n=DR(t,e,r),i=m9.spawn(n.command,n.args,n.options);return NR.hookChildProcess(i,n),i}function Lve(t,e,r){let n=DR(t,e,r),i=m9.spawnSync(n.command,n.args,n.options);return i.error=i.error||NR.verifyENOENTSync(i.status,n),i}Il.exports=h9;Il.exports.spawn=h9;Il.exports.sync=Lve;Il.exports._parse=DR;Il.exports._enoent=NR});function hb(t={}){let{env:e=process.env,platform:r=process.platform}=t;return r!=="win32"?"PATH":Object.keys(e).reverse().find(n=>n.toUpperCase()==="PATH")||"Path"}var y9=y(()=>{});var _9=y(()=>{});import{promisify as zve}from"node:util";import{execFile as Uve,execFileSync as Ptt}from"node:child_process";import b9 from"node:path";import{fileURLToPath as qve}from"node:url";function gb(t){return t instanceof URL?qve(t):t}function v9(t){return{*[Symbol.iterator](){let e=b9.resolve(gb(t)),r;for(;r!==e;)yield e,r=e,e=b9.resolve(e,"..")}}}var Ntt,jtt,S9=y(()=>{_9();Ntt=zve(Uve);jtt=10*1024*1024});import yb from"node:process";import Ia from"node:path";var Bve,Hve,Gve,w9,x9=y(()=>{y9();S9();Bve=({cwd:t=yb.cwd(),path:e=yb.env[hb()],preferLocal:r=!0,execPath:n=yb.execPath,addExecPath:i=!0}={})=>{let o=Ia.resolve(gb(t)),s=[],a=e.split(Ia.delimiter);return r&&Hve(s,a,o),i&&Gve(s,a,n,o),e===""||e===Ia.delimiter?`${s.join(Ia.delimiter)}${e}`:[...s,e].join(Ia.delimiter)},Hve=(t,e,r)=>{for(let n of v9(r)){let i=Ia.join(n,"node_modules/.bin");e.includes(i)||t.push(i)}},Gve=(t,e,r,n)=>{let i=Ia.resolve(n,gb(r),"..");e.includes(i)||t.push(i)},w9=({env:t=yb.env,...e}={})=>{t={...t};let r=hb({env:t});return e.path=t[r],t[r]=Bve(e),t}});var $9,ri,k9,E9,A9,_b,Xf,Qf,Pa=y(()=>{$9=(t,e,r)=>{let n=r?Qf:Xf,i=t instanceof ri?{}:{cause:t};return new n(e,i)},ri=class extends Error{},k9=(t,e)=>{Object.defineProperty(t.prototype,"name",{value:e,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,A9,{value:!0,writable:!1,enumerable:!1,configurable:!1})},E9=t=>_b(t)&&A9 in t,A9=Symbol("isExecaError"),_b=t=>Object.prototype.toString.call(t)==="[object Error]",Xf=class extends Error{};k9(Xf,Xf.name);Qf=class extends Error{};k9(Qf,Qf.name)});var T9,Zve,O9,R9,I9=y(()=>{T9=()=>{let t=R9-O9+1;return Array.from({length:t},Zve)},Zve=(t,e)=>({name:`SIGRT${e+1}`,number:O9+e,action:"terminate",description:"Application-specific signal (realtime)",standard:"posix"}),O9=34,R9=64});var P9,C9=y(()=>{P9=[{name:"SIGHUP",number:1,action:"terminate",description:"Terminal closed",standard:"posix"},{name:"SIGINT",number:2,action:"terminate",description:"User interruption with CTRL-C",standard:"ansi"},{name:"SIGQUIT",number:3,action:"core",description:"User interruption with CTRL-\\",standard:"posix"},{name:"SIGILL",number:4,action:"core",description:"Invalid machine instruction",standard:"ansi"},{name:"SIGTRAP",number:5,action:"core",description:"Debugger breakpoint",standard:"posix"},{name:"SIGABRT",number:6,action:"core",description:"Aborted",standard:"ansi"},{name:"SIGIOT",number:6,action:"core",description:"Aborted",standard:"bsd"},{name:"SIGBUS",number:7,action:"core",description:"Bus error due to misaligned, non-existing address or paging error",standard:"bsd"},{name:"SIGEMT",number:7,action:"terminate",description:"Command should be emulated but is not implemented",standard:"other"},{name:"SIGFPE",number:8,action:"core",description:"Floating point arithmetic error",standard:"ansi"},{name:"SIGKILL",number:9,action:"terminate",description:"Forced termination",standard:"posix",forced:!0},{name:"SIGUSR1",number:10,action:"terminate",description:"Application-specific signal",standard:"posix"},{name:"SIGSEGV",number:11,action:"core",description:"Segmentation fault",standard:"ansi"},{name:"SIGUSR2",number:12,action:"terminate",description:"Application-specific signal",standard:"posix"},{name:"SIGPIPE",number:13,action:"terminate",description:"Broken pipe or socket",standard:"posix"},{name:"SIGALRM",number:14,action:"terminate",description:"Timeout or timer",standard:"posix"},{name:"SIGTERM",number:15,action:"terminate",description:"Termination",standard:"ansi"},{name:"SIGSTKFLT",number:16,action:"terminate",description:"Stack is empty or overflowed",standard:"other"},{name:"SIGCHLD",number:17,action:"ignore",description:"Child process terminated, paused or unpaused",standard:"posix"},{name:"SIGCLD",number:17,action:"ignore",description:"Child process terminated, paused or unpaused",standard:"other"},{name:"SIGCONT",number:18,action:"unpause",description:"Unpaused",standard:"posix",forced:!0},{name:"SIGSTOP",number:19,action:"pause",description:"Paused",standard:"posix",forced:!0},{name:"SIGTSTP",number:20,action:"pause",description:'Paused using CTRL-Z or "suspend"',standard:"posix"},{name:"SIGTTIN",number:21,action:"pause",description:"Background process cannot read terminal input",standard:"posix"},{name:"SIGBREAK",number:21,action:"terminate",description:"User interruption with CTRL-BREAK",standard:"other"},{name:"SIGTTOU",number:22,action:"pause",description:"Background process cannot write to terminal output",standard:"posix"},{name:"SIGURG",number:23,action:"ignore",description:"Socket received out-of-band data",standard:"bsd"},{name:"SIGXCPU",number:24,action:"core",description:"Process timed out",standard:"bsd"},{name:"SIGXFSZ",number:25,action:"core",description:"File too big",standard:"bsd"},{name:"SIGVTALRM",number:26,action:"terminate",description:"Timeout or timer",standard:"bsd"},{name:"SIGPROF",number:27,action:"terminate",description:"Timeout or timer",standard:"bsd"},{name:"SIGWINCH",number:28,action:"ignore",description:"Terminal window size changed",standard:"bsd"},{name:"SIGIO",number:29,action:"terminate",description:"I/O is available",standard:"other"},{name:"SIGPOLL",number:29,action:"terminate",description:"Watched event",standard:"other"},{name:"SIGINFO",number:29,action:"ignore",description:"Request for process information",standard:"other"},{name:"SIGPWR",number:30,action:"terminate",description:"Device running out of power",standard:"systemv"},{name:"SIGSYS",number:31,action:"core",description:"Invalid system call",standard:"other"},{name:"SIGUNUSED",number:31,action:"terminate",description:"Invalid system call",standard:"other"}]});import{constants as Vve}from"node:os";var jR,Wve,D9=y(()=>{C9();I9();jR=()=>{let t=T9();return[...P9,...t].map(Wve)},Wve=({name:t,number:e,description:r,action:n,forced:i=!1,standard:o})=>{let{signals:{[t]:s}}=Vve,a=s!==void 0;return{name:t,number:a?s:e,description:r,supported:a,action:n,forced:i,standard:o}}});import{constants as Kve}from"node:os";var Jve,Yve,N9,Xve,Qve,eSe,Qtt,j9=y(()=>{D9();Jve=()=>{let t=jR();return Object.fromEntries(t.map(Yve))},Yve=({name:t,number:e,description:r,supported:n,action:i,forced:o,standard:s})=>[t,{name:t,number:e,description:r,supported:n,action:i,forced:o,standard:s}],N9=Jve(),Xve=()=>{let t=jR(),e=65,r=Array.from({length:e},(n,i)=>Qve(i,t));return Object.assign({},...r)},Qve=(t,e)=>{let r=eSe(t,e);if(r===void 0)return{};let{name:n,description:i,supported:o,action:s,forced:a,standard:c}=r;return{[t]:{name:n,number:t,description:i,supported:o,action:s,forced:a,standard:c}}},eSe=(t,e)=>{let r=e.find(({name:n})=>Kve.signals[n]===t);return r!==void 0?r:e.find(n=>n.number===t)},Qtt=Xve()});import{constants as ep}from"node:os";var F9,L9,z9,tSe,rSe,M9,nSe,MR,iSe,oSe,bb,tp=y(()=>{j9();F9=t=>{let e="option `killSignal`";if(t===0)throw new TypeError(`Invalid ${e}: 0 cannot be used.`);return z9(t,e)},L9=t=>t===0?t:z9(t,"`subprocess.kill()`'s argument"),z9=(t,e)=>{if(Number.isInteger(t))return tSe(t,e);if(typeof t=="string")return nSe(t,e);throw new TypeError(`Invalid ${e} ${String(t)}: it must be a string or an integer. -${MR()}`)},tSe=(t,e)=>{if(M9.has(t))return M9.get(t);throw new TypeError(`Invalid ${e} ${t}: this signal integer does not exist. -${MR()}`)},rSe=()=>new Map(Object.entries(ep.signals).reverse().map(([t,e])=>[e,t])),M9=rSe(),nSe=(t,e)=>{if(t in ep.signals)return t;throw t.toUpperCase()in ep.signals?new TypeError(`Invalid ${e} '${t}': please rename it to '${t.toUpperCase()}'.`):new TypeError(`Invalid ${e} '${t}': this signal name does not exist. -${MR()}`)},MR=()=>`Available signal names: ${iSe()}. -Available signal numbers: ${oSe()}.`,iSe=()=>Object.keys(ep.signals).sort().map(t=>`'${t}'`).join(", "),oSe=()=>[...new Set(Object.values(ep.signals).sort((t,e)=>t-e))].join(", "),bb=t=>N9[t].description});import{setTimeout as sSe}from"node:timers/promises";var U9,aSe,q9,cSe,lSe,uSe,FR,vb=y(()=>{Pa();tp();U9=t=>{if(t===!1)return t;if(t===!0)return aSe;if(!Number.isFinite(t)||t<0)throw new TypeError(`Expected the \`forceKillAfterDelay\` option to be a non-negative integer, got \`${t}\` (${typeof t})`);return t},aSe=1e3*5,q9=({kill:t,options:{forceKillAfterDelay:e,killSignal:r},onInternalError:n,context:i,controller:o},s,a)=>{let{signal:c,error:l}=cSe(s,a,r);lSe(l,n);let u=t(c);return uSe({kill:t,signal:c,forceKillAfterDelay:e,killSignal:r,killResult:u,context:i,controller:o}),u},cSe=(t,e,r)=>{let[n=r,i]=_b(t)?[void 0,t]:[t,e];if(typeof n!="string"&&!Number.isInteger(n))throw new TypeError(`The first argument must be an error instance or a signal name string/integer: ${String(n)}`);if(i!==void 0&&!_b(i))throw new TypeError(`The second argument is optional. If specified, it must be an error instance: ${i}`);return{signal:L9(n),error:i}},lSe=(t,e)=>{t!==void 0&&e.reject(t)},uSe=async({kill:t,signal:e,forceKillAfterDelay:r,killSignal:n,killResult:i,context:o,controller:s})=>{e===n&&i&&FR({kill:t,forceKillAfterDelay:r,context:o,controllerSignal:s.signal})},FR=async({kill:t,forceKillAfterDelay:e,context:r,controllerSignal:n})=>{if(e!==!1)try{await sSe(e,void 0,{signal:n}),t("SIGKILL")&&(r.isForcefullyTerminated??=!0)}catch{}}});import{once as dSe}from"node:events";var Sb,LR=y(()=>{Sb=async(t,e)=>{t.aborted||await dSe(t,"abort",{signal:e})}});var B9,H9,fSe,zR=y(()=>{LR();B9=({cancelSignal:t})=>{if(t!==void 0&&Object.prototype.toString.call(t)!=="[object AbortSignal]")throw new Error(`The \`cancelSignal\` option must be an AbortSignal: ${String(t)}`)},H9=({subprocess:t,cancelSignal:e,gracefulCancel:r,context:n,controller:i})=>e===void 0||r?[]:[fSe(t,e,n,i)],fSe=async(t,e,r,{signal:n})=>{throw await Sb(e,n),r.terminationReason??="cancel",t.kill(),e.reason}});var Pl,pSe,UR,G9,Z9,wb,V9,W9,K9,J9,Y9,X9,mSe,hSe,gSe,ni,ySe,fs,Cl,Dl=y(()=>{Pl=({methodName:t,isSubprocess:e,ipc:r,isConnected:n})=>{pSe(t,e,r),UR(t,e,n)},pSe=(t,e,r)=>{if(!r)throw new Error(`${ni(t,e)} can only be used if the \`ipc\` option is \`true\`.`)},UR=(t,e,r)=>{if(!r)throw new Error(`${ni(t,e)} cannot be used: the ${fs(e)} has already exited or disconnected.`)},G9=t=>{throw new Error(`${ni("getOneMessage",t)} could not complete: the ${fs(t)} exited or disconnected.`)},Z9=t=>{throw new Error(`${ni("sendMessage",t)} failed: the ${fs(t)} is sending a message too, instead of listening to incoming messages. +`});import{inspect as Gve}from"node:util";var Ci,Zve,Vve,Wve,pb,Kve,Pl=y(()=>{lb();jZ();FZ();Ci=({type:t,verboseMessage:e,fdNumber:r,verboseInfo:n,result:i})=>{let o=Zve({type:t,result:i,verboseInfo:n}),s=Vve(e,o),a=MZ(s,n,r);a!==""&&console.warn(a.slice(0,-1))},Zve=({type:t,result:e,verboseInfo:{escapedCommand:r,commandId:n,rawOptions:{piped:i=!1,...o}}})=>({type:t,escapedCommand:r,commandId:`${n}`,timestamp:new Date,piped:i,result:e,options:o}),Vve=(t,e)=>t.split(` +`).map(r=>Wve({...e,message:r})),Wve=t=>({verboseLine:NZ(t),verboseObject:t}),pb=t=>{let e=typeof t=="string"?t:Gve(t);return ep(e).replaceAll(" "," ".repeat(Kve))},Kve=2});var LZ,zZ=y(()=>{ps();Pl();LZ=(t,e)=>{Rl(e)&&Ci({type:"command",verboseMessage:t,verboseInfo:e})}});var UZ,Jve,Yve,Xve,qZ=y(()=>{ps();UZ=(t,e,r)=>{Xve(t);let n=Jve(t);return{verbose:t,escapedCommand:e,commandId:n,rawOptions:r}},Jve=t=>Rl({verbose:t})?Yve++:void 0,Yve=0n,Xve=t=>{for(let e of t){if(e===!1)throw new TypeError(`The "verbose: false" option was renamed to "verbose: 'none'".`);if(e===!0)throw new TypeError(`The "verbose: true" option was renamed to "verbose: 'short'".`);if(!cb.includes(e)&&!ab(e)){let r=cb.map(n=>`'${n}'`).join(", ");throw new TypeError(`The "verbose" option must not be ${e}. Allowed values are: ${r} or a function.`)}}}});import{hrtime as HZ}from"node:process";var mb,DR,hb=y(()=>{mb=()=>HZ.bigint(),DR=t=>Number(HZ.bigint()-t)/1e6});var gb,NR=y(()=>{zZ();qZ();hb();lb();xo();gb=(t,e,r)=>{let n=mb(),{command:i,escapedCommand:o}=wZ(t,e),s=OR(r,"verbose"),a=UZ(s,o,{...r});return LZ(o,a),{command:i,escapedCommand:o,startTime:n,verboseInfo:a}}});var WZ=v((Grt,VZ)=>{VZ.exports=ZZ;ZZ.sync=eSe;var BZ=Ze("fs");function Qve(t,e){var r=e.pathExt!==void 0?e.pathExt:process.env.PATHEXT;if(!r||(r=r.split(";"),r.indexOf("")!==-1))return!0;for(var n=0;n{XZ.exports=JZ;JZ.sync=tSe;var KZ=Ze("fs");function JZ(t,e,r){KZ.stat(t,function(n,i){r(n,n?!1:YZ(i,e))})}function tSe(t,e){return YZ(KZ.statSync(t),e)}function YZ(t,e){return t.isFile()&&rSe(t,e)}function rSe(t,e){var r=t.mode,n=t.uid,i=t.gid,o=e.uid!==void 0?e.uid:process.getuid&&process.getuid(),s=e.gid!==void 0?e.gid:process.getgid&&process.getgid(),a=parseInt("100",8),c=parseInt("010",8),l=parseInt("001",8),u=a|c,d=r&l||r&c&&i===s||r&a&&n===o||r&u&&o===0;return d}});var tV=v((Wrt,eV)=>{var Vrt=Ze("fs"),yb;process.platform==="win32"||global.TESTING_WINDOWS?yb=WZ():yb=QZ();eV.exports=jR;jR.sync=nSe;function jR(t,e,r){if(typeof e=="function"&&(r=e,e={}),!r){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(n,i){jR(t,e||{},function(o,s){o?i(o):n(s)})})}yb(t,e||{},function(n,i){n&&(n.code==="EACCES"||e&&e.ignoreErrors)&&(n=null,i=!1),r(n,i)})}function nSe(t,e){try{return yb.sync(t,e||{})}catch(r){if(e&&e.ignoreErrors||r.code==="EACCES")return!1;throw r}}});var cV=v((Krt,aV)=>{var Cl=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",rV=Ze("path"),iSe=Cl?";":":",nV=tV(),iV=t=>Object.assign(new Error(`not found: ${t}`),{code:"ENOENT"}),oV=(t,e)=>{let r=e.colon||iSe,n=t.match(/\//)||Cl&&t.match(/\\/)?[""]:[...Cl?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(r)],i=Cl?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",o=Cl?i.split(r):[""];return Cl&&t.indexOf(".")!==-1&&o[0]!==""&&o.unshift(""),{pathEnv:n,pathExt:o,pathExtExe:i}},sV=(t,e,r)=>{typeof e=="function"&&(r=e,e={}),e||(e={});let{pathEnv:n,pathExt:i,pathExtExe:o}=oV(t,e),s=[],a=l=>new Promise((u,d)=>{if(l===n.length)return e.all&&s.length?u(s):d(iV(t));let f=n[l],p=/^".*"$/.test(f)?f.slice(1,-1):f,m=rV.join(p,t),h=!p&&/^\.[\\\/]/.test(t)?t.slice(0,2)+m:m;u(c(h,l,0))}),c=(l,u,d)=>new Promise((f,p)=>{if(d===i.length)return f(a(u+1));let m=i[d];nV(l+m,{pathExt:o},(h,g)=>{if(!h&&g)if(e.all)s.push(l+m);else return f(l+m);return f(c(l,u,d+1))})});return r?a(0).then(l=>r(null,l),r):a(0)},oSe=(t,e)=>{e=e||{};let{pathEnv:r,pathExt:n,pathExtExe:i}=oV(t,e),o=[];for(let s=0;s{"use strict";var lV=(t={})=>{let e=t.env||process.env;return(t.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(n=>n.toUpperCase()==="PATH")||"Path"};MR.exports=lV;MR.exports.default=lV});var mV=v((Yrt,pV)=>{"use strict";var dV=Ze("path"),sSe=cV(),aSe=uV();function fV(t,e){let r=t.options.env||process.env,n=process.cwd(),i=t.options.cwd!=null,o=i&&process.chdir!==void 0&&!process.chdir.disabled;if(o)try{process.chdir(t.options.cwd)}catch{}let s;try{s=sSe.sync(t.command,{path:r[aSe({env:r})],pathExt:e?dV.delimiter:void 0})}catch{}finally{o&&process.chdir(n)}return s&&(s=dV.resolve(i?t.options.cwd:"",s)),s}function cSe(t){return fV(t)||fV(t,!0)}pV.exports=cSe});var hV=v((Xrt,LR)=>{"use strict";var FR=/([()\][%!^"`<>&|;, *?])/g;function lSe(t){return t=t.replace(FR,"^$1"),t}function uSe(t,e){return t=`${t}`,t=t.replace(/(?=(\\+?)?)\1"/g,'$1$1\\"'),t=t.replace(/(?=(\\+?)?)\1$/,"$1$1"),t=`"${t}"`,t=t.replace(FR,"^$1"),e&&(t=t.replace(FR,"^$1")),t}LR.exports.command=lSe;LR.exports.argument=uSe});var yV=v((Qrt,gV)=>{"use strict";gV.exports=/^#!(.*)/});var bV=v((ent,_V)=>{"use strict";var dSe=yV();_V.exports=(t="")=>{let e=t.match(dSe);if(!e)return null;let[r,n]=e[0].replace(/#! ?/,"").split(" "),i=r.split("/").pop();return i==="env"?n:n?`${i} ${n}`:i}});var SV=v((tnt,vV)=>{"use strict";var zR=Ze("fs"),fSe=bV();function pSe(t){let r=Buffer.alloc(150),n;try{n=zR.openSync(t,"r"),zR.readSync(n,r,0,150,0),zR.closeSync(n)}catch{}return fSe(r.toString())}vV.exports=pSe});var kV=v((rnt,$V)=>{"use strict";var mSe=Ze("path"),wV=mV(),xV=hV(),hSe=SV(),gSe=process.platform==="win32",ySe=/\.(?:com|exe)$/i,_Se=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function bSe(t){t.file=wV(t);let e=t.file&&hSe(t.file);return e?(t.args.unshift(t.file),t.command=e,wV(t)):t.file}function vSe(t){if(!gSe)return t;let e=bSe(t),r=!ySe.test(e);if(t.options.forceShell||r){let n=_Se.test(e);t.command=mSe.normalize(t.command),t.command=xV.command(t.command),t.args=t.args.map(o=>xV.argument(o,n));let i=[t.command].concat(t.args).join(" ");t.args=["/d","/s","/c",`"${i}"`],t.command=process.env.comspec||"cmd.exe",t.options.windowsVerbatimArguments=!0}return t}function SSe(t,e,r){e&&!Array.isArray(e)&&(r=e,e=null),e=e?e.slice(0):[],r=Object.assign({},r);let n={command:t,args:e,options:r,file:void 0,original:{command:t,args:e}};return r.shell?n:vSe(n)}$V.exports=SSe});var OV=v((nnt,AV)=>{"use strict";var UR=process.platform==="win32";function qR(t,e){return Object.assign(new Error(`${e} ${t.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${t.command}`,path:t.command,spawnargs:t.args})}function wSe(t,e){if(!UR)return;let r=t.emit;t.emit=function(n,i){if(n==="exit"){let o=EV(i,e);if(o)return r.call(t,"error",o)}return r.apply(t,arguments)}}function EV(t,e){return UR&&t===1&&!e.file?qR(e.original,"spawn"):null}function xSe(t,e){return UR&&t===1&&!e.file?qR(e.original,"spawnSync"):null}AV.exports={hookChildProcess:wSe,verifyENOENT:EV,verifyENOENTSync:xSe,notFoundError:qR}});var IV=v((int,Dl)=>{"use strict";var TV=Ze("child_process"),HR=kV(),BR=OV();function RV(t,e,r){let n=HR(t,e,r),i=TV.spawn(n.command,n.args,n.options);return BR.hookChildProcess(i,n),i}function $Se(t,e,r){let n=HR(t,e,r),i=TV.spawnSync(n.command,n.args,n.options);return i.error=i.error||BR.verifyENOENTSync(i.status,n),i}Dl.exports=RV;Dl.exports.spawn=RV;Dl.exports.sync=$Se;Dl.exports._parse=HR;Dl.exports._enoent=BR});function _b(t={}){let{env:e=process.env,platform:r=process.platform}=t;return r!=="win32"?"PATH":Object.keys(e).reverse().find(n=>n.toUpperCase()==="PATH")||"Path"}var PV=y(()=>{});var CV=y(()=>{});import{promisify as kSe}from"node:util";import{execFile as ESe,execFileSync as lnt}from"node:child_process";import DV from"node:path";import{fileURLToPath as ASe}from"node:url";function bb(t){return t instanceof URL?ASe(t):t}function NV(t){return{*[Symbol.iterator](){let e=DV.resolve(bb(t)),r;for(;r!==e;)yield e,r=e,e=DV.resolve(e,"..")}}}var fnt,pnt,jV=y(()=>{CV();fnt=kSe(ESe);pnt=10*1024*1024});import vb from"node:process";import Ca from"node:path";var OSe,TSe,RSe,MV,FV=y(()=>{PV();jV();OSe=({cwd:t=vb.cwd(),path:e=vb.env[_b()],preferLocal:r=!0,execPath:n=vb.execPath,addExecPath:i=!0}={})=>{let o=Ca.resolve(bb(t)),s=[],a=e.split(Ca.delimiter);return r&&TSe(s,a,o),i&&RSe(s,a,n,o),e===""||e===Ca.delimiter?`${s.join(Ca.delimiter)}${e}`:[...s,e].join(Ca.delimiter)},TSe=(t,e,r)=>{for(let n of NV(r)){let i=Ca.join(n,"node_modules/.bin");e.includes(i)||t.push(i)}},RSe=(t,e,r,n)=>{let i=Ca.resolve(n,bb(r),"..");e.includes(i)||t.push(i)},MV=({env:t=vb.env,...e}={})=>{t={...t};let r=_b({env:t});return e.path=t[r],t[r]=OSe(e),t}});var LV,ni,zV,UV,qV,Sb,tp,rp,Da=y(()=>{LV=(t,e,r)=>{let n=r?rp:tp,i=t instanceof ni?{}:{cause:t};return new n(e,i)},ni=class extends Error{},zV=(t,e)=>{Object.defineProperty(t.prototype,"name",{value:e,writable:!0,enumerable:!1,configurable:!0}),Object.defineProperty(t.prototype,qV,{value:!0,writable:!1,enumerable:!1,configurable:!1})},UV=t=>Sb(t)&&qV in t,qV=Symbol("isExecaError"),Sb=t=>Object.prototype.toString.call(t)==="[object Error]",tp=class extends Error{};zV(tp,tp.name);rp=class extends Error{};zV(rp,rp.name)});var HV,ISe,BV,GV,ZV=y(()=>{HV=()=>{let t=GV-BV+1;return Array.from({length:t},ISe)},ISe=(t,e)=>({name:`SIGRT${e+1}`,number:BV+e,action:"terminate",description:"Application-specific signal (realtime)",standard:"posix"}),BV=34,GV=64});var VV,WV=y(()=>{VV=[{name:"SIGHUP",number:1,action:"terminate",description:"Terminal closed",standard:"posix"},{name:"SIGINT",number:2,action:"terminate",description:"User interruption with CTRL-C",standard:"ansi"},{name:"SIGQUIT",number:3,action:"core",description:"User interruption with CTRL-\\",standard:"posix"},{name:"SIGILL",number:4,action:"core",description:"Invalid machine instruction",standard:"ansi"},{name:"SIGTRAP",number:5,action:"core",description:"Debugger breakpoint",standard:"posix"},{name:"SIGABRT",number:6,action:"core",description:"Aborted",standard:"ansi"},{name:"SIGIOT",number:6,action:"core",description:"Aborted",standard:"bsd"},{name:"SIGBUS",number:7,action:"core",description:"Bus error due to misaligned, non-existing address or paging error",standard:"bsd"},{name:"SIGEMT",number:7,action:"terminate",description:"Command should be emulated but is not implemented",standard:"other"},{name:"SIGFPE",number:8,action:"core",description:"Floating point arithmetic error",standard:"ansi"},{name:"SIGKILL",number:9,action:"terminate",description:"Forced termination",standard:"posix",forced:!0},{name:"SIGUSR1",number:10,action:"terminate",description:"Application-specific signal",standard:"posix"},{name:"SIGSEGV",number:11,action:"core",description:"Segmentation fault",standard:"ansi"},{name:"SIGUSR2",number:12,action:"terminate",description:"Application-specific signal",standard:"posix"},{name:"SIGPIPE",number:13,action:"terminate",description:"Broken pipe or socket",standard:"posix"},{name:"SIGALRM",number:14,action:"terminate",description:"Timeout or timer",standard:"posix"},{name:"SIGTERM",number:15,action:"terminate",description:"Termination",standard:"ansi"},{name:"SIGSTKFLT",number:16,action:"terminate",description:"Stack is empty or overflowed",standard:"other"},{name:"SIGCHLD",number:17,action:"ignore",description:"Child process terminated, paused or unpaused",standard:"posix"},{name:"SIGCLD",number:17,action:"ignore",description:"Child process terminated, paused or unpaused",standard:"other"},{name:"SIGCONT",number:18,action:"unpause",description:"Unpaused",standard:"posix",forced:!0},{name:"SIGSTOP",number:19,action:"pause",description:"Paused",standard:"posix",forced:!0},{name:"SIGTSTP",number:20,action:"pause",description:'Paused using CTRL-Z or "suspend"',standard:"posix"},{name:"SIGTTIN",number:21,action:"pause",description:"Background process cannot read terminal input",standard:"posix"},{name:"SIGBREAK",number:21,action:"terminate",description:"User interruption with CTRL-BREAK",standard:"other"},{name:"SIGTTOU",number:22,action:"pause",description:"Background process cannot write to terminal output",standard:"posix"},{name:"SIGURG",number:23,action:"ignore",description:"Socket received out-of-band data",standard:"bsd"},{name:"SIGXCPU",number:24,action:"core",description:"Process timed out",standard:"bsd"},{name:"SIGXFSZ",number:25,action:"core",description:"File too big",standard:"bsd"},{name:"SIGVTALRM",number:26,action:"terminate",description:"Timeout or timer",standard:"bsd"},{name:"SIGPROF",number:27,action:"terminate",description:"Timeout or timer",standard:"bsd"},{name:"SIGWINCH",number:28,action:"ignore",description:"Terminal window size changed",standard:"bsd"},{name:"SIGIO",number:29,action:"terminate",description:"I/O is available",standard:"other"},{name:"SIGPOLL",number:29,action:"terminate",description:"Watched event",standard:"other"},{name:"SIGINFO",number:29,action:"ignore",description:"Request for process information",standard:"other"},{name:"SIGPWR",number:30,action:"terminate",description:"Device running out of power",standard:"systemv"},{name:"SIGSYS",number:31,action:"core",description:"Invalid system call",standard:"other"},{name:"SIGUNUSED",number:31,action:"terminate",description:"Invalid system call",standard:"other"}]});import{constants as PSe}from"node:os";var GR,CSe,KV=y(()=>{WV();ZV();GR=()=>{let t=HV();return[...VV,...t].map(CSe)},CSe=({name:t,number:e,description:r,action:n,forced:i=!1,standard:o})=>{let{signals:{[t]:s}}=PSe,a=s!==void 0;return{name:t,number:a?s:e,description:r,supported:a,action:n,forced:i,standard:o}}});import{constants as DSe}from"node:os";var NSe,jSe,JV,MSe,FSe,LSe,Rnt,YV=y(()=>{KV();NSe=()=>{let t=GR();return Object.fromEntries(t.map(jSe))},jSe=({name:t,number:e,description:r,supported:n,action:i,forced:o,standard:s})=>[t,{name:t,number:e,description:r,supported:n,action:i,forced:o,standard:s}],JV=NSe(),MSe=()=>{let t=GR(),e=65,r=Array.from({length:e},(n,i)=>FSe(i,t));return Object.assign({},...r)},FSe=(t,e)=>{let r=LSe(t,e);if(r===void 0)return{};let{name:n,description:i,supported:o,action:s,forced:a,standard:c}=r;return{[t]:{name:n,number:t,description:i,supported:o,action:s,forced:a,standard:c}}},LSe=(t,e)=>{let r=e.find(({name:n})=>DSe.signals[n]===t);return r!==void 0?r:e.find(n=>n.number===t)},Rnt=MSe()});import{constants as np}from"node:os";var QV,e9,t9,zSe,USe,XV,qSe,ZR,HSe,BSe,wb,ip=y(()=>{YV();QV=t=>{let e="option `killSignal`";if(t===0)throw new TypeError(`Invalid ${e}: 0 cannot be used.`);return t9(t,e)},e9=t=>t===0?t:t9(t,"`subprocess.kill()`'s argument"),t9=(t,e)=>{if(Number.isInteger(t))return zSe(t,e);if(typeof t=="string")return qSe(t,e);throw new TypeError(`Invalid ${e} ${String(t)}: it must be a string or an integer. +${ZR()}`)},zSe=(t,e)=>{if(XV.has(t))return XV.get(t);throw new TypeError(`Invalid ${e} ${t}: this signal integer does not exist. +${ZR()}`)},USe=()=>new Map(Object.entries(np.signals).reverse().map(([t,e])=>[e,t])),XV=USe(),qSe=(t,e)=>{if(t in np.signals)return t;throw t.toUpperCase()in np.signals?new TypeError(`Invalid ${e} '${t}': please rename it to '${t.toUpperCase()}'.`):new TypeError(`Invalid ${e} '${t}': this signal name does not exist. +${ZR()}`)},ZR=()=>`Available signal names: ${HSe()}. +Available signal numbers: ${BSe()}.`,HSe=()=>Object.keys(np.signals).sort().map(t=>`'${t}'`).join(", "),BSe=()=>[...new Set(Object.values(np.signals).sort((t,e)=>t-e))].join(", "),wb=t=>JV[t].description});import{setTimeout as GSe}from"node:timers/promises";var r9,ZSe,n9,VSe,WSe,KSe,VR,xb=y(()=>{Da();ip();r9=t=>{if(t===!1)return t;if(t===!0)return ZSe;if(!Number.isFinite(t)||t<0)throw new TypeError(`Expected the \`forceKillAfterDelay\` option to be a non-negative integer, got \`${t}\` (${typeof t})`);return t},ZSe=1e3*5,n9=({kill:t,options:{forceKillAfterDelay:e,killSignal:r},onInternalError:n,context:i,controller:o},s,a)=>{let{signal:c,error:l}=VSe(s,a,r);WSe(l,n);let u=t(c);return KSe({kill:t,signal:c,forceKillAfterDelay:e,killSignal:r,killResult:u,context:i,controller:o}),u},VSe=(t,e,r)=>{let[n=r,i]=Sb(t)?[void 0,t]:[t,e];if(typeof n!="string"&&!Number.isInteger(n))throw new TypeError(`The first argument must be an error instance or a signal name string/integer: ${String(n)}`);if(i!==void 0&&!Sb(i))throw new TypeError(`The second argument is optional. If specified, it must be an error instance: ${i}`);return{signal:e9(n),error:i}},WSe=(t,e)=>{t!==void 0&&e.reject(t)},KSe=async({kill:t,signal:e,forceKillAfterDelay:r,killSignal:n,killResult:i,context:o,controller:s})=>{e===n&&i&&VR({kill:t,forceKillAfterDelay:r,context:o,controllerSignal:s.signal})},VR=async({kill:t,forceKillAfterDelay:e,context:r,controllerSignal:n})=>{if(e!==!1)try{await GSe(e,void 0,{signal:n}),t("SIGKILL")&&(r.isForcefullyTerminated??=!0)}catch{}}});import{once as JSe}from"node:events";var $b,WR=y(()=>{$b=async(t,e)=>{t.aborted||await JSe(t,"abort",{signal:e})}});var i9,o9,YSe,KR=y(()=>{WR();i9=({cancelSignal:t})=>{if(t!==void 0&&Object.prototype.toString.call(t)!=="[object AbortSignal]")throw new Error(`The \`cancelSignal\` option must be an AbortSignal: ${String(t)}`)},o9=({subprocess:t,cancelSignal:e,gracefulCancel:r,context:n,controller:i})=>e===void 0||r?[]:[YSe(t,e,n,i)],YSe=async(t,e,r,{signal:n})=>{throw await $b(e,n),r.terminationReason??="cancel",t.kill(),e.reason}});var Nl,XSe,JR,s9,a9,kb,c9,l9,u9,d9,f9,p9,QSe,ewe,twe,ii,rwe,ms,jl,Ml=y(()=>{Nl=({methodName:t,isSubprocess:e,ipc:r,isConnected:n})=>{XSe(t,e,r),JR(t,e,n)},XSe=(t,e,r)=>{if(!r)throw new Error(`${ii(t,e)} can only be used if the \`ipc\` option is \`true\`.`)},JR=(t,e,r)=>{if(!r)throw new Error(`${ii(t,e)} cannot be used: the ${ms(e)} has already exited or disconnected.`)},s9=t=>{throw new Error(`${ii("getOneMessage",t)} could not complete: the ${ms(t)} exited or disconnected.`)},a9=t=>{throw new Error(`${ii("sendMessage",t)} failed: the ${ms(t)} is sending a message too, instead of listening to incoming messages. This can be fixed by both sending a message and listening to incoming messages at the same time: const [receivedMessage] = await Promise.all([ - ${ni("getOneMessage",t)}, - ${ni("sendMessage",t,"message, {strict: true}")}, -]);`)},wb=(t,e)=>new Error(`${ni("sendMessage",e)} failed when sending an acknowledgment response to the ${fs(e)}.`,{cause:t}),V9=t=>{throw new Error(`${ni("sendMessage",t)} failed: the ${fs(t)} is not listening to incoming messages.`)},W9=t=>{throw new Error(`${ni("sendMessage",t)} failed: the ${fs(t)} exited without listening to incoming messages.`)},K9=()=>new Error(`\`cancelSignal\` aborted: the ${fs(!0)} disconnected.`),J9=()=>{throw new Error("`getCancelSignal()` cannot be used without setting the `cancelSignal` subprocess option.")},Y9=({error:t,methodName:e,isSubprocess:r})=>{if(t.code==="EPIPE")throw new Error(`${ni(e,r)} cannot be used: the ${fs(r)} is disconnecting.`,{cause:t})},X9=({error:t,methodName:e,isSubprocess:r,message:n})=>{if(mSe(t))throw new Error(`${ni(e,r)}'s argument type is invalid: the message cannot be serialized: ${String(n)}.`,{cause:t})},mSe=({code:t,message:e})=>hSe.has(t)||gSe.some(r=>e.includes(r)),hSe=new Set(["ERR_MISSING_ARGS","ERR_INVALID_ARG_TYPE"]),gSe=["could not be cloned","circular structure","call stack size exceeded"],ni=(t,e,r="")=>t==="cancelSignal"?"`cancelSignal`'s `controller.abort()`":`${ySe(e)}${t}(${r})`,ySe=t=>t?"":"subprocess.",fs=t=>t?"parent process":"subprocess",Cl=t=>{t.connected&&t.disconnect()}});var Di,Nl=y(()=>{Di=()=>{let t={},e=new Promise((r,n)=>{Object.assign(t,{resolve:r,reject:n})});return Object.assign(e,t)}});var $b,jl,Ni,Q9,_Se,bSe,eV,vSe,tV,rp,xb,ps=y(()=>{wo();$b=(t,e="stdin")=>{let{options:n,fileDescriptors:i}=Ni.get(t),o=Q9(i,e,!0),s=t.stdio[o];if(s===null)throw new TypeError(eV(o,e,n,!0));return s},jl=(t,e="stdout")=>{let{options:n,fileDescriptors:i}=Ni.get(t),o=Q9(i,e,!1),s=o==="all"?t.all:t.stdio[o];if(s==null)throw new TypeError(eV(o,e,n,!1));return s},Ni=new WeakMap,Q9=(t,e,r)=>{let n=_Se(e,r);return bSe(n,e,r,t),n},_Se=(t,e)=>{let r=vR(t);if(r!==void 0)return r;let{validOptions:n,defaultValue:i}=e?{validOptions:'"stdin"',defaultValue:"stdin"}:{validOptions:'"stdout", "stderr", "all"',defaultValue:"stdout"};throw new TypeError(`"${rp(e)}" must not be "${t}". + ${ii("getOneMessage",t)}, + ${ii("sendMessage",t,"message, {strict: true}")}, +]);`)},kb=(t,e)=>new Error(`${ii("sendMessage",e)} failed when sending an acknowledgment response to the ${ms(e)}.`,{cause:t}),c9=t=>{throw new Error(`${ii("sendMessage",t)} failed: the ${ms(t)} is not listening to incoming messages.`)},l9=t=>{throw new Error(`${ii("sendMessage",t)} failed: the ${ms(t)} exited without listening to incoming messages.`)},u9=()=>new Error(`\`cancelSignal\` aborted: the ${ms(!0)} disconnected.`),d9=()=>{throw new Error("`getCancelSignal()` cannot be used without setting the `cancelSignal` subprocess option.")},f9=({error:t,methodName:e,isSubprocess:r})=>{if(t.code==="EPIPE")throw new Error(`${ii(e,r)} cannot be used: the ${ms(r)} is disconnecting.`,{cause:t})},p9=({error:t,methodName:e,isSubprocess:r,message:n})=>{if(QSe(t))throw new Error(`${ii(e,r)}'s argument type is invalid: the message cannot be serialized: ${String(n)}.`,{cause:t})},QSe=({code:t,message:e})=>ewe.has(t)||twe.some(r=>e.includes(r)),ewe=new Set(["ERR_MISSING_ARGS","ERR_INVALID_ARG_TYPE"]),twe=["could not be cloned","circular structure","call stack size exceeded"],ii=(t,e,r="")=>t==="cancelSignal"?"`cancelSignal`'s `controller.abort()`":`${rwe(e)}${t}(${r})`,rwe=t=>t?"":"subprocess.",ms=t=>t?"parent process":"subprocess",jl=t=>{t.connected&&t.disconnect()}});var Di,Fl=y(()=>{Di=()=>{let t={},e=new Promise((r,n)=>{Object.assign(t,{resolve:r,reject:n})});return Object.assign(e,t)}});var Ab,Ll,Ni,m9,nwe,iwe,h9,owe,g9,op,Eb,hs=y(()=>{xo();Ab=(t,e="stdin")=>{let{options:n,fileDescriptors:i}=Ni.get(t),o=m9(i,e,!0),s=t.stdio[o];if(s===null)throw new TypeError(h9(o,e,n,!0));return s},Ll=(t,e="stdout")=>{let{options:n,fileDescriptors:i}=Ni.get(t),o=m9(i,e,!1),s=o==="all"?t.all:t.stdio[o];if(s==null)throw new TypeError(h9(o,e,n,!1));return s},Ni=new WeakMap,m9=(t,e,r)=>{let n=nwe(e,r);return iwe(n,e,r,t),n},nwe=(t,e)=>{let r=TR(t);if(r!==void 0)return r;let{validOptions:n,defaultValue:i}=e?{validOptions:'"stdin"',defaultValue:"stdin"}:{validOptions:'"stdout", "stderr", "all"',defaultValue:"stdout"};throw new TypeError(`"${op(e)}" must not be "${t}". It must be ${n} or "fd3", "fd4" (and so on). -It is optional and defaults to "${i}".`)},bSe=(t,e,r,n)=>{let i=n[tV(t)];if(i===void 0)throw new TypeError(`"${rp(r)}" must not be ${e}. That file descriptor does not exist. -Please set the "stdio" option to ensure that file descriptor exists.`);if(i.direction==="input"&&!r)throw new TypeError(`"${rp(r)}" must not be ${e}. It must be a readable stream, not writable.`);if(i.direction!=="input"&&r)throw new TypeError(`"${rp(r)}" must not be ${e}. It must be a writable stream, not readable.`)},eV=(t,e,r,n)=>{if(t==="all"&&!r.all)return`The "all" option must be true to use "from: 'all'".`;let{optionName:i,optionValue:o}=vSe(t,r);return`The "${i}: ${xb(o)}" option is incompatible with using "${rp(n)}: ${xb(e)}". -Please set this option with "pipe" instead.`},vSe=(t,{stdin:e,stdout:r,stderr:n,stdio:i})=>{let o=tV(t);return o===0&&e!==void 0?{optionName:"stdin",optionValue:e}:o===1&&r!==void 0?{optionName:"stdout",optionValue:r}:o===2&&n!==void 0?{optionName:"stderr",optionValue:n}:{optionName:`stdio[${o}]`,optionValue:i[o]}},tV=t=>t==="all"?1:t,rp=t=>t?"to":"from",xb=t=>typeof t=="string"?`'${t}'`:typeof t=="number"?`${t}`:"Stream"});import{addAbortListener as SSe}from"node:events";var Ca,kb=y(()=>{Ca=(t,e,r)=>{let n=t.getMaxListeners();n===0||n===Number.POSITIVE_INFINITY||(t.setMaxListeners(n+e),SSe(r,()=>{t.setMaxListeners(t.getMaxListeners()-e)}))}});var Eb,qR,Ab,BR,rV,nV,np=y(()=>{Eb=(t,e)=>{e&&qR(t)},qR=t=>{t.refCounted()},Ab=(t,e)=>{e&&BR(t)},BR=t=>{t.unrefCounted()},rV=(t,e)=>{e&&(BR(t),BR(t))},nV=(t,e)=>{e&&(qR(t),qR(t))}});import{once as wSe}from"node:events";import{scheduler as xSe}from"node:timers/promises";var iV,oV,Tb,sV=y(()=>{Rb();np();Ob();Ib();iV=async({anyProcess:t,channel:e,isSubprocess:r,ipcEmitter:n},i)=>{if(cV(i)||uV(i))return;Tb.has(t)||Tb.set(t,[]);let o=Tb.get(t);if(o.push(i),!(o.length>1))for(;o.length>0;){await lV(t,n,i),await xSe.yield();let s=await aV({wrappedMessage:o[0],anyProcess:t,channel:e,isSubprocess:r,ipcEmitter:n});o.shift(),n.emit("message",s),n.emit("message:done")}},oV=async({anyProcess:t,channel:e,isSubprocess:r,ipcEmitter:n,boundOnMessage:i})=>{HR();let o=Tb.get(t);for(;o?.length>0;)await wSe(n,"message:done");t.removeListener("message",i),nV(e,r),n.connected=!1,n.emit("disconnect")},Tb=new WeakMap});import{EventEmitter as $Se}from"node:events";var ms,Pb,kSe,Cb,ip=y(()=>{sV();np();ms=(t,e,r)=>{if(Pb.has(t))return Pb.get(t);let n=new $Se;return n.connected=!0,Pb.set(t,n),kSe({ipcEmitter:n,anyProcess:t,channel:e,isSubprocess:r}),n},Pb=new WeakMap,kSe=({ipcEmitter:t,anyProcess:e,channel:r,isSubprocess:n})=>{let i=iV.bind(void 0,{anyProcess:e,channel:r,isSubprocess:n,ipcEmitter:t});e.on("message",i),e.once("disconnect",oV.bind(void 0,{anyProcess:e,channel:r,isSubprocess:n,ipcEmitter:t,boundOnMessage:i})),rV(r,n)},Cb=t=>{let e=Pb.get(t);return e===void 0?t.channel!==null:e.connected}});import{once as ESe}from"node:events";var dV,ASe,fV,aV,cV,pV,Db,TSe,Nb,mV,Ob=y(()=>{Nl();kb();Fb();Dl();ip();Rb();dV=({anyProcess:t,channel:e,isSubprocess:r,message:n,strict:i})=>{if(!i)return n;let o=ms(t,e,r),s=jb(t,o);return{id:ASe++,type:Nb,message:n,hasListeners:s}},ASe=0n,fV=(t,e)=>{if(!(e?.type!==Nb||e.hasListeners))for(let{id:r}of t)r!==void 0&&Db[r].resolve({isDeadlock:!0,hasListeners:!1})},aV=async({wrappedMessage:t,anyProcess:e,channel:r,isSubprocess:n,ipcEmitter:i})=>{if(t?.type!==Nb||!e.connected)return t;let{id:o,message:s}=t,a={id:o,type:mV,message:jb(e,i)};try{await Mb({anyProcess:e,channel:r,isSubprocess:n,ipc:!0},a)}catch(c){i.emit("strict:error",c)}return s},cV=t=>{if(t?.type!==mV)return!1;let{id:e,message:r}=t;return Db[e]?.resolve({isDeadlock:!1,hasListeners:r}),!0},pV=async(t,e,r)=>{if(t?.type!==Nb)return;let n=Di();Db[t.id]=n;let i=new AbortController;try{let{isDeadlock:o,hasListeners:s}=await Promise.race([n,TSe(e,r,i)]);o&&Z9(r),s||V9(r)}finally{i.abort(),delete Db[t.id]}},Db={},TSe=async(t,e,{signal:r})=>{Ca(t,1,r),await ESe(t,"disconnect",{signal:r}),W9(e)},Nb="execa:ipc:request",mV="execa:ipc:response"});var hV,gV,lV,op,jb,OSe,Rb=y(()=>{Nl();wo();ps();Ob();hV=(t,e,r)=>{op.has(t)||op.set(t,new Set);let n=op.get(t),i=Di(),o=r?e.id:void 0,s={onMessageSent:i,id:o};return n.add(s),{outgoingMessages:n,outgoingMessage:s}},gV=({outgoingMessages:t,outgoingMessage:e})=>{t.delete(e),e.onMessageSent.resolve()},lV=async(t,e,r)=>{for(;!jb(t,e)&&op.get(t)?.size>0;){let n=[...op.get(t)];fV(n,r),await Promise.all(n.map(({onMessageSent:i})=>i))}},op=new WeakMap,jb=(t,e)=>e.listenerCount("message")>OSe(t),OSe=t=>Ni.has(t)&&!So(Ni.get(t).options.buffer,"ipc")?1:0});import{promisify as RSe}from"node:util";var Mb,ISe,ZR,PSe,GR,Fb=y(()=>{Dl();Rb();Ob();Mb=({anyProcess:t,channel:e,isSubprocess:r,ipc:n},i,{strict:o=!1}={})=>{let s="sendMessage";return Pl({methodName:s,isSubprocess:r,ipc:n,isConnected:t.connected}),ISe({anyProcess:t,channel:e,methodName:s,isSubprocess:r,message:i,strict:o})},ISe=async({anyProcess:t,channel:e,methodName:r,isSubprocess:n,message:i,strict:o})=>{let s=dV({anyProcess:t,channel:e,isSubprocess:n,message:i,strict:o}),a=hV(t,s,o);try{await ZR({anyProcess:t,methodName:r,isSubprocess:n,wrappedMessage:s,message:i})}catch(c){throw Cl(t),c}finally{gV(a)}},ZR=async({anyProcess:t,methodName:e,isSubprocess:r,wrappedMessage:n,message:i})=>{let o=PSe(t);try{await Promise.all([pV(n,t,r),o(n)])}catch(s){throw Y9({error:s,methodName:e,isSubprocess:r}),X9({error:s,methodName:e,isSubprocess:r,message:i}),s}},PSe=t=>{if(GR.has(t))return GR.get(t);let e=RSe(t.send.bind(t));return GR.set(t,e),e},GR=new WeakMap});import{scheduler as CSe}from"node:timers/promises";var _V,bV,DSe,yV,uV,vV,HR,VR,Ib=y(()=>{Fb();ip();Dl();_V=(t,e)=>{let r="cancelSignal";return UR(r,!1,t.connected),ZR({anyProcess:t,methodName:r,isSubprocess:!1,wrappedMessage:{type:vV,message:e},message:e})},bV=async({anyProcess:t,channel:e,isSubprocess:r,ipc:n})=>(await DSe({anyProcess:t,channel:e,isSubprocess:r,ipc:n}),VR.signal),DSe=async({anyProcess:t,channel:e,isSubprocess:r,ipc:n})=>{if(!yV){if(yV=!0,!n){J9();return}if(e===null){HR();return}ms(t,e,r),await CSe.yield()}},yV=!1,uV=t=>t?.type!==vV?!1:(VR.abort(t.message),!0),vV="execa:ipc:cancel",HR=()=>{VR.abort(K9())},VR=new AbortController});var SV,wV,NSe,jSe,WR=y(()=>{LR();Ib();vb();SV=({gracefulCancel:t,cancelSignal:e,ipc:r,serialization:n})=>{if(t){if(e===void 0)throw new Error("The `cancelSignal` option must be defined when setting the `gracefulCancel` option.");if(!r)throw new Error("The `ipc` option cannot be false when setting the `gracefulCancel` option.");if(n==="json")throw new Error("The `serialization` option cannot be 'json' when setting the `gracefulCancel` option.")}},wV=({subprocess:t,cancelSignal:e,gracefulCancel:r,forceKillAfterDelay:n,context:i,controller:o})=>r?[NSe({subprocess:t,cancelSignal:e,forceKillAfterDelay:n,context:i,controller:o})]:[],NSe=async({subprocess:t,cancelSignal:e,forceKillAfterDelay:r,context:n,controller:{signal:i}})=>{await Sb(e,i);let o=jSe(e);throw await _V(t,o),FR({kill:t.kill,forceKillAfterDelay:r,context:n,controllerSignal:i}),n.terminationReason??="gracefulCancel",e.reason},jSe=({reason:t})=>{if(!(t instanceof DOMException))return t;let e=new Error(t.message);return Object.defineProperty(e,"stack",{value:t.stack,enumerable:!1,configurable:!0,writable:!0}),e}});import{setTimeout as MSe}from"node:timers/promises";var xV,$V,FSe,KR=y(()=>{Pa();xV=({timeout:t})=>{if(t!==void 0&&(!Number.isFinite(t)||t<0))throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${t}\` (${typeof t})`)},$V=(t,e,r,n)=>e===0||e===void 0?[]:[FSe(t,e,r,n)],FSe=async(t,e,r,{signal:n})=>{throw await MSe(e,void 0,{signal:n}),r.terminationReason??="timeout",t.kill(),new ri}});import{execPath as LSe,execArgv as zSe}from"node:process";import kV from"node:path";var EV,AV,JR=y(()=>{El();EV=({options:t})=>{if(t.node===!1)throw new TypeError('The "node" option cannot be false with `execaNode()`.');return{options:{...t,node:!0}}},AV=(t,e,{node:r=!1,nodePath:n=LSe,nodeOptions:i=zSe.filter(c=>!c.startsWith("--inspect")),cwd:o,execPath:s,...a})=>{if(s!==void 0)throw new TypeError('The "execPath" option has been removed. Please use the "nodePath" option instead.');let c=kl(n,'The "nodePath" option'),l=kV.resolve(o,c),u={...a,nodePath:l,node:r,cwd:o};if(!r)return[t,e,u];if(kV.basename(t,".exe")==="node")throw new TypeError('When the "node" option is true, the first argument does not need to be "node".');return[l,[...i,t,...e],{ipc:!0,...u,shell:!1}]}});import{serialize as USe}from"node:v8";var TV,qSe,BSe,HSe,OV,YR=y(()=>{TV=({ipcInput:t,ipc:e,serialization:r})=>{if(t!==void 0){if(!e)throw new Error("The `ipcInput` option cannot be set unless the `ipc` option is `true`.");HSe[r](t)}},qSe=t=>{try{USe(t)}catch(e){throw new Error("The `ipcInput` option is not serializable with a structured clone.",{cause:e})}},BSe=t=>{try{JSON.stringify(t)}catch(e){throw new Error("The `ipcInput` option is not serializable with JSON.",{cause:e})}},HSe={advanced:qSe,json:BSe},OV=async(t,e)=>{e!==void 0&&await t.sendMessage(e)}});var IV,GSe,an,XR,ZSe,RV,Lb,Da=y(()=>{IV=({encoding:t})=>{if(XR.has(t))return;let e=ZSe(t);if(e!==void 0)throw new TypeError(`Invalid option \`encoding: ${Lb(t)}\`. -Please rename it to ${Lb(e)}.`);let r=[...XR].map(n=>Lb(n)).join(", ");throw new TypeError(`Invalid option \`encoding: ${Lb(t)}\`. -Please rename it to one of: ${r}.`)},GSe=new Set(["utf8","utf16le"]),an=new Set(["buffer","hex","base64","base64url","latin1","ascii"]),XR=new Set([...GSe,...an]),ZSe=t=>{if(t===null)return"buffer";if(typeof t!="string")return;let e=t.toLowerCase();if(e in RV)return RV[e];if(XR.has(e))return e},RV={"utf-8":"utf8","utf-16le":"utf16le","ucs-2":"utf16le",ucs2:"utf16le",binary:"latin1"},Lb=t=>typeof t=="string"?`"${t}"`:String(t)});import{statSync as VSe}from"node:fs";import WSe from"node:path";import KSe from"node:process";var PV,CV,DV,QR=y(()=>{El();PV=(t=CV())=>{let e=kl(t,'The "cwd" option');return WSe.resolve(e)},CV=()=>{try{return KSe.cwd()}catch(t){throw t.message=`The current directory does not exist. -${t.message}`,t}},DV=(t,e)=>{if(e===CV())return t;let r;try{r=VSe(e)}catch(n){return`The "cwd" option is invalid: ${e}. +It is optional and defaults to "${i}".`)},iwe=(t,e,r,n)=>{let i=n[g9(t)];if(i===void 0)throw new TypeError(`"${op(r)}" must not be ${e}. That file descriptor does not exist. +Please set the "stdio" option to ensure that file descriptor exists.`);if(i.direction==="input"&&!r)throw new TypeError(`"${op(r)}" must not be ${e}. It must be a readable stream, not writable.`);if(i.direction!=="input"&&r)throw new TypeError(`"${op(r)}" must not be ${e}. It must be a writable stream, not readable.`)},h9=(t,e,r,n)=>{if(t==="all"&&!r.all)return`The "all" option must be true to use "from: 'all'".`;let{optionName:i,optionValue:o}=owe(t,r);return`The "${i}: ${Eb(o)}" option is incompatible with using "${op(n)}: ${Eb(e)}". +Please set this option with "pipe" instead.`},owe=(t,{stdin:e,stdout:r,stderr:n,stdio:i})=>{let o=g9(t);return o===0&&e!==void 0?{optionName:"stdin",optionValue:e}:o===1&&r!==void 0?{optionName:"stdout",optionValue:r}:o===2&&n!==void 0?{optionName:"stderr",optionValue:n}:{optionName:`stdio[${o}]`,optionValue:i[o]}},g9=t=>t==="all"?1:t,op=t=>t?"to":"from",Eb=t=>typeof t=="string"?`'${t}'`:typeof t=="number"?`${t}`:"Stream"});import{addAbortListener as swe}from"node:events";var Na,Ob=y(()=>{Na=(t,e,r)=>{let n=t.getMaxListeners();n===0||n===Number.POSITIVE_INFINITY||(t.setMaxListeners(n+e),swe(r,()=>{t.setMaxListeners(t.getMaxListeners()-e)}))}});var Tb,YR,Rb,XR,y9,_9,sp=y(()=>{Tb=(t,e)=>{e&&YR(t)},YR=t=>{t.refCounted()},Rb=(t,e)=>{e&&XR(t)},XR=t=>{t.unrefCounted()},y9=(t,e)=>{e&&(XR(t),XR(t))},_9=(t,e)=>{e&&(YR(t),YR(t))}});import{once as awe}from"node:events";import{scheduler as cwe}from"node:timers/promises";var b9,v9,Ib,S9=y(()=>{Cb();sp();Pb();Db();b9=async({anyProcess:t,channel:e,isSubprocess:r,ipcEmitter:n},i)=>{if(x9(i)||k9(i))return;Ib.has(t)||Ib.set(t,[]);let o=Ib.get(t);if(o.push(i),!(o.length>1))for(;o.length>0;){await $9(t,n,i),await cwe.yield();let s=await w9({wrappedMessage:o[0],anyProcess:t,channel:e,isSubprocess:r,ipcEmitter:n});o.shift(),n.emit("message",s),n.emit("message:done")}},v9=async({anyProcess:t,channel:e,isSubprocess:r,ipcEmitter:n,boundOnMessage:i})=>{QR();let o=Ib.get(t);for(;o?.length>0;)await awe(n,"message:done");t.removeListener("message",i),_9(e,r),n.connected=!1,n.emit("disconnect")},Ib=new WeakMap});import{EventEmitter as lwe}from"node:events";var gs,Nb,uwe,jb,ap=y(()=>{S9();sp();gs=(t,e,r)=>{if(Nb.has(t))return Nb.get(t);let n=new lwe;return n.connected=!0,Nb.set(t,n),uwe({ipcEmitter:n,anyProcess:t,channel:e,isSubprocess:r}),n},Nb=new WeakMap,uwe=({ipcEmitter:t,anyProcess:e,channel:r,isSubprocess:n})=>{let i=b9.bind(void 0,{anyProcess:e,channel:r,isSubprocess:n,ipcEmitter:t});e.on("message",i),e.once("disconnect",v9.bind(void 0,{anyProcess:e,channel:r,isSubprocess:n,ipcEmitter:t,boundOnMessage:i})),y9(r,n)},jb=t=>{let e=Nb.get(t);return e===void 0?t.channel!==null:e.connected}});import{once as dwe}from"node:events";var E9,fwe,A9,w9,x9,O9,Mb,pwe,Fb,T9,Pb=y(()=>{Fl();Ob();Ub();Ml();ap();Cb();E9=({anyProcess:t,channel:e,isSubprocess:r,message:n,strict:i})=>{if(!i)return n;let o=gs(t,e,r),s=Lb(t,o);return{id:fwe++,type:Fb,message:n,hasListeners:s}},fwe=0n,A9=(t,e)=>{if(!(e?.type!==Fb||e.hasListeners))for(let{id:r}of t)r!==void 0&&Mb[r].resolve({isDeadlock:!0,hasListeners:!1})},w9=async({wrappedMessage:t,anyProcess:e,channel:r,isSubprocess:n,ipcEmitter:i})=>{if(t?.type!==Fb||!e.connected)return t;let{id:o,message:s}=t,a={id:o,type:T9,message:Lb(e,i)};try{await zb({anyProcess:e,channel:r,isSubprocess:n,ipc:!0},a)}catch(c){i.emit("strict:error",c)}return s},x9=t=>{if(t?.type!==T9)return!1;let{id:e,message:r}=t;return Mb[e]?.resolve({isDeadlock:!1,hasListeners:r}),!0},O9=async(t,e,r)=>{if(t?.type!==Fb)return;let n=Di();Mb[t.id]=n;let i=new AbortController;try{let{isDeadlock:o,hasListeners:s}=await Promise.race([n,pwe(e,r,i)]);o&&a9(r),s||c9(r)}finally{i.abort(),delete Mb[t.id]}},Mb={},pwe=async(t,e,{signal:r})=>{Na(t,1,r),await dwe(t,"disconnect",{signal:r}),l9(e)},Fb="execa:ipc:request",T9="execa:ipc:response"});var R9,I9,$9,cp,Lb,mwe,Cb=y(()=>{Fl();xo();hs();Pb();R9=(t,e,r)=>{cp.has(t)||cp.set(t,new Set);let n=cp.get(t),i=Di(),o=r?e.id:void 0,s={onMessageSent:i,id:o};return n.add(s),{outgoingMessages:n,outgoingMessage:s}},I9=({outgoingMessages:t,outgoingMessage:e})=>{t.delete(e),e.onMessageSent.resolve()},$9=async(t,e,r)=>{for(;!Lb(t,e)&&cp.get(t)?.size>0;){let n=[...cp.get(t)];A9(n,r),await Promise.all(n.map(({onMessageSent:i})=>i))}},cp=new WeakMap,Lb=(t,e)=>e.listenerCount("message")>mwe(t),mwe=t=>Ni.has(t)&&!wo(Ni.get(t).options.buffer,"ipc")?1:0});import{promisify as hwe}from"node:util";var zb,gwe,tI,ywe,eI,Ub=y(()=>{Ml();Cb();Pb();zb=({anyProcess:t,channel:e,isSubprocess:r,ipc:n},i,{strict:o=!1}={})=>{let s="sendMessage";return Nl({methodName:s,isSubprocess:r,ipc:n,isConnected:t.connected}),gwe({anyProcess:t,channel:e,methodName:s,isSubprocess:r,message:i,strict:o})},gwe=async({anyProcess:t,channel:e,methodName:r,isSubprocess:n,message:i,strict:o})=>{let s=E9({anyProcess:t,channel:e,isSubprocess:n,message:i,strict:o}),a=R9(t,s,o);try{await tI({anyProcess:t,methodName:r,isSubprocess:n,wrappedMessage:s,message:i})}catch(c){throw jl(t),c}finally{I9(a)}},tI=async({anyProcess:t,methodName:e,isSubprocess:r,wrappedMessage:n,message:i})=>{let o=ywe(t);try{await Promise.all([O9(n,t,r),o(n)])}catch(s){throw f9({error:s,methodName:e,isSubprocess:r}),p9({error:s,methodName:e,isSubprocess:r,message:i}),s}},ywe=t=>{if(eI.has(t))return eI.get(t);let e=hwe(t.send.bind(t));return eI.set(t,e),e},eI=new WeakMap});import{scheduler as _we}from"node:timers/promises";var C9,D9,bwe,P9,k9,N9,QR,rI,Db=y(()=>{Ub();ap();Ml();C9=(t,e)=>{let r="cancelSignal";return JR(r,!1,t.connected),tI({anyProcess:t,methodName:r,isSubprocess:!1,wrappedMessage:{type:N9,message:e},message:e})},D9=async({anyProcess:t,channel:e,isSubprocess:r,ipc:n})=>(await bwe({anyProcess:t,channel:e,isSubprocess:r,ipc:n}),rI.signal),bwe=async({anyProcess:t,channel:e,isSubprocess:r,ipc:n})=>{if(!P9){if(P9=!0,!n){d9();return}if(e===null){QR();return}gs(t,e,r),await _we.yield()}},P9=!1,k9=t=>t?.type!==N9?!1:(rI.abort(t.message),!0),N9="execa:ipc:cancel",QR=()=>{rI.abort(u9())},rI=new AbortController});var j9,M9,vwe,Swe,nI=y(()=>{WR();Db();xb();j9=({gracefulCancel:t,cancelSignal:e,ipc:r,serialization:n})=>{if(t){if(e===void 0)throw new Error("The `cancelSignal` option must be defined when setting the `gracefulCancel` option.");if(!r)throw new Error("The `ipc` option cannot be false when setting the `gracefulCancel` option.");if(n==="json")throw new Error("The `serialization` option cannot be 'json' when setting the `gracefulCancel` option.")}},M9=({subprocess:t,cancelSignal:e,gracefulCancel:r,forceKillAfterDelay:n,context:i,controller:o})=>r?[vwe({subprocess:t,cancelSignal:e,forceKillAfterDelay:n,context:i,controller:o})]:[],vwe=async({subprocess:t,cancelSignal:e,forceKillAfterDelay:r,context:n,controller:{signal:i}})=>{await $b(e,i);let o=Swe(e);throw await C9(t,o),VR({kill:t.kill,forceKillAfterDelay:r,context:n,controllerSignal:i}),n.terminationReason??="gracefulCancel",e.reason},Swe=({reason:t})=>{if(!(t instanceof DOMException))return t;let e=new Error(t.message);return Object.defineProperty(e,"stack",{value:t.stack,enumerable:!1,configurable:!0,writable:!0}),e}});import{setTimeout as wwe}from"node:timers/promises";var F9,L9,xwe,iI=y(()=>{Da();F9=({timeout:t})=>{if(t!==void 0&&(!Number.isFinite(t)||t<0))throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${t}\` (${typeof t})`)},L9=(t,e,r,n)=>e===0||e===void 0?[]:[xwe(t,e,r,n)],xwe=async(t,e,r,{signal:n})=>{throw await wwe(e,void 0,{signal:n}),r.terminationReason??="timeout",t.kill(),new ni}});import{execPath as $we,execArgv as kwe}from"node:process";import z9 from"node:path";var U9,q9,oI=y(()=>{Tl();U9=({options:t})=>{if(t.node===!1)throw new TypeError('The "node" option cannot be false with `execaNode()`.');return{options:{...t,node:!0}}},q9=(t,e,{node:r=!1,nodePath:n=$we,nodeOptions:i=kwe.filter(c=>!c.startsWith("--inspect")),cwd:o,execPath:s,...a})=>{if(s!==void 0)throw new TypeError('The "execPath" option has been removed. Please use the "nodePath" option instead.');let c=Ol(n,'The "nodePath" option'),l=z9.resolve(o,c),u={...a,nodePath:l,node:r,cwd:o};if(!r)return[t,e,u];if(z9.basename(t,".exe")==="node")throw new TypeError('When the "node" option is true, the first argument does not need to be "node".');return[l,[...i,t,...e],{ipc:!0,...u,shell:!1}]}});import{serialize as Ewe}from"node:v8";var H9,Awe,Owe,Twe,B9,sI=y(()=>{H9=({ipcInput:t,ipc:e,serialization:r})=>{if(t!==void 0){if(!e)throw new Error("The `ipcInput` option cannot be set unless the `ipc` option is `true`.");Twe[r](t)}},Awe=t=>{try{Ewe(t)}catch(e){throw new Error("The `ipcInput` option is not serializable with a structured clone.",{cause:e})}},Owe=t=>{try{JSON.stringify(t)}catch(e){throw new Error("The `ipcInput` option is not serializable with JSON.",{cause:e})}},Twe={advanced:Awe,json:Owe},B9=async(t,e)=>{e!==void 0&&await t.sendMessage(e)}});var Z9,Rwe,cn,aI,Iwe,G9,qb,ja=y(()=>{Z9=({encoding:t})=>{if(aI.has(t))return;let e=Iwe(t);if(e!==void 0)throw new TypeError(`Invalid option \`encoding: ${qb(t)}\`. +Please rename it to ${qb(e)}.`);let r=[...aI].map(n=>qb(n)).join(", ");throw new TypeError(`Invalid option \`encoding: ${qb(t)}\`. +Please rename it to one of: ${r}.`)},Rwe=new Set(["utf8","utf16le"]),cn=new Set(["buffer","hex","base64","base64url","latin1","ascii"]),aI=new Set([...Rwe,...cn]),Iwe=t=>{if(t===null)return"buffer";if(typeof t!="string")return;let e=t.toLowerCase();if(e in G9)return G9[e];if(aI.has(e))return e},G9={"utf-8":"utf8","utf-16le":"utf16le","ucs-2":"utf16le",ucs2:"utf16le",binary:"latin1"},qb=t=>typeof t=="string"?`"${t}"`:String(t)});import{statSync as Pwe}from"node:fs";import Cwe from"node:path";import Dwe from"node:process";var V9,W9,K9,cI=y(()=>{Tl();V9=(t=W9())=>{let e=Ol(t,'The "cwd" option');return Cwe.resolve(e)},W9=()=>{try{return Dwe.cwd()}catch(t){throw t.message=`The current directory does not exist. +${t.message}`,t}},K9=(t,e)=>{if(e===W9())return t;let r;try{r=Pwe(e)}catch(n){return`The "cwd" option is invalid: ${e}. ${n.message} ${t}`}return r.isDirectory()?t:`The "cwd" option is not a directory: ${e}. -${t}`}});import JSe from"node:path";import NV from"node:process";var jV,zb,YSe,XSe,eI=y(()=>{jV=St(g9(),1);x9();vb();tp();zR();WR();KR();JR();YR();Da();QR();El();wo();zb=(t,e,r)=>{r.cwd=PV(r.cwd);let[n,i,o]=AV(t,e,r),{command:s,args:a,options:c}=jV.default._parse(n,i,o),l=oZ(c),u=YSe(l);return xV(u),IV(u),TV(u),B9(u),SV(u),u.shell=hR(u.shell),u.env=XSe(u),u.killSignal=F9(u.killSignal),u.forceKillAfterDelay=U9(u.forceKillAfterDelay),u.lines=u.lines.map((d,f)=>d&&!an.has(u.encoding)&&u.buffer[f]),NV.platform==="win32"&&JSe.basename(s,".exe")==="cmd"&&a.unshift("/q"),{file:s,commandArguments:a,options:u}},YSe=({extendEnv:t=!0,preferLocal:e=!1,cwd:r,localDir:n=r,encoding:i="utf8",reject:o=!0,cleanup:s=!0,all:a=!1,windowsHide:c=!0,killSignal:l="SIGTERM",forceKillAfterDelay:u=!0,gracefulCancel:d=!1,ipcInput:f,ipc:p=f!==void 0||d,serialization:m="advanced",...h})=>({...h,extendEnv:t,preferLocal:e,cwd:r,localDirectory:n,encoding:i,reject:o,cleanup:s,all:a,windowsHide:c,killSignal:l,forceKillAfterDelay:u,gracefulCancel:d,ipcInput:f,ipc:p,serialization:m}),XSe=({env:t,extendEnv:e,preferLocal:r,node:n,localDirectory:i,nodePath:o})=>{let s=e?{...NV.env,...t}:t;return r||n?w9({env:s,cwd:i,execPath:o,preferLocal:r,addExecPath:n}):s}});var Ub,tI=y(()=>{Ub=(t,e,r)=>r.shell&&e.length>0?[[t,...e].join(" "),[],r]:[t,e,r]});function Ml(t){if(typeof t=="string")return QSe(t);if(!(ArrayBuffer.isView(t)&&t.BYTES_PER_ELEMENT===1))throw new Error("Input must be a string or a Uint8Array");return ewe(t)}var QSe,ewe,MV,twe,FV,rwe,rI=y(()=>{QSe=t=>t.at(-1)===MV?t.slice(0,t.at(-2)===FV?-2:-1):t,ewe=t=>t.at(-1)===twe?t.subarray(0,t.at(-2)===rwe?-2:-1):t,MV=` -`,twe=MV.codePointAt(0),FV="\r",rwe=FV.codePointAt(0)});function ii(t,{checkOpen:e=!0}={}){return t!==null&&typeof t=="object"&&(t.writable||t.readable||!e||t.writable===void 0&&t.readable===void 0)&&typeof t.pipe=="function"}function nI(t,{checkOpen:e=!0}={}){return ii(t,{checkOpen:e})&&(t.writable||!e)&&typeof t.write=="function"&&typeof t.end=="function"&&typeof t.writable=="boolean"&&typeof t.writableObjectMode=="boolean"&&typeof t.destroy=="function"&&typeof t.destroyed=="boolean"}function Na(t,{checkOpen:e=!0}={}){return ii(t,{checkOpen:e})&&(t.readable||!e)&&typeof t.read=="function"&&typeof t.readable=="boolean"&&typeof t.readableObjectMode=="boolean"&&typeof t.destroy=="function"&&typeof t.destroyed=="boolean"}function iI(t,e){return nI(t,e)&&Na(t,e)}var ja=y(()=>{});function LV(){return this[sI].next()}function zV(t){return this[sI].return(t)}function aI({preventCancel:t=!1}={}){let e=this.getReader(),r=new oI(e,t),n=Object.create(iwe);return n[sI]=r,n}var nwe,oI,sI,iwe,UV=y(()=>{nwe=Object.getPrototypeOf(Object.getPrototypeOf(async function*(){}).prototype),oI=class{#t;#r;#e=!1;#n=void 0;constructor(e,r){this.#t=e,this.#r=r}next(){let e=()=>this.#o();return this.#n=this.#n?this.#n.then(e,e):e(),this.#n}return(e){let r=()=>this.#i(e);return this.#n?this.#n.then(r,r):r()}async#o(){if(this.#e)return{done:!0,value:void 0};let e;try{e=await this.#t.read()}catch(r){throw this.#n=void 0,this.#e=!0,this.#t.releaseLock(),r}return e.done&&(this.#n=void 0,this.#e=!0,this.#t.releaseLock()),e}async#i(e){if(this.#e)return{done:!0,value:e};if(this.#e=!0,!this.#r){let r=this.#t.cancel(e);return this.#t.releaseLock(),await r,{done:!0,value:e}}return this.#t.releaseLock(),{done:!0,value:e}}},sI=Symbol();Object.defineProperty(LV,"name",{value:"next"});Object.defineProperty(zV,"name",{value:"return"});iwe=Object.create(nwe,{next:{enumerable:!0,configurable:!0,writable:!0,value:LV},return:{enumerable:!0,configurable:!0,writable:!0,value:zV}})});var qV=y(()=>{});var BV=y(()=>{UV();qV()});var HV,owe,swe,awe,sp,cI=y(()=>{ja();BV();HV=t=>{if(Na(t,{checkOpen:!1})&&sp.on!==void 0)return swe(t);if(typeof t?.[Symbol.asyncIterator]=="function")return t;if(owe.call(t)==="[object ReadableStream]")return aI.call(t);throw new TypeError("The first argument must be a Readable, a ReadableStream, or an async iterable.")},{toString:owe}=Object.prototype,swe=async function*(t){let e=new AbortController,r={};awe(t,e,r);try{for await(let[n]of sp.on(t,"data",{signal:e.signal}))yield n}catch(n){if(r.error!==void 0)throw r.error;if(!e.signal.aborted)throw n}finally{t.destroy()}},awe=async(t,e,r)=>{try{await sp.finished(t,{cleanup:!0,readable:!0,writable:!1,error:!1})}catch(n){r.error=n}finally{e.abort()}},sp={}});var Fl,cwe,VV,GV,lwe,ZV,ji,ap=y(()=>{cI();Fl=async(t,{init:e,convertChunk:r,getSize:n,truncateChunk:i,addChunk:o,getFinalChunk:s,finalize:a},{maxBuffer:c=Number.POSITIVE_INFINITY}={})=>{let l=HV(t),u=e();u.length=0;try{for await(let d of l){let f=lwe(d),p=r[f](d,u);VV({convertedChunk:p,state:u,getSize:n,truncateChunk:i,addChunk:o,maxBuffer:c})}return cwe({state:u,convertChunk:r,getSize:n,truncateChunk:i,addChunk:o,getFinalChunk:s,maxBuffer:c}),a(u)}catch(d){let f=typeof d=="object"&&d!==null?d:new Error(d);throw f.bufferedData=a(u),f}},cwe=({state:t,getSize:e,truncateChunk:r,addChunk:n,getFinalChunk:i,maxBuffer:o})=>{let s=i(t);s!==void 0&&VV({convertedChunk:s,state:t,getSize:e,truncateChunk:r,addChunk:n,maxBuffer:o})},VV=({convertedChunk:t,state:e,getSize:r,truncateChunk:n,addChunk:i,maxBuffer:o})=>{let s=r(t),a=e.length+s;if(a<=o){GV(t,e,i,a);return}let c=n(t,o-e.length);throw c!==void 0&&GV(c,e,i,o),new ji},GV=(t,e,r,n)=>{e.contents=r(t,e,n),e.length=n},lwe=t=>{let e=typeof t;if(e==="string")return"string";if(e!=="object"||t===null)return"others";if(globalThis.Buffer?.isBuffer(t))return"buffer";let r=ZV.call(t);return r==="[object ArrayBuffer]"?"arrayBuffer":r==="[object DataView]"?"dataView":Number.isInteger(t.byteLength)&&Number.isInteger(t.byteOffset)&&ZV.call(t.buffer)==="[object ArrayBuffer]"?"typedArray":"others"},{toString:ZV}=Object.prototype,ji=class extends Error{name="MaxBufferError";constructor(){super("maxBuffer exceeded")}}});var xo,cp,qb,Bb,Hb,Gb=y(()=>{xo=t=>t,cp=()=>{},qb=({contents:t})=>t,Bb=t=>{throw new Error(`Streams in object mode are not supported: ${String(t)}`)},Hb=t=>t.length});async function Zb(t,e){return Fl(t,pwe,e)}var uwe,dwe,fwe,pwe,WV=y(()=>{ap();Gb();uwe=()=>({contents:[]}),dwe=()=>1,fwe=(t,{contents:e})=>(e.push(t),e),pwe={init:uwe,convertChunk:{string:xo,buffer:xo,arrayBuffer:xo,dataView:xo,typedArray:xo,others:xo},getSize:dwe,truncateChunk:cp,addChunk:fwe,getFinalChunk:cp,finalize:qb}});async function Vb(t,e){return Fl(t,wwe,e)}var mwe,hwe,gwe,KV,JV,ywe,_we,bwe,vwe,XV,YV,Swe,QV,wwe,eW=y(()=>{ap();Gb();mwe=()=>({contents:new ArrayBuffer(0)}),hwe=t=>gwe.encode(t),gwe=new TextEncoder,KV=t=>new Uint8Array(t),JV=t=>new Uint8Array(t.buffer,t.byteOffset,t.byteLength),ywe=(t,e)=>t.slice(0,e),_we=(t,{contents:e,length:r},n)=>{let i=QV()?vwe(e,n):bwe(e,n);return new Uint8Array(i).set(t,r),i},bwe=(t,e)=>{if(e<=t.byteLength)return t;let r=new ArrayBuffer(XV(e));return new Uint8Array(r).set(new Uint8Array(t),0),r},vwe=(t,e)=>{if(e<=t.maxByteLength)return t.resize(e),t;let r=new ArrayBuffer(e,{maxByteLength:XV(e)});return new Uint8Array(r).set(new Uint8Array(t),0),r},XV=t=>YV**Math.ceil(Math.log(t)/Math.log(YV)),YV=2,Swe=({contents:t,length:e})=>QV()?t:t.slice(0,e),QV=()=>"resize"in ArrayBuffer.prototype,wwe={init:mwe,convertChunk:{string:hwe,buffer:KV,arrayBuffer:KV,dataView:JV,typedArray:JV,others:Bb},getSize:Hb,truncateChunk:ywe,addChunk:_we,getFinalChunk:cp,finalize:Swe}});async function Kb(t,e){return Fl(t,Awe,e)}var xwe,Wb,$we,kwe,Ewe,Awe,tW=y(()=>{ap();Gb();xwe=()=>({contents:"",textDecoder:new TextDecoder}),Wb=(t,{textDecoder:e})=>e.decode(t,{stream:!0}),$we=(t,{contents:e})=>e+t,kwe=(t,e)=>t.slice(0,e),Ewe=({textDecoder:t})=>{let e=t.decode();return e===""?void 0:e},Awe={init:xwe,convertChunk:{string:xo,buffer:Wb,arrayBuffer:Wb,dataView:Wb,typedArray:Wb,others:Bb},getSize:Hb,truncateChunk:kwe,addChunk:$we,getFinalChunk:Ewe,finalize:qb}});var rW=y(()=>{WV();eW();tW();ap()});import{on as Twe}from"node:events";import{finished as Owe}from"node:stream/promises";var Jb=y(()=>{cI();rW();Object.assign(sp,{on:Twe,finished:Owe})});var nW,Rwe,iW,oW,Iwe,sW,aW,Yb,Ma=y(()=>{Jb();vo();wo();nW=({error:t,stream:e,readableObjectMode:r,lines:n,encoding:i,fdNumber:o})=>{if(!(t instanceof ji))throw t;if(o==="all")return t;let s=Rwe(r,n,i);throw t.maxBufferInfo={fdNumber:o,unit:s},e.destroy(),t},Rwe=(t,e,r)=>t?"objects":e?"lines":r==="buffer"?"bytes":"characters",iW=(t,e,r)=>{if(e.length!==r)return;let n=new ji;throw n.maxBufferInfo={fdNumber:"ipc"},n},oW=(t,e)=>{let{streamName:r,threshold:n,unit:i}=Iwe(t,e);return`Command's ${r} was larger than ${n} ${i}`},Iwe=(t,e)=>{if(t?.maxBufferInfo===void 0)return{streamName:"output",threshold:e[1],unit:"bytes"};let{maxBufferInfo:{fdNumber:r,unit:n}}=t;delete t.maxBufferInfo;let i=So(e,r);return r==="ipc"?{streamName:"IPC output",threshold:i,unit:"messages"}:{streamName:nb(r),threshold:i,unit:n}},sW=(t,e,r)=>t?.code==="ENOBUFS"&&e!==null&&e.some(n=>n!==null&&n.length>Yb(r)),aW=(t,e,r)=>{if(!e)return t;let n=Yb(r);return t.length>n?t.slice(0,n):t},Yb=([,t])=>t});import{inspect as Pwe}from"node:util";var lW,Cwe,Dwe,Nwe,jwe,Mwe,cW,uW=y(()=>{rI();sn();QR();sb();Ma();tp();Pa();lW=({stdio:t,all:e,ipcOutput:r,originalError:n,signal:i,signalDescription:o,exitCode:s,escapedCommand:a,timedOut:c,isCanceled:l,isGracefullyCanceled:u,isMaxBuffer:d,isForcefullyTerminated:f,forceKillAfterDelay:p,killSignal:m,maxBuffer:h,timeout:g,cwd:b})=>{let _=n?.code,S=Cwe({originalError:n,timedOut:c,timeout:g,isMaxBuffer:d,maxBuffer:h,errorCode:_,signal:i,signalDescription:o,exitCode:s,isCanceled:l,isGracefullyCanceled:u,isForcefullyTerminated:f,forceKillAfterDelay:p,killSignal:m}),x=Nwe(n,b),w=x===void 0?"":` -${x}`,O=`${S}: ${a}${w}`,T=e===void 0?[t[2],t[1]]:[e],A=[O,...T,...t.slice(3),r.map(D=>jwe(D)).join(` -`)].map(D=>Yf(Ml(Mwe(D)))).filter(Boolean).join(` - -`);return{originalMessage:x,shortMessage:O,message:A}},Cwe=({originalError:t,timedOut:e,timeout:r,isMaxBuffer:n,maxBuffer:i,errorCode:o,signal:s,signalDescription:a,exitCode:c,isCanceled:l,isGracefullyCanceled:u,isForcefullyTerminated:d,forceKillAfterDelay:f,killSignal:p})=>{let m=Dwe(d,f);return e?`Command timed out after ${r} milliseconds${m}`:u?s===void 0?`Command was gracefully canceled with exit code ${c}`:d?`Command was gracefully canceled${m}`:`Command was gracefully canceled with ${s} (${a})`:l?`Command was canceled${m}`:n?`${oW(t,i)}${m}`:o!==void 0?`Command failed with ${o}${m}`:d?`Command was killed with ${p} (${bb(p)})${m}`:s!==void 0?`Command was killed with ${s} (${a})`:c!==void 0?`Command failed with exit code ${c}`:"Command failed"},Dwe=(t,e)=>t?` and was forcefully terminated after ${e} milliseconds`:"",Nwe=(t,e)=>{if(t instanceof ri)return;let r=E9(t)?t.originalMessage:String(t?.message??t),n=Yf(DV(r,e));return n===""?void 0:n},jwe=t=>typeof t=="string"?t:Pwe(t),Mwe=t=>Array.isArray(t)?t.map(e=>Ml(cW(e))).filter(Boolean).join(` -`):cW(t),cW=t=>typeof t=="string"?t:qt(t)?tb(t):""});var Xb,Ll,lp,Fwe,dW,Lwe,up=y(()=>{tp();fb();Pa();uW();Xb=({command:t,escapedCommand:e,stdio:r,all:n,ipcOutput:i,options:{cwd:o},startTime:s})=>dW({command:t,escapedCommand:e,cwd:o,durationMs:kR(s),failed:!1,timedOut:!1,isCanceled:!1,isGracefullyCanceled:!1,isTerminated:!1,isMaxBuffer:!1,isForcefullyTerminated:!1,exitCode:0,stdout:r[1],stderr:r[2],all:n,stdio:r,ipcOutput:i,pipedFrom:[]}),Ll=({error:t,command:e,escapedCommand:r,fileDescriptors:n,options:i,startTime:o,isSync:s})=>lp({error:t,command:e,escapedCommand:r,startTime:o,timedOut:!1,isCanceled:!1,isGracefullyCanceled:!1,isMaxBuffer:!1,isForcefullyTerminated:!1,stdio:Array.from({length:n.length}),ipcOutput:[],options:i,isSync:s}),lp=({error:t,command:e,escapedCommand:r,startTime:n,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isMaxBuffer:a,isForcefullyTerminated:c,exitCode:l,signal:u,stdio:d,all:f,ipcOutput:p,options:{timeoutDuration:m,timeout:h=m,forceKillAfterDelay:g,killSignal:b,cwd:_,maxBuffer:S},isSync:x})=>{let{exitCode:w,signal:O,signalDescription:T}=Lwe(l,u),{originalMessage:A,shortMessage:D,message:$}=lW({stdio:d,all:f,ipcOutput:p,originalError:t,signal:O,signalDescription:T,exitCode:w,escapedCommand:r,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isMaxBuffer:a,isForcefullyTerminated:c,forceKillAfterDelay:g,killSignal:b,maxBuffer:S,timeout:h,cwd:_}),re=$9(t,$,x);return Object.assign(re,Fwe({error:re,command:e,escapedCommand:r,startTime:n,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isMaxBuffer:a,isForcefullyTerminated:c,exitCode:w,signal:O,signalDescription:T,stdio:d,all:f,ipcOutput:p,cwd:_,originalMessage:A,shortMessage:D})),re},Fwe=({error:t,command:e,escapedCommand:r,startTime:n,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isMaxBuffer:a,isForcefullyTerminated:c,exitCode:l,signal:u,signalDescription:d,stdio:f,all:p,ipcOutput:m,cwd:h,originalMessage:g,shortMessage:b})=>dW({shortMessage:b,originalMessage:g,command:e,escapedCommand:r,cwd:h,durationMs:kR(n),failed:!0,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isTerminated:u!==void 0,isMaxBuffer:a,isForcefullyTerminated:c,exitCode:l,signal:u,signalDescription:d,code:t.cause?.code,stdout:f[1],stderr:f[2],all:p,stdio:f,ipcOutput:m,pipedFrom:[]}),dW=t=>Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0)),Lwe=(t,e)=>{let r=t===null?void 0:t,n=e===null?void 0:e,i=n===void 0?void 0:bb(e);return{exitCode:r,signal:n,signalDescription:i}}});function zwe(t){return{days:Math.trunc(t/864e5),hours:Math.trunc(t/36e5%24),minutes:Math.trunc(t/6e4%60),seconds:Math.trunc(t/1e3%60),milliseconds:Math.trunc(t%1e3),microseconds:Math.trunc(fW(t*1e3)%1e3),nanoseconds:Math.trunc(fW(t*1e6)%1e3)}}function Uwe(t){return{days:t/86400000n,hours:t/3600000n%24n,minutes:t/60000n%60n,seconds:t/1000n%60n,milliseconds:t%1000n,microseconds:0n,nanoseconds:0n}}function lI(t){switch(typeof t){case"number":{if(Number.isFinite(t))return zwe(t);break}case"bigint":return Uwe(t)}throw new TypeError("Expected a finite number or bigint")}var fW,pW=y(()=>{fW=t=>Number.isFinite(t)?t:0});function uI(t,e){let r=typeof t=="bigint";if(!r&&!Number.isFinite(t))throw new TypeError("Expected a finite number or bigint");e={...e};let n=t<0?"-":"";t=t<0?-t:t,e.colonNotation&&(e.compact=!1,e.formatSubMilliseconds=!1,e.separateMilliseconds=!1,e.verbose=!1),e.compact&&(e.unitCount=1,e.secondsDecimalDigits=0,e.millisecondsDecimalDigits=0);let i=[],o=(u,d)=>{let f=Math.floor(u*10**d+Hwe);return(Math.round(f)/10**d).toFixed(d)},s=(u,d,f,p)=>{if(!((i.length===0||!e.colonNotation)&&qwe(u)&&!(e.colonNotation&&f==="m"))){if(p??=String(u),e.colonNotation){let m=p.includes(".")?p.split(".")[0].length:p.length,h=i.length>0?2:1;p="0".repeat(Math.max(0,h-m))+p}else p+=e.verbose?" "+Bwe(d,u):f;i.push(p)}},a=lI(t),c=BigInt(a.days);if(e.hideYearAndDays?s(BigInt(c)*24n+BigInt(a.hours),"hour","h"):(e.hideYear?s(c,"day","d"):(s(c/365n,"year","y"),s(c%365n,"day","d")),s(Number(a.hours),"hour","h")),s(Number(a.minutes),"minute","m"),!e.hideSeconds)if(e.separateMilliseconds||e.formatSubMilliseconds||!e.colonNotation&&t<1e3&&!e.subSecondsAsDecimals){let u=Number(a.seconds),d=Number(a.milliseconds),f=Number(a.microseconds),p=Number(a.nanoseconds);if(s(u,"second","s"),e.formatSubMilliseconds)s(d,"millisecond","ms"),s(f,"microsecond","\xB5s"),s(p,"nanosecond","ns");else{let m=d+f/1e3+p/1e6,h=typeof e.millisecondsDecimalDigits=="number"?e.millisecondsDecimalDigits:0,g=m>=1?Math.round(m):Math.ceil(m),b=h?m.toFixed(h):g;s(Number.parseFloat(b),"millisecond","ms",b)}}else{let u=(r?Number(t%Gwe):t)/1e3%60,d=typeof e.secondsDecimalDigits=="number"?e.secondsDecimalDigits:1,f=o(u,d),p=e.keepDecimalsOnWholeSeconds?f:f.replace(/\.0+$/,"");s(Number.parseFloat(p),"second","s",p)}if(i.length===0)return n+"0"+(e.verbose?" milliseconds":"ms");let l=e.colonNotation?":":" ";return typeof e.unitCount=="number"&&(i=i.slice(0,Math.max(e.unitCount,1))),n+i.join(l)}var qwe,Bwe,Hwe,Gwe,mW=y(()=>{pW();qwe=t=>t===0||t===0n,Bwe=(t,e)=>e===1||e===1n?t:`${t}s`,Hwe=1e-7,Gwe=24n*60n*60n*1000n});var hW,gW=y(()=>{Ol();hW=(t,e)=>{t.failed&&Ci({type:"error",verboseMessage:t.shortMessage,verboseInfo:e,result:t})}});var yW,Zwe,_W=y(()=>{mW();ds();Ol();gW();yW=(t,e)=>{Al(e)&&(hW(t,e),Zwe(t,e))},Zwe=(t,e)=>{let r=`(done in ${uI(t.durationMs)})`;Ci({type:"duration",verboseMessage:r,verboseInfo:e,result:t})}});var zl,Qb=y(()=>{_W();zl=(t,e,{reject:r})=>{if(yW(t,e),t.failed&&r)throw t;return t}});var SW,Vwe,Wwe,wW,xW,bW,Kwe,dI,vW,Fa,$W,Jwe,ev,kW,Ywe,Xwe,fI,EW,Qwe,AW,tv,exe,pI,txe,rxe,TW,Pn,rv,mI,OW,RW,hs,wr=y(()=>{ja();_o();sn();SW=(t,e)=>Fa(t)?"asyncGenerator":$W(t)?"generator":ev(t)?"fileUrl":Ywe(t)?"filePath":exe(t)?"webStream":ii(t,{checkOpen:!1})?"native":qt(t)?"uint8Array":txe(t)?"asyncIterable":rxe(t)?"iterable":pI(t)?wW({transform:t},e):Jwe(t)?Vwe(t,e):"native",Vwe=(t,e)=>iI(t.transform,{checkOpen:!1})?Wwe(t,e):pI(t.transform)?wW(t,e):Kwe(t,e),Wwe=(t,e)=>(xW(t,e,"Duplex stream"),"duplex"),wW=(t,e)=>(xW(t,e,"web TransformStream"),"webTransform"),xW=({final:t,binary:e,objectMode:r},n,i)=>{bW(t,`${n}.final`,i),bW(e,`${n}.binary`,i),dI(r,`${n}.objectMode`)},bW=(t,e,r)=>{if(t!==void 0)throw new TypeError(`The \`${e}\` option can only be defined when using a generator, not a ${r}.`)},Kwe=({transform:t,final:e,binary:r,objectMode:n},i)=>{if(t!==void 0&&!vW(t))throw new TypeError(`The \`${i}.transform\` option must be a generator, a Duplex stream or a web TransformStream.`);if(iI(e,{checkOpen:!1}))throw new TypeError(`The \`${i}.final\` option must not be a Duplex stream.`);if(pI(e))throw new TypeError(`The \`${i}.final\` option must not be a web TransformStream.`);if(e!==void 0&&!vW(e))throw new TypeError(`The \`${i}.final\` option must be a generator.`);return dI(r,`${i}.binary`),dI(n,`${i}.objectMode`),Fa(t)||Fa(e)?"asyncGenerator":"generator"},dI=(t,e)=>{if(t!==void 0&&typeof t!="boolean")throw new TypeError(`The \`${e}\` option must use a boolean.`)},vW=t=>Fa(t)||$W(t),Fa=t=>Object.prototype.toString.call(t)==="[object AsyncGeneratorFunction]",$W=t=>Object.prototype.toString.call(t)==="[object GeneratorFunction]",Jwe=t=>Ot(t)&&(t.transform!==void 0||t.final!==void 0),ev=t=>Object.prototype.toString.call(t)==="[object URL]",kW=t=>ev(t)&&t.protocol!=="file:",Ywe=t=>Ot(t)&&Object.keys(t).length>0&&Object.keys(t).every(e=>Xwe.has(e))&&fI(t.file),Xwe=new Set(["file","append"]),fI=t=>typeof t=="string",EW=(t,e)=>t==="native"&&typeof e=="string"&&!Qwe.has(e),Qwe=new Set(["ipc","ignore","inherit","overlapped","pipe"]),AW=t=>Object.prototype.toString.call(t)==="[object ReadableStream]",tv=t=>Object.prototype.toString.call(t)==="[object WritableStream]",exe=t=>AW(t)||tv(t),pI=t=>AW(t?.readable)&&tv(t?.writable),txe=t=>TW(t)&&typeof t[Symbol.asyncIterator]=="function",rxe=t=>TW(t)&&typeof t[Symbol.iterator]=="function",TW=t=>typeof t=="object"&&t!==null,Pn=new Set(["generator","asyncGenerator","duplex","webTransform"]),rv=new Set(["fileUrl","filePath","fileNumber"]),mI=new Set(["fileUrl","filePath"]),OW=new Set([...mI,"webStream","nodeStream"]),RW=new Set(["webTransform","duplex"]),hs={generator:"a generator",asyncGenerator:"an async generator",fileUrl:"a file URL",filePath:"a file path string",fileNumber:"a file descriptor number",webStream:"a web stream",nodeStream:"a Node.js stream",webTransform:"a web TransformStream",duplex:"a Duplex stream",native:"any value",iterable:"an iterable",asyncIterable:"an async iterable",string:"a string",uint8Array:"a Uint8Array"}});var hI,nxe,ixe,IW,gI=y(()=>{wr();hI=(t,e,r,n)=>n==="output"?nxe(t,e,r):ixe(t,e,r),nxe=(t,e,r)=>{let n=e!==0&&r[e-1].value.readableObjectMode;return{writableObjectMode:n,readableObjectMode:t??n}},ixe=(t,e,r)=>{let n=e===0?t===!0:r[e-1].value.readableObjectMode,i=e!==r.length-1&&(t??n);return{writableObjectMode:n,readableObjectMode:i}},IW=(t,e)=>{let r=t.findLast(({type:n})=>Pn.has(n));return r===void 0?!1:e==="input"?r.value.writableObjectMode:r.value.readableObjectMode}});var PW,oxe,sxe,axe,cxe,lxe,uxe,CW=y(()=>{_o();Da();wr();gI();PW=(t,e,r,n)=>[...t.filter(({type:i})=>!Pn.has(i)),...oxe(t,e,r,n)],oxe=(t,e,r,{encoding:n})=>{let i=t.filter(({type:s})=>Pn.has(s)),o=Array.from({length:i.length});for(let[s,a]of Object.entries(i))o[s]=sxe({stdioItem:a,index:Number(s),newTransforms:o,optionName:e,direction:r,encoding:n});return uxe(o,r)},sxe=({stdioItem:t,stdioItem:{type:e},index:r,newTransforms:n,optionName:i,direction:o,encoding:s})=>e==="duplex"?axe({stdioItem:t,optionName:i}):e==="webTransform"?cxe({stdioItem:t,index:r,newTransforms:n,direction:o}):lxe({stdioItem:t,index:r,newTransforms:n,direction:o,encoding:s}),axe=({stdioItem:t,stdioItem:{value:{transform:e,transform:{writableObjectMode:r,readableObjectMode:n},objectMode:i=n}},optionName:o})=>{if(i&&!n)throw new TypeError(`The \`${o}.objectMode\` option can only be \`true\` if \`new Duplex({objectMode: true})\` is used.`);if(!i&&n)throw new TypeError(`The \`${o}.objectMode\` option cannot be \`false\` if \`new Duplex({objectMode: true})\` is used.`);return{...t,value:{transform:e,writableObjectMode:r,readableObjectMode:n}}},cxe=({stdioItem:t,stdioItem:{value:e},index:r,newTransforms:n,direction:i})=>{let{transform:o,objectMode:s}=Ot(e)?e:{transform:e},{writableObjectMode:a,readableObjectMode:c}=hI(s,r,n,i);return{...t,value:{transform:o,writableObjectMode:a,readableObjectMode:c}}},lxe=({stdioItem:t,stdioItem:{value:e},index:r,newTransforms:n,direction:i,encoding:o})=>{let{transform:s,final:a,binary:c=!1,preserveNewlines:l=!1,objectMode:u}=Ot(e)?e:{transform:e},d=c||an.has(o),{writableObjectMode:f,readableObjectMode:p}=hI(u,r,n,i);return{...t,value:{transform:s,final:a,binary:d,preserveNewlines:l,writableObjectMode:f,readableObjectMode:p}}},uxe=(t,e)=>e==="input"?t.reverse():t});import yI from"node:process";var DW,dxe,fxe,Ul,_I,NW,pxe,mxe,jW=y(()=>{ja();wr();DW=(t,e,r)=>{let n=t.map(i=>dxe(i,e));if(n.includes("input")&&n.includes("output"))throw new TypeError(`The \`${r}\` option must not be an array of both readable and writable values.`);return n.find(Boolean)??mxe},dxe=({type:t,value:e},r)=>fxe[r]??NW[t](e),fxe=["input","output","output"],Ul=()=>{},_I=()=>"input",NW={generator:Ul,asyncGenerator:Ul,fileUrl:Ul,filePath:Ul,iterable:_I,asyncIterable:_I,uint8Array:_I,webStream:t=>tv(t)?"output":"input",nodeStream(t){return Na(t,{checkOpen:!1})?nI(t,{checkOpen:!1})?void 0:"input":"output"},webTransform:Ul,duplex:Ul,native(t){let e=pxe(t);if(e!==void 0)return e;if(ii(t,{checkOpen:!1}))return NW.nodeStream(t)}},pxe=t=>{if([0,yI.stdin].includes(t))return"input";if([1,2,yI.stdout,yI.stderr].includes(t))return"output"},mxe="output"});var MW,FW=y(()=>{MW=(t,e)=>e&&!t.includes("ipc")?[...t,"ipc"]:t});var LW,hxe,gxe,zW,yxe,_xe,UW=y(()=>{vo();FW();ds();LW=({stdio:t,ipc:e,buffer:r,...n},i,o)=>{let s=hxe(t,n).map((a,c)=>zW(a,c));return o?yxe(s,r,i):MW(s,e)},hxe=(t,e)=>{if(t===void 0)return In.map(n=>e[n]);if(gxe(e))throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${In.map(n=>`\`${n}\``).join(", ")}`);if(typeof t=="string")return[t,t,t];if(!Array.isArray(t))throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof t}\``);let r=Math.max(t.length,In.length);return Array.from({length:r},(n,i)=>t[i])},gxe=t=>In.some(e=>t[e]!==void 0),zW=(t,e)=>Array.isArray(t)?t.map(r=>zW(r,e)):t??(e>=In.length?"ignore":"pipe"),yxe=(t,e,r)=>t.map((n,i)=>!e[i]&&i!==0&&!Tl(r,i)&&_xe(n)?"ignore":n),_xe=t=>t==="pipe"||Array.isArray(t)&&t.every(e=>e==="pipe")});import{readFileSync as bxe}from"node:fs";import vxe from"node:tty";var BW,Sxe,wxe,xxe,$xe,qW,HW=y(()=>{ja();vo();sn();ps();BW=({stdioItem:t,stdioItem:{type:e},isStdioArray:r,fdNumber:n,direction:i,isSync:o})=>!r||e!=="native"?t:o?Sxe({stdioItem:t,fdNumber:n,direction:i}):$xe({stdioItem:t,fdNumber:n}),Sxe=({stdioItem:t,stdioItem:{value:e,optionName:r},fdNumber:n,direction:i})=>{let o=wxe({value:e,optionName:r,fdNumber:n,direction:i});if(o!==void 0)return o;if(ii(e,{checkOpen:!1}))throw new TypeError(`The \`${r}: Stream\` option cannot both be an array and include a stream with synchronous methods.`);return t},wxe=({value:t,optionName:e,fdNumber:r,direction:n})=>{let i=xxe(t,r);if(i!==void 0){if(n==="output")return{type:"fileNumber",value:i,optionName:e};if(vxe.isatty(i))throw new TypeError(`The \`${e}: ${xb(t)}\` option is invalid: it cannot be a TTY with synchronous methods.`);return{type:"uint8Array",value:bo(bxe(i)),optionName:e}}},xxe=(t,e)=>{if(t==="inherit")return e;if(typeof t=="number")return t;let r=rb.indexOf(t);if(r!==-1)return r},$xe=({stdioItem:t,stdioItem:{value:e,optionName:r},fdNumber:n})=>e==="inherit"?{type:"nodeStream",value:qW(n,e,r),optionName:r}:typeof e=="number"?{type:"nodeStream",value:qW(e,e,r),optionName:r}:ii(e,{checkOpen:!1})?{type:"nodeStream",value:e,optionName:r}:t,qW=(t,e,r)=>{let n=rb[t];if(n===void 0)throw new TypeError(`The \`${r}: ${e}\` option is invalid: no such standard stream.`);return n}});var GW,kxe,Exe,Axe,Txe,ZW=y(()=>{ja();sn();wr();GW=({input:t,inputFile:e},r)=>r===0?[...kxe(t),...Axe(e)]:[],kxe=t=>t===void 0?[]:[{type:Exe(t),value:t,optionName:"input"}],Exe=t=>{if(Na(t,{checkOpen:!1}))return"nodeStream";if(typeof t=="string")return"string";if(qt(t))return"uint8Array";throw new Error("The `input` option must be a string, a Uint8Array or a Node.js Readable stream.")},Axe=t=>t===void 0?[]:[{...Txe(t),optionName:"inputFile"}],Txe=t=>{if(ev(t))return{type:"fileUrl",value:t};if(fI(t))return{type:"filePath",value:{file:t}};throw new Error("The `inputFile` option must be a file path string or a file URL.")}});var VW,WW,Oxe,Rxe,KW,Ixe,Pxe,JW,YW=y(()=>{wr();VW=t=>t.filter((e,r)=>t.every((n,i)=>e.value!==n.value||r>=i||e.type==="generator"||e.type==="asyncGenerator")),WW=({stdioItem:{type:t,value:e,optionName:r},direction:n,fileDescriptors:i,isSync:o})=>{let s=Oxe(i,t);if(s.length!==0){if(o){Rxe({otherStdioItems:s,type:t,value:e,optionName:r,direction:n});return}if(OW.has(t))return KW({otherStdioItems:s,type:t,value:e,optionName:r,direction:n});RW.has(t)&&Pxe({otherStdioItems:s,type:t,value:e,optionName:r})}},Oxe=(t,e)=>t.flatMap(({direction:r,stdioItems:n})=>n.filter(i=>i.type===e).map((i=>({...i,direction:r})))),Rxe=({otherStdioItems:t,type:e,value:r,optionName:n,direction:i})=>{mI.has(e)&&KW({otherStdioItems:t,type:e,value:r,optionName:n,direction:i})},KW=({otherStdioItems:t,type:e,value:r,optionName:n,direction:i})=>{let o=t.filter(a=>Ixe(a,r));if(o.length===0)return;let s=o.find(a=>a.direction!==i);return JW(s,n,e),i==="output"?o[0].stream:void 0},Ixe=({type:t,value:e},r)=>t==="filePath"?e.file===r.file:t==="fileUrl"?e.href===r.href:e===r,Pxe=({otherStdioItems:t,type:e,value:r,optionName:n})=>{let i=t.find(({value:{transform:o}})=>o===r.transform);JW(i,n,e)},JW=(t,e,r)=>{if(t!==void 0)throw new TypeError(`The \`${t.optionName}\` and \`${e}\` options must not target ${hs[r]} that is the same.`)}});var nv,Cxe,Dxe,Nxe,jxe,Mxe,Fxe,Lxe,zxe,Uxe,qxe,Bxe,bI,Hxe,iv=y(()=>{vo();CW();gI();wr();jW();UW();HW();ZW();YW();nv=(t,e,r,n)=>{let o=LW(e,r,n).map((a,c)=>Cxe({stdioOption:a,fdNumber:c,options:e,isSync:n})),s=Uxe({initialFileDescriptors:o,addProperties:t,options:e,isSync:n});return e.stdio=s.map(({stdioItems:a})=>Hxe(a)),s},Cxe=({stdioOption:t,fdNumber:e,options:r,isSync:n})=>{let i=nb(e),{stdioItems:o,isStdioArray:s}=Dxe({stdioOption:t,fdNumber:e,options:r,optionName:i}),a=DW(o,e,i),c=o.map(d=>BW({stdioItem:d,isStdioArray:s,fdNumber:e,direction:a,isSync:n})),l=PW(c,i,a,r),u=IW(l,a);return zxe(l,u),{direction:a,objectMode:u,stdioItems:l}},Dxe=({stdioOption:t,fdNumber:e,options:r,optionName:n})=>{let o=[...(Array.isArray(t)?t:[t]).map(c=>Nxe(c,n)),...GW(r,e)],s=VW(o),a=s.length>1;return jxe(s,a,n),Fxe(s),{stdioItems:s,isStdioArray:a}},Nxe=(t,e)=>({type:SW(t,e),value:t,optionName:e}),jxe=(t,e,r)=>{if(t.length===0)throw new TypeError(`The \`${r}\` option must not be an empty array.`);if(e){for(let{value:n,optionName:i}of t)if(Mxe.has(n))throw new Error(`The \`${i}\` option must not include \`${n}\`.`)}},Mxe=new Set(["ignore","ipc"]),Fxe=t=>{for(let e of t)Lxe(e)},Lxe=({type:t,value:e,optionName:r})=>{if(kW(e))throw new TypeError(`The \`${r}: URL\` option must use the \`file:\` scheme. -For example, you can use the \`pathToFileURL()\` method of the \`url\` core module.`);if(EW(t,e))throw new TypeError(`The \`${r}: { file: '...' }\` option must be used instead of \`${r}: '...'\`.`)},zxe=(t,e)=>{if(!e)return;let r=t.find(({type:n})=>rv.has(n));if(r!==void 0)throw new TypeError(`The \`${r.optionName}\` option cannot use both files and transforms in objectMode.`)},Uxe=({initialFileDescriptors:t,addProperties:e,options:r,isSync:n})=>{let i=[];try{for(let o of t)i.push(qxe({fileDescriptor:o,fileDescriptors:i,addProperties:e,options:r,isSync:n}));return i}catch(o){throw bI(i),o}},qxe=({fileDescriptor:{direction:t,objectMode:e,stdioItems:r},fileDescriptors:n,addProperties:i,options:o,isSync:s})=>{let a=r.map(c=>Bxe({stdioItem:c,addProperties:i,direction:t,options:o,fileDescriptors:n,isSync:s}));return{direction:t,objectMode:e,stdioItems:a}},Bxe=({stdioItem:t,addProperties:e,direction:r,options:n,fileDescriptors:i,isSync:o})=>{let s=WW({stdioItem:t,direction:r,fileDescriptors:i,isSync:o});return s!==void 0?{...t,stream:s}:{...t,...e[r][t.type](t,n)}},bI=t=>{for(let{stdioItems:e}of t)for(let{stream:r}of e)r!==void 0&&!ti(r)&&r.destroy()},Hxe=t=>{if(t.length>1)return t.some(({value:n})=>n==="overlapped")?"overlapped":"pipe";let[{type:e,value:r}]=t;return e==="native"?r:"pipe"}});import{readFileSync as XW}from"node:fs";var e3,Mi,Gxe,t3,QW,Zxe,r3=y(()=>{sn();iv();wr();e3=(t,e)=>nv(Zxe,t,e,!0),Mi=({type:t,optionName:e})=>{t3(e,hs[t])},Gxe=({optionName:t,value:e})=>((e==="ipc"||e==="overlapped")&&t3(t,`"${e}"`),{}),t3=(t,e)=>{throw new TypeError(`The \`${t}\` option cannot be ${e} with synchronous methods.`)},QW={generator(){},asyncGenerator:Mi,webStream:Mi,nodeStream:Mi,webTransform:Mi,duplex:Mi,asyncIterable:Mi,native:Gxe},Zxe={input:{...QW,fileUrl:({value:t})=>({contents:[bo(XW(t))]}),filePath:({value:{file:t}})=>({contents:[bo(XW(t))]}),fileNumber:Mi,iterable:({value:t})=>({contents:[...t]}),string:({value:t})=>({contents:[t]}),uint8Array:({value:t})=>({contents:[t]})},output:{...QW,fileUrl:({value:t})=>({path:t}),filePath:({value:{file:t,append:e}})=>({path:t,append:e}),fileNumber:({value:t})=>({path:t}),iterable:Mi,string:Mi,uint8Array:Mi}}});var $o,vI,dp=y(()=>{rI();$o=(t,{stripFinalNewline:e},r)=>vI(e,r)&&t!==void 0&&!Array.isArray(t)?Ml(t):t,vI=(t,e)=>e==="all"?t[1]||t[2]:t[e]});var ov,wI,n3,i3,Vxe,Wxe,Kxe,o3,Jxe,SI,Yxe,Xxe,Qxe,sv=y(()=>{ov=(t,e,r,n)=>t||r?void 0:i3(e,n),wI=(t,e,r)=>r?t.flatMap(n=>n3(n,e)):n3(t,e),n3=(t,e)=>{let{transform:r,final:n}=i3(e,{});return[...r(t),...n()]},i3=(t,e)=>(e.previousChunks="",{transform:Vxe.bind(void 0,e,t),final:Kxe.bind(void 0,e)}),Vxe=function*(t,e,r){if(typeof r!="string"){yield r;return}let{previousChunks:n}=t,i=-1;for(let o=0;o0&&(a=SI(n,a),n=""),yield a,i=o}i!==r.length-1&&(n=SI(n,r.slice(i+1))),t.previousChunks=n},Wxe=(t,e,r,n)=>r?0:(n.isWindowsNewline=e!==0&&t[e-1]==="\r",n.isWindowsNewline?2:1),Kxe=function*({previousChunks:t}){t.length>0&&(yield t)},o3=({binary:t,preserveNewlines:e,readableObjectMode:r,state:n})=>t||e||r?void 0:{transform:Jxe.bind(void 0,n)},Jxe=function*({isWindowsNewline:t=!1},e){let{unixNewline:r,windowsNewline:n,LF:i,concatBytes:o}=typeof e=="string"?Yxe:Qxe;if(e.at(-1)===i){yield e;return}yield o(e,t?n:r)},SI=(t,e)=>`${t}${e}`,Yxe={windowsNewline:`\r +${t}`}});import Nwe from"node:path";import J9 from"node:process";var Y9,Hb,jwe,Mwe,lI=y(()=>{Y9=wt(IV(),1);FV();xb();ip();KR();nI();iI();oI();sI();ja();cI();Tl();xo();Hb=(t,e,r)=>{r.cwd=V9(r.cwd);let[n,i,o]=q9(t,e,r),{command:s,args:a,options:c}=Y9.default._parse(n,i,o),l=vZ(c),u=jwe(l);return F9(u),Z9(u),H9(u),i9(u),j9(u),u.shell=$R(u.shell),u.env=Mwe(u),u.killSignal=QV(u.killSignal),u.forceKillAfterDelay=r9(u.forceKillAfterDelay),u.lines=u.lines.map((d,f)=>d&&!cn.has(u.encoding)&&u.buffer[f]),J9.platform==="win32"&&Nwe.basename(s,".exe")==="cmd"&&a.unshift("/q"),{file:s,commandArguments:a,options:u}},jwe=({extendEnv:t=!0,preferLocal:e=!1,cwd:r,localDir:n=r,encoding:i="utf8",reject:o=!0,cleanup:s=!0,all:a=!1,windowsHide:c=!0,killSignal:l="SIGTERM",forceKillAfterDelay:u=!0,gracefulCancel:d=!1,ipcInput:f,ipc:p=f!==void 0||d,serialization:m="advanced",...h})=>({...h,extendEnv:t,preferLocal:e,cwd:r,localDirectory:n,encoding:i,reject:o,cleanup:s,all:a,windowsHide:c,killSignal:l,forceKillAfterDelay:u,gracefulCancel:d,ipcInput:f,ipc:p,serialization:m}),Mwe=({env:t,extendEnv:e,preferLocal:r,node:n,localDirectory:i,nodePath:o})=>{let s=e?{...J9.env,...t}:t;return r||n?MV({env:s,cwd:i,execPath:o,preferLocal:r,addExecPath:n}):s}});var Bb,uI=y(()=>{Bb=(t,e,r)=>r.shell&&e.length>0?[[t,...e].join(" "),[],r]:[t,e,r]});function zl(t){if(typeof t=="string")return Fwe(t);if(!(ArrayBuffer.isView(t)&&t.BYTES_PER_ELEMENT===1))throw new Error("Input must be a string or a Uint8Array");return Lwe(t)}var Fwe,Lwe,X9,zwe,Q9,Uwe,dI=y(()=>{Fwe=t=>t.at(-1)===X9?t.slice(0,t.at(-2)===Q9?-2:-1):t,Lwe=t=>t.at(-1)===zwe?t.subarray(0,t.at(-2)===Uwe?-2:-1):t,X9=` +`,zwe=X9.codePointAt(0),Q9="\r",Uwe=Q9.codePointAt(0)});function oi(t,{checkOpen:e=!0}={}){return t!==null&&typeof t=="object"&&(t.writable||t.readable||!e||t.writable===void 0&&t.readable===void 0)&&typeof t.pipe=="function"}function fI(t,{checkOpen:e=!0}={}){return oi(t,{checkOpen:e})&&(t.writable||!e)&&typeof t.write=="function"&&typeof t.end=="function"&&typeof t.writable=="boolean"&&typeof t.writableObjectMode=="boolean"&&typeof t.destroy=="function"&&typeof t.destroyed=="boolean"}function Ma(t,{checkOpen:e=!0}={}){return oi(t,{checkOpen:e})&&(t.readable||!e)&&typeof t.read=="function"&&typeof t.readable=="boolean"&&typeof t.readableObjectMode=="boolean"&&typeof t.destroy=="function"&&typeof t.destroyed=="boolean"}function pI(t,e){return fI(t,e)&&Ma(t,e)}var Fa=y(()=>{});function eW(){return this[hI].next()}function tW(t){return this[hI].return(t)}function gI({preventCancel:t=!1}={}){let e=this.getReader(),r=new mI(e,t),n=Object.create(Hwe);return n[hI]=r,n}var qwe,mI,hI,Hwe,rW=y(()=>{qwe=Object.getPrototypeOf(Object.getPrototypeOf(async function*(){}).prototype),mI=class{#t;#r;#e=!1;#n=void 0;constructor(e,r){this.#t=e,this.#r=r}next(){let e=()=>this.#o();return this.#n=this.#n?this.#n.then(e,e):e(),this.#n}return(e){let r=()=>this.#i(e);return this.#n?this.#n.then(r,r):r()}async#o(){if(this.#e)return{done:!0,value:void 0};let e;try{e=await this.#t.read()}catch(r){throw this.#n=void 0,this.#e=!0,this.#t.releaseLock(),r}return e.done&&(this.#n=void 0,this.#e=!0,this.#t.releaseLock()),e}async#i(e){if(this.#e)return{done:!0,value:e};if(this.#e=!0,!this.#r){let r=this.#t.cancel(e);return this.#t.releaseLock(),await r,{done:!0,value:e}}return this.#t.releaseLock(),{done:!0,value:e}}},hI=Symbol();Object.defineProperty(eW,"name",{value:"next"});Object.defineProperty(tW,"name",{value:"return"});Hwe=Object.create(qwe,{next:{enumerable:!0,configurable:!0,writable:!0,value:eW},return:{enumerable:!0,configurable:!0,writable:!0,value:tW}})});var nW=y(()=>{});var iW=y(()=>{rW();nW()});var oW,Bwe,Gwe,Zwe,lp,yI=y(()=>{Fa();iW();oW=t=>{if(Ma(t,{checkOpen:!1})&&lp.on!==void 0)return Gwe(t);if(typeof t?.[Symbol.asyncIterator]=="function")return t;if(Bwe.call(t)==="[object ReadableStream]")return gI.call(t);throw new TypeError("The first argument must be a Readable, a ReadableStream, or an async iterable.")},{toString:Bwe}=Object.prototype,Gwe=async function*(t){let e=new AbortController,r={};Zwe(t,e,r);try{for await(let[n]of lp.on(t,"data",{signal:e.signal}))yield n}catch(n){if(r.error!==void 0)throw r.error;if(!e.signal.aborted)throw n}finally{t.destroy()}},Zwe=async(t,e,r)=>{try{await lp.finished(t,{cleanup:!0,readable:!0,writable:!1,error:!1})}catch(n){r.error=n}finally{e.abort()}},lp={}});var Ul,Vwe,cW,sW,Wwe,aW,ji,up=y(()=>{yI();Ul=async(t,{init:e,convertChunk:r,getSize:n,truncateChunk:i,addChunk:o,getFinalChunk:s,finalize:a},{maxBuffer:c=Number.POSITIVE_INFINITY}={})=>{let l=oW(t),u=e();u.length=0;try{for await(let d of l){let f=Wwe(d),p=r[f](d,u);cW({convertedChunk:p,state:u,getSize:n,truncateChunk:i,addChunk:o,maxBuffer:c})}return Vwe({state:u,convertChunk:r,getSize:n,truncateChunk:i,addChunk:o,getFinalChunk:s,maxBuffer:c}),a(u)}catch(d){let f=typeof d=="object"&&d!==null?d:new Error(d);throw f.bufferedData=a(u),f}},Vwe=({state:t,getSize:e,truncateChunk:r,addChunk:n,getFinalChunk:i,maxBuffer:o})=>{let s=i(t);s!==void 0&&cW({convertedChunk:s,state:t,getSize:e,truncateChunk:r,addChunk:n,maxBuffer:o})},cW=({convertedChunk:t,state:e,getSize:r,truncateChunk:n,addChunk:i,maxBuffer:o})=>{let s=r(t),a=e.length+s;if(a<=o){sW(t,e,i,a);return}let c=n(t,o-e.length);throw c!==void 0&&sW(c,e,i,o),new ji},sW=(t,e,r,n)=>{e.contents=r(t,e,n),e.length=n},Wwe=t=>{let e=typeof t;if(e==="string")return"string";if(e!=="object"||t===null)return"others";if(globalThis.Buffer?.isBuffer(t))return"buffer";let r=aW.call(t);return r==="[object ArrayBuffer]"?"arrayBuffer":r==="[object DataView]"?"dataView":Number.isInteger(t.byteLength)&&Number.isInteger(t.byteOffset)&&aW.call(t.buffer)==="[object ArrayBuffer]"?"typedArray":"others"},{toString:aW}=Object.prototype,ji=class extends Error{name="MaxBufferError";constructor(){super("maxBuffer exceeded")}}});var $o,dp,Gb,Zb,Vb,Wb=y(()=>{$o=t=>t,dp=()=>{},Gb=({contents:t})=>t,Zb=t=>{throw new Error(`Streams in object mode are not supported: ${String(t)}`)},Vb=t=>t.length});async function Kb(t,e){return Ul(t,Xwe,e)}var Kwe,Jwe,Ywe,Xwe,lW=y(()=>{up();Wb();Kwe=()=>({contents:[]}),Jwe=()=>1,Ywe=(t,{contents:e})=>(e.push(t),e),Xwe={init:Kwe,convertChunk:{string:$o,buffer:$o,arrayBuffer:$o,dataView:$o,typedArray:$o,others:$o},getSize:Jwe,truncateChunk:dp,addChunk:Ywe,getFinalChunk:dp,finalize:Gb}});async function Jb(t,e){return Ul(t,axe,e)}var Qwe,exe,txe,uW,dW,rxe,nxe,ixe,oxe,pW,fW,sxe,mW,axe,hW=y(()=>{up();Wb();Qwe=()=>({contents:new ArrayBuffer(0)}),exe=t=>txe.encode(t),txe=new TextEncoder,uW=t=>new Uint8Array(t),dW=t=>new Uint8Array(t.buffer,t.byteOffset,t.byteLength),rxe=(t,e)=>t.slice(0,e),nxe=(t,{contents:e,length:r},n)=>{let i=mW()?oxe(e,n):ixe(e,n);return new Uint8Array(i).set(t,r),i},ixe=(t,e)=>{if(e<=t.byteLength)return t;let r=new ArrayBuffer(pW(e));return new Uint8Array(r).set(new Uint8Array(t),0),r},oxe=(t,e)=>{if(e<=t.maxByteLength)return t.resize(e),t;let r=new ArrayBuffer(e,{maxByteLength:pW(e)});return new Uint8Array(r).set(new Uint8Array(t),0),r},pW=t=>fW**Math.ceil(Math.log(t)/Math.log(fW)),fW=2,sxe=({contents:t,length:e})=>mW()?t:t.slice(0,e),mW=()=>"resize"in ArrayBuffer.prototype,axe={init:Qwe,convertChunk:{string:exe,buffer:uW,arrayBuffer:uW,dataView:dW,typedArray:dW,others:Zb},getSize:Vb,truncateChunk:rxe,addChunk:nxe,getFinalChunk:dp,finalize:sxe}});async function Xb(t,e){return Ul(t,fxe,e)}var cxe,Yb,lxe,uxe,dxe,fxe,gW=y(()=>{up();Wb();cxe=()=>({contents:"",textDecoder:new TextDecoder}),Yb=(t,{textDecoder:e})=>e.decode(t,{stream:!0}),lxe=(t,{contents:e})=>e+t,uxe=(t,e)=>t.slice(0,e),dxe=({textDecoder:t})=>{let e=t.decode();return e===""?void 0:e},fxe={init:cxe,convertChunk:{string:$o,buffer:Yb,arrayBuffer:Yb,dataView:Yb,typedArray:Yb,others:Zb},getSize:Vb,truncateChunk:uxe,addChunk:lxe,getFinalChunk:dxe,finalize:Gb}});var yW=y(()=>{lW();hW();gW();up()});import{on as pxe}from"node:events";import{finished as mxe}from"node:stream/promises";var Qb=y(()=>{yI();yW();Object.assign(lp,{on:pxe,finished:mxe})});var _W,hxe,bW,vW,gxe,SW,wW,ev,La=y(()=>{Qb();So();xo();_W=({error:t,stream:e,readableObjectMode:r,lines:n,encoding:i,fdNumber:o})=>{if(!(t instanceof ji))throw t;if(o==="all")return t;let s=hxe(r,n,i);throw t.maxBufferInfo={fdNumber:o,unit:s},e.destroy(),t},hxe=(t,e,r)=>t?"objects":e?"lines":r==="buffer"?"bytes":"characters",bW=(t,e,r)=>{if(e.length!==r)return;let n=new ji;throw n.maxBufferInfo={fdNumber:"ipc"},n},vW=(t,e)=>{let{streamName:r,threshold:n,unit:i}=gxe(t,e);return`Command's ${r} was larger than ${n} ${i}`},gxe=(t,e)=>{if(t?.maxBufferInfo===void 0)return{streamName:"output",threshold:e[1],unit:"bytes"};let{maxBufferInfo:{fdNumber:r,unit:n}}=t;delete t.maxBufferInfo;let i=wo(e,r);return r==="ipc"?{streamName:"IPC output",threshold:i,unit:"messages"}:{streamName:sb(r),threshold:i,unit:n}},SW=(t,e,r)=>t?.code==="ENOBUFS"&&e!==null&&e.some(n=>n!==null&&n.length>ev(r)),wW=(t,e,r)=>{if(!e)return t;let n=ev(r);return t.length>n?t.slice(0,n):t},ev=([,t])=>t});import{inspect as yxe}from"node:util";var $W,_xe,bxe,vxe,Sxe,wxe,xW,kW=y(()=>{dI();an();cI();lb();La();ip();Da();$W=({stdio:t,all:e,ipcOutput:r,originalError:n,signal:i,signalDescription:o,exitCode:s,escapedCommand:a,timedOut:c,isCanceled:l,isGracefullyCanceled:u,isMaxBuffer:d,isForcefullyTerminated:f,forceKillAfterDelay:p,killSignal:m,maxBuffer:h,timeout:g,cwd:b})=>{let _=n?.code,S=_xe({originalError:n,timedOut:c,timeout:g,isMaxBuffer:d,maxBuffer:h,errorCode:_,signal:i,signalDescription:o,exitCode:s,isCanceled:l,isGracefullyCanceled:u,isForcefullyTerminated:f,forceKillAfterDelay:p,killSignal:m}),x=vxe(n,b),w=x===void 0?"":` +${x}`,R=`${S}: ${a}${w}`,A=e===void 0?[t[2],t[1]]:[e],O=[R,...A,...t.slice(3),r.map(D=>Sxe(D)).join(` +`)].map(D=>ep(zl(wxe(D)))).filter(Boolean).join(` + +`);return{originalMessage:x,shortMessage:R,message:O}},_xe=({originalError:t,timedOut:e,timeout:r,isMaxBuffer:n,maxBuffer:i,errorCode:o,signal:s,signalDescription:a,exitCode:c,isCanceled:l,isGracefullyCanceled:u,isForcefullyTerminated:d,forceKillAfterDelay:f,killSignal:p})=>{let m=bxe(d,f);return e?`Command timed out after ${r} milliseconds${m}`:u?s===void 0?`Command was gracefully canceled with exit code ${c}`:d?`Command was gracefully canceled${m}`:`Command was gracefully canceled with ${s} (${a})`:l?`Command was canceled${m}`:n?`${vW(t,i)}${m}`:o!==void 0?`Command failed with ${o}${m}`:d?`Command was killed with ${p} (${wb(p)})${m}`:s!==void 0?`Command was killed with ${s} (${a})`:c!==void 0?`Command failed with exit code ${c}`:"Command failed"},bxe=(t,e)=>t?` and was forcefully terminated after ${e} milliseconds`:"",vxe=(t,e)=>{if(t instanceof ni)return;let r=UV(t)?t.originalMessage:String(t?.message??t),n=ep(K9(r,e));return n===""?void 0:n},Sxe=t=>typeof t=="string"?t:yxe(t),wxe=t=>Array.isArray(t)?t.map(e=>zl(xW(e))).filter(Boolean).join(` +`):xW(t),xW=t=>typeof t=="string"?t:qt(t)?ib(t):""});var tv,ql,fp,xxe,EW,$xe,pp=y(()=>{ip();hb();Da();kW();tv=({command:t,escapedCommand:e,stdio:r,all:n,ipcOutput:i,options:{cwd:o},startTime:s})=>EW({command:t,escapedCommand:e,cwd:o,durationMs:DR(s),failed:!1,timedOut:!1,isCanceled:!1,isGracefullyCanceled:!1,isTerminated:!1,isMaxBuffer:!1,isForcefullyTerminated:!1,exitCode:0,stdout:r[1],stderr:r[2],all:n,stdio:r,ipcOutput:i,pipedFrom:[]}),ql=({error:t,command:e,escapedCommand:r,fileDescriptors:n,options:i,startTime:o,isSync:s})=>fp({error:t,command:e,escapedCommand:r,startTime:o,timedOut:!1,isCanceled:!1,isGracefullyCanceled:!1,isMaxBuffer:!1,isForcefullyTerminated:!1,stdio:Array.from({length:n.length}),ipcOutput:[],options:i,isSync:s}),fp=({error:t,command:e,escapedCommand:r,startTime:n,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isMaxBuffer:a,isForcefullyTerminated:c,exitCode:l,signal:u,stdio:d,all:f,ipcOutput:p,options:{timeoutDuration:m,timeout:h=m,forceKillAfterDelay:g,killSignal:b,cwd:_,maxBuffer:S},isSync:x})=>{let{exitCode:w,signal:R,signalDescription:A}=$xe(l,u),{originalMessage:O,shortMessage:D,message:E}=$W({stdio:d,all:f,ipcOutput:p,originalError:t,signal:R,signalDescription:A,exitCode:w,escapedCommand:r,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isMaxBuffer:a,isForcefullyTerminated:c,forceKillAfterDelay:g,killSignal:b,maxBuffer:S,timeout:h,cwd:_}),ae=LV(t,E,x);return Object.assign(ae,xxe({error:ae,command:e,escapedCommand:r,startTime:n,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isMaxBuffer:a,isForcefullyTerminated:c,exitCode:w,signal:R,signalDescription:A,stdio:d,all:f,ipcOutput:p,cwd:_,originalMessage:O,shortMessage:D})),ae},xxe=({error:t,command:e,escapedCommand:r,startTime:n,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isMaxBuffer:a,isForcefullyTerminated:c,exitCode:l,signal:u,signalDescription:d,stdio:f,all:p,ipcOutput:m,cwd:h,originalMessage:g,shortMessage:b})=>EW({shortMessage:b,originalMessage:g,command:e,escapedCommand:r,cwd:h,durationMs:DR(n),failed:!0,timedOut:i,isCanceled:o,isGracefullyCanceled:s,isTerminated:u!==void 0,isMaxBuffer:a,isForcefullyTerminated:c,exitCode:l,signal:u,signalDescription:d,code:t.cause?.code,stdout:f[1],stderr:f[2],all:p,stdio:f,ipcOutput:m,pipedFrom:[]}),EW=t=>Object.fromEntries(Object.entries(t).filter(([,e])=>e!==void 0)),$xe=(t,e)=>{let r=t===null?void 0:t,n=e===null?void 0:e,i=n===void 0?void 0:wb(e);return{exitCode:r,signal:n,signalDescription:i}}});function kxe(t){return{days:Math.trunc(t/864e5),hours:Math.trunc(t/36e5%24),minutes:Math.trunc(t/6e4%60),seconds:Math.trunc(t/1e3%60),milliseconds:Math.trunc(t%1e3),microseconds:Math.trunc(AW(t*1e3)%1e3),nanoseconds:Math.trunc(AW(t*1e6)%1e3)}}function Exe(t){return{days:t/86400000n,hours:t/3600000n%24n,minutes:t/60000n%60n,seconds:t/1000n%60n,milliseconds:t%1000n,microseconds:0n,nanoseconds:0n}}function _I(t){switch(typeof t){case"number":{if(Number.isFinite(t))return kxe(t);break}case"bigint":return Exe(t)}throw new TypeError("Expected a finite number or bigint")}var AW,OW=y(()=>{AW=t=>Number.isFinite(t)?t:0});function bI(t,e){let r=typeof t=="bigint";if(!r&&!Number.isFinite(t))throw new TypeError("Expected a finite number or bigint");e={...e};let n=t<0?"-":"";t=t<0?-t:t,e.colonNotation&&(e.compact=!1,e.formatSubMilliseconds=!1,e.separateMilliseconds=!1,e.verbose=!1),e.compact&&(e.unitCount=1,e.secondsDecimalDigits=0,e.millisecondsDecimalDigits=0);let i=[],o=(u,d)=>{let f=Math.floor(u*10**d+Txe);return(Math.round(f)/10**d).toFixed(d)},s=(u,d,f,p)=>{if(!((i.length===0||!e.colonNotation)&&Axe(u)&&!(e.colonNotation&&f==="m"))){if(p??=String(u),e.colonNotation){let m=p.includes(".")?p.split(".")[0].length:p.length,h=i.length>0?2:1;p="0".repeat(Math.max(0,h-m))+p}else p+=e.verbose?" "+Oxe(d,u):f;i.push(p)}},a=_I(t),c=BigInt(a.days);if(e.hideYearAndDays?s(BigInt(c)*24n+BigInt(a.hours),"hour","h"):(e.hideYear?s(c,"day","d"):(s(c/365n,"year","y"),s(c%365n,"day","d")),s(Number(a.hours),"hour","h")),s(Number(a.minutes),"minute","m"),!e.hideSeconds)if(e.separateMilliseconds||e.formatSubMilliseconds||!e.colonNotation&&t<1e3&&!e.subSecondsAsDecimals){let u=Number(a.seconds),d=Number(a.milliseconds),f=Number(a.microseconds),p=Number(a.nanoseconds);if(s(u,"second","s"),e.formatSubMilliseconds)s(d,"millisecond","ms"),s(f,"microsecond","\xB5s"),s(p,"nanosecond","ns");else{let m=d+f/1e3+p/1e6,h=typeof e.millisecondsDecimalDigits=="number"?e.millisecondsDecimalDigits:0,g=m>=1?Math.round(m):Math.ceil(m),b=h?m.toFixed(h):g;s(Number.parseFloat(b),"millisecond","ms",b)}}else{let u=(r?Number(t%Rxe):t)/1e3%60,d=typeof e.secondsDecimalDigits=="number"?e.secondsDecimalDigits:1,f=o(u,d),p=e.keepDecimalsOnWholeSeconds?f:f.replace(/\.0+$/,"");s(Number.parseFloat(p),"second","s",p)}if(i.length===0)return n+"0"+(e.verbose?" milliseconds":"ms");let l=e.colonNotation?":":" ";return typeof e.unitCount=="number"&&(i=i.slice(0,Math.max(e.unitCount,1))),n+i.join(l)}var Axe,Oxe,Txe,Rxe,TW=y(()=>{OW();Axe=t=>t===0||t===0n,Oxe=(t,e)=>e===1||e===1n?t:`${t}s`,Txe=1e-7,Rxe=24n*60n*60n*1000n});var RW,IW=y(()=>{Pl();RW=(t,e)=>{t.failed&&Ci({type:"error",verboseMessage:t.shortMessage,verboseInfo:e,result:t})}});var PW,Ixe,CW=y(()=>{TW();ps();Pl();IW();PW=(t,e)=>{Rl(e)&&(RW(t,e),Ixe(t,e))},Ixe=(t,e)=>{let r=`(done in ${bI(t.durationMs)})`;Ci({type:"duration",verboseMessage:r,verboseInfo:e,result:t})}});var Hl,rv=y(()=>{CW();Hl=(t,e,{reject:r})=>{if(PW(t,e),t.failed&&r)throw t;return t}});var jW,Pxe,Cxe,MW,FW,DW,Dxe,vI,NW,za,LW,Nxe,nv,zW,jxe,Mxe,SI,UW,Fxe,qW,iv,Lxe,wI,zxe,Uxe,HW,Cn,ov,xI,BW,GW,ys,$r=y(()=>{Fa();bo();an();jW=(t,e)=>za(t)?"asyncGenerator":LW(t)?"generator":nv(t)?"fileUrl":jxe(t)?"filePath":Lxe(t)?"webStream":oi(t,{checkOpen:!1})?"native":qt(t)?"uint8Array":zxe(t)?"asyncIterable":Uxe(t)?"iterable":wI(t)?MW({transform:t},e):Nxe(t)?Pxe(t,e):"native",Pxe=(t,e)=>pI(t.transform,{checkOpen:!1})?Cxe(t,e):wI(t.transform)?MW(t,e):Dxe(t,e),Cxe=(t,e)=>(FW(t,e,"Duplex stream"),"duplex"),MW=(t,e)=>(FW(t,e,"web TransformStream"),"webTransform"),FW=({final:t,binary:e,objectMode:r},n,i)=>{DW(t,`${n}.final`,i),DW(e,`${n}.binary`,i),vI(r,`${n}.objectMode`)},DW=(t,e,r)=>{if(t!==void 0)throw new TypeError(`The \`${e}\` option can only be defined when using a generator, not a ${r}.`)},Dxe=({transform:t,final:e,binary:r,objectMode:n},i)=>{if(t!==void 0&&!NW(t))throw new TypeError(`The \`${i}.transform\` option must be a generator, a Duplex stream or a web TransformStream.`);if(pI(e,{checkOpen:!1}))throw new TypeError(`The \`${i}.final\` option must not be a Duplex stream.`);if(wI(e))throw new TypeError(`The \`${i}.final\` option must not be a web TransformStream.`);if(e!==void 0&&!NW(e))throw new TypeError(`The \`${i}.final\` option must be a generator.`);return vI(r,`${i}.binary`),vI(n,`${i}.objectMode`),za(t)||za(e)?"asyncGenerator":"generator"},vI=(t,e)=>{if(t!==void 0&&typeof t!="boolean")throw new TypeError(`The \`${e}\` option must use a boolean.`)},NW=t=>za(t)||LW(t),za=t=>Object.prototype.toString.call(t)==="[object AsyncGeneratorFunction]",LW=t=>Object.prototype.toString.call(t)==="[object GeneratorFunction]",Nxe=t=>Tt(t)&&(t.transform!==void 0||t.final!==void 0),nv=t=>Object.prototype.toString.call(t)==="[object URL]",zW=t=>nv(t)&&t.protocol!=="file:",jxe=t=>Tt(t)&&Object.keys(t).length>0&&Object.keys(t).every(e=>Mxe.has(e))&&SI(t.file),Mxe=new Set(["file","append"]),SI=t=>typeof t=="string",UW=(t,e)=>t==="native"&&typeof e=="string"&&!Fxe.has(e),Fxe=new Set(["ipc","ignore","inherit","overlapped","pipe"]),qW=t=>Object.prototype.toString.call(t)==="[object ReadableStream]",iv=t=>Object.prototype.toString.call(t)==="[object WritableStream]",Lxe=t=>qW(t)||iv(t),wI=t=>qW(t?.readable)&&iv(t?.writable),zxe=t=>HW(t)&&typeof t[Symbol.asyncIterator]=="function",Uxe=t=>HW(t)&&typeof t[Symbol.iterator]=="function",HW=t=>typeof t=="object"&&t!==null,Cn=new Set(["generator","asyncGenerator","duplex","webTransform"]),ov=new Set(["fileUrl","filePath","fileNumber"]),xI=new Set(["fileUrl","filePath"]),BW=new Set([...xI,"webStream","nodeStream"]),GW=new Set(["webTransform","duplex"]),ys={generator:"a generator",asyncGenerator:"an async generator",fileUrl:"a file URL",filePath:"a file path string",fileNumber:"a file descriptor number",webStream:"a web stream",nodeStream:"a Node.js stream",webTransform:"a web TransformStream",duplex:"a Duplex stream",native:"any value",iterable:"an iterable",asyncIterable:"an async iterable",string:"a string",uint8Array:"a Uint8Array"}});var $I,qxe,Hxe,ZW,kI=y(()=>{$r();$I=(t,e,r,n)=>n==="output"?qxe(t,e,r):Hxe(t,e,r),qxe=(t,e,r)=>{let n=e!==0&&r[e-1].value.readableObjectMode;return{writableObjectMode:n,readableObjectMode:t??n}},Hxe=(t,e,r)=>{let n=e===0?t===!0:r[e-1].value.readableObjectMode,i=e!==r.length-1&&(t??n);return{writableObjectMode:n,readableObjectMode:i}},ZW=(t,e)=>{let r=t.findLast(({type:n})=>Cn.has(n));return r===void 0?!1:e==="input"?r.value.writableObjectMode:r.value.readableObjectMode}});var VW,Bxe,Gxe,Zxe,Vxe,Wxe,Kxe,WW=y(()=>{bo();ja();$r();kI();VW=(t,e,r,n)=>[...t.filter(({type:i})=>!Cn.has(i)),...Bxe(t,e,r,n)],Bxe=(t,e,r,{encoding:n})=>{let i=t.filter(({type:s})=>Cn.has(s)),o=Array.from({length:i.length});for(let[s,a]of Object.entries(i))o[s]=Gxe({stdioItem:a,index:Number(s),newTransforms:o,optionName:e,direction:r,encoding:n});return Kxe(o,r)},Gxe=({stdioItem:t,stdioItem:{type:e},index:r,newTransforms:n,optionName:i,direction:o,encoding:s})=>e==="duplex"?Zxe({stdioItem:t,optionName:i}):e==="webTransform"?Vxe({stdioItem:t,index:r,newTransforms:n,direction:o}):Wxe({stdioItem:t,index:r,newTransforms:n,direction:o,encoding:s}),Zxe=({stdioItem:t,stdioItem:{value:{transform:e,transform:{writableObjectMode:r,readableObjectMode:n},objectMode:i=n}},optionName:o})=>{if(i&&!n)throw new TypeError(`The \`${o}.objectMode\` option can only be \`true\` if \`new Duplex({objectMode: true})\` is used.`);if(!i&&n)throw new TypeError(`The \`${o}.objectMode\` option cannot be \`false\` if \`new Duplex({objectMode: true})\` is used.`);return{...t,value:{transform:e,writableObjectMode:r,readableObjectMode:n}}},Vxe=({stdioItem:t,stdioItem:{value:e},index:r,newTransforms:n,direction:i})=>{let{transform:o,objectMode:s}=Tt(e)?e:{transform:e},{writableObjectMode:a,readableObjectMode:c}=$I(s,r,n,i);return{...t,value:{transform:o,writableObjectMode:a,readableObjectMode:c}}},Wxe=({stdioItem:t,stdioItem:{value:e},index:r,newTransforms:n,direction:i,encoding:o})=>{let{transform:s,final:a,binary:c=!1,preserveNewlines:l=!1,objectMode:u}=Tt(e)?e:{transform:e},d=c||cn.has(o),{writableObjectMode:f,readableObjectMode:p}=$I(u,r,n,i);return{...t,value:{transform:s,final:a,binary:d,preserveNewlines:l,writableObjectMode:f,readableObjectMode:p}}},Kxe=(t,e)=>e==="input"?t.reverse():t});import EI from"node:process";var KW,Jxe,Yxe,Bl,AI,JW,Xxe,Qxe,YW=y(()=>{Fa();$r();KW=(t,e,r)=>{let n=t.map(i=>Jxe(i,e));if(n.includes("input")&&n.includes("output"))throw new TypeError(`The \`${r}\` option must not be an array of both readable and writable values.`);return n.find(Boolean)??Qxe},Jxe=({type:t,value:e},r)=>Yxe[r]??JW[t](e),Yxe=["input","output","output"],Bl=()=>{},AI=()=>"input",JW={generator:Bl,asyncGenerator:Bl,fileUrl:Bl,filePath:Bl,iterable:AI,asyncIterable:AI,uint8Array:AI,webStream:t=>iv(t)?"output":"input",nodeStream(t){return Ma(t,{checkOpen:!1})?fI(t,{checkOpen:!1})?void 0:"input":"output"},webTransform:Bl,duplex:Bl,native(t){let e=Xxe(t);if(e!==void 0)return e;if(oi(t,{checkOpen:!1}))return JW.nodeStream(t)}},Xxe=t=>{if([0,EI.stdin].includes(t))return"input";if([1,2,EI.stdout,EI.stderr].includes(t))return"output"},Qxe="output"});var XW,QW=y(()=>{XW=(t,e)=>e&&!t.includes("ipc")?[...t,"ipc"]:t});var eK,e0e,t0e,tK,r0e,n0e,rK=y(()=>{So();QW();ps();eK=({stdio:t,ipc:e,buffer:r,...n},i,o)=>{let s=e0e(t,n).map((a,c)=>tK(a,c));return o?r0e(s,r,i):XW(s,e)},e0e=(t,e)=>{if(t===void 0)return Pn.map(n=>e[n]);if(t0e(e))throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${Pn.map(n=>`\`${n}\``).join(", ")}`);if(typeof t=="string")return[t,t,t];if(!Array.isArray(t))throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof t}\``);let r=Math.max(t.length,Pn.length);return Array.from({length:r},(n,i)=>t[i])},t0e=t=>Pn.some(e=>t[e]!==void 0),tK=(t,e)=>Array.isArray(t)?t.map(r=>tK(r,e)):t??(e>=Pn.length?"ignore":"pipe"),r0e=(t,e,r)=>t.map((n,i)=>!e[i]&&i!==0&&!Il(r,i)&&n0e(n)?"ignore":n),n0e=t=>t==="pipe"||Array.isArray(t)&&t.every(e=>e==="pipe")});import{readFileSync as i0e}from"node:fs";import o0e from"node:tty";var iK,s0e,a0e,c0e,l0e,nK,oK=y(()=>{Fa();So();an();hs();iK=({stdioItem:t,stdioItem:{type:e},isStdioArray:r,fdNumber:n,direction:i,isSync:o})=>!r||e!=="native"?t:o?s0e({stdioItem:t,fdNumber:n,direction:i}):l0e({stdioItem:t,fdNumber:n}),s0e=({stdioItem:t,stdioItem:{value:e,optionName:r},fdNumber:n,direction:i})=>{let o=a0e({value:e,optionName:r,fdNumber:n,direction:i});if(o!==void 0)return o;if(oi(e,{checkOpen:!1}))throw new TypeError(`The \`${r}: Stream\` option cannot both be an array and include a stream with synchronous methods.`);return t},a0e=({value:t,optionName:e,fdNumber:r,direction:n})=>{let i=c0e(t,r);if(i!==void 0){if(n==="output")return{type:"fileNumber",value:i,optionName:e};if(o0e.isatty(i))throw new TypeError(`The \`${e}: ${Eb(t)}\` option is invalid: it cannot be a TTY with synchronous methods.`);return{type:"uint8Array",value:vo(i0e(i)),optionName:e}}},c0e=(t,e)=>{if(t==="inherit")return e;if(typeof t=="number")return t;let r=ob.indexOf(t);if(r!==-1)return r},l0e=({stdioItem:t,stdioItem:{value:e,optionName:r},fdNumber:n})=>e==="inherit"?{type:"nodeStream",value:nK(n,e,r),optionName:r}:typeof e=="number"?{type:"nodeStream",value:nK(e,e,r),optionName:r}:oi(e,{checkOpen:!1})?{type:"nodeStream",value:e,optionName:r}:t,nK=(t,e,r)=>{let n=ob[t];if(n===void 0)throw new TypeError(`The \`${r}: ${e}\` option is invalid: no such standard stream.`);return n}});var sK,u0e,d0e,f0e,p0e,aK=y(()=>{Fa();an();$r();sK=({input:t,inputFile:e},r)=>r===0?[...u0e(t),...f0e(e)]:[],u0e=t=>t===void 0?[]:[{type:d0e(t),value:t,optionName:"input"}],d0e=t=>{if(Ma(t,{checkOpen:!1}))return"nodeStream";if(typeof t=="string")return"string";if(qt(t))return"uint8Array";throw new Error("The `input` option must be a string, a Uint8Array or a Node.js Readable stream.")},f0e=t=>t===void 0?[]:[{...p0e(t),optionName:"inputFile"}],p0e=t=>{if(nv(t))return{type:"fileUrl",value:t};if(SI(t))return{type:"filePath",value:{file:t}};throw new Error("The `inputFile` option must be a file path string or a file URL.")}});var cK,lK,m0e,h0e,uK,g0e,y0e,dK,fK=y(()=>{$r();cK=t=>t.filter((e,r)=>t.every((n,i)=>e.value!==n.value||r>=i||e.type==="generator"||e.type==="asyncGenerator")),lK=({stdioItem:{type:t,value:e,optionName:r},direction:n,fileDescriptors:i,isSync:o})=>{let s=m0e(i,t);if(s.length!==0){if(o){h0e({otherStdioItems:s,type:t,value:e,optionName:r,direction:n});return}if(BW.has(t))return uK({otherStdioItems:s,type:t,value:e,optionName:r,direction:n});GW.has(t)&&y0e({otherStdioItems:s,type:t,value:e,optionName:r})}},m0e=(t,e)=>t.flatMap(({direction:r,stdioItems:n})=>n.filter(i=>i.type===e).map((i=>({...i,direction:r})))),h0e=({otherStdioItems:t,type:e,value:r,optionName:n,direction:i})=>{xI.has(e)&&uK({otherStdioItems:t,type:e,value:r,optionName:n,direction:i})},uK=({otherStdioItems:t,type:e,value:r,optionName:n,direction:i})=>{let o=t.filter(a=>g0e(a,r));if(o.length===0)return;let s=o.find(a=>a.direction!==i);return dK(s,n,e),i==="output"?o[0].stream:void 0},g0e=({type:t,value:e},r)=>t==="filePath"?e.file===r.file:t==="fileUrl"?e.href===r.href:e===r,y0e=({otherStdioItems:t,type:e,value:r,optionName:n})=>{let i=t.find(({value:{transform:o}})=>o===r.transform);dK(i,n,e)},dK=(t,e,r)=>{if(t!==void 0)throw new TypeError(`The \`${t.optionName}\` and \`${e}\` options must not target ${ys[r]} that is the same.`)}});var sv,_0e,b0e,v0e,S0e,w0e,x0e,$0e,k0e,E0e,A0e,O0e,OI,T0e,av=y(()=>{So();WW();kI();$r();YW();rK();oK();aK();fK();sv=(t,e,r,n)=>{let o=eK(e,r,n).map((a,c)=>_0e({stdioOption:a,fdNumber:c,options:e,isSync:n})),s=E0e({initialFileDescriptors:o,addProperties:t,options:e,isSync:n});return e.stdio=s.map(({stdioItems:a})=>T0e(a)),s},_0e=({stdioOption:t,fdNumber:e,options:r,isSync:n})=>{let i=sb(e),{stdioItems:o,isStdioArray:s}=b0e({stdioOption:t,fdNumber:e,options:r,optionName:i}),a=KW(o,e,i),c=o.map(d=>iK({stdioItem:d,isStdioArray:s,fdNumber:e,direction:a,isSync:n})),l=VW(c,i,a,r),u=ZW(l,a);return k0e(l,u),{direction:a,objectMode:u,stdioItems:l}},b0e=({stdioOption:t,fdNumber:e,options:r,optionName:n})=>{let o=[...(Array.isArray(t)?t:[t]).map(c=>v0e(c,n)),...sK(r,e)],s=cK(o),a=s.length>1;return S0e(s,a,n),x0e(s),{stdioItems:s,isStdioArray:a}},v0e=(t,e)=>({type:jW(t,e),value:t,optionName:e}),S0e=(t,e,r)=>{if(t.length===0)throw new TypeError(`The \`${r}\` option must not be an empty array.`);if(e){for(let{value:n,optionName:i}of t)if(w0e.has(n))throw new Error(`The \`${i}\` option must not include \`${n}\`.`)}},w0e=new Set(["ignore","ipc"]),x0e=t=>{for(let e of t)$0e(e)},$0e=({type:t,value:e,optionName:r})=>{if(zW(e))throw new TypeError(`The \`${r}: URL\` option must use the \`file:\` scheme. +For example, you can use the \`pathToFileURL()\` method of the \`url\` core module.`);if(UW(t,e))throw new TypeError(`The \`${r}: { file: '...' }\` option must be used instead of \`${r}: '...'\`.`)},k0e=(t,e)=>{if(!e)return;let r=t.find(({type:n})=>ov.has(n));if(r!==void 0)throw new TypeError(`The \`${r.optionName}\` option cannot use both files and transforms in objectMode.`)},E0e=({initialFileDescriptors:t,addProperties:e,options:r,isSync:n})=>{let i=[];try{for(let o of t)i.push(A0e({fileDescriptor:o,fileDescriptors:i,addProperties:e,options:r,isSync:n}));return i}catch(o){throw OI(i),o}},A0e=({fileDescriptor:{direction:t,objectMode:e,stdioItems:r},fileDescriptors:n,addProperties:i,options:o,isSync:s})=>{let a=r.map(c=>O0e({stdioItem:c,addProperties:i,direction:t,options:o,fileDescriptors:n,isSync:s}));return{direction:t,objectMode:e,stdioItems:a}},O0e=({stdioItem:t,addProperties:e,direction:r,options:n,fileDescriptors:i,isSync:o})=>{let s=lK({stdioItem:t,direction:r,fileDescriptors:i,isSync:o});return s!==void 0?{...t,stream:s}:{...t,...e[r][t.type](t,n)}},OI=t=>{for(let{stdioItems:e}of t)for(let{stream:r}of e)r!==void 0&&!ri(r)&&r.destroy()},T0e=t=>{if(t.length>1)return t.some(({value:n})=>n==="overlapped")?"overlapped":"pipe";let[{type:e,value:r}]=t;return e==="native"?r:"pipe"}});import{readFileSync as pK}from"node:fs";var hK,Mi,R0e,gK,mK,I0e,yK=y(()=>{an();av();$r();hK=(t,e)=>sv(I0e,t,e,!0),Mi=({type:t,optionName:e})=>{gK(e,ys[t])},R0e=({optionName:t,value:e})=>((e==="ipc"||e==="overlapped")&&gK(t,`"${e}"`),{}),gK=(t,e)=>{throw new TypeError(`The \`${t}\` option cannot be ${e} with synchronous methods.`)},mK={generator(){},asyncGenerator:Mi,webStream:Mi,nodeStream:Mi,webTransform:Mi,duplex:Mi,asyncIterable:Mi,native:R0e},I0e={input:{...mK,fileUrl:({value:t})=>({contents:[vo(pK(t))]}),filePath:({value:{file:t}})=>({contents:[vo(pK(t))]}),fileNumber:Mi,iterable:({value:t})=>({contents:[...t]}),string:({value:t})=>({contents:[t]}),uint8Array:({value:t})=>({contents:[t]})},output:{...mK,fileUrl:({value:t})=>({path:t}),filePath:({value:{file:t,append:e}})=>({path:t,append:e}),fileNumber:({value:t})=>({path:t}),iterable:Mi,string:Mi,uint8Array:Mi}}});var ko,TI,mp=y(()=>{dI();ko=(t,{stripFinalNewline:e},r)=>TI(e,r)&&t!==void 0&&!Array.isArray(t)?zl(t):t,TI=(t,e)=>e==="all"?t[1]||t[2]:t[e]});var cv,II,_K,bK,P0e,C0e,D0e,vK,N0e,RI,j0e,M0e,F0e,lv=y(()=>{cv=(t,e,r,n)=>t||r?void 0:bK(e,n),II=(t,e,r)=>r?t.flatMap(n=>_K(n,e)):_K(t,e),_K=(t,e)=>{let{transform:r,final:n}=bK(e,{});return[...r(t),...n()]},bK=(t,e)=>(e.previousChunks="",{transform:P0e.bind(void 0,e,t),final:D0e.bind(void 0,e)}),P0e=function*(t,e,r){if(typeof r!="string"){yield r;return}let{previousChunks:n}=t,i=-1;for(let o=0;o0&&(a=RI(n,a),n=""),yield a,i=o}i!==r.length-1&&(n=RI(n,r.slice(i+1))),t.previousChunks=n},C0e=(t,e,r,n)=>r?0:(n.isWindowsNewline=e!==0&&t[e-1]==="\r",n.isWindowsNewline?2:1),D0e=function*({previousChunks:t}){t.length>0&&(yield t)},vK=({binary:t,preserveNewlines:e,readableObjectMode:r,state:n})=>t||e||r?void 0:{transform:N0e.bind(void 0,n)},N0e=function*({isWindowsNewline:t=!1},e){let{unixNewline:r,windowsNewline:n,LF:i,concatBytes:o}=typeof e=="string"?j0e:F0e;if(e.at(-1)===i){yield e;return}yield o(e,t?n:r)},RI=(t,e)=>`${t}${e}`,j0e={windowsNewline:`\r `,unixNewline:` `,LF:` -`,concatBytes:SI},Xxe=(t,e)=>{let r=new Uint8Array(t.length+e.length);return r.set(t,0),r.set(e,t.length),r},Qxe={windowsNewline:new Uint8Array([13,10]),unixNewline:new Uint8Array([10]),LF:10,concatBytes:Xxe}});import{Buffer as e0e}from"node:buffer";var s3,t0e,a3,r0e,n0e,c3,l3=y(()=>{sn();s3=(t,e)=>t?void 0:t0e.bind(void 0,e),t0e=function*(t,e){if(typeof e!="string"&&!qt(e)&&!e0e.isBuffer(e))throw new TypeError(`The \`${t}\` option's transform must use "objectMode: true" to receive as input: ${typeof e}.`);yield e},a3=(t,e)=>t?r0e.bind(void 0,e):n0e.bind(void 0,e),r0e=function*(t,e){c3(t,e),yield e},n0e=function*(t,e){if(c3(t,e),typeof e!="string"&&!qt(e))throw new TypeError(`The \`${t}\` option's function must yield a string or an Uint8Array, not ${typeof e}.`);yield e},c3=(t,e)=>{if(e==null)throw new TypeError(`The \`${t}\` option's function must not call \`yield ${e}\`. +`,concatBytes:RI},M0e=(t,e)=>{let r=new Uint8Array(t.length+e.length);return r.set(t,0),r.set(e,t.length),r},F0e={windowsNewline:new Uint8Array([13,10]),unixNewline:new Uint8Array([10]),LF:10,concatBytes:M0e}});import{Buffer as L0e}from"node:buffer";var SK,z0e,wK,U0e,q0e,xK,$K=y(()=>{an();SK=(t,e)=>t?void 0:z0e.bind(void 0,e),z0e=function*(t,e){if(typeof e!="string"&&!qt(e)&&!L0e.isBuffer(e))throw new TypeError(`The \`${t}\` option's transform must use "objectMode: true" to receive as input: ${typeof e}.`);yield e},wK=(t,e)=>t?U0e.bind(void 0,e):q0e.bind(void 0,e),U0e=function*(t,e){xK(t,e),yield e},q0e=function*(t,e){if(xK(t,e),typeof e!="string"&&!qt(e))throw new TypeError(`The \`${t}\` option's function must yield a string or an Uint8Array, not ${typeof e}.`);yield e},xK=(t,e)=>{if(e==null)throw new TypeError(`The \`${t}\` option's function must not call \`yield ${e}\`. Instead, \`yield\` should either be called with a value, or not be called at all. For example: - if (condition) { yield value; }`)}});import{Buffer as i0e}from"node:buffer";import{StringDecoder as o0e}from"node:string_decoder";var av,s0e,a0e,c0e,xI=y(()=>{sn();av=(t,e,r)=>{if(r)return;if(t)return{transform:s0e.bind(void 0,new TextEncoder)};let n=new o0e(e);return{transform:a0e.bind(void 0,n),final:c0e.bind(void 0,n)}},s0e=function*(t,e){i0e.isBuffer(e)?yield bo(e):typeof e=="string"?yield t.encode(e):yield e},a0e=function*(t,e){yield qt(e)?t.write(e):e},c0e=function*(t){let e=t.end();e!==""&&(yield e)}});import{callbackify as u3}from"node:util";var $I,cv,d3,l0e,f3,u0e,p3=y(()=>{$I=u3(async(t,e,r,n)=>{e.currentIterable=t(...r);try{for await(let i of e.currentIterable)n.push(i)}finally{delete e.currentIterable}}),cv=async function*(t,e,r){if(r===e.length){yield t;return}let{transform:n=u0e}=e[r];for await(let i of n(t))yield*cv(i,e,r+1)},d3=async function*(t){for(let[e,{final:r}]of Object.entries(t))yield*l0e(r,Number(e),t)},l0e=async function*(t,e,r){if(t!==void 0)for await(let n of t())yield*cv(n,r,e+1)},f3=u3(async({currentIterable:t},e)=>{if(t!==void 0){await(e?t.throw(e):t.return());return}if(e)throw e}),u0e=function*(t){yield t}});var kI,m3,La,fp,d0e,f0e,EI=y(()=>{kI=(t,e,r,n)=>{try{for(let i of t(...e))r.push(i);n()}catch(i){n(i)}},m3=(t,e)=>[...e.flatMap(r=>[...La(r,t,0)]),...fp(t)],La=function*(t,e,r){if(r===e.length){yield t;return}let{transform:n=f0e}=e[r];for(let i of n(t))yield*La(i,e,r+1)},fp=function*(t){for(let[e,{final:r}]of Object.entries(t))yield*d0e(r,Number(e),t)},d0e=function*(t,e,r){if(t!==void 0)for(let n of t())yield*La(n,r,e+1)},f0e=function*(t){yield t}});import{Transform as p0e,getDefaultHighWaterMark as h3}from"node:stream";var AI,lv,g3,uv=y(()=>{wr();sv();l3();xI();p3();EI();AI=({value:t,value:{transform:e,final:r,writableObjectMode:n,readableObjectMode:i},optionName:o},{encoding:s})=>{let a={},c=g3(t,s,o),l=Fa(e),u=Fa(r),d=l?$I.bind(void 0,cv,a):kI.bind(void 0,La),f=l||u?$I.bind(void 0,d3,a):kI.bind(void 0,fp),p=l||u?f3.bind(void 0,a):void 0;return{stream:new p0e({writableObjectMode:n,writableHighWaterMark:h3(n),readableObjectMode:i,readableHighWaterMark:h3(i),transform(h,g,b){d([h,c,0],this,b)},flush(h){f([c],this,h)},destroy:p})}},lv=(t,e,r,n)=>{let i=e.filter(({type:s})=>s==="generator"),o=n?i.reverse():i;for(let{value:s,optionName:a}of o){let c=g3(s,r,a);t=m3(c,t)}return t},g3=({transform:t,final:e,binary:r,writableObjectMode:n,readableObjectMode:i,preserveNewlines:o},s,a)=>{let c={};return[{transform:s3(n,a)},av(r,s,n),ov(r,o,n,c),{transform:t,final:e},{transform:a3(i,a)},o3({binary:r,preserveNewlines:o,readableObjectMode:i,state:c})].filter(Boolean)}});var y3,m0e,h0e,g0e,y0e,_3=y(()=>{uv();sn();wr();y3=(t,e)=>{for(let r of m0e(t))h0e(t,r,e)},m0e=t=>new Set(Object.entries(t).filter(([,{direction:e}])=>e==="input").map(([e])=>Number(e))),h0e=(t,e,r)=>{let{stdioItems:n}=t[e],i=n.filter(({contents:a})=>a!==void 0);if(i.length===0)return;if(e!==0){let[{type:a,optionName:c}]=i;throw new TypeError(`Only the \`stdin\` option, not \`${c}\`, can be ${hs[a]} with synchronous methods.`)}let s=i.map(({contents:a})=>a).map(a=>g0e(a,n));r.input=Jf(s)},g0e=(t,e)=>{let r=lv(t,e,"utf8",!0);return y0e(r),Jf(r)},y0e=t=>{let e=t.find(r=>typeof r!="string"&&!qt(r));if(e!==void 0)throw new TypeError(`The \`stdin\` option is invalid: when passing objects as input, a transform must be used to serialize them to strings or Uint8Arrays: ${e}.`)}});var dv,_0e,b0e,b3,v3,v0e,S3,TI=y(()=>{Da();wr();Ol();ds();dv=({stdioItems:t,encoding:e,verboseInfo:r,fdNumber:n})=>n!=="all"&&Tl(r,n)&&!an.has(e)&&_0e(n)&&(t.some(({type:i,value:o})=>i==="native"&&b0e.has(o))||t.every(({type:i})=>Pn.has(i))),_0e=t=>t===1||t===2,b0e=new Set(["pipe","overlapped"]),b3=async(t,e,r,n)=>{for await(let i of t)v0e(e)||S3(i,r,n)},v3=(t,e,r)=>{for(let n of t)S3(n,e,r)},v0e=t=>t._readableState.pipes.length>0,S3=(t,e,r)=>{let n=ub(t);Ci({type:"output",verboseMessage:n,fdNumber:e,verboseInfo:r})}});import{writeFileSync as S0e,appendFileSync as w0e}from"node:fs";var w3,x0e,$0e,k0e,E0e,A0e,x3=y(()=>{TI();uv();sv();sn();wr();Ma();w3=({fileDescriptors:t,syncResult:{output:e},options:r,isMaxBuffer:n,verboseInfo:i})=>{if(e===null)return{output:Array.from({length:3})};let o={},s=new Set([]);return{output:e.map((c,l)=>x0e({result:c,fileDescriptors:t,fdNumber:l,state:o,outputFiles:s,isMaxBuffer:n,verboseInfo:i},r)),...o}},x0e=({result:t,fileDescriptors:e,fdNumber:r,state:n,outputFiles:i,isMaxBuffer:o,verboseInfo:s},{buffer:a,encoding:c,lines:l,stripFinalNewline:u,maxBuffer:d})=>{if(t===null)return;let f=aW(t,o,d),p=bo(f),{stdioItems:m,objectMode:h}=e[r],g=$0e([p],m,c,n),{serializedResult:b,finalResult:_=b}=k0e({chunks:g,objectMode:h,encoding:c,lines:l,stripFinalNewline:u,fdNumber:r});E0e({serializedResult:b,fdNumber:r,state:n,verboseInfo:s,encoding:c,stdioItems:m,objectMode:h});let S=a[r]?_:void 0;try{return n.error===void 0&&A0e(b,m,i),S}catch(x){return n.error=x,S}},$0e=(t,e,r,n)=>{try{return lv(t,e,r,!1)}catch(i){return n.error=i,t}},k0e=({chunks:t,objectMode:e,encoding:r,lines:n,stripFinalNewline:i,fdNumber:o})=>{if(e)return{serializedResult:t};if(r==="buffer")return{serializedResult:Jf(t)};let s=YG(t,r);return n[o]?{serializedResult:s,finalResult:wI(s,!i[o],e)}:{serializedResult:s}},E0e=({serializedResult:t,fdNumber:e,state:r,verboseInfo:n,encoding:i,stdioItems:o,objectMode:s})=>{if(!dv({stdioItems:o,encoding:i,verboseInfo:n,fdNumber:e}))return;let a=wI(t,!1,s);try{v3(a,e,n)}catch(c){r.error??=c}},A0e=(t,e,r)=>{for(let{path:n,append:i}of e.filter(({type:o})=>rv.has(o))){let o=typeof n=="string"?n:n.toString();i||r.has(o)?w0e(n,t):(r.add(o),S0e(n,t))}}});var $3,k3=y(()=>{sn();dp();$3=([,t,e],r)=>{if(r.all)return t===void 0?e:e===void 0?t:Array.isArray(t)?Array.isArray(e)?[...t,...e]:[...t,$o(e,r,"all")]:Array.isArray(e)?[$o(t,r,"all"),...e]:qt(t)&&qt(e)?yR([t,e]):`${t}${e}`}});import{once as OI}from"node:events";var E3,T0e,A3,T3,O0e,RI,II=y(()=>{Pa();E3=async(t,e)=>{let[r,n]=await T0e(t);return e.isForcefullyTerminated??=!1,[r,n]},T0e=async t=>{let[e,r]=await Promise.allSettled([OI(t,"spawn"),OI(t,"exit")]);return e.status==="rejected"?[]:r.status==="rejected"?A3(t):r.value},A3=async t=>{try{return await OI(t,"exit")}catch{return A3(t)}},T3=async t=>{let[e,r]=await t;if(!O0e(e,r)&&RI(e,r))throw new ri;return[e,r]},O0e=(t,e)=>t===void 0&&e===void 0,RI=(t,e)=>t!==0||e!==null});var O3,R0e,R3=y(()=>{Pa();Ma();II();O3=({error:t,status:e,signal:r,output:n},{maxBuffer:i})=>{let o=R0e(t,e,r),s=o?.code==="ETIMEDOUT",a=sW(o,n,i);return{resultError:o,exitCode:e,signal:r,timedOut:s,isMaxBuffer:a}},R0e=(t,e,r)=>t!==void 0?t:RI(e,r)?new ri:void 0});import{spawnSync as I0e}from"node:child_process";var I3,P0e,C0e,D0e,fv,N0e,j0e,M0e,F0e,P3=y(()=>{ER();eI();tI();up();Qb();r3();dp();_3();x3();Ma();k3();R3();I3=(t,e,r)=>{let{file:n,commandArguments:i,command:o,escapedCommand:s,startTime:a,verboseInfo:c,options:l,fileDescriptors:u}=P0e(t,e,r),d=N0e({file:n,commandArguments:i,options:l,command:o,escapedCommand:s,verboseInfo:c,fileDescriptors:u,startTime:a});return zl(d,c,l)},P0e=(t,e,r)=>{let{command:n,escapedCommand:i,startTime:o,verboseInfo:s}=pb(t,e,r),a=C0e(r),{file:c,commandArguments:l,options:u}=zb(t,e,a);D0e(u);let d=e3(u,s);return{file:c,commandArguments:l,command:n,escapedCommand:i,startTime:o,verboseInfo:s,options:u,fileDescriptors:d}},C0e=t=>t.node&&!t.ipc?{...t,ipc:!1}:t,D0e=({ipc:t,ipcInput:e,detached:r,cancelSignal:n})=>{e&&fv("ipcInput"),t&&fv("ipc: true"),r&&fv("detached: true"),n&&fv("cancelSignal")},fv=t=>{throw new TypeError(`The "${t}" option cannot be used with synchronous methods.`)},N0e=({file:t,commandArguments:e,options:r,command:n,escapedCommand:i,verboseInfo:o,fileDescriptors:s,startTime:a})=>{let c=j0e({file:t,commandArguments:e,options:r,command:n,escapedCommand:i,fileDescriptors:s,startTime:a});if(c.failed)return c;let{resultError:l,exitCode:u,signal:d,timedOut:f,isMaxBuffer:p}=O3(c,r),{output:m,error:h=l}=w3({fileDescriptors:s,syncResult:c,options:r,isMaxBuffer:p,verboseInfo:o}),g=m.map((_,S)=>$o(_,r,S)),b=$o($3(m,r),r,"all");return F0e({error:h,exitCode:u,signal:d,timedOut:f,isMaxBuffer:p,stdio:g,all:b,options:r,command:n,escapedCommand:i,startTime:a})},j0e=({file:t,commandArguments:e,options:r,command:n,escapedCommand:i,fileDescriptors:o,startTime:s})=>{try{y3(o,r);let a=M0e(r);return I0e(...Ub(t,e,a))}catch(a){return Ll({error:a,command:n,escapedCommand:i,fileDescriptors:o,options:r,startTime:s,isSync:!0})}},M0e=({encoding:t,maxBuffer:e,...r})=>({...r,encoding:"buffer",maxBuffer:Yb(e)}),F0e=({error:t,exitCode:e,signal:r,timedOut:n,isMaxBuffer:i,stdio:o,all:s,options:a,command:c,escapedCommand:l,startTime:u})=>t===void 0?Xb({command:c,escapedCommand:l,stdio:o,all:s,ipcOutput:[],options:a,startTime:u}):lp({error:t,command:c,escapedCommand:l,timedOut:n,isCanceled:!1,isGracefullyCanceled:!1,isMaxBuffer:i,isForcefullyTerminated:!1,exitCode:e,signal:r,stdio:o,all:s,ipcOutput:[],options:a,startTime:u,isSync:!0})});import{once as PI,on as L0e}from"node:events";var C3,z0e,U0e,q0e,B0e,D3=y(()=>{Dl();ip();np();C3=({anyProcess:t,channel:e,isSubprocess:r,ipc:n},{reference:i=!0,filter:o}={})=>(Pl({methodName:"getOneMessage",isSubprocess:r,ipc:n,isConnected:Cb(t)}),z0e({anyProcess:t,channel:e,isSubprocess:r,filter:o,reference:i})),z0e=async({anyProcess:t,channel:e,isSubprocess:r,filter:n,reference:i})=>{Eb(e,i);let o=ms(t,e,r),s=new AbortController;try{return await Promise.race([U0e(o,n,s),q0e(o,r,s),B0e(o,r,s)])}catch(a){throw Cl(t),a}finally{s.abort(),Ab(e,i)}},U0e=async(t,e,{signal:r})=>{if(e===void 0){let[n]=await PI(t,"message",{signal:r});return n}for await(let[n]of L0e(t,"message",{signal:r}))if(e(n))return n},q0e=async(t,e,{signal:r})=>{await PI(t,"disconnect",{signal:r}),G9(e)},B0e=async(t,e,{signal:r})=>{let[n]=await PI(t,"strict:error",{signal:r});throw wb(n,e)}});import{once as j3,on as H0e}from"node:events";var M3,CI,G0e,Z0e,V0e,N3,DI=y(()=>{Dl();ip();np();M3=({anyProcess:t,channel:e,isSubprocess:r,ipc:n},{reference:i=!0}={})=>CI({anyProcess:t,channel:e,isSubprocess:r,ipc:n,shouldAwait:!r,reference:i}),CI=({anyProcess:t,channel:e,isSubprocess:r,ipc:n,shouldAwait:i,reference:o})=>{Pl({methodName:"getEachMessage",isSubprocess:r,ipc:n,isConnected:Cb(t)}),Eb(e,o);let s=ms(t,e,r),a=new AbortController,c={};return G0e(t,s,a),Z0e({ipcEmitter:s,isSubprocess:r,controller:a,state:c}),V0e({anyProcess:t,channel:e,ipcEmitter:s,isSubprocess:r,shouldAwait:i,controller:a,state:c,reference:o})},G0e=async(t,e,r)=>{try{await j3(e,"disconnect",{signal:r.signal}),r.abort()}catch{}},Z0e=async({ipcEmitter:t,isSubprocess:e,controller:r,state:n})=>{try{let[i]=await j3(t,"strict:error",{signal:r.signal});n.error=wb(i,e),r.abort()}catch{}},V0e=async function*({anyProcess:t,channel:e,ipcEmitter:r,isSubprocess:n,shouldAwait:i,controller:o,state:s,reference:a}){try{for await(let[c]of H0e(r,"message",{signal:o.signal}))N3(s),yield c}catch{N3(s)}finally{o.abort(),Ab(e,a),n||Cl(t),i&&await t}},N3=({error:t})=>{if(t)throw t}});import F3 from"node:process";var L3,z3,U3,NI=y(()=>{Fb();D3();DI();Ib();L3=(t,{ipc:e})=>{Object.assign(t,U3(t,!1,e))},z3=()=>{let t=F3,e=!0,r=F3.channel!==void 0;return{...U3(t,e,r),getCancelSignal:bV.bind(void 0,{anyProcess:t,channel:t.channel,isSubprocess:e,ipc:r})}},U3=(t,e,r)=>({sendMessage:Mb.bind(void 0,{anyProcess:t,channel:t.channel,isSubprocess:e,ipc:r}),getOneMessage:C3.bind(void 0,{anyProcess:t,channel:t.channel,isSubprocess:e,ipc:r}),getEachMessage:M3.bind(void 0,{anyProcess:t,channel:t.channel,isSubprocess:e,ipc:r})})});import{ChildProcess as W0e}from"node:child_process";import{PassThrough as K0e,Readable as J0e,Writable as Y0e,Duplex as X0e}from"node:stream";var q3,Q0e,pp,e$e,t$e,r$e,n$e,B3=y(()=>{iv();up();Qb();q3=({error:t,command:e,escapedCommand:r,fileDescriptors:n,options:i,startTime:o,verboseInfo:s})=>{bI(n);let a=new W0e;Q0e(a,n),Object.assign(a,{readable:e$e,writable:t$e,duplex:r$e});let c=Ll({error:t,command:e,escapedCommand:r,fileDescriptors:n,options:i,startTime:o,isSync:!1}),l=n$e(c,s,i);return{subprocess:a,promise:l}},Q0e=(t,e)=>{let r=pp(),n=pp(),i=pp(),o=Array.from({length:e.length-3},pp),s=pp(),a=[r,n,i,...o];Object.assign(t,{stdin:r,stdout:n,stderr:i,all:s,stdio:a})},pp=()=>{let t=new K0e;return t.end(),t},e$e=()=>new J0e({read(){}}),t$e=()=>new Y0e({write(){}}),r$e=()=>new X0e({read(){},write(){}}),n$e=async(t,e,r)=>zl(t,e,r)});import{createReadStream as H3,createWriteStream as G3}from"node:fs";import{Buffer as i$e}from"node:buffer";import{Readable as mp,Writable as o$e,Duplex as s$e}from"node:stream";var V3,hp,Z3,a$e,W3=y(()=>{uv();iv();wr();V3=(t,e)=>nv(a$e,t,e,!1),hp=({type:t,optionName:e})=>{throw new TypeError(`The \`${e}\` option cannot be ${hs[t]}.`)},Z3={fileNumber:hp,generator:AI,asyncGenerator:AI,nodeStream:({value:t})=>({stream:t}),webTransform({value:{transform:t,writableObjectMode:e,readableObjectMode:r}}){let n=e||r;return{stream:s$e.fromWeb(t,{objectMode:n})}},duplex:({value:{transform:t}})=>({stream:t}),native(){}},a$e={input:{...Z3,fileUrl:({value:t})=>({stream:H3(t)}),filePath:({value:{file:t}})=>({stream:H3(t)}),webStream:({value:t})=>({stream:mp.fromWeb(t)}),iterable:({value:t})=>({stream:mp.from(t)}),asyncIterable:({value:t})=>({stream:mp.from(t)}),string:({value:t})=>({stream:mp.from(t)}),uint8Array:({value:t})=>({stream:mp.from(i$e.from(t))})},output:{...Z3,fileUrl:({value:t})=>({stream:G3(t)}),filePath:({value:{file:t,append:e}})=>({stream:G3(t,e?{flags:"a"}:{})}),webStream:({value:t})=>({stream:o$e.fromWeb(t)}),iterable:hp,asyncIterable:hp,string:hp,uint8Array:hp}}});import{on as c$e,once as K3}from"node:events";import{PassThrough as l$e,getDefaultHighWaterMark as u$e}from"node:stream";import{finished as X3}from"node:stream/promises";function za(t){if(!Array.isArray(t))throw new TypeError(`Expected an array, got \`${typeof t}\`.`);for(let i of t)MI(i);let e=t.some(({readableObjectMode:i})=>i),r=d$e(t,e),n=new jI({objectMode:e,writableHighWaterMark:r,readableHighWaterMark:r});for(let i of t)n.add(i);return n}var d$e,jI,f$e,p$e,m$e,MI,h$e,g$e,y$e,_$e,b$e,Q3,eK,FI,tK,v$e,pv,J3,Y3,mv=y(()=>{d$e=(t,e)=>{if(t.length===0)return u$e(e);let r=t.filter(({readableObjectMode:n})=>n===e).map(({readableHighWaterMark:n})=>n);return Math.max(...r)},jI=class extends l$e{#t=new Set([]);#r=new Set([]);#e=new Set([]);#n;#o=Symbol("unpipe");#i=new WeakMap;add(e){if(MI(e),this.#t.has(e))return;this.#t.add(e),this.#n??=f$e(this,this.#t,this.#o);let r=h$e({passThroughStream:this,stream:e,streams:this.#t,ended:this.#r,aborted:this.#e,onFinished:this.#n,unpipeEvent:this.#o});this.#i.set(e,r),e.pipe(this,{end:!1})}async remove(e){if(MI(e),!this.#t.has(e))return!1;let r=this.#i.get(e);return r===void 0?!1:(this.#i.delete(e),e.unpipe(this),await r,!0)}},f$e=async(t,e,r)=>{pv(t,J3);let n=new AbortController;try{await Promise.race([p$e(t,n),m$e(t,e,r,n)])}finally{n.abort(),pv(t,-J3)}},p$e=async(t,{signal:e})=>{try{await X3(t,{signal:e,cleanup:!0})}catch(r){throw Q3(t,r),r}},m$e=async(t,e,r,{signal:n})=>{for await(let[i]of c$e(t,"unpipe",{signal:n}))e.has(i)&&i.emit(r)},MI=t=>{if(typeof t?.pipe!="function")throw new TypeError(`Expected a readable stream, got: \`${typeof t}\`.`)},h$e=async({passThroughStream:t,stream:e,streams:r,ended:n,aborted:i,onFinished:o,unpipeEvent:s})=>{pv(t,Y3);let a=new AbortController;try{await Promise.race([g$e(o,e,a),y$e({passThroughStream:t,stream:e,streams:r,ended:n,aborted:i,controller:a}),_$e({stream:e,streams:r,ended:n,aborted:i,unpipeEvent:s,controller:a})])}finally{a.abort(),pv(t,-Y3)}r.size>0&&r.size===n.size+i.size&&(n.size===0&&i.size>0?FI(t):b$e(t))},g$e=async(t,e,{signal:r})=>{try{await t,r.aborted||FI(e)}catch(n){r.aborted||Q3(e,n)}},y$e=async({passThroughStream:t,stream:e,streams:r,ended:n,aborted:i,controller:{signal:o}})=>{try{await X3(e,{signal:o,cleanup:!0,readable:!0,writable:!1}),r.has(e)&&n.add(e)}catch(s){if(o.aborted||!r.has(e))return;eK(s)?i.add(e):tK(t,s)}},_$e=async({stream:t,streams:e,ended:r,aborted:n,unpipeEvent:i,controller:{signal:o}})=>{if(await K3(t,i,{signal:o}),!t.readable)return K3(o,"abort",{signal:o});e.delete(t),r.delete(t),n.delete(t)},b$e=t=>{t.writable&&t.end()},Q3=(t,e)=>{eK(e)?FI(t):tK(t,e)},eK=t=>t?.code==="ERR_STREAM_PREMATURE_CLOSE",FI=t=>{(t.readable||t.writable)&&t.destroy()},tK=(t,e)=>{t.destroyed||(t.once("error",v$e),t.destroy(e))},v$e=()=>{},pv=(t,e)=>{let r=t.getMaxListeners();r!==0&&r!==Number.POSITIVE_INFINITY&&t.setMaxListeners(r+e)},J3=2,Y3=1});import{finished as rK}from"node:stream/promises";var ql,S$e,LI,w$e,zI,hv=y(()=>{vo();ql=(t,e)=>{t.pipe(e),S$e(t,e),w$e(t,e)},S$e=async(t,e)=>{if(!(ti(t)||ti(e))){try{await rK(t,{cleanup:!0,readable:!0,writable:!1})}catch{}LI(e)}},LI=t=>{t.writable&&t.end()},w$e=async(t,e)=>{if(!(ti(t)||ti(e))){try{await rK(e,{cleanup:!0,readable:!1,writable:!0})}catch{}zI(t)}},zI=t=>{t.readable&&t.destroy()}});var nK,x$e,$$e,k$e,E$e,A$e,iK=y(()=>{mv();vo();kb();wr();hv();nK=(t,e,r)=>{let n=new Map;for(let[i,{stdioItems:o,direction:s}]of Object.entries(e)){for(let{stream:a}of o.filter(({type:c})=>Pn.has(c)))x$e(t,a,s,i);for(let{stream:a}of o.filter(({type:c})=>!Pn.has(c)))k$e({subprocess:t,stream:a,direction:s,fdNumber:i,pipeGroups:n,controller:r})}for(let[i,o]of n.entries()){let s=o.length===1?o[0]:za(o);ql(s,i)}},x$e=(t,e,r,n)=>{r==="output"?ql(t.stdio[n],e):ql(e,t.stdio[n]);let i=$$e[n];i!==void 0&&(t[i]=e),t.stdio[n]=e},$$e=["stdin","stdout","stderr"],k$e=({subprocess:t,stream:e,direction:r,fdNumber:n,pipeGroups:i,controller:o})=>{if(e===void 0)return;E$e(e,o);let[s,a]=r==="output"?[e,t.stdio[n]]:[t.stdio[n],e],c=i.get(s)??[];i.set(s,[...c,a])},E$e=(t,{signal:e})=>{ti(t)&&Ca(t,A$e,e)},A$e=2});var Ua,oK=y(()=>{Ua=[];Ua.push("SIGHUP","SIGINT","SIGTERM");process.platform!=="win32"&&Ua.push("SIGALRM","SIGABRT","SIGVTALRM","SIGXCPU","SIGXFSZ","SIGUSR2","SIGTRAP","SIGSYS","SIGQUIT","SIGIOT");process.platform==="linux"&&Ua.push("SIGIO","SIGPOLL","SIGPWR","SIGSTKFLT")});var gv,UI,qI,T$e,BI,yv,O$e,HI,GI,ZI,sK,jat,Mat,aK=y(()=>{oK();gv=t=>!!t&&typeof t=="object"&&typeof t.removeListener=="function"&&typeof t.emit=="function"&&typeof t.reallyExit=="function"&&typeof t.listeners=="function"&&typeof t.kill=="function"&&typeof t.pid=="number"&&typeof t.on=="function",UI=Symbol.for("signal-exit emitter"),qI=globalThis,T$e=Object.defineProperty.bind(Object),BI=class{emitted={afterExit:!1,exit:!1};listeners={afterExit:[],exit:[]};count=0;id=Math.random();constructor(){if(qI[UI])return qI[UI];T$e(qI,UI,{value:this,writable:!1,enumerable:!1,configurable:!1})}on(e,r){this.listeners[e].push(r)}removeListener(e,r){let n=this.listeners[e],i=n.indexOf(r);i!==-1&&(i===0&&n.length===1?n.length=0:n.splice(i,1))}emit(e,r,n){if(this.emitted[e])return!1;this.emitted[e]=!0;let i=!1;for(let o of this.listeners[e])i=o(r,n)===!0||i;return e==="exit"&&(i=this.emit("afterExit",r,n)||i),i}},yv=class{},O$e=t=>({onExit(e,r){return t.onExit(e,r)},load(){return t.load()},unload(){return t.unload()}}),HI=class extends yv{onExit(){return()=>{}}load(){}unload(){}},GI=class extends yv{#t=ZI.platform==="win32"?"SIGINT":"SIGHUP";#r=new BI;#e;#n;#o;#i={};#s=!1;constructor(e){super(),this.#e=e,this.#i={};for(let r of Ua)this.#i[r]=()=>{let n=this.#e.listeners(r),{count:i}=this.#r,o=e;if(typeof o.__signal_exit_emitter__=="object"&&typeof o.__signal_exit_emitter__.count=="number"&&(i+=o.__signal_exit_emitter__.count),n.length===i){this.unload();let s=this.#r.emit("exit",null,r),a=r==="SIGHUP"?this.#t:r;s||e.kill(e.pid,a)}};this.#o=e.reallyExit,this.#n=e.emit}onExit(e,r){if(!gv(this.#e))return()=>{};this.#s===!1&&this.load();let n=r?.alwaysLast?"afterExit":"exit";return this.#r.on(n,e),()=>{this.#r.removeListener(n,e),this.#r.listeners.exit.length===0&&this.#r.listeners.afterExit.length===0&&this.unload()}}load(){if(!this.#s){this.#s=!0,this.#r.count+=1;for(let e of Ua)try{let r=this.#i[e];r&&this.#e.on(e,r)}catch{}this.#e.emit=(e,...r)=>this.#c(e,...r),this.#e.reallyExit=e=>this.#a(e)}}unload(){this.#s&&(this.#s=!1,Ua.forEach(e=>{let r=this.#i[e];if(!r)throw new Error("Listener not defined for signal: "+e);try{this.#e.removeListener(e,r)}catch{}}),this.#e.emit=this.#n,this.#e.reallyExit=this.#o,this.#r.count-=1)}#a(e){return gv(this.#e)?(this.#e.exitCode=e||0,this.#r.emit("exit",this.#e.exitCode,null),this.#o.call(this.#e,this.#e.exitCode)):0}#c(e,...r){let n=this.#n;if(e==="exit"&&gv(this.#e)){typeof r[0]=="number"&&(this.#e.exitCode=r[0]);let i=n.call(this.#e,e,...r);return this.#r.emit("exit",this.#e.exitCode,null),i}else return n.call(this.#e,e,...r)}},ZI=globalThis.process,{onExit:sK,load:jat,unload:Mat}=O$e(gv(ZI)?new GI(ZI):new HI)});import{addAbortListener as R$e}from"node:events";var cK,lK=y(()=>{aK();cK=(t,{cleanup:e,detached:r},{signal:n})=>{if(!e||r)return;let i=sK(()=>{t.kill()});R$e(n,()=>{i()})}});var dK,I$e,P$e,uK,C$e,fK=y(()=>{gR();fb();ps();El();dK=({source:t,sourcePromise:e,boundOptions:r,createNested:n},...i)=>{let o=db(),{destination:s,destinationStream:a,destinationError:c,from:l,unpipeSignal:u}=I$e(r,n,i),{sourceStream:d,sourceError:f}=C$e(t,l),{options:p,fileDescriptors:m}=Ni.get(t);return{sourcePromise:e,sourceStream:d,sourceOptions:p,sourceError:f,destination:s,destinationStream:a,destinationError:c,unpipeSignal:u,fileDescriptors:m,startTime:o}},I$e=(t,e,r)=>{try{let{destination:n,pipeOptions:{from:i,to:o,unpipeSignal:s}={}}=P$e(t,e,...r),a=$b(n,o);return{destination:n,destinationStream:a,from:i,unpipeSignal:s}}catch(n){return{destinationError:n}}},P$e=(t,e,r,...n)=>{if(Array.isArray(r))return{destination:e(uK,t)(r,...n),pipeOptions:t};if(typeof r=="string"||r instanceof URL||mR(r)){if(Object.keys(t).length>0)throw new TypeError('Please use .pipe("file", ..., options) or .pipe(execa("file", ..., options)) instead of .pipe(options)("file", ...).');let[i,o,s]=eb(r,...n);return{destination:e(uK)(i,o,s),pipeOptions:s}}if(Ni.has(r)){if(Object.keys(t).length>0)throw new TypeError("Please use .pipe(options)`command` or .pipe($(options)`command`) instead of .pipe(options)($`command`).");return{destination:r,pipeOptions:n[0]}}throw new TypeError(`The first argument must be a template string, an options object, or an Execa subprocess: ${r}`)},uK=({options:t})=>({options:{...t,stdin:"pipe",piped:!0}}),C$e=(t,e)=>{try{return{sourceStream:jl(t,e)}}catch(r){return{sourceError:r}}}});var mK,D$e,VI,pK,WI=y(()=>{up();hv();mK=({sourceStream:t,sourceError:e,destinationStream:r,destinationError:n,fileDescriptors:i,sourceOptions:o,startTime:s})=>{let a=D$e({sourceStream:t,sourceError:e,destinationStream:r,destinationError:n});if(a!==void 0)throw VI({error:a,fileDescriptors:i,sourceOptions:o,startTime:s})},D$e=({sourceStream:t,sourceError:e,destinationStream:r,destinationError:n})=>{if(e!==void 0&&n!==void 0)return n;if(n!==void 0)return zI(t),n;if(e!==void 0)return LI(r),e},VI=({error:t,fileDescriptors:e,sourceOptions:r,startTime:n})=>Ll({error:t,command:pK,escapedCommand:pK,fileDescriptors:e,options:r,startTime:n,isSync:!1}),pK="source.pipe(destination)"});var hK,gK=y(()=>{hK=async t=>{let[{status:e,reason:r,value:n=r},{status:i,reason:o,value:s=o}]=await t;if(s.pipedFrom.includes(n)||s.pipedFrom.push(n),i==="rejected")throw s;if(e==="rejected")throw n;return s}});import{finished as N$e}from"node:stream/promises";var yK,j$e,M$e,F$e,_v,L$e,z$e,_K=y(()=>{mv();kb();hv();yK=(t,e,r)=>{let n=_v.has(e)?M$e(t,e):j$e(t,e);return Ca(t,L$e,r.signal),Ca(e,z$e,r.signal),F$e(e),n},j$e=(t,e)=>{let r=za([t]);return ql(r,e),_v.set(e,r),r},M$e=(t,e)=>{let r=_v.get(e);return r.add(t),r},F$e=async t=>{try{await N$e(t,{cleanup:!0,readable:!1,writable:!0})}catch{}_v.delete(t)},_v=new WeakMap,L$e=2,z$e=1});import{aborted as U$e}from"node:util";var bK,q$e,vK=y(()=>{WI();bK=(t,e)=>t===void 0?[]:[q$e(t,e)],q$e=async(t,{sourceStream:e,mergedStream:r,fileDescriptors:n,sourceOptions:i,startTime:o})=>{await U$e(t,e),await r.remove(e);let s=new Error("Pipe canceled by `unpipeSignal` option.");throw VI({error:s,fileDescriptors:n,sourceOptions:i,startTime:o})}});var bv,B$e,H$e,SK=y(()=>{_o();fK();WI();gK();_K();vK();bv=(t,...e)=>{if(Ot(e[0]))return bv.bind(void 0,{...t,boundOptions:{...t.boundOptions,...e[0]}});let{destination:r,...n}=dK(t,...e),i=B$e({...n,destination:r});return i.pipe=bv.bind(void 0,{...t,source:r,sourcePromise:i,boundOptions:{}}),i},B$e=async({sourcePromise:t,sourceStream:e,sourceOptions:r,sourceError:n,destination:i,destinationStream:o,destinationError:s,unpipeSignal:a,fileDescriptors:c,startTime:l})=>{let u=H$e(t,i);mK({sourceStream:e,sourceError:n,destinationStream:o,destinationError:s,fileDescriptors:c,sourceOptions:r,startTime:l});let d=new AbortController;try{let f=yK(e,o,d);return await Promise.race([hK(u),...bK(a,{sourceStream:e,mergedStream:f,sourceOptions:r,fileDescriptors:c,startTime:l})])}finally{d.abort()}},H$e=(t,e)=>Promise.allSettled([t,e])});import{on as G$e}from"node:events";import{getDefaultHighWaterMark as Z$e}from"node:stream";var vv,V$e,KI,W$e,xK,JI,wK,K$e,J$e,Sv=y(()=>{xI();sv();EI();vv=({subprocessStdout:t,subprocess:e,binary:r,shouldEncode:n,encoding:i,preserveNewlines:o})=>{let s=new AbortController;return V$e(e,s),xK({stream:t,controller:s,binary:r,shouldEncode:!t.readableObjectMode&&n,encoding:i,shouldSplit:!t.readableObjectMode,preserveNewlines:o})},V$e=async(t,e)=>{try{await t}catch{}finally{e.abort()}},KI=({stream:t,onStreamEnd:e,lines:r,encoding:n,stripFinalNewline:i,allMixed:o})=>{let s=new AbortController;W$e(e,s,t);let a=t.readableObjectMode&&!o;return xK({stream:t,controller:s,binary:n==="buffer",shouldEncode:!a,encoding:n,shouldSplit:!a&&r,preserveNewlines:!i})},W$e=async(t,e,r)=>{try{await t}catch{r.destroy()}finally{e.abort()}},xK=({stream:t,controller:e,binary:r,shouldEncode:n,encoding:i,shouldSplit:o,preserveNewlines:s})=>{let a=G$e(t,"data",{signal:e.signal,highWaterMark:wK,highWatermark:wK});return K$e({onStdoutChunk:a,controller:e,binary:r,shouldEncode:n,encoding:i,shouldSplit:o,preserveNewlines:s})},JI=Z$e(!0),wK=JI,K$e=async function*({onStdoutChunk:t,controller:e,binary:r,shouldEncode:n,encoding:i,shouldSplit:o,preserveNewlines:s}){let a=J$e({binary:r,shouldEncode:n,encoding:i,shouldSplit:o,preserveNewlines:s});try{for await(let[c]of t)yield*La(c,a,0)}catch(c){if(!e.signal.aborted)throw c}finally{yield*fp(a)}},J$e=({binary:t,shouldEncode:e,encoding:r,shouldSplit:n,preserveNewlines:i})=>[av(t,r,!e),ov(t,i,!n,{})].filter(Boolean)});import{setImmediate as Y$e}from"node:timers/promises";var $K,X$e,Q$e,eke,YI,kK,XI=y(()=>{Jb();sn();TI();Sv();Ma();dp();$K=async({stream:t,onStreamEnd:e,fdNumber:r,encoding:n,buffer:i,maxBuffer:o,lines:s,allMixed:a,stripFinalNewline:c,verboseInfo:l,streamInfo:u})=>{let d=X$e({stream:t,onStreamEnd:e,fdNumber:r,encoding:n,allMixed:a,verboseInfo:l,streamInfo:u});if(!i){await Promise.all([Q$e(t),d]);return}let f=vI(c,r),p=KI({stream:t,onStreamEnd:e,lines:s,encoding:n,stripFinalNewline:f,allMixed:a}),[m]=await Promise.all([eke({stream:t,iterable:p,fdNumber:r,encoding:n,maxBuffer:o,lines:s}),d]);return m},X$e=async({stream:t,onStreamEnd:e,fdNumber:r,encoding:n,allMixed:i,verboseInfo:o,streamInfo:{fileDescriptors:s}})=>{if(!dv({stdioItems:s[r]?.stdioItems,encoding:n,verboseInfo:o,fdNumber:r}))return;let a=KI({stream:t,onStreamEnd:e,lines:!0,encoding:n,stripFinalNewline:!0,allMixed:i});await b3(a,t,r,o)},Q$e=async t=>{await Y$e(),t.readableFlowing===null&&t.resume()},eke=async({stream:t,stream:{readableObjectMode:e},iterable:r,fdNumber:n,encoding:i,maxBuffer:o,lines:s})=>{try{return e||s?await Zb(r,{maxBuffer:o}):i==="buffer"?new Uint8Array(await Vb(r,{maxBuffer:o})):await Kb(r,{maxBuffer:o})}catch(a){return kK(nW({error:a,stream:t,readableObjectMode:e,lines:s,encoding:i,fdNumber:n}))}},YI=async t=>{try{return await t}catch(e){return kK(e)}},kK=({bufferedData:t})=>KG(t)?new Uint8Array(t):t});import{finished as tke}from"node:stream/promises";var gp,rke,nke,ike,oke,ske,QI,wv,EK,xv=y(()=>{gp=async(t,e,r,{isSameDirection:n,stopOnExit:i=!1}={})=>{let o=rke(t,r),s=new AbortController;try{await Promise.race([...i?[r.exitPromise]:[],tke(t,{cleanup:!0,signal:s.signal})])}catch(a){o.stdinCleanedUp||oke(a,e,r,n)}finally{s.abort()}},rke=(t,{originalStreams:[e],subprocess:r})=>{let n={stdinCleanedUp:!1};return t===e&&nke(t,r,n),n},nke=(t,e,r)=>{let{_destroy:n}=t;t._destroy=(...i)=>{ike(e,r),n.call(t,...i)}},ike=({exitCode:t,signalCode:e},r)=>{(t!==null||e!==null)&&(r.stdinCleanedUp=!0)},oke=(t,e,r,n)=>{if(!ske(t,e,r,n))throw t},ske=(t,e,r,n=!0)=>r.propagating?EK(t)||wv(t):(r.propagating=!0,QI(r,e)===n?EK(t):wv(t)),QI=({fileDescriptors:t},e)=>e!=="all"&&t[e].direction==="input",wv=t=>t?.code==="ERR_STREAM_PREMATURE_CLOSE",EK=t=>t?.code==="EPIPE"});var AK,eP,tP=y(()=>{XI();xv();AK=({subprocess:t,encoding:e,buffer:r,maxBuffer:n,lines:i,stripFinalNewline:o,verboseInfo:s,streamInfo:a})=>t.stdio.map((c,l)=>eP({stream:c,fdNumber:l,encoding:e,buffer:r[l],maxBuffer:n[l],lines:i[l],allMixed:!1,stripFinalNewline:o,verboseInfo:s,streamInfo:a})),eP=async({stream:t,fdNumber:e,encoding:r,buffer:n,maxBuffer:i,lines:o,allMixed:s,stripFinalNewline:a,verboseInfo:c,streamInfo:l})=>{if(!t)return;let u=gp(t,e,l);if(QI(l,e)){await u;return}let[d]=await Promise.all([$K({stream:t,onStreamEnd:u,fdNumber:e,encoding:r,buffer:n,maxBuffer:i,lines:o,allMixed:s,stripFinalNewline:a,verboseInfo:c,streamInfo:l}),u]);return d}});var TK,OK,ake,cke,rP=y(()=>{mv();tP();TK=({stdout:t,stderr:e},{all:r})=>r&&(t||e)?za([t,e].filter(Boolean)):void 0,OK=({subprocess:t,encoding:e,buffer:r,maxBuffer:n,lines:i,stripFinalNewline:o,verboseInfo:s,streamInfo:a})=>eP({...ake(t,r),fdNumber:"all",encoding:e,maxBuffer:n[1]+n[2],lines:i[1]||i[2],allMixed:cke(t),stripFinalNewline:o,verboseInfo:s,streamInfo:a}),ake=({stdout:t,stderr:e,all:r},[,n,i])=>{let o=n||i;return o?n?i?{stream:r,buffer:o}:{stream:t,buffer:o}:{stream:e,buffer:o}:{stream:r,buffer:o}},cke=({all:t,stdout:e,stderr:r})=>t&&e&&r&&e.readableObjectMode!==r.readableObjectMode});var RK,IK,PK=y(()=>{Ol();ds();RK=t=>Tl(t,"ipc"),IK=(t,e)=>{let r=ub(t);Ci({type:"ipc",verboseMessage:r,fdNumber:"ipc",verboseInfo:e})}});var CK,DK,NK=y(()=>{Ma();PK();wo();DI();CK=async({subprocess:t,buffer:e,maxBuffer:r,ipc:n,ipcOutput:i,verboseInfo:o})=>{if(!n)return i;let s=RK(o),a=So(e,"ipc"),c=So(r,"ipc");for await(let l of CI({anyProcess:t,channel:t.channel,isSubprocess:!1,ipc:n,shouldAwait:!1,reference:!0}))a&&(iW(t,i,c),i.push(l)),s&&IK(l,o);return i},DK=async(t,e)=>(await Promise.allSettled([t]),e)});import{once as lke}from"node:events";var jK,uke,dke,fke,MK=y(()=>{ja();KR();zR();WR();vo();wr();XI();NK();YR();rP();tP();II();xv();jK=async({subprocess:t,options:{encoding:e,buffer:r,maxBuffer:n,lines:i,timeoutDuration:o,cancelSignal:s,gracefulCancel:a,forceKillAfterDelay:c,stripFinalNewline:l,ipc:u,ipcInput:d},context:f,verboseInfo:p,fileDescriptors:m,originalStreams:h,onInternalError:g,controller:b})=>{let _=E3(t,f),S={originalStreams:h,fileDescriptors:m,subprocess:t,exitPromise:_,propagating:!1},x=AK({subprocess:t,encoding:e,buffer:r,maxBuffer:n,lines:i,stripFinalNewline:l,verboseInfo:p,streamInfo:S}),w=OK({subprocess:t,encoding:e,buffer:r,maxBuffer:n,lines:i,stripFinalNewline:l,verboseInfo:p,streamInfo:S}),O=[],T=CK({subprocess:t,buffer:r,maxBuffer:n,ipc:u,ipcOutput:O,verboseInfo:p}),A=uke(h,t,S),D=dke(m,S);try{return await Promise.race([Promise.all([{},T3(_),Promise.all(x),w,T,OV(t,d),...A,...D]),g,fke(t,b),...$V(t,o,f,b),...H9({subprocess:t,cancelSignal:s,gracefulCancel:a,context:f,controller:b}),...wV({subprocess:t,cancelSignal:s,gracefulCancel:a,forceKillAfterDelay:c,context:f,controller:b})])}catch($){return f.terminationReason??="other",Promise.all([{error:$},_,Promise.all(x.map(re=>YI(re))),YI(w),DK(T,O),Promise.allSettled(A),Promise.allSettled(D)])}},uke=(t,e,r)=>t.map((n,i)=>n===e.stdio[i]?void 0:gp(n,i,r)),dke=(t,e)=>t.flatMap(({stdioItems:r},n)=>r.filter(({value:i,stream:o=i})=>ii(o,{checkOpen:!1})&&!ti(o)).map(({type:i,value:o,stream:s=o})=>gp(s,n,e,{isSameDirection:Pn.has(i),stopOnExit:i==="native"}))),fke=async(t,{signal:e})=>{let[r]=await lke(t,"error",{signal:e});throw r}});var FK,yp,Bl,$v=y(()=>{Nl();FK=()=>({readableDestroy:new WeakMap,writableFinal:new WeakMap,writableDestroy:new WeakMap}),yp=(t,e,r)=>{let n=t[r];n.has(e)||n.set(e,[]);let i=n.get(e),o=Di();return i.push(o),{resolve:o.resolve.bind(o),promises:i}},Bl=async({resolve:t,promises:e},r)=>{t();let[n]=await Promise.race([Promise.allSettled([!0,r]),Promise.all([!1,...e])]);return!n}});import{finished as LK}from"node:stream/promises";var nP,zK,iP,oP,kv,Ev,sP=y(()=>{xv();nP=async t=>{if(t!==void 0)try{await iP(t)}catch{}},zK=async t=>{if(t!==void 0)try{await oP(t)}catch{}},iP=async t=>{await LK(t,{cleanup:!0,readable:!1,writable:!0})},oP=async t=>{await LK(t,{cleanup:!0,readable:!0,writable:!1})},kv=async(t,e)=>{if(await t,e)throw e},Ev=(t,e,r)=>{r&&!wv(r)?t.destroy(r):e&&t.destroy()}});import{Readable as pke}from"node:stream";import{callbackify as mke}from"node:util";var UK,aP,cP,lP,hke,uP,dP,qK,fP=y(()=>{Da();ps();Sv();Nl();$v();sP();UK=({subprocess:t,concurrentStreams:e,encoding:r},{from:n,binary:i=!0,preserveNewlines:o=!0}={})=>{let s=i||an.has(r),{subprocessStdout:a,waitReadableDestroy:c}=aP(t,n,e),{readableEncoding:l,readableObjectMode:u,readableHighWaterMark:d}=cP(a,s),{read:f,onStdoutDataDone:p}=lP({subprocessStdout:a,subprocess:t,binary:s,encoding:r,preserveNewlines:o}),m=new pke({read:f,destroy:mke(dP.bind(void 0,{subprocessStdout:a,subprocess:t,waitReadableDestroy:c})),highWaterMark:d,objectMode:u,encoding:l});return uP({subprocessStdout:a,onStdoutDataDone:p,readable:m,subprocess:t}),m},aP=(t,e,r)=>{let n=jl(t,e),i=yp(r,n,"readableDestroy");return{subprocessStdout:n,waitReadableDestroy:i}},cP=({readableEncoding:t,readableObjectMode:e,readableHighWaterMark:r},n)=>n?{readableEncoding:t,readableObjectMode:e,readableHighWaterMark:r}:{readableEncoding:t,readableObjectMode:!0,readableHighWaterMark:JI},lP=({subprocessStdout:t,subprocess:e,binary:r,encoding:n,preserveNewlines:i})=>{let o=Di(),s=vv({subprocessStdout:t,subprocess:e,binary:r,shouldEncode:!r,encoding:n,preserveNewlines:i});return{read(){hke(this,s,o)},onStdoutDataDone:o}},hke=async(t,e,r)=>{try{let{value:n,done:i}=await e.next();i?r.resolve():t.push(n)}catch{}},uP=async({subprocessStdout:t,onStdoutDataDone:e,readable:r,subprocess:n,subprocessStdin:i})=>{try{await oP(t),await n,await nP(i),await e,r.readable&&r.push(null)}catch(o){await nP(i),qK(r,o)}},dP=async({subprocessStdout:t,subprocess:e,waitReadableDestroy:r},n)=>{await Bl(r,e)&&(qK(t,n),await kv(e,n))},qK=(t,e)=>{Ev(t,t.readable,e)}});import{Writable as gke}from"node:stream";import{callbackify as BK}from"node:util";var HK,pP,mP,yke,_ke,hP,gP,GK,yP=y(()=>{ps();$v();sP();HK=({subprocess:t,concurrentStreams:e},{to:r}={})=>{let{subprocessStdin:n,waitWritableFinal:i,waitWritableDestroy:o}=pP(t,r,e),s=new gke({...mP(n,t,i),destroy:BK(gP.bind(void 0,{subprocessStdin:n,subprocess:t,waitWritableFinal:i,waitWritableDestroy:o})),highWaterMark:n.writableHighWaterMark,objectMode:n.writableObjectMode});return hP(n,s),s},pP=(t,e,r)=>{let n=$b(t,e),i=yp(r,n,"writableFinal"),o=yp(r,n,"writableDestroy");return{subprocessStdin:n,waitWritableFinal:i,waitWritableDestroy:o}},mP=(t,e,r)=>({write:yke.bind(void 0,t),final:BK(_ke.bind(void 0,t,e,r))}),yke=(t,e,r,n)=>{t.write(e,r)?n():t.once("drain",n)},_ke=async(t,e,r)=>{await Bl(r,e)&&(t.writable&&t.end(),await e)},hP=async(t,e,r)=>{try{await iP(t),e.writable&&e.end()}catch(n){await zK(r),GK(e,n)}},gP=async({subprocessStdin:t,subprocess:e,waitWritableFinal:r,waitWritableDestroy:n},i)=>{await Bl(r,e),await Bl(n,e)&&(GK(t,i),await kv(e,i))},GK=(t,e)=>{Ev(t,t.writable,e)}});import{Duplex as bke}from"node:stream";import{callbackify as vke}from"node:util";var ZK,Ske,VK=y(()=>{Da();fP();yP();ZK=({subprocess:t,concurrentStreams:e,encoding:r},{from:n,to:i,binary:o=!0,preserveNewlines:s=!0}={})=>{let a=o||an.has(r),{subprocessStdout:c,waitReadableDestroy:l}=aP(t,n,e),{subprocessStdin:u,waitWritableFinal:d,waitWritableDestroy:f}=pP(t,i,e),{readableEncoding:p,readableObjectMode:m,readableHighWaterMark:h}=cP(c,a),{read:g,onStdoutDataDone:b}=lP({subprocessStdout:c,subprocess:t,binary:a,encoding:r,preserveNewlines:s}),_=new bke({read:g,...mP(u,t,d),destroy:vke(Ske.bind(void 0,{subprocessStdout:c,subprocessStdin:u,subprocess:t,waitReadableDestroy:l,waitWritableFinal:d,waitWritableDestroy:f})),readableHighWaterMark:h,writableHighWaterMark:u.writableHighWaterMark,readableObjectMode:m,writableObjectMode:u.writableObjectMode,encoding:p});return uP({subprocessStdout:c,onStdoutDataDone:b,readable:_,subprocess:t,subprocessStdin:u}),hP(u,_,c),_},Ske=async({subprocessStdout:t,subprocessStdin:e,subprocess:r,waitReadableDestroy:n,waitWritableFinal:i,waitWritableDestroy:o},s)=>{await Promise.all([dP({subprocessStdout:t,subprocess:r,waitReadableDestroy:n},s),gP({subprocessStdin:e,subprocess:r,waitWritableFinal:i,waitWritableDestroy:o},s)])}});var _P,wke,WK=y(()=>{Da();ps();Sv();_P=(t,e,{from:r,binary:n=!1,preserveNewlines:i=!1}={})=>{let o=n||an.has(e),s=jl(t,r),a=vv({subprocessStdout:s,subprocess:t,binary:o,shouldEncode:!0,encoding:e,preserveNewlines:i});return wke(a,s,t)},wke=async function*(t,e,r){try{yield*t}finally{e.readable&&e.destroy(),await r}}});var KK,JK=y(()=>{$v();fP();yP();VK();WK();KK=(t,{encoding:e})=>{let r=FK();t.readable=UK.bind(void 0,{subprocess:t,concurrentStreams:r,encoding:e}),t.writable=HK.bind(void 0,{subprocess:t,concurrentStreams:r}),t.duplex=ZK.bind(void 0,{subprocess:t,concurrentStreams:r,encoding:e}),t.iterable=_P.bind(void 0,t,e),t[Symbol.asyncIterator]=_P.bind(void 0,t,e,{})}});var YK,xke,$ke,XK=y(()=>{YK=(t,e)=>{for(let[r,n]of $ke){let i=n.value.bind(e);Reflect.defineProperty(t,r,{...n,value:i})}},xke=(async()=>{})().constructor.prototype,$ke=["then","catch","finally"].map(t=>[t,Reflect.getOwnPropertyDescriptor(xke,t)])});import{setMaxListeners as kke}from"node:events";import{spawn as Eke}from"node:child_process";var QK,Ake,Tke,Oke,Rke,Ike,eJ=y(()=>{Jb();ER();eI();ps();tI();NI();up();Qb();B3();W3();dp();iK();vb();lK();SK();rP();MK();JK();Nl();XK();QK=(t,e,r,n)=>{let{file:i,commandArguments:o,command:s,escapedCommand:a,startTime:c,verboseInfo:l,options:u,fileDescriptors:d}=Ake(t,e,r),{subprocess:f,promise:p}=Oke({file:i,commandArguments:o,options:u,startTime:c,verboseInfo:l,command:s,escapedCommand:a,fileDescriptors:d});return f.pipe=bv.bind(void 0,{source:f,sourcePromise:p,boundOptions:{},createNested:n}),YK(f,p),Ni.set(f,{options:u,fileDescriptors:d}),f},Ake=(t,e,r)=>{let{command:n,escapedCommand:i,startTime:o,verboseInfo:s}=pb(t,e,r),{file:a,commandArguments:c,options:l}=zb(t,e,r),u=Tke(l),d=V3(u,s);return{file:a,commandArguments:c,command:n,escapedCommand:i,startTime:o,verboseInfo:s,options:u,fileDescriptors:d}},Tke=({timeout:t,signal:e,...r})=>{if(e!==void 0)throw new TypeError('The "signal" option has been renamed to "cancelSignal" instead.');return{...r,timeoutDuration:t}},Oke=({file:t,commandArguments:e,options:r,startTime:n,verboseInfo:i,command:o,escapedCommand:s,fileDescriptors:a})=>{let c;try{c=Eke(...Ub(t,e,r))}catch(m){return q3({error:m,command:o,escapedCommand:s,fileDescriptors:a,options:r,startTime:n,verboseInfo:i})}let l=new AbortController;kke(Number.POSITIVE_INFINITY,l.signal);let u=[...c.stdio];nK(c,a,l),cK(c,r,l);let d={},f=Di();c.kill=q9.bind(void 0,{kill:c.kill.bind(c),options:r,onInternalError:f,context:d,controller:l}),c.all=TK(c,r),KK(c,r),L3(c,r);let p=Rke({subprocess:c,options:r,startTime:n,verboseInfo:i,fileDescriptors:a,originalStreams:u,command:o,escapedCommand:s,context:d,onInternalError:f,controller:l});return{subprocess:c,promise:p}},Rke=async({subprocess:t,options:e,startTime:r,verboseInfo:n,fileDescriptors:i,originalStreams:o,command:s,escapedCommand:a,context:c,onInternalError:l,controller:u})=>{let[d,[f,p],m,h,g]=await jK({subprocess:t,options:e,context:c,verboseInfo:n,fileDescriptors:i,originalStreams:o,onInternalError:l,controller:u});u.abort(),l.resolve();let b=m.map((x,w)=>$o(x,e,w)),_=$o(h,e,"all"),S=Ike({errorInfo:d,exitCode:f,signal:p,stdio:b,all:_,ipcOutput:g,context:c,options:e,command:s,escapedCommand:a,startTime:r});return zl(S,n,e)},Ike=({errorInfo:t,exitCode:e,signal:r,stdio:n,all:i,ipcOutput:o,context:s,options:a,command:c,escapedCommand:l,startTime:u})=>"error"in t?lp({error:t.error,command:c,escapedCommand:l,timedOut:s.terminationReason==="timeout",isCanceled:s.terminationReason==="cancel"||s.terminationReason==="gracefulCancel",isGracefullyCanceled:s.terminationReason==="gracefulCancel",isMaxBuffer:t.error instanceof ji,isForcefullyTerminated:s.isForcefullyTerminated,exitCode:e,signal:r,stdio:n,all:i,ipcOutput:o,options:a,startTime:u,isSync:!1}):Xb({command:c,escapedCommand:l,stdio:n,all:i,ipcOutput:o,options:a,startTime:u})});var Av,Pke,Cke,tJ=y(()=>{_o();wo();Av=(t,e)=>{let r=Object.fromEntries(Object.entries(e).map(([n,i])=>[n,Pke(n,t[n],i)]));return{...t,...r}},Pke=(t,e,r)=>Cke.has(t)&&Ot(e)&&Ot(r)?{...e,...r}:r,Cke=new Set(["env",...SR])});var gs,Dke,Nke,rJ=y(()=>{_o();gR();nZ();P3();eJ();tJ();gs=(t,e,r,n)=>{let i=(s,a,c)=>gs(s,a,r,c),o=(...s)=>Dke({mapArguments:t,deepOptions:r,boundOptions:e,setBoundExeca:n,createNested:i},...s);return n!==void 0&&n(o,i,e),o},Dke=({mapArguments:t,deepOptions:e={},boundOptions:r={},setBoundExeca:n,createNested:i},o,...s)=>{if(Ot(o))return i(t,Av(r,o),n);let{file:a,commandArguments:c,options:l,isSync:u}=Nke({mapArguments:t,firstArgument:o,nextArguments:s,deepOptions:e,boundOptions:r});return u?I3(a,c,l):QK(a,c,l,i)},Nke=({mapArguments:t,firstArgument:e,nextArguments:r,deepOptions:n,boundOptions:i})=>{let o=tZ(e)?rZ(e,r):[e,...r],[s,a,c]=eb(...o),l=Av(Av(n,i),c),{file:u=s,commandArguments:d=a,options:f=l,isSync:p=!1}=t({file:s,commandArguments:a,options:l});return{file:u,commandArguments:d,options:f,isSync:p}}});var nJ,iJ,oJ,jke,Mke,sJ=y(()=>{nJ=({file:t,commandArguments:e})=>oJ(t,e),iJ=({file:t,commandArguments:e})=>({...oJ(t,e),isSync:!0}),oJ=(t,e)=>{if(e.length>0)throw new TypeError(`The command and its arguments must be passed as a single string: ${t} ${e}.`);let[r,...n]=jke(t);return{file:r,commandArguments:n}},jke=t=>{if(typeof t!="string")throw new TypeError(`The command must be a string: ${String(t)}.`);let e=t.trim();if(e==="")return[];let r=[];for(let n of e.split(Mke)){let i=r.at(-1);i&&i.endsWith("\\")?r[r.length-1]=`${i.slice(0,-1)} ${n}`:r.push(n)}return r},Mke=/ +/g});var aJ,cJ,Fke,lJ,Lke,uJ,dJ=y(()=>{aJ=(t,e,r)=>{t.sync=e(Fke,r),t.s=t.sync},cJ=({options:t})=>lJ(t),Fke=({options:t})=>({...lJ(t),isSync:!0}),lJ=t=>({options:{...Lke(t),...t}}),Lke=({input:t,inputFile:e,stdio:r})=>t===void 0&&e===void 0&&r===void 0?{stdin:"inherit"}:{},uJ={preferLocal:!0}});var Eut,We,Aut,Tut,Out,Rut,Iut,Put,Cut,Dut,Lr=y(()=>{rJ();sJ();JR();dJ();NI();Eut=gs(()=>({})),We=gs(()=>({isSync:!0})),Aut=gs(nJ),Tut=gs(iJ),Out=gs(EV),Rut=gs(cJ,{},uJ,aJ),{sendMessage:Iut,getOneMessage:Put,getEachMessage:Cut,getCancelSignal:Dut}=z3()});import{existsSync as Tv,statSync as zke}from"node:fs";import{dirname as bP,extname as Uke,isAbsolute as fJ,join as vP,relative as SP,resolve as Ov,sep as qke}from"node:path";function Rv(t){return t==="./gradlew"||t==="gradle"}function Bke(t){return(Tv(vP(t,"build.gradle.kts"))||Tv(vP(t,"build.gradle")))&&Tv(vP(t,"gradle.properties"))}function Hke(t,e){let n=SP(t,e).split(qke).filter(Boolean);return n.length===0?":":`:${n.join(":")}`}function ys(t,e){return t===":"?`:${e}`:`${t}:${e}`}function Gke(t,e){let r=Ov(t,e),n=r;Tv(r)?zke(r).isFile()&&(n=bP(r)):Uke(r)!==""&&(n=bP(r));let i=SP(t,n);if(i.startsWith("..")||fJ(i))return null;let o=n;for(;;){if(Bke(o))return o;if(Ov(o)===Ov(t))return null;let s=bP(o);if(s===o)return null;let a=SP(t,s);if(a.startsWith("..")||fJ(a))return null;o=s}}function Iv(t,e){let r=Ov(t),n=new Map,i=[];for(let o of e){let s=Gke(r,o);if(!s){i.push(o);continue}let a=Hke(r,s);n.has(a)||n.set(a,{path:a,dir:s})}if(i.length>0)throw new Error(`cannot map module(s) to a Gradle project (no build.gradle[.kts] + gradle.properties ancestor under ${r}): ${i.join(", ")}`);return[...n.values()].sort((o,s)=>o.paths.path?1:0)}var Pv=y(()=>{"use strict"});import{existsSync as xP,readFileSync as Zke}from"node:fs";import{join as Hl}from"node:path";function Gl(t="."){let e=Hl(t,".cladding","config.yaml");if(!xP(e))return wP;try{let n=(0,pJ.parse)(Zke(e,"utf8"))?.gate;if(!n)return wP;let i=n.scope==="repo"?"repo":"feature",o=n.coverage==="kover"||n.coverage==="jacoco"?n.coverage:void 0,s=typeof n.test_report=="string"?n.test_report:void 0,a={};if(n.commands&&typeof n.commands=="object")for(let l of Vke){let u=n.commands[l];Array.isArray(u)&&u.every(d=>typeof d=="string")&&(a[l]=u)}let c={scope:i};return Object.keys(a).length>0&&(c.commands=a),o&&(c.coverage=o),s&&(c.testReport=s),c}catch{return wP}}function mJ(t="."){let e=Gl(t).testReport,r=e?[e,...$P]:$P;return[...new Set(r.map(n=>Hl(t,n)))]}function hJ(t="."){let e=Gl(t).testReport;if(e){let r=Hl(t,e);return xP(r)?r:null}return $P.map(r=>Hl(t,r)).find(r=>xP(r))??null}function gJ(t,e){let r=[],n=!1;for(let i of t){let o=Wke.exec(i);if(o){n=!0;for(let s of e)r.push(ys(s.path,o[1]))}else r.push(i)}return n&&e.length===0||r.length===0?null:{cmd:r[0],args:r.slice(1)}}var pJ,Vke,wP,$P,Wke,_p=y(()=>{"use strict";pJ=St(er(),1);Pv();Vke=["type","lint","test","coverage"],wP={scope:"feature"},$P=["test-report.junit.xml",Hl("coverage","junit.xml"),Hl(".cladding","test-report.junit.xml")];Wke=/^\{modules:([A-Za-z0-9_.:-]+)\}$/});import{existsSync as EP,readFileSync as yJ,readdirSync as Kke,statSync as Jke}from"node:fs";import{join as Cv}from"node:path";function OP(t){for(let e of["build.gradle.kts","build.gradle","gradle.properties"]){let r=Cv(t,e);if(EP(r))try{if(_J.test(yJ(r,"utf8")))return!0}catch{}}return!1}function bJ(t){try{return EP(t)&&_J.test(yJ(t,"utf8"))}catch{return!1}}function vJ(t,e=0){if(e>4||!EP(t))return!1;let r;try{r=Kke(t)}catch{return!1}for(let n of r){let i=Cv(t,n),o=!1;try{o=Jke(i).isDirectory()}catch{continue}if(o){if(n==="build"||n===".gradle"||n==="node_modules")continue;if(vJ(i,e+1))return!0}else if(/\.(kts|gradle|toml)$/.test(n)&&bJ(i))return!0}return!1}function Qke(t){if(OP(t))return!0;for(let e of Yke)if(bJ(Cv(t,e)))return!0;for(let e of Xke)if(vJ(Cv(t,e)))return!0;return!1}function SJ(t="."){let e=Gl(t).coverage;return e||(Qke(t)?"kover":"jacoco")}function wJ(t="."){return AP[SJ(t)]}function xJ(t="."){return kP[SJ(t)]}var AP,kP,TP,_J,Yke,Xke,Dv=y(()=>{"use strict";_p();AP={kover:"koverXmlReport",jacoco:"jacocoTestReport"},kP={kover:"build/reports/kover/report.xml",jacoco:"build/reports/jacoco/test/jacocoTestReport.xml"},TP=[kP.kover,kP.jacoco],_J=/kover/i;Yke=["build.gradle.kts","build.gradle","settings.gradle.kts","settings.gradle","gradle/libs.versions.toml"],Xke=["buildSrc","build-logic"]});import{existsSync as vp,readFileSync as IP,readdirSync as kJ,statSync as eEe}from"node:fs";import{dirname as tEe,join as xr,resolve as rEe}from"node:path";import Zl from"node:process";function PP(t){return vp(xr(t,"gradlew"))?"./gradlew":"gradle"}function nEe(t){let e=PP(t);return{type:{cmd:e,args:["compileKotlin","compileTestKotlin"]},lint:{cmd:e,args:["ktlintCheck"]},test:{cmd:e,args:["test"]},coverage:{cmd:e,args:[wJ(t)]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}}function iEe(t){let e=!1;try{e=/(^|\n)\s*flutter\s*:|sdk:\s*flutter/.test(IP(xr(t,"pubspec.yaml"),"utf8"))}catch{}let r={cmd:"dart",args:["format","--output=none","--set-exit-if-changed","."]},n={cmd:"gitleaks",args:["detect","--no-banner"]};return e?{type:{cmd:"flutter",args:["analyze"]},lint:r,test:{cmd:"flutter",args:["test"]},coverage:{cmd:"flutter",args:["test","--coverage"]},secret:n}:{type:{cmd:"dart",args:["analyze"]},lint:r,test:{cmd:"dart",args:["test"]},coverage:{cmd:"dart",args:["test","--coverage=coverage"]},secret:n}}function sEe(t,e){let r=[t],n=0,i=4e3;for(;r.length>0&&na.name.endsWith(c)))return!0}return!1}function lEe(t,e){for(let r of e)if(vp(xr(t,r)))return r}function uEe(t,e){try{return kJ(t).find(n=>n.endsWith(e))}catch{return}}function mEe(t){let e=[],r=Zl.platform==="win32";r||e.push(xr("/etc","madge","config"),xr("/etc","madgerc"));let n=r?Zl.env.USERPROFILE:Zl.env.HOME;n&&e.push(xr(n,".config","madge","config"),xr(n,".config","madge"),xr(n,".madge","config"),xr(n,".madgerc"));for(let o=rEe(t);;){e.push(xr(o,".madgerc"));let s=tEe(o);if(s===o)break;o=s}let i=Zl.env.MADGE_config??Zl.env.madge_config;return i&&e.push(i),e}function hEe(){for(let[t,e]of Object.entries(Zl.env))if(/^madge_excluderegexp/i.test(t)&&typeof e=="string"&&e.trim().length>0)return!0;return!1}function EJ(t){return Array.isArray(t)?t.length>0:typeof t=="string"&&t.trim().length>0}function yEe(t){try{return eEe(t).isFile()}catch{return!1}}function _Ee(t){let e;try{e=IP(t,"utf8")}catch{return!0}try{return EJ(JSON.parse(e).excludeRegExp)}catch{return gEe.test(e)}}function bEe(t,e){let r=e.madge;return r&&typeof r=="object"&&EJ(r.excludeRegExp)||hEe()?!0:mEe(t).some(n=>yEe(n)&&_Ee(n))}function vEe(t){try{return JSON.parse(IP(xr(t,"package.json"),"utf8").replace(/^\uFEFF/,""))}catch{return{}}}function bp(t,e){let r=t.scripts?.[e];return typeof r=="string"&&r.trim().length>0?r.trim():void 0}function $J(t,e){return[t.dependencies,t.devDependencies,t.optionalDependencies,t.peerDependencies].some(r=>r?.[e]!==void 0)}function SEe(t,e,r){if(bEe(t,r))return e;let n=[...e.args];return n.splice(n.length-1,0,"--exclude",pEe),{...e,args:n}}function wEe(t,e,r){if(bp(r,"lint"))return{cmd:"npm",args:["run","--silent","lint"]};for(let n of dEe)if(n.configs.some(i=>vp(xr(t,i))))return n.gate;if(fEe.some(n=>vp(xr(t,n)))||r.eslintConfig!==void 0)return e}function $Ee(t,e){return xEe.some(r=>vp(xr(t,r)))?!0:e.jest!==void 0}function kEe(t){if(/^(?:(?:npx|npm exec)\s+(?:--offline\s+)?(?:--no-install\s+)?(?:--\s+)?)?vitest(?:\s+run)?$/i.test(t))return"vitest";if(/^(?:(?:npx|npm exec)\s+(?:--offline\s+)?(?:--no-install\s+)?(?:--\s+)?)?jest$/i.test(t))return"jest"}function RP(t,e){let r={...t};return e==="lint"?delete r.lint:delete r.coverage,r}function EEe(t,e){let r=vEe(t),n=e.lint?wEe(t,e.lint,r):void 0,i=e.arch?{...e,arch:SEe(t,e.arch,r)}:e,o=n?{...i,lint:n}:RP(i,"lint"),s=bp(r,"test"),a=s?kEe(s):void 0;return s&&!a?(o=RP(o,"coverage"),{...o,test:{cmd:"npm",args:["test"]},...bp(r,"coverage")?{coverage:{cmd:"npm",args:["run","--silent","coverage"]}}:{}}):a==="jest"||!s&&$Ee(t,r)?{...o,test:{cmd:"npx",args:[...Fi,"jest"]},coverage:{cmd:"npx",args:[...Fi,"jest","--coverage"]}}:(a==="vitest"&&!bp(r,"coverage")&&!$J(r,"@vitest/coverage-v8")&&!$J(r,"@vitest/coverage-istanbul")?o=RP(o,"coverage"):a==="vitest"&&bp(r,"coverage")&&(o={...o,coverage:{cmd:"npm",args:["run","--silent","coverage"]}}),o)}function dt(t="."){for(let e of aEe){let r;for(let o of e.manifests)if(o.startsWith(".")?r=uEe(t,o):r=lEe(t,[o]),r)break;if(!r||e.requiresSource&&!sEe(t,e.requiresSource))continue;let n=typeof e.gates=="function"?e.gates(t):e.gates,i=e.language==="typescript"?EEe(t,n):n;return{language:e.language,manifest:r,gates:i}}return cEe}var Fi,oEe,aEe,cEe,dEe,fEe,pEe,gEe,xEe,cn=y(()=>{"use strict";Dv();Fi=["--offline","--no-install"];oEe=new Set(["node_modules",".git",".gradle",".idea","build","target","dist","out",".cladding"]);aEe=[{language:"typescript",manifests:["package.json"],gates:{type:{cmd:"npx",args:[...Fi,"tsc","--noEmit"]},lint:{cmd:"npx",args:[...Fi,"eslint","."]},test:{cmd:"npx",args:[...Fi,"vitest","run"]},coverage:{cmd:"npx",args:[...Fi,"vitest","run","--coverage"]},secret:{cmd:"npx",args:[...Fi,"secretlint","**/*"]},arch:{cmd:"npx",args:[...Fi,"madge","--circular","--extensions","ts,tsx,js,jsx","."]},smoke:{cmd:"npm",args:["run","--silent","smoke"]},perf:{cmd:"npm",args:["run","--silent","perf"]},visual:{cmd:"npm",args:["run","--silent","visual"]}}},{language:"python",manifests:["pyproject.toml","setup.py","requirements.txt"],gates:{type:{cmd:"mypy",args:["."]},lint:{cmd:"ruff",args:["check","."]},test:{cmd:"pytest",args:[]},coverage:{cmd:"coverage",args:["run","-m","pytest"]},secret:{cmd:"detect-secrets",args:["scan"]},arch:{cmd:"lint-imports",args:[]}}},{language:"rust",manifests:["Cargo.toml"],gates:{type:{cmd:"cargo",args:["check"]},lint:{cmd:"cargo",args:["clippy","--","-D","warnings"]},test:{cmd:"cargo",args:["test"]},coverage:{cmd:"cargo",args:["llvm-cov"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"go",manifests:["go.mod"],gates:{type:{cmd:"go",args:["vet","./..."]},lint:{cmd:"golangci-lint",args:["run"]},test:{cmd:"go",args:["test","./..."]},coverage:{cmd:"go",args:["test","-cover","./..."]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"kotlin",manifests:["build.gradle.kts","build.gradle","pom.xml"],requiresSource:[".kt",".kts"],gates:nEe},{language:"java",manifests:["pom.xml","build.gradle","build.gradle.kts"],gates:{type:{cmd:"mvn",args:["compile","-q"]},lint:{cmd:"mvn",args:["checkstyle:check","-q"]},test:{cmd:"mvn",args:["test","-q"]},coverage:{cmd:"mvn",args:["jacoco:report","-q"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"php",manifests:["composer.json"],gates:{type:{cmd:"phpstan",args:["analyse"]},lint:{cmd:"phpcs",args:[]},test:{cmd:"phpunit",args:[]},coverage:{cmd:"phpunit",args:["--coverage-text"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"ruby",manifests:["Gemfile"],gates:{type:{cmd:"srb",args:["tc"]},lint:{cmd:"rubocop",args:[]},test:{cmd:"bundle",args:["exec","rspec"]},coverage:{cmd:"bundle",args:["exec","rspec","--format","documentation"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"elixir",manifests:["mix.exs"],gates:{type:{cmd:"mix",args:["dialyzer"]},lint:{cmd:"mix",args:["credo"]},test:{cmd:"mix",args:["test"]},coverage:{cmd:"mix",args:["coveralls"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"dotnet",manifests:[".csproj",".sln",".fsproj"],gates:{type:{cmd:"dotnet",args:["build","--nologo","-v","q"]},lint:{cmd:"dotnet",args:["format","--verify-no-changes"]},test:{cmd:"dotnet",args:["test","--nologo"]},coverage:{cmd:"dotnet",args:["test",'--collect:"XPlat Code Coverage"']},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"swift",manifests:["Package.swift"],gates:{type:{cmd:"swift",args:["build"]},lint:{cmd:"swiftlint",args:["lint"]},test:{cmd:"swift",args:["test"]},coverage:{cmd:"swift",args:["test","--enable-code-coverage"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"dart",manifests:["pubspec.yaml"],gates:iEe}],cEe={language:"unknown",manifest:"",gates:{}};dEe=[{configs:["biome.json","biome.jsonc"],gate:{cmd:"npx",args:[...Fi,"biome","lint","."]}},{configs:[".oxlintrc.json",".oxlintrc.jsonc","oxlint.config.ts"],gate:{cmd:"npx",args:[...Fi,"oxlint"]}}],fEe=["eslint.config.js","eslint.config.mjs","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts",".eslintrc",".eslintrc.js",".eslintrc.cjs",".eslintrc.json",".eslintrc.yaml",".eslintrc.yml"],pEe="(^|/)(dist|coverage|\\.next|\\.nuxt|\\.output|\\.svelte-kit|\\.vite)/|^(build|out|target)/";gEe=/^[ \t]*excludeRegExp[ \t]*(?:\[[^\]]*\])?[ \t]*=[ \t]*(\S.*?)[ \t]*$/m;xEe=["jest.config.js","jest.config.ts","jest.config.mjs","jest.config.cjs","jest.config.json"]});import{existsSync as AEe,readFileSync as TEe}from"node:fs";import{join as OEe}from"node:path";function qa(t){return t.code==="ENOENT"}function Nv(t,e,r,n){let i=t.exitCode??1;if(i===0)return[];let o=(t.stderr??"").toString().trim(),s=(t.stdout??"").toString().trim(),a=[s,o].filter(c=>c.length>0).join(` -`).slice(0,2e3)||`exit ${i}`;return AJ.test(o)||AJ.test(s)?[{detector:e,severity:"info",message:n(a)}]:[{detector:e,severity:"error",message:r(a)}]}function Nt(t,e,r,n=[]){if(qa(r))return{stage:t,pass:!1,exitCode:2,stderr:`'${e}' not installed`};let i=`${String(r.stderr??"")} -${String(r.stdout??"")}`,o=/ENOTCACHED|ENOTFOUND|EAI_AGAIN|canceled due to missing packages|could not determine executable/i.test(i),a=n.find(l=>l!=="--"&&!l.startsWith("-"))?.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=r.exitCode===127&&a!==void 0&&new RegExp(`(?:^|[\\s:])${a}: (?:command )?not found\\b`,"i").test(i);return e==="npx"&&(o||c)?{stage:t,pass:!1,exitCode:2,stderr:"setup gap: 'npx' could not resolve the configured tool without installing it; the inferred tool is not installed or unavailable offline"}:null}function Yt(t,e){if((e.exitCode??1)===0)return{stage:t,pass:!0,exitCode:0};let n=[String(e.stdout??"").trim(),String(e.stderr??"").trim()].filter(i=>i.length>0).join(` -`);return n?{stage:t,pass:!1,exitCode:1,stderr:n}:{stage:t,pass:!1,exitCode:1}}function Vl(t,e){let r=OEe(t,"package.json");if(!AEe(r))return!1;try{return!!JSON.parse(TEe(r,"utf8")).scripts?.[e]}catch{return!1}}var AJ,Cn=y(()=>{"use strict";AJ=/config (is |file )?not found|no such file|ENOENT|ENOTCACHED|ENOTFOUND|EAI_AGAIN|cannot find (a |the )?(config|module|package|preset)|require[sd]?\b.{0,40}\bconfig|canceled due to missing packages|could not determine executable/i});function REe(t){let{cwd:e="."}=t,r=dt(e),n=r.gates.arch;if(!n)return[{detector:jv,severity:"info",message:`no architecture validator registered for language '${r.language}' (compiler may already enforce acyclic imports)`}];let i=We(n.cmd,[...n.args],{cwd:e,reject:!1});return qa(i)?[{detector:jv,severity:"info",message:`architecture validator '${n.cmd}' not installed`}]:Nv(i,jv,o=>`${n.cmd} reported architecture violations: ${o}`,o=>`${n.cmd} could not validate (config/setup gap, not a violation): ${o}`)}var jv,Ba,Mv=y(()=>{"use strict";Lr();cn();Cn();jv="ARCHITECTURE_VIOLATION";Ba={name:jv,subprocess:!0,run:REe}});function IEe(t){let{cwd:e="."}=t,r=dt(e),n=r.gates.secret;if(!n)return[{detector:Fv,severity:"info",message:`no secret scanner registered for language '${r.language}'`}];let i=We(n.cmd,[...n.args],{cwd:e,reject:!1});return qa(i)?[{detector:Fv,severity:"info",message:`secret scanner '${n.cmd}' not installed`}]:Nv(i,Fv,o=>`${n.cmd} reported secrets: ${o}`,o=>`${n.cmd} could not scan (config/setup gap, not a secret): ${o}`)}var Fv,Ha,Lv=y(()=>{"use strict";Lr();cn();Cn();Fv="HARDCODED_SECRET";Ha={name:Fv,subprocess:!0,run:IEe}});import{existsSync as CP,readdirSync as TJ}from"node:fs";import{join as zv}from"node:path";function CEe(t,e){let r=zv(t,e.path);if(!CP(r))return!0;if(e.isDirectory)try{return TJ(r).filter(i=>i.endsWith(".yaml")||i.endsWith(".yml")).length===0}catch{return!0}return!1}function DEe(t){let{cwd:e="."}=t,r=[];for(let i of PEe)CEe(e,i)&&r.push({detector:Sp,severity:i.severity,path:i.path,message:`${i.path} is absent \u2014 cladding scaffold incomplete (${i.purpose}). Run \`clad init --intent ""\` to populate it.`});let n=zv(e,"spec.yaml");if(CP(n)){let i=MEe(n),o=i?null:NEe(e);if(i)r.push({detector:Sp,severity:"error",path:"spec.yaml",message:`spec.yaml is present but unreadable (${i}) \u2014 cladding is governing nothing. Fix the SSoT root, then \`clad sync\` to validate.`});else if(o)r.push({detector:Sp,severity:"error",path:o.path,message:`spec shard '${o.path}' is present but unparseable (${o.reason}) \u2014 loadSpec throws on it, so every spec-gated detector silently passes. Fix it, then \`clad sync\`.`});else{let s=jEe(e);s&&r.push({detector:Sp,severity:"error",path:"spec.yaml",message:`spec.yaml is present and parses, but the assembled spec does not load (${s}) \u2014 every spec-gated detector then degrades to non-blocking info, so the gate would pass GREEN on an unloadable SSoT. Fix it, then \`clad sync\` to validate.`})}}return r}function NEe(t){for(let e of["spec/features","spec/scenarios"]){let r=zv(t,e);if(!CP(r))continue;let n;try{n=TJ(r).filter(i=>i.endsWith(".yaml")||i.endsWith(".yml"))}catch{continue}for(let i of[...n].sort())try{Ri(zv(r,i))}catch(o){return{path:`${e}/${i}`,reason:o.message}}}return null}function jEe(t){try{return q(t),null}catch(e){return e.message}}function MEe(t){let e;try{e=Ri(t)}catch(r){return`unparseable: ${r.message}`}return e===null||typeof e!="object"||Array.isArray(e)?"empty or not a YAML mapping":null}var Sp,PEe,OJ,RJ=y(()=>{"use strict";Ue();H_();Sp="ABSENCE_OF_GOVERNANCE",PEe=[{path:"spec.yaml",severity:"error",purpose:"SSoT root \u2014 every spec-gated detector needs it"},{path:"spec/architecture.yaml",severity:"warn",purpose:"architecture invariants (layers + forbidden_imports)"},{path:"spec/capabilities.yaml",severity:"warn",purpose:"capability \u2194 feature traceability"},{path:"docs/project-context.md",severity:"warn",purpose:"intent narrative + decision history"},{path:"docs/conventions.md",severity:"info",purpose:"project style guide (recommended)"},{path:"spec/scenarios",severity:"info",purpose:"user-journey scenarios (recommended)",isDirectory:!0}];OJ={name:Sp,run:DEe}});function Uv(t){let e=t.trim().match(/^(\S+)/);return e?e[1].toLowerCase():""}function DP(t,e){let r=e?.trim()??"";if(!t)return r.length>0?"condition is present but ears pattern is not declared":null;if(t==="ubiquitous")return r.length>0?`ears='ubiquitous' but condition is present ('${r.slice(0,40)}\u2026')`:null;if(t==="complex"){if(r.length===0)return"ears='complex' requires a 'while' precondition and a 'when' trigger \u2014 empty";let i=Uv(r)==="while",o=LEe.test(r);return i?o?null:"ears='complex' requires a 'when' trigger clause after the 'while' precondition \u2014 none found":`ears='complex' requires the condition to start with 'while' (precondition) \u2014 got '${Uv(r)}'`}let n=FEe[t];return r.length===0?`ears='${t}' requires condition starting with '${n}' \u2014 empty`:Uv(r)!==n?`ears='${t}' requires condition to start with '${n}' \u2014 got '${Uv(r)}'`:null}function zEe(t,e){let r=DP(e.ears,e.condition);return r?[{featureId:t.id,acId:e.id,pattern:e.ears??"unspecified",message:r}]:[]}function IJ(t){let e=[];for(let r of t)for(let n of r.acceptance_criteria??[])e.push(...zEe(r,n));return e}var FEe,LEe,NP=y(()=>{"use strict";FEe={event:"when",state:"while",optional:"where",unwanted:"if"},LEe=/\bwhen\b/i});function ge(t,e,r){let n;try{n=q(t)}catch(i){return[{detector:e,severity:"info",message:`spec.yaml not loaded: ${i.message}`}]}return r(n)}var wt=y(()=>{"use strict";Ue()});function UEe(t){let{cwd:e="."}=t;return ge(e,qv,qEe)}function qEe(t){let e=[];for(let r of t.features)for(let n of r.acceptance_criteria??[]){let i=!!n.text?.trim(),o=!!(n.condition?.trim()||n.action?.trim()||n.response?.trim());!i&&!o&&e.push({detector:qv,severity:"error",message:`${r.id}.${n.id} has neither rendered text nor any EARS field (condition/action/response) \u2014 structurally empty AC`})}for(let r of IJ(t.features))e.push({detector:qv,severity:"error",message:`${r.featureId}.${r.acId} EARS: ${r.message}`});return e}var qv,PJ,CJ=y(()=>{"use strict";NP();wt();qv="AC_DRIFT";PJ={name:qv,run:UEe}});function Li(t=".",e){let n=(e??"").trim().toLowerCase()||dt(t).language;return NJ[n]??DJ}var BEe,HEe,GEe,DJ,ZEe,VEe,NJ,WEe,jJ,Ga=y(()=>{"use strict";cn();BEe=/(?:import\s+(?:[\s\S]*?\sfrom\s+)?|import\s*\()['"]([^'"]+)['"]\)?/g,HEe=/^[ \t]*import\s+([\w.]+)/gm,GEe=/^[ \t]*(?:from|import)\s+([\w.]+)/gm,DJ={ext:"ts",extensions:[".ts",".tsx"],sourceRoots:["src"],mainRoot:"src",testGlobs:["tests/**/*.test.ts"],coverageSummary:"coverage/coverage-summary.json",coverageFormat:"istanbul-json",importMatcher:BEe,importStyle:"relative"},ZEe={ext:"kt",extensions:[".kt",".kts"],sourceRoots:["src/main/kotlin","src/test/kotlin"],mainRoot:"src/main/kotlin",testGlobs:["src/test/kotlin/**/*Test.kt","src/test/kotlin/**/*Tests.kt"],coverageSummary:"build/reports/jacoco/test/jacocoTestReport.xml",coverageFormat:"jacoco-xml",importMatcher:HEe,importStyle:"dotted"},VEe={ext:"py",extensions:[".py"],sourceRoots:["."],mainRoot:"src",testGlobs:["tests/test_*.py","tests/**/test_*.py","tests/**/*_test.py"],coverageSummary:"coverage.xml",coverageFormat:"cobertura-xml",importMatcher:GEe,importStyle:"dotted"},NJ={typescript:DJ,kotlin:ZEe,python:VEe},WEe=[".js",".jsx",".mts",".cts",".rs",".go",".java",".rb",".php",".cs",".fs",".ex",".exs"],jJ=new Set([...Object.values(NJ).flatMap(t=>t?.extensions??[]),...WEe].map(t=>t.toLowerCase()))});import{existsSync as KEe,readFileSync as JEe,readdirSync as YEe,statSync as XEe}from"node:fs";import{join as FJ,relative as MJ}from"node:path";function QEe(t,e){if(!KEe(t))return[];let r=[],n=[t];for(;n.length>0;){let i=n.pop(),o;try{o=YEe(i)}catch{continue}for(let s of o){if(s==="node_modules"||s===".cladding"||s.startsWith("."))continue;let a=FJ(i,s),c;try{c=XEe(a)}catch{continue}c.isDirectory()?n.push(a):e.some(l=>s.endsWith(l))&&r.push(a)}}return r}function eAe(t){let e=t.trim();return e.startsWith("//")||e.startsWith("/*")||e.startsWith("*")}function rAe(t){return tAe.test(t)}function nAe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=r.project.ai_hints?.forbidden_patterns;if(!n||n.length===0)return[];let i=Li(e,r.project?.language),o=i.sourceRoots.flatMap(a=>QEe(FJ(e,a),i.extensions));if(o.length===0)return[];let s=[];for(let a of o){let c;try{c=JEe(a,"utf8")}catch{continue}let l=c.split(` -`);for(let u=0;u{"use strict";Ue();Ga();LJ="AI_HINTS_FORBIDDEN_PATTERN";tAe=/\/\/\s*cladding-disable[:\s]+AI_HINTS_FORBIDDEN_PATTERN\b/;zJ={name:LJ,run:nAe}});function iAe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=[];for(let i of r.features){let o=(i.acceptance_criteria??[]).map(a=>a.id),s=new Map;for(let a of o)s.set(a,(s.get(a)??0)+1);for(let[a,c]of s)c>1&&n.push({detector:qJ,severity:"error",message:`${i.id}.${a} appears ${c} times \u2014 AC ids must be unique within a feature`})}return n}var qJ,BJ,HJ=y(()=>{"use strict";Ue();qJ="AC_DUPLICATE_WITHIN_FEATURE";BJ={name:qJ,run:iAe}});import{createRequire as oAe}from"module";import{basename as sAe,dirname as MP,normalize as aAe,relative as cAe,resolve as lAe,sep as VJ}from"path";import*as uAe from"fs";function dAe(t){let e=aAe(t);return e.length>1&&e[e.length-1]===VJ&&(e=e.substring(0,e.length-1)),e}function WJ(t,e){return t.replace(fAe,e)}function mAe(t){return t==="/"||pAe.test(t)}function jP(t,e){let{resolvePaths:r,normalizePath:n,pathSeparator:i}=e,o=process.platform==="win32"&&t.includes("/")||t.startsWith(".");if(r&&(t=lAe(t)),(n||o)&&(t=dAe(t)),t===".")return"";let s=t[t.length-1]!==i;return WJ(s?t+i:t,i)}function KJ(t,e){return e+t}function hAe(t,e){return function(r,n){return n.startsWith(t)?n.slice(t.length)+r:WJ(cAe(t,n),e.pathSeparator)+e.pathSeparator+r}}function gAe(t){return t}function yAe(t,e,r){return e+t+r}function _Ae(t,e){let{relativePaths:r,includeBasePath:n}=e;return r&&t?hAe(t,e):n?KJ:gAe}function bAe(t){return function(e,r){r.push(e.substring(t.length)||".")}}function vAe(t){return function(e,r,n){let i=e.substring(t.length)||".";n.every(o=>o(i,!0))&&r.push(i)}}function $Ae(t,e){let{includeDirs:r,filters:n,relativePaths:i}=e;return r?i?n&&n.length?vAe(t):bAe(t):n&&n.length?wAe:SAe:xAe}function RAe(t){let{excludeFiles:e,filters:r,onlyCounts:n}=t;return e?OAe:r&&r.length?n?kAe:EAe:n?AAe:TAe}function CAe(t){return t.group?PAe:IAe}function jAe(t){return t.group?DAe:NAe}function LAe(t,e){return!t.resolveSymlinks||t.excludeSymlinks?null:e?FAe:MAe}function JJ(t,e,r){if(r.options.useRealPaths)return zAe(e,r);let n=MP(t),i=1;for(;n!==r.root&&i<2;){let o=r.symlinks.get(n);!!o&&(o===e||o.startsWith(e)||e.startsWith(o))?i++:n=MP(n)}return r.symlinks.set(t,e),i>1}function zAe(t,e){return e.visited.includes(t+e.options.pathSeparator)}function Bv(t,e,r,n){e(t&&!n?t:null,r)}function KAe(t,e){let{onlyCounts:r,group:n,maxFiles:i}=t;return r?e?UAe:GAe:n?e?qAe:WAe:i?e?HAe:VAe:e?BAe:ZAe}function XAe(t){return t?YAe:JAe}function rTe(t,e){return new Promise((r,n)=>{QJ(t,e,(i,o)=>{if(i)return n(i);r(o)})})}function QJ(t,e,r){new XJ(t,e,r).start()}function nTe(t,e){return new XJ(t,e).start()}var GJ,fAe,pAe,SAe,wAe,xAe,kAe,EAe,AAe,TAe,OAe,IAe,PAe,DAe,NAe,MAe,FAe,UAe,qAe,BAe,HAe,GAe,ZAe,VAe,WAe,YJ,JAe,YAe,QAe,eTe,tTe,XJ,ZJ,e8,t8,r8=y(()=>{GJ=oAe(import.meta.url);fAe=/[\\/]/g;pAe=/^[a-z]:[\\/]$/i;SAe=(t,e)=>{e.push(t||".")},wAe=(t,e,r)=>{let n=t||".";r.every(i=>i(n,!0))&&e.push(n)},xAe=()=>{};kAe=(t,e,r,n)=>{n.every(i=>i(t,!1))&&r.files++},EAe=(t,e,r,n)=>{n.every(i=>i(t,!1))&&e.push(t)},AAe=(t,e,r,n)=>{r.files++},TAe=(t,e)=>{e.push(t)},OAe=()=>{};IAe=t=>t,PAe=()=>[""].slice(0,0);DAe=(t,e,r)=>{t.push({directory:e,files:r,dir:e})},NAe=()=>{};MAe=function(t,e,r){let{queue:n,fs:i,options:{suppressErrors:o}}=e;n.enqueue(),i.realpath(t,(s,a)=>{if(s)return n.dequeue(o?null:s,e);i.stat(a,(c,l)=>{if(c)return n.dequeue(o?null:c,e);if(l.isDirectory()&&JJ(t,a,e))return n.dequeue(null,e);r(l,a),n.dequeue(null,e)})})},FAe=function(t,e,r){let{queue:n,fs:i,options:{suppressErrors:o}}=e;n.enqueue();try{let s=i.realpathSync(t),a=i.statSync(s);if(a.isDirectory()&&JJ(t,s,e))return;r(a,s)}catch(s){if(!o)throw s}};UAe=t=>t.counts,qAe=t=>t.groups,BAe=t=>t.paths,HAe=t=>t.paths.slice(0,t.options.maxFiles),GAe=(t,e,r)=>(Bv(e,r,t.counts,t.options.suppressErrors),null),ZAe=(t,e,r)=>(Bv(e,r,t.paths,t.options.suppressErrors),null),VAe=(t,e,r)=>(Bv(e,r,t.paths.slice(0,t.options.maxFiles),t.options.suppressErrors),null),WAe=(t,e,r)=>(Bv(e,r,t.groups,t.options.suppressErrors),null);YJ={withFileTypes:!0},JAe=(t,e,r,n,i)=>{if(t.queue.enqueue(),n<0)return t.queue.dequeue(null,t);let{fs:o}=t;t.visited.push(e),t.counts.directories++,o.readdir(e||".",YJ,(s,a=[])=>{i(a,r,n),t.queue.dequeue(t.options.suppressErrors?null:s,t)})},YAe=(t,e,r,n,i)=>{let{fs:o}=t;if(n<0)return;t.visited.push(e),t.counts.directories++;let s=[];try{s=o.readdirSync(e||".",YJ)}catch(a){if(!t.options.suppressErrors)throw a}i(s,r,n)};QAe=class{count=0;constructor(t){this.onQueueEmpty=t}enqueue(){return this.count++,this.count}dequeue(t,e){this.onQueueEmpty&&(--this.count<=0||t)&&(this.onQueueEmpty(t,e),t&&(e.controller.abort(),this.onQueueEmpty=void 0))}},eTe=class{_files=0;_directories=0;set files(t){this._files=t}get files(){return this._files}set directories(t){this._directories=t}get directories(){return this._directories}get dirs(){return this._directories}},tTe=class{aborted=!1;abort(){this.aborted=!0}},XJ=class{root;isSynchronous;state;joinPath;pushDirectory;pushFile;getArray;groupFiles;resolveSymlink;walkDirectory;callbackInvoker;constructor(t,e,r){this.isSynchronous=!r,this.callbackInvoker=KAe(e,this.isSynchronous),this.root=jP(t,e),this.state={root:mAe(this.root)?this.root:this.root.slice(0,-1),paths:[""].slice(0,0),groups:[],counts:new eTe,options:e,queue:new QAe((n,i)=>this.callbackInvoker(i,n,r)),symlinks:new Map,visited:[""].slice(0,0),controller:new tTe,fs:e.fs||uAe},this.joinPath=_Ae(this.root,e),this.pushDirectory=$Ae(this.root,e),this.pushFile=RAe(e),this.getArray=CAe(e),this.groupFiles=jAe(e),this.resolveSymlink=LAe(e,this.isSynchronous),this.walkDirectory=XAe(this.isSynchronous)}start(){return this.pushDirectory(this.root,this.state.paths,this.state.options.filters),this.walkDirectory(this.state,this.root,this.root,this.state.options.maxDepth,this.walk),this.isSynchronous?this.callbackInvoker(this.state,null):null}walk=(t,e,r)=>{let{paths:n,options:{filters:i,resolveSymlinks:o,excludeSymlinks:s,exclude:a,maxFiles:c,signal:l,useRealPaths:u,pathSeparator:d},controller:f}=this.state;if(f.aborted||l&&l.aborted||c&&n.length>c)return;let p=this.getArray(this.state.paths);for(let m=0;m{if(b.isDirectory()){if(_=jP(_,this.state.options),a&&a(h.name,u?_:g+d))return;this.walkDirectory(this.state,_,u?_:g+d,r-1,this.walk)}else{_=u?_:g;let S=sAe(_),x=jP(MP(_),this.state.options);_=this.joinPath(S,x),this.pushFile(_,p,this.state.counts,i)}})}}this.groupFiles(this.state.groups,e,p)}};ZJ=class{constructor(t,e){this.root=t,this.options=e}withPromise(){return rTe(this.root,this.options)}withCallback(t){QJ(this.root,this.options,t)}sync(){return nTe(this.root,this.options)}},e8=null;try{GJ.resolve("picomatch"),e8=GJ("picomatch")}catch{}t8=class{globCache={};options={maxDepth:1/0,suppressErrors:!0,pathSeparator:VJ,filters:[]};globFunction;constructor(t){this.options={...this.options,...t},this.globFunction=this.options.globFunction}group(){return this.options.group=!0,this}withPathSeparator(t){return this.options.pathSeparator=t,this}withBasePath(){return this.options.includeBasePath=!0,this}withRelativePaths(){return this.options.relativePaths=!0,this}withDirs(){return this.options.includeDirs=!0,this}withMaxDepth(t){return this.options.maxDepth=t,this}withMaxFiles(t){return this.options.maxFiles=t,this}withFullPaths(){return this.options.resolvePaths=!0,this.options.includeBasePath=!0,this}withErrors(){return this.options.suppressErrors=!1,this}withSymlinks({resolvePaths:t=!0}={}){return this.options.resolveSymlinks=!0,this.options.useRealPaths=t,this.withFullPaths()}withAbortSignal(t){return this.options.signal=t,this}normalize(){return this.options.normalizePath=!0,this}filter(t){return this.options.filters.push(t),this}onlyDirs(){return this.options.excludeFiles=!0,this.options.includeDirs=!0,this}exclude(t){return this.options.exclude=t,this}onlyCounts(){return this.options.onlyCounts=!0,this}crawl(t){return new ZJ(t||".",this.options)}withGlobFunction(t){return this.globFunction=t,this}crawlWithOptions(t,e){return this.options={...this.options,...e},new ZJ(t||".",this.options)}glob(...t){return this.globFunction?this.globWithOptions(t):this.globWithOptions(t,{dot:!0})}globWithOptions(t,...e){let r=this.globFunction||e8;if(!r)throw new Error("Please specify a glob function to use glob matching.");var n=this.globCache[t.join("\0")];return n||(n=r(t,...e),this.globCache[t.join("\0")]=n),this.options.filters.push(i=>n(i)),this}}});var wp=v((Fdt,a8)=>{"use strict";var n8="[^\\\\/]",iTe="(?=.)",i8="[^/]",FP="(?:\\/|$)",o8="(?:^|\\/)",LP=`\\.{1,2}${FP}`,oTe="(?!\\.)",sTe=`(?!${o8}${LP})`,aTe=`(?!\\.{0,1}${FP})`,cTe=`(?!${LP})`,lTe="[^.\\/]",uTe=`${i8}*?`,dTe="/",s8={DOT_LITERAL:"\\.",PLUS_LITERAL:"\\+",QMARK_LITERAL:"\\?",SLASH_LITERAL:"\\/",ONE_CHAR:iTe,QMARK:i8,END_ANCHOR:FP,DOTS_SLASH:LP,NO_DOT:oTe,NO_DOTS:sTe,NO_DOT_SLASH:aTe,NO_DOTS_SLASH:cTe,QMARK_NO_DOT:lTe,STAR:uTe,START_ANCHOR:o8,SEP:dTe},fTe={...s8,SLASH_LITERAL:"[\\\\/]",QMARK:n8,STAR:`${n8}*?`,DOTS_SLASH:"\\.{1,2}(?:[\\\\/]|$)",NO_DOT:"(?!\\.)",NO_DOTS:"(?!(?:^|[\\\\/])\\.{1,2}(?:[\\\\/]|$))",NO_DOT_SLASH:"(?!\\.{0,1}(?:[\\\\/]|$))",NO_DOTS_SLASH:"(?!\\.{1,2}(?:[\\\\/]|$))",QMARK_NO_DOT:"[^.\\\\/]",START_ANCHOR:"(?:^|[\\\\/])",END_ANCHOR:"(?:[\\\\/]|$)",SEP:"\\"},pTe={__proto__:null,alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};a8.exports={DEFAULT_MAX_EXTGLOB_RECURSION:0,MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:pTe,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{__proto__:null,"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,extglobChars(t){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${t.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(t){return t===!0?fTe:s8}}});var xp=v(zr=>{"use strict";var{REGEX_BACKSLASH:mTe,REGEX_REMOVE_BACKSLASH:hTe,REGEX_SPECIAL_CHARS:gTe,REGEX_SPECIAL_CHARS_GLOBAL:yTe}=wp();zr.isObject=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);zr.hasRegexChars=t=>gTe.test(t);zr.isRegexChar=t=>t.length===1&&zr.hasRegexChars(t);zr.escapeRegex=t=>t.replace(yTe,"\\$1");zr.toPosixSlashes=t=>t.replace(mTe,"/");zr.isWindows=()=>{if(typeof navigator<"u"&&navigator.platform){let t=navigator.platform.toLowerCase();return t==="win32"||t==="windows"}return typeof process<"u"&&process.platform?process.platform==="win32":!1};zr.removeBackslashes=t=>t.replace(hTe,e=>e==="\\"?"":e);zr.escapeLast=(t,e,r)=>{let n=t.lastIndexOf(e,r);return n===-1?t:t[n-1]==="\\"?zr.escapeLast(t,e,n-1):`${t.slice(0,n)}\\${t.slice(n)}`};zr.removePrefix=(t,e={})=>{let r=t;return r.startsWith("./")&&(r=r.slice(2),e.prefix="./"),r};zr.wrapOutput=(t,e={},r={})=>{let n=r.contains?"":"^",i=r.contains?"":"$",o=`${n}(?:${t})${i}`;return e.negated===!0&&(o=`(?:^(?!${o}).*$)`),o};zr.basename=(t,{windows:e}={})=>{let r=t.split(e?/[\\/]/:"/"),n=r[r.length-1];return n===""?r[r.length-2]:n}});var h8=v((zdt,m8)=>{"use strict";var c8=xp(),{CHAR_ASTERISK:zP,CHAR_AT:_Te,CHAR_BACKWARD_SLASH:$p,CHAR_COMMA:bTe,CHAR_DOT:UP,CHAR_EXCLAMATION_MARK:qP,CHAR_FORWARD_SLASH:p8,CHAR_LEFT_CURLY_BRACE:BP,CHAR_LEFT_PARENTHESES:HP,CHAR_LEFT_SQUARE_BRACKET:vTe,CHAR_PLUS:STe,CHAR_QUESTION_MARK:l8,CHAR_RIGHT_CURLY_BRACE:wTe,CHAR_RIGHT_PARENTHESES:u8,CHAR_RIGHT_SQUARE_BRACKET:xTe}=wp(),d8=t=>t===p8||t===$p,f8=t=>{t.isPrefix!==!0&&(t.depth=t.isGlobstar?1/0:1)},$Te=(t,e)=>{let r=e||{},n=t.length-1,i=r.parts===!0||r.scanToEnd===!0,o=[],s=[],a=[],c=t,l=-1,u=0,d=0,f=!1,p=!1,m=!1,h=!1,g=!1,b=!1,_=!1,S=!1,x=!1,w=!1,O=0,T,A,D={value:"",depth:0,isGlob:!1},$=()=>l>=n,re=()=>c.charCodeAt(l+1),K=()=>(T=A,c.charCodeAt(++l));for(;l0&&(C=c.slice(0,u),c=c.slice(u),d-=u),xe&&m===!0&&d>0?(xe=c.slice(0,d),P=c.slice(d)):m===!0?(xe="",P=c):xe=c,xe&&xe!==""&&xe!=="/"&&xe!==c&&d8(xe.charCodeAt(xe.length-1))&&(xe=xe.slice(0,-1)),r.unescape===!0&&(P&&(P=c8.removeBackslashes(P)),xe&&_===!0&&(xe=c8.removeBackslashes(xe)));let Cr={prefix:C,input:t,start:u,base:xe,glob:P,isBrace:f,isBracket:p,isGlob:m,isExtglob:h,isGlobstar:g,negated:S,negatedExtglob:x};if(r.tokens===!0&&(Cr.maxDepth=0,d8(A)||s.push(D),Cr.tokens=s),r.parts===!0||r.tokens===!0){let se;for(let Ce=0;Ce{"use strict";var kp=wp(),ln=xp(),{MAX_LENGTH:Hv,POSIX_REGEX_SOURCE:kTe,REGEX_NON_SPECIAL_CHARS:ETe,REGEX_SPECIAL_CHARS_BACKREF:ATe,REPLACEMENTS:g8}=kp,TTe=(t,e)=>{if(typeof e.expandRange=="function")return e.expandRange(...t,e);t.sort();let r=`[${t.join("-")}]`;try{new RegExp(r)}catch{return t.map(i=>ln.escapeRegex(i)).join("..")}return r},Wl=(t,e)=>`Missing ${t}: "${e}" - use "\\\\${e}" to match literal characters`,y8=t=>{let e=[],r=0,n=0,i=0,o="",s=!1;for(let a of t){if(s===!0){o+=a,s=!1;continue}if(a==="\\"){o+=a,s=!0;continue}if(a==='"'){i=i===1?0:1,o+=a;continue}if(i===0){if(a==="[")r++;else if(a==="]"&&r>0)r--;else if(r===0){if(a==="(")n++;else if(a===")"&&n>0)n--;else if(a==="|"&&n===0){e.push(o),o="";continue}}}o+=a}return e.push(o),e},OTe=t=>{let e=!1;for(let r of t){if(e===!0){e=!1;continue}if(r==="\\"){e=!0;continue}if(/[?*+@!()[\]{}]/.test(r))return!1}return!0},_8=t=>{let e=t.trim(),r=!0;for(;r===!0;)r=!1,/^@\([^\\()[\]{}|]+\)$/.test(e)&&(e=e.slice(2,-1),r=!0);if(OTe(e))return e.replace(/\\(.)/g,"$1")},RTe=t=>{let e=t.map(_8).filter(Boolean);for(let r=0;r{if(t[0]!=="+"&&t[0]!=="*"||t[1]!=="(")return;let r=0,n=0,i=0,o=!1;for(let s=1;s0){r--;continue}if(!(r>0)){if(a==="("){n++;continue}if(a===")"&&(n--,n===0))return e===!0&&s!==t.length-1?void 0:{type:t[0],body:t.slice(2,s),end:s}}}}},ITe=t=>{let e=0,r=[];for(;ea.trim());if(o.length!==1)return;let s=_8(o[0]);if(!s||s.length!==1)return;r.push(s),e+=i.end+1}return r.length<1?void 0:`${r.length===1?ln.escapeRegex(r[0]):`[${r.map(i=>ln.escapeRegex(i)).join("")}]`}*`},PTe=t=>{let e=0,r=t.trim(),n=GP(r);for(;n;)e++,r=n.body.trim(),n=GP(r);return e},CTe=(t,e)=>{if(e.maxExtglobRecursion===!1)return{risky:!1};let r=typeof e.maxExtglobRecursion=="number"?e.maxExtglobRecursion:kp.DEFAULT_MAX_EXTGLOB_RECURSION,n=y8(t).map(i=>i.trim());if(n.length>1&&(n.some(i=>i==="")||n.some(i=>/^[*?]+$/.test(i))||RTe(n)))return{risky:!0};for(let i of n){let o=ITe(i);if(o)return{risky:!0,safeOutput:o};if(PTe(i)>r)return{risky:!0}}return{risky:!1}},ZP=(t,e)=>{if(typeof t!="string")throw new TypeError("Expected a string");t=g8[t]||t;let r={...e},n=typeof r.maxLength=="number"?Math.min(Hv,r.maxLength):Hv,i=t.length;if(i>n)throw new SyntaxError(`Input length: ${i}, exceeds maximum allowed length: ${n}`);let o={type:"bos",value:"",output:r.prepend||""},s=[o],a=r.capture?"":"?:",c=kp.globChars(r.windows),l=kp.extglobChars(c),{DOT_LITERAL:u,PLUS_LITERAL:d,SLASH_LITERAL:f,ONE_CHAR:p,DOTS_SLASH:m,NO_DOT:h,NO_DOT_SLASH:g,NO_DOTS_SLASH:b,QMARK:_,QMARK_NO_DOT:S,STAR:x,START_ANCHOR:w}=c,O=G=>`(${a}(?:(?!${w}${G.dot?m:u}).)*?)`,T=r.dot?"":h,A=r.dot?_:S,D=r.bash===!0?O(r):x;r.capture&&(D=`(${D})`),typeof r.noext=="boolean"&&(r.noextglob=r.noext);let $={input:t,index:-1,start:0,dot:r.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:s};t=ln.removePrefix(t,$),i=t.length;let re=[],K=[],xe=[],C=o,P,Cr=()=>$.index===i-1,se=$.peek=(G=1)=>t[$.index+G],Ce=$.advance=()=>t[++$.index]||"",Kt=()=>t.slice($.index+1),dr=(G="",ht=0)=>{$.consumed+=G,$.index+=ht},Xt=G=>{$.output+=G.output!=null?G.output:G.value,dr(G.value)},uo=()=>{let G=1;for(;se()==="!"&&(se(2)!=="("||se(3)==="?");)Ce(),$.start++,G++;return G%2===0?!1:($.negated=!0,$.start++,!0)},ki=G=>{$[G]++,xe.push(G)},en=G=>{$[G]--,xe.pop()},de=G=>{if(C.type==="globstar"){let ht=$.braces>0&&(G.type==="comma"||G.type==="brace"),H=G.extglob===!0||re.length&&(G.type==="pipe"||G.type==="paren");G.type!=="slash"&&G.type!=="paren"&&!ht&&!H&&($.output=$.output.slice(0,-C.output.length),C.type="star",C.value="*",C.output=D,$.output+=C.output)}if(re.length&&G.type!=="paren"&&(re[re.length-1].inner+=G.value),(G.value||G.output)&&Xt(G),C&&C.type==="text"&&G.type==="text"){C.output=(C.output||C.value)+G.value,C.value+=G.value;return}G.prev=C,s.push(G),C=G},fo=(G,ht)=>{let H={...l[ht],conditions:1,inner:""};H.prev=C,H.parens=$.parens,H.output=$.output,H.startIndex=$.index,H.tokensIndex=s.length;let Oe=(r.capture?"(":"")+H.open;ki("parens"),de({type:G,value:ht,output:$.output?"":p}),de({type:"paren",extglob:!0,value:Ce(),output:Oe}),re.push(H)},Jde=G=>{let ht=t.slice(G.startIndex,$.index+1),H=t.slice(G.startIndex+2,$.index),Oe=CTe(H,r);if((G.type==="plus"||G.type==="star")&&Oe.risky){let lt=Oe.safeOutput?(G.output?"":p)+(r.capture?`(${Oe.safeOutput})`:Oe.safeOutput):void 0,Ei=s[G.tokensIndex];Ei.type="text",Ei.value=ht,Ei.output=lt||ln.escapeRegex(ht);for(let Ai=G.tokensIndex+1;Ai1&&G.inner.includes("/")&&(lt=O(r)),(lt!==D||Cr()||/^\)+$/.test(Kt()))&&(ut=G.close=`)$))${lt}`),G.inner.includes("*")&&(zt=Kt())&&/^\.[^\\/.]+$/.test(zt)){let Ei=ZP(zt,{...e,fastpaths:!1}).output;ut=G.close=`)${Ei})${lt})`}G.prev.type==="bos"&&($.negatedExtglob=!0)}de({type:"paren",extglob:!0,value:P,output:ut}),en("parens")};if(r.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(t)){let G=!1,ht=t.replace(ATe,(H,Oe,ut,zt,lt,Ei)=>zt==="\\"?(G=!0,H):zt==="?"?Oe?Oe+zt+(lt?_.repeat(lt.length):""):Ei===0?A+(lt?_.repeat(lt.length):""):_.repeat(ut.length):zt==="."?u.repeat(ut.length):zt==="*"?Oe?Oe+zt+(lt?D:""):D:Oe?H:`\\${H}`);return G===!0&&(r.unescape===!0?ht=ht.replace(/\\/g,""):ht=ht.replace(/\\+/g,H=>H.length%2===0?"\\\\":H?"\\":"")),ht===t&&r.contains===!0?($.output=t,$):($.output=ln.wrapOutput(ht,$,e),$)}for(;!Cr();){if(P=Ce(),P==="\0")continue;if(P==="\\"){let H=se();if(H==="/"&&r.bash!==!0||H==="."||H===";")continue;if(!H){P+="\\",de({type:"text",value:P});continue}let Oe=/^\\+/.exec(Kt()),ut=0;if(Oe&&Oe[0].length>2&&(ut=Oe[0].length,$.index+=ut,ut%2!==0&&(P+="\\")),r.unescape===!0?P=Ce():P+=Ce(),$.brackets===0){de({type:"text",value:P});continue}}if($.brackets>0&&(P!=="]"||C.value==="["||C.value==="[^")){if(r.posix!==!1&&P===":"){let H=C.value.slice(1);if(H.includes("[")&&(C.posix=!0,H.includes(":"))){let Oe=C.value.lastIndexOf("["),ut=C.value.slice(0,Oe),zt=C.value.slice(Oe+2),lt=kTe[zt];if(lt){C.value=ut+lt,$.backtrack=!0,Ce(),!o.output&&s.indexOf(C)===1&&(o.output=p);continue}}}(P==="["&&se()!==":"||P==="-"&&se()==="]")&&(P=`\\${P}`),P==="]"&&(C.value==="["||C.value==="[^")&&(P=`\\${P}`),r.posix===!0&&P==="!"&&C.value==="["&&(P="^"),C.value+=P,Xt({value:P});continue}if($.quotes===1&&P!=='"'){P=ln.escapeRegex(P),C.value+=P,Xt({value:P});continue}if(P==='"'){$.quotes=$.quotes===1?0:1,r.keepQuotes===!0&&de({type:"text",value:P});continue}if(P==="("){ki("parens"),de({type:"paren",value:P});continue}if(P===")"){if($.parens===0&&r.strictBrackets===!0)throw new SyntaxError(Wl("opening","("));let H=re[re.length-1];if(H&&$.parens===H.parens+1){Jde(re.pop());continue}de({type:"paren",value:P,output:$.parens?")":"\\)"}),en("parens");continue}if(P==="["){if(r.nobracket===!0||!Kt().includes("]")){if(r.nobracket!==!0&&r.strictBrackets===!0)throw new SyntaxError(Wl("closing","]"));P=`\\${P}`}else ki("brackets");de({type:"bracket",value:P});continue}if(P==="]"){if(r.nobracket===!0||C&&C.type==="bracket"&&C.value.length===1){de({type:"text",value:P,output:`\\${P}`});continue}if($.brackets===0){if(r.strictBrackets===!0)throw new SyntaxError(Wl("opening","["));de({type:"text",value:P,output:`\\${P}`});continue}en("brackets");let H=C.value.slice(1);if(C.posix!==!0&&H[0]==="^"&&!H.includes("/")&&(P=`/${P}`),C.value+=P,Xt({value:P}),r.literalBrackets===!1||ln.hasRegexChars(H))continue;let Oe=ln.escapeRegex(C.value);if($.output=$.output.slice(0,-C.value.length),r.literalBrackets===!0){$.output+=Oe,C.value=Oe;continue}C.value=`(${a}${Oe}|${C.value})`,$.output+=C.value;continue}if(P==="{"&&r.nobrace!==!0){ki("braces");let H={type:"brace",value:P,output:"(",outputIndex:$.output.length,tokensIndex:$.tokens.length};K.push(H),de(H);continue}if(P==="}"){let H=K[K.length-1];if(r.nobrace===!0||!H){de({type:"text",value:P,output:P});continue}let Oe=")";if(H.dots===!0){let ut=s.slice(),zt=[];for(let lt=ut.length-1;lt>=0&&(s.pop(),ut[lt].type!=="brace");lt--)ut[lt].type!=="dots"&&zt.unshift(ut[lt].value);Oe=TTe(zt,r),$.backtrack=!0}if(H.comma!==!0&&H.dots!==!0){let ut=$.output.slice(0,H.outputIndex),zt=$.tokens.slice(H.tokensIndex);H.value=H.output="\\{",P=Oe="\\}",$.output=ut;for(let lt of zt)$.output+=lt.output||lt.value}de({type:"brace",value:P,output:Oe}),en("braces"),K.pop();continue}if(P==="|"){re.length>0&&re[re.length-1].conditions++,de({type:"text",value:P});continue}if(P===","){let H=P,Oe=K[K.length-1];Oe&&xe[xe.length-1]==="braces"&&(Oe.comma=!0,H="|"),de({type:"comma",value:P,output:H});continue}if(P==="/"){if(C.type==="dot"&&$.index===$.start+1){$.start=$.index+1,$.consumed="",$.output="",s.pop(),C=o;continue}de({type:"slash",value:P,output:f});continue}if(P==="."){if($.braces>0&&C.type==="dot"){C.value==="."&&(C.output=u);let H=K[K.length-1];C.type="dots",C.output+=P,C.value+=P,H.dots=!0;continue}if($.braces+$.parens===0&&C.type!=="bos"&&C.type!=="slash"){de({type:"text",value:P,output:u});continue}de({type:"dot",value:P,output:u});continue}if(P==="?"){if(!(C&&C.value==="(")&&r.noextglob!==!0&&se()==="("&&se(2)!=="?"){fo("qmark",P);continue}if(C&&C.type==="paren"){let Oe=se(),ut=P;(C.value==="("&&!/[!=<:]/.test(Oe)||Oe==="<"&&!/<([!=]|\w+>)/.test(Kt()))&&(ut=`\\${P}`),de({type:"text",value:P,output:ut});continue}if(r.dot!==!0&&(C.type==="slash"||C.type==="bos")){de({type:"qmark",value:P,output:S});continue}de({type:"qmark",value:P,output:_});continue}if(P==="!"){if(r.noextglob!==!0&&se()==="("&&(se(2)!=="?"||!/[!=<:]/.test(se(3)))){fo("negate",P);continue}if(r.nonegate!==!0&&$.index===0){uo();continue}}if(P==="+"){if(r.noextglob!==!0&&se()==="("&&se(2)!=="?"){fo("plus",P);continue}if(C&&C.value==="("||r.regex===!1){de({type:"plus",value:P,output:d});continue}if(C&&(C.type==="bracket"||C.type==="paren"||C.type==="brace")||$.parens>0){de({type:"plus",value:P});continue}de({type:"plus",value:d});continue}if(P==="@"){if(r.noextglob!==!0&&se()==="("&&se(2)!=="?"){de({type:"at",extglob:!0,value:P,output:""});continue}de({type:"text",value:P});continue}if(P!=="*"){(P==="$"||P==="^")&&(P=`\\${P}`);let H=ETe.exec(Kt());H&&(P+=H[0],$.index+=H[0].length),de({type:"text",value:P});continue}if(C&&(C.type==="globstar"||C.star===!0)){C.type="star",C.star=!0,C.value+=P,C.output=D,$.backtrack=!0,$.globstar=!0,dr(P);continue}let G=Kt();if(r.noextglob!==!0&&/^\([^?]/.test(G)){fo("star",P);continue}if(C.type==="star"){if(r.noglobstar===!0){dr(P);continue}let H=C.prev,Oe=H.prev,ut=H.type==="slash"||H.type==="bos",zt=Oe&&(Oe.type==="star"||Oe.type==="globstar");if(r.bash===!0&&(!ut||G[0]&&G[0]!=="/")){de({type:"star",value:P,output:""});continue}let lt=$.braces>0&&(H.type==="comma"||H.type==="brace"),Ei=re.length&&(H.type==="pipe"||H.type==="paren");if(!ut&&H.type!=="paren"&&!lt&&!Ei){de({type:"star",value:P,output:""});continue}for(;G.slice(0,3)==="/**";){let Ai=t[$.index+4];if(Ai&&Ai!=="/")break;G=G.slice(3),dr("/**",3)}if(H.type==="bos"&&Cr()){C.type="globstar",C.value+=P,C.output=O(r),$.output=C.output,$.globstar=!0,dr(P);continue}if(H.type==="slash"&&H.prev.type!=="bos"&&!zt&&Cr()){$.output=$.output.slice(0,-(H.output+C.output).length),H.output=`(?:${H.output}`,C.type="globstar",C.output=O(r)+(r.strictSlashes?")":"|$)"),C.value+=P,$.globstar=!0,$.output+=H.output+C.output,dr(P);continue}if(H.type==="slash"&&H.prev.type!=="bos"&&G[0]==="/"){let Ai=G[1]!==void 0?"|$":"";$.output=$.output.slice(0,-(H.output+C.output).length),H.output=`(?:${H.output}`,C.type="globstar",C.output=`${O(r)}${f}|${f}${Ai})`,C.value+=P,$.output+=H.output+C.output,$.globstar=!0,dr(P+Ce()),de({type:"slash",value:"/",output:""});continue}if(H.type==="bos"&&G[0]==="/"){C.type="globstar",C.value+=P,C.output=`(?:^|${f}|${O(r)}${f})`,$.output=C.output,$.globstar=!0,dr(P+Ce()),de({type:"slash",value:"/",output:""});continue}$.output=$.output.slice(0,-C.output.length),C.type="globstar",C.output=O(r),C.value+=P,$.output+=C.output,$.globstar=!0,dr(P);continue}let ht={type:"star",value:P,output:D};if(r.bash===!0){ht.output=".*?",(C.type==="bos"||C.type==="slash")&&(ht.output=T+ht.output),de(ht);continue}if(C&&(C.type==="bracket"||C.type==="paren")&&r.regex===!0){ht.output=P,de(ht);continue}($.index===$.start||C.type==="slash"||C.type==="dot")&&(C.type==="dot"?($.output+=g,C.output+=g):r.dot===!0?($.output+=b,C.output+=b):($.output+=T,C.output+=T),se()!=="*"&&($.output+=p,C.output+=p)),de(ht)}for(;$.brackets>0;){if(r.strictBrackets===!0)throw new SyntaxError(Wl("closing","]"));$.output=ln.escapeLast($.output,"["),en("brackets")}for(;$.parens>0;){if(r.strictBrackets===!0)throw new SyntaxError(Wl("closing",")"));$.output=ln.escapeLast($.output,"("),en("parens")}for(;$.braces>0;){if(r.strictBrackets===!0)throw new SyntaxError(Wl("closing","}"));$.output=ln.escapeLast($.output,"{"),en("braces")}if(r.strictSlashes!==!0&&(C.type==="star"||C.type==="bracket")&&de({type:"maybe_slash",value:"",output:`${f}?`}),$.backtrack===!0){$.output="";for(let G of $.tokens)$.output+=G.output!=null?G.output:G.value,G.suffix&&($.output+=G.suffix)}return $};ZP.fastpaths=(t,e)=>{let r={...e},n=typeof r.maxLength=="number"?Math.min(Hv,r.maxLength):Hv,i=t.length;if(i>n)throw new SyntaxError(`Input length: ${i}, exceeds maximum allowed length: ${n}`);t=g8[t]||t;let{DOT_LITERAL:o,SLASH_LITERAL:s,ONE_CHAR:a,DOTS_SLASH:c,NO_DOT:l,NO_DOTS:u,NO_DOTS_SLASH:d,STAR:f,START_ANCHOR:p}=kp.globChars(r.windows),m=r.dot?u:l,h=r.dot?d:l,g=r.capture?"":"?:",b={negated:!1,prefix:""},_=r.bash===!0?".*?":f;r.capture&&(_=`(${_})`);let S=T=>T.noglobstar===!0?_:`(${g}(?:(?!${p}${T.dot?c:o}).)*?)`,x=T=>{switch(T){case"*":return`${m}${a}${_}`;case".*":return`${o}${a}${_}`;case"*.*":return`${m}${_}${o}${a}${_}`;case"*/*":return`${m}${_}${s}${a}${h}${_}`;case"**":return m+S(r);case"**/*":return`(?:${m}${S(r)}${s})?${h}${a}${_}`;case"**/*.*":return`(?:${m}${S(r)}${s})?${h}${_}${o}${a}${_}`;case"**/.*":return`(?:${m}${S(r)}${s})?${o}${a}${_}`;default:{let A=/^(.*?)\.(\w+)$/.exec(T);if(!A)return;let D=x(A[1]);return D?D+o+A[2]:void 0}}},w=ln.removePrefix(t,b),O=x(w);return O&&r.strictSlashes!==!0&&(O+=`${s}?`),O};b8.exports=ZP});var x8=v((qdt,w8)=>{"use strict";var DTe=h8(),VP=v8(),S8=xp(),NTe=wp(),jTe=t=>t&&typeof t=="object"&&!Array.isArray(t),Rt=(t,e,r=!1)=>{if(Array.isArray(t)){let u=t.map(f=>Rt(f,e,r));return f=>{for(let p of u){let m=p(f);if(m)return m}return!1}}let n=jTe(t)&&t.tokens&&t.input;if(t===""||typeof t!="string"&&!n)throw new TypeError("Expected pattern to be a non-empty string");let i=e||{},o=i.windows,s=n?Rt.compileRe(t,e):Rt.makeRe(t,e,!1,!0),a=s.state;delete s.state;let c=()=>!1;if(i.ignore){let u={...e,ignore:null,onMatch:null,onResult:null};c=Rt(i.ignore,u,r)}let l=(u,d=!1)=>{let{isMatch:f,match:p,output:m}=Rt.test(u,s,e,{glob:t,posix:o}),h={glob:t,state:a,regex:s,posix:o,input:u,output:m,match:p,isMatch:f};return typeof i.onResult=="function"&&i.onResult(h),f===!1?(h.isMatch=!1,d?h:!1):c(u)?(typeof i.onIgnore=="function"&&i.onIgnore(h),h.isMatch=!1,d?h:!1):(typeof i.onMatch=="function"&&i.onMatch(h),d?h:!0)};return r&&(l.state=a),l};Rt.test=(t,e,r,{glob:n,posix:i}={})=>{if(typeof t!="string")throw new TypeError("Expected input to be a string");if(t==="")return{isMatch:!1,output:""};let o=r||{},s=o.format||(i?S8.toPosixSlashes:null),a=t===n,c=a&&s?s(t):t;return a===!1&&(c=s?s(t):t,a=c===n),(a===!1||o.capture===!0)&&(o.matchBase===!0||o.basename===!0?a=Rt.matchBase(t,e,r,i):a=e.exec(c)),{isMatch:!!a,match:a,output:c}};Rt.matchBase=(t,e,r)=>(e instanceof RegExp?e:Rt.makeRe(e,r)).test(S8.basename(t));Rt.isMatch=(t,e,r)=>Rt(e,r)(t);Rt.parse=(t,e)=>Array.isArray(t)?t.map(r=>Rt.parse(r,e)):VP(t,{...e,fastpaths:!1});Rt.scan=(t,e)=>DTe(t,e);Rt.compileRe=(t,e,r=!1,n=!1)=>{if(r===!0)return t.output;let i=e||{},o=i.contains?"":"^",s=i.contains?"":"$",a=`${o}(?:${t.output})${s}`;t&&t.negated===!0&&(a=`^(?!${a}).*$`);let c=Rt.toRegex(a,e);return n===!0&&(c.state=t),c};Rt.makeRe=(t,e={},r=!1,n=!1)=>{if(!t||typeof t!="string")throw new TypeError("Expected a non-empty string");let i={negated:!1,fastpaths:!0};return e.fastpaths!==!1&&(t[0]==="."||t[0]==="*")&&(i.output=VP.fastpaths(t,e)),i.output||(i=VP(t,e)),Rt.compileRe(i,e,r,n)};Rt.toRegex=(t,e)=>{try{let r=e||{};return new RegExp(t,r.flags||(r.nocase?"i":""))}catch(r){if(e&&e.debug===!0)throw r;return/$^/}};Rt.constants=NTe;w8.exports=Rt});var A8=v((Bdt,E8)=>{"use strict";var $8=x8(),MTe=xp();function k8(t,e,r=!1){return e&&(e.windows===null||e.windows===void 0)&&(e={...e,windows:MTe.isWindows()}),$8(t,e,r)}Object.assign(k8,$8);E8.exports=k8});import{readdir as FTe,readdirSync as LTe,realpath as zTe,realpathSync as UTe,stat as qTe,statSync as BTe}from"fs";import{isAbsolute as HTe,posix as Za,resolve as GTe}from"path";import{fileURLToPath as ZTe}from"url";function KTe(t,e={}){let r=t.length,n=Array(r),i=Array(r),o,s;for(o=0;o{let c=a.split("/");if(c[0]===".."&&WTe.test(a))return!0;for(o=0;oo.slice(i,s?-1:void 0)||"."}let n=e.slice(t.length+1);return n?(i,o)=>{if(i===".")return n;let s=`${n}/${i}`;return o?s.slice(0,-1):s}:(i,o)=>o&&i!=="."?i.slice(0,-1):i}return r?n=>Za.relative(t,n)||".":n=>Za.relative(t,`${e}/${n}`)||"."}function XTe(t,e){if(e.startsWith(`${t}/`)){let r=e.slice(t.length+1);return n=>`${r}/${n}`}return r=>{let n=Za.relative(t,`${e}/${r}`);return r[r.length-1]==="/"&&n!==""?`${n}/`:n||"."}}function I8(t){var e;let r=Kl.default.scan(t,QTe);return!((e=r.parts)===null||e===void 0)&&e.length?r.parts:[t]}function oOe(t,e){if(e?.caseSensitiveMatch===!1)return!0;let r=Kl.default.scan(t);return r.isGlob||r.negated}function Ep(...t){console.log(`[tinyglobby ${new Date().toLocaleTimeString("es")}]`,...t)}function P8(t){return typeof t=="string"?[t]:t??[]}function WP(t,e,r,n){var i;let o=e.cwd,s=t;t[t.length-1]==="/"&&(s=t.slice(0,-1)),s[s.length-1]!=="*"&&e.expandDirectories&&(s+="/**");let a=iOe(o);s=HTe(s.replace(aOe,""))?Za.relative(a,s):Za.normalize(s);let c=(i=sOe.exec(s))===null||i===void 0?void 0:i[0],l=I8(s);if(c){let d=(c.length+1)/3,f=0,p=a.split("/");for(;fm.length&&(r.root=m,r.depthOffset=-d+f)}if(!n&&r.depthOffset>=0){var u;(u=r.commonPath)!==null&&u!==void 0||(r.commonPath=l);let d=[],f=Math.min(r.commonPath.length,l.length);for(let p=0;p0?Za.join(o,...d):o}return s}function cOe(t,e,r){let n=[],i=[];for(let o of t.ignore)o&&(o[0]!=="!"||o[1]==="(")&&i.push(WP(o,t,r,!0));for(let o of e)o&&(o[0]!=="!"||o[1]==="("?n.push(WP(o,t,r,!1)):(o[1]!=="!"||o[2]==="(")&&i.push(WP(o.slice(1),t,r,!0)));return{match:n,ignore:i}}function lOe(t,e){let r=t.cwd,n={root:r,depthOffset:0},i=cOe(t,e,n);t.debug&&Ep("internal processing patterns:",i);let{absolute:o,caseSensitiveMatch:s,debug:a,dot:c,followSymbolicLinks:l,onlyDirectories:u}=t,d=n.root.replace(O8,""),f={dot:c,nobrace:t.braceExpansion===!1,nocase:!s,noextglob:t.extglob===!1,noglobstar:t.globstar===!1,posix:!0},p=(0,Kl.default)(i.match,f),m=(0,Kl.default)(i.ignore,f),h=KTe(i.match,f),g=T8(r,d,o),b=o?g:T8(r,d,!0),_=(w,O)=>{let T=b(O,!0);return T!=="."&&!h(T)||m(T)},S;t.deep!==void 0&&(S=Math.round(t.deep-n.depthOffset));let x=new t8({filters:[a?(w,O)=>{let T=g(w,O),A=p(T)&&!m(T);return A&&Ep(`matched ${T}`),A}:(w,O)=>{let T=g(w,O);return p(T)&&!m(T)}],exclude:a?(w,O)=>{let T=_(w,O);return Ep(`${T?"skipped":"crawling"} ${O}`),T}:_,fs:t.fs,pathSeparator:"/",relativePaths:!o,resolvePaths:o,includeBasePath:o,resolveSymlinks:l,excludeSymlinks:!l,excludeFiles:u,includeDirs:u||!t.onlyFiles,maxDepth:S,signal:t.signal}).crawl(d);return t.debug&&Ep("internal properties:",{...n,root:d}),[x,r!==d&&!o&&XTe(r,d)]}function uOe(t,e){if(e)for(let r=t.length-1;r>=0;r--)t[r]=e(t[r]);return t}function fOe(t){let e={...dOe,...t};return e.cwd=(e.cwd instanceof URL?ZTe(e.cwd):GTe(e.cwd)).replace(O8,"/"),e.ignore=P8(e.ignore),e.fs&&(e.fs={readdir:e.fs.readdir||FTe,readdirSync:e.fs.readdirSync||LTe,realpath:e.fs.realpath||zTe,realpathSync:e.fs.realpathSync||UTe,stat:e.fs.stat||qTe,statSync:e.fs.statSync||BTe}),e.debug&&Ep("globbing with options:",e),e}function pOe(t,e={}){var r;if(t&&e?.patterns)throw new Error("Cannot pass patterns as both an argument and an option");let n=VTe(t)||typeof t=="string",i=P8((r=n?t:t.patterns)!==null&&r!==void 0?r:"**/*"),o=fOe(n?e:t);return i.length>0?lOe(o,i):[]}function _s(t,e){let[r,n]=pOe(t,e);return r?uOe(r.sync(),n):[]}var Kl,VTe,O8,R8,WTe,JTe,YTe,QTe,eOe,tOe,rOe,nOe,iOe,sOe,aOe,dOe,Ap=y(()=>{r8();Kl=St(A8(),1),VTe=Array.isArray,O8=/\\/g,R8=process.platform==="win32",WTe=/^(\/?\.\.)+$/;JTe=/^[A-Z]:\/$/i,YTe=R8?t=>JTe.test(t):t=>t==="/";QTe={parts:!0};eOe=/(?t.replace(eOe,"\\$&"),nOe=t=>t.replace(tOe,"\\$&"),iOe=R8?nOe:rOe;sOe=/^(\/?\.\.)+/,aOe=/\\(?=[()[\]{}!*+?@|])/g;dOe={caseSensitiveMatch:!0,cwd:process.cwd(),debug:!!process.env.TINYGLOBBY_DEBUG,expandDirectories:!0,followSymbolicLinks:!0,onlyFiles:!0}});import{existsSync as Tp,readFileSync as mOe,readdirSync as hOe,statSync as C8}from"node:fs";import{join as Va}from"node:path";function gOe(t){let{cwd:e="."}=t,r,n;try{let c=q(e);r=c.architecture,n=c.project?.language}catch{return[]}if(!r)return[];let i=Li(e,n),o=[],{layers:s,forbiddenImports:a}=KP(r);return(s.size>0||a.length>0)&&!Tp(Va(e,i.mainRoot))?[{detector:Op,severity:"info",path:`${i.mainRoot}/`,message:`architecture layers declared but ${i.mainRoot}/ not found \u2014 layer checks skipped (flat layout not yet supported)`}]:(s.size>0&&(yOe(e,i,s,o),_Oe(e,i,s,o)),a.length>0&&bOe(e,i,a,o),o)}function KP(t){let e=new Set,r=[];for(let i of t.layers??[])if(Array.isArray(i))for(let o of i)e.add(o);else{let o=i;if(typeof o.name=="string"&&o.name.length>0){e.add(o.name);for(let s of o.forbidden_imports??[])typeof s=="string"&&r.push({from:o.name,to:s})}}let n=t.forbidden_imports??[];return{layers:e,forbiddenImports:[...n,...r]}}function yOe(t,e,r,n){let i=e.mainRoot,o=Va(t,i);if(Tp(o))for(let s of hOe(o)){let a=Va(o,s);C8(a).isDirectory()&&(r.has(s)||n.push({detector:Op,severity:"warn",path:`${i}/${s}/`,message:`${i}/${s}/ is not declared in spec/architecture.yaml layers \u2014 add it or remove the directory`}))}}function _Oe(t,e,r,n){let i=e.mainRoot,o=Va(t,i);if(Tp(o))for(let s of r){let a=Va(o,s);Tp(a)&&C8(a).isDirectory()||n.push({detector:Op,severity:"warn",path:`${i}/${s}/`,message:`spec/architecture.yaml declares layer '${s}' but ${i}/${s}/ does not exist \u2014 fix the spec or create the directory`})}}function bOe(t,e,r,n){let i=e.mainRoot,o=e.importMatcher;for(let s of r){let a=Va(t,i,s.from);if(!Tp(a))continue;let c=_s([`**/*.${e.ext}`],{cwd:a,dot:!1});for(let l of c){let u=Va(a,l),d;try{d=mOe(u,"utf8")}catch{continue}let f;for(o.lastIndex=0;(f=o.exec(d))!==null;){let p=f[1];vOe(p,s.to,e.importStyle)&&n.push({detector:Op,severity:"error",path:`${i}/${s.from}/${l}`,message:`${i}/${s.from}/${l} imports from '${p}' which crosses into the '${s.to}' layer \u2014 spec/architecture.yaml forbids imports from '${s.from}' to '${s.to}'`})}}}}function vOe(t,e,r){return r==="dotted"?t.split(".").includes(e):t.startsWith(".")?t.split("/").includes(e):!1}var Op,D8,JP=y(()=>{"use strict";Ap();Ue();Ga();Op="ARCHITECTURE_FROM_SPEC";D8={name:Op,run:gOe}});import{existsSync as SOe,readFileSync as wOe}from"node:fs";import{join as xOe}from"node:path";function kOe(t){let{cwd:e="."}=t,r=xOe(e,"spec/capabilities.yaml");if(!SOe(r))return[];let n;try{let u=wOe(r,"utf8"),d=N8.default.parse(u);if(!d||typeof d!="object")return[];n=d}catch{return[]}let i=n.capabilities??[];if(i.length===0)return[];let o,s=!1;try{let u=q(e);o=new Set(u.features.map(d=>d.id)),s=u.project.onboarding_seeded===!0}catch{return[]}let a=[],c=new Set,l=s&&o.size<$Oe;for(let u of i){if(typeof u!="object"||u===null)continue;let d=String(u.id??"(unnamed)"),f=Array.isArray(u.features)?u.features:[];if(f.length===0){a.push({detector:Gv,severity:l?"info":"warn",path:"spec/capabilities.yaml",message:l?`capability "${d}" has no features mapped yet \u2014 retained as future onboarding intent; bind it when a matching feature lands`:`capability "${d}" has no features mapped \u2014 bind at least one feature via the features[] field, or remove the capability if it's no longer relevant`});continue}for(let p of f){let m=String(p);o.has(m)?c.add(m):a.push({detector:Gv,severity:"error",path:"spec/capabilities.yaml",message:`capability "${d}" references feature ${m} which does not exist in spec.yaml \u2014 either add the feature or remove it from this capability's features[]`})}}for(let u of o)c.has(u)||a.push({detector:Gv,severity:"info",path:"spec.yaml",message:`feature ${u} is not claimed by any capability \u2014 if it's user-facing, consider adding it to a capability's features[] in spec/capabilities.yaml`});return a}var N8,Gv,$Oe,j8,M8=y(()=>{"use strict";N8=St(er(),1);Ue();Gv="CAPABILITIES_FEATURE_MAPPING",$Oe=8;j8={name:Gv,run:kOe}});import{existsSync as EOe,readFileSync as AOe}from"node:fs";import{join as TOe}from"node:path";function OOe(t){let e=t.trimStart();return e.startsWith("//")||e.startsWith("/*")||e.startsWith("#")||e.startsWith('"""')||e.startsWith("'''")}function ROe(t){let{cwd:e="."}=t;return ge(e,YP,r=>IOe(r,e))}function IOe(t,e){let r=Li(e,t.project?.language),n=[];for(let i of t.features)for(let o of i.modules??[]){if(!r.extensions.some(c=>o.endsWith(c)))continue;let s=TOe(e,o);if(!EOe(s))continue;let a=AOe(s,"utf8");OOe(a)||n.push({detector:YP,severity:"warn",path:o,message:`${o} has no file-header comment \u2014 Why>What guardrail recommends a one-line intent`})}return n}var YP,F8,L8=y(()=>{"use strict";Ga();wt();YP="CONVENTION_DRIFT";F8={name:YP,run:ROe}});import{existsSync as XP,readFileSync as z8}from"node:fs";import{join as Zv}from"node:path";function POe(t){return JSON.parse(t).total?.lines?.pct??0}function U8(t){let e=/]*\bline-rate="([0-9]*\.?[0-9]+)"/.exec(t);return e?Number(e[1])*100:null}function NOe(t,e){if(!Rv(dt(t).gates.coverage?.cmd))return null;let r;try{r=Iv(t,e)}catch(c){return[{detector:ko,severity:"error",message:c.message}]}let n=0,i=0,o=0,s=[];for(let c of r){let l=TP.find(d=>XP(Zv(c.dir,d)));if(!l){s.push(c.path);continue}let u=U8(z8(Zv(c.dir,l),"utf8"));u&&(n+=u.missed,i+=u.covered,o++)}if(o===0)return[{detector:ko,severity:"info",message:`no module coverage report present for ${r.map(c=>c.path).join(", ")} \u2014 run stage_2.2 first`}];let a=q8(n,i);return a0?[{detector:ko,severity:"info",message:`module coverage ${a.toFixed(1)}% OK; no report yet for ${s.join(", ")}`}]:[]}function jOe(t){let{cwd:e="."}=t;if(t.focusModules&&t.focusModules.length>0){let a=NOe(e,t.focusModules);if(a)return a}let r;try{r=q(e).project?.language}catch{}let n=Li(e,r),i=dt(e).language==="kotlin"?TP.find(a=>XP(Zv(e,a)))??xJ(e):n.coverageSummary,o=Zv(e,i);if(!XP(o))return[{detector:ko,severity:"info",message:`${i} not present \u2014 run stage_2.2 first`}];let s;try{let a=z8(o,"utf8");s=n.coverageFormat==="jacoco-xml"?COe(a):n.coverageFormat==="cobertura-xml"?DOe(a):POe(a)}catch(a){return[{detector:ko,severity:"warn",message:`${i} unparseable: ${a.message}`}]}return s===null?n.coverageFormat==="cobertura-xml"?[]:[{detector:ko,severity:"warn",message:`${i} contained no line-coverage counter`}]:s>=Vv?[]:[{detector:ko,severity:"warn",message:`line coverage ${s.toFixed(1)}% < floor ${Vv}%`}]}var ko,Vv,B8,H8=y(()=>{"use strict";Ue();Dv();Ga();Pv();cn();ko="COVERAGE_DROP",Vv=70;B8={name:ko,run:jOe}});import{existsSync as MOe}from"node:fs";import{join as FOe}from"node:path";function zOe(t){let{cwd:e="."}=t;return ge(e,Wv,r=>UOe(r,e))}function UOe(t,e){let r=t.project.deliverable,n=t.features.filter(i=>i.status==="done"&&(i.modules?.length??0)>0);if(!r){if(n.length===0)return[];let i=t.project.onboarding_seeded===!0&&t.features.length{"use strict";wt();Wv="DELIVERABLE_INTEGRITY",LOe=8;G8={name:Wv,run:zOe}});function qOe(t){let e=new Set((t.features??[]).map(n=>n.id)),r=[];for(let n of t.project?.smoke??[]){let i=n.feature;if(i===void 0||e.has(i))continue;let o=(n.run??[]).join(" ")||`kind:${n.kind}`;r.push({detector:Kv,severity:"warn",path:"spec.yaml",message:`smoke probe '${o}' binds feature ${i}, which is not in the spec \u2014 a dangling binding is annotation drift (the bound feature was renamed, archived, or never existed). Fix the id or drop the binding.`})}return r}function BOe(t){let e=qOe(t),r=(t.features??[]).filter(o=>o.status==="done");return r.length===0||!!!t.project?.deliverable||(t.project?.smoke??[]).length>0?e:[...e,{detector:Kv,severity:"warn",path:"spec.yaml",message:`${r.length} feature(s) are done and the project ships a runnable deliverable, but no functional smoke probe is declared (project.smoke) \u2014 an exit-only deliverable is liveness, not AC-verification. Declare a smoke probe with an expect.token so the gate re-executes the shipped entry against its AC result.`}]}function HOe(t){let{cwd:e="."}=t;return ge(e,Kv,r=>BOe(r))}var Kv,V8,W8=y(()=>{"use strict";wt();Kv="SMOKE_PROBE_DEMAND";V8={name:Kv,run:HOe}});function GOe(t){let{cwd:e="."}=t;return ge(e,Jv,r=>ZOe(r,e))}function ZOe(t,e){let r=(t.features??[]).filter(o=>o.status==="done"&&(o.modules??[]).length>0);if(r.length===0)return[];let n=ls(e);if(n===null)return[{detector:Jv,severity:"info",path:"spec/attestation.yaml",message:"no verification attestation \u2014 when this tree was last verified is unknown. Run `clad check --tier=pre-push --strict` GREEN once to attest (the gate writes spec/attestation.yaml)."}];let i=[];for(let o of r){let s=J_(n,e,o);s.state!=="fresh"&&i.push({detector:Jv,severity:"warn",path:"spec/attestation.yaml",message:s.state==="unattested"?`${o.id} is done but has no attestation entry \u2014 its modules were never verified by an attested gate. Run \`clad check --tier=pre-push --strict\` to attest.`:s.module?`${o.id}'s module ${s.module} changed since the last attested verification \u2014 shipped code is running ahead of its verification. Run \`clad check --tier=pre-push --strict\` to re-verify and re-attest.`:`${o.id}'s modules changed since the last attested verification \u2014 shipped code is running ahead of its verification. Run \`clad check --tier=pre-push --strict\` to re-verify and re-attest.`})}return i}var Jv,Yv,QP=y(()=>{"use strict";xl();wt();Jv="STALE_ATTESTATION";Yv={name:Jv,run:GOe}});function VOe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}return WOe(r)}function WOe(t){let e=new Set(t.features.map(d=>d.id)),r=new Map;for(let d of t.features)r.set(d.id,(d.depends_on??[]).filter(f=>e.has(f)));let n=0,i=1,o=2,s=new Map;for(let d of r.keys())s.set(d,n);let a=[],c=new Set,l=[];function u(d){s.set(d,i),l.push(d);for(let f of r.get(d)??[]){let p=s.get(f);if(p===i){let m=l.indexOf(f),h=l.slice(m).concat(f),g=[...h].sort().join(",");c.has(g)||(c.add(g),a.push({detector:K8,severity:"error",path:"spec.yaml",message:`circular depends_on cycle: ${h.join(" \u2192 ")} \u2014 these features can never all become ready, so the drive loop deadlocks. Break the cycle by removing one edge.`}))}else p===n&&u(f)}l.pop(),s.set(d,o)}for(let d of r.keys())s.get(d)===n&&u(d);return a}var K8,Xv,eC=y(()=>{"use strict";Ue();K8="DEPENDENCY_CYCLE";Xv={name:K8,run:VOe}});import{appendFileSync as KOe,existsSync as J8,mkdirSync as JOe,readFileSync as YOe}from"node:fs";import{dirname as XOe,join as QOe}from"node:path";function Y8(t){return QOe(t,eRe,tRe)}function X8(t){return tC.add(t),()=>tC.delete(t)}function Wa(t,e){let r=Y8(t),n=XOe(r);J8(n)||JOe(n,{recursive:!0}),KOe(r,`${JSON.stringify(e)} -`,"utf8");for(let i of tC)try{i(t,e)}catch{}}function fr(t){let e=Y8(t);if(!J8(e))return[];let r=YOe(e,"utf8").trim();return r.length===0?[]:r.split(` -`).filter(n=>n.length>0).map(n=>JSON.parse(n))}var eRe,tRe,tC,un=y(()=>{"use strict";eRe=".cladding",tRe="audit.log.jsonl";tC=new Set});import{existsSync as rRe}from"node:fs";import{join as nRe}from"node:path";function iRe(t){let{cwd:e="."}=t,r=fr(e);if(r.length===0)return[{detector:rC,severity:"info",message:"no audit log present \u2014 detector is opt-in on prior stage_4 runs"}];let n=[];for(let i of r)i.artifact&&(rRe(nRe(e,i.artifact))||n.push({detector:rC,severity:"error",path:i.artifact,message:`evidence ${i.id} references missing artifact '${i.artifact}'`}));return n}var rC,Q8,e5=y(()=>{"use strict";un();rC="EVIDENCE_MISMATCH";Q8={name:rC,run:iRe}});import{existsSync as oRe,readFileSync as sRe}from"node:fs";import{join as aRe}from"node:path";function cRe(t){let e=aRe(t,i5);if(!oRe(e))return null;try{let n=((0,n5.parse)(sRe(e,"utf8"))?.fixtures??[]).map(i=>i.name).filter(Boolean);return new Set(n)}catch{return null}}function*r5(t,e){for(let r of t??[])r.startsWith(t5)&&(yield{ref:r,name:r.slice(t5.length),field:e})}function lRe(t){let{cwd:e="."}=t,r=cRe(e);if(r===null)return[];let n;try{n=q(e)}catch(o){return[{detector:nC,severity:"info",message:`spec.yaml not loaded: ${o.message}`}]}let i=[];for(let o of n.features)for(let s of o.acceptance_criteria??[]){let a=[...r5(s.evidence_refs,"evidence_refs"),...r5(s.test_refs,"test_refs")];for(let{ref:c,name:l,field:u}of a)r.has(l)||i.push({detector:nC,severity:"warn",path:i5,message:`${o.id}.${s.id} cites '${c}' in ${u} but no fixture named '${l}' is registered in conformance/fixtures.yaml`})}return i}var n5,nC,t5,i5,o5,s5=y(()=>{"use strict";n5=St(er(),1);Ue();nC="FIXTURE_REFERENCE_INVALID",t5="fixture:",i5="conformance/fixtures.yaml";o5={name:nC,run:lRe}});import{existsSync as Jl,readFileSync as iC}from"node:fs";import{join as Ka}from"node:path";function uRe(t){return _s(["src/stages/detectors/*.ts"],{cwd:t,dot:!1}).filter(r=>!/[/\\](index|with-spec|spec-first-window)\.ts$/.test(r)).length}function Rp(t){if(!Jl(t))return null;try{return JSON.parse(iC(t,"utf8"))}catch{return null}}function dRe(t,e){let r=Ka(t,"plugins","claude-code",".claude-plugin","plugin.json"),n;try{n=JSON.parse(iC(r,"utf8"))}catch(c){e.push({detector:Eo,severity:"info",message:`plugin.json not loaded: ${c.message}`});return}let i=n.ironclad?.current?.detectors;if(!i)return;let o=i.match(/^(\d+)\/(\d+)$/);if(!o){e.push({detector:Eo,severity:"warn",message:`plugin.json current.detectors='${i}' is not in 'N/M' form`});return}let s=Number(o[1]),a=uRe(t);s!==a&&e.push({detector:Eo,severity:"error",message:`plugin.json current.detectors='${i}' but stages/detectors/contains ${a} non-index .ts file(s)`})}function fRe(t,e){for(let r of a5){let n=Ka(t,r.path);if(!Jl(n))continue;let i=Rp(n);if(!i){e.push({detector:Eo,severity:"warn",message:`${r.host}: ${r.path} could not be parsed as JSON`});continue}for(let o of r.required)(i[o]===void 0||i[o]===null||i[o]==="")&&e.push({detector:Eo,severity:"error",message:`${r.host}: ${r.path} is missing required field '${String(o)}'`})}}function pRe(t,e){let r=Rp(Ka(t,"package.json"));if(!r?.version)return;let n=r.version;for(let o of a5){let s=Ka(t,o.path);if(!Jl(s))continue;let a=Rp(s);a?.version&&a.version!==n&&e.push({detector:Eo,severity:"error",message:`${o.host}: ${o.path} version='${a.version}' but package.json version='${n}' \u2014 bump them in lockstep`})}let i=Ka(t,".claude-plugin","marketplace.json");if(Jl(i)){let o=Rp(i);for(let s of o?.plugins??[])s?.version&&s.version!==n&&e.push({detector:Eo,severity:"error",message:`marketplace: .claude-plugin/marketplace.json plugin '${s.name??"?"}' version='${s.version}' but package.json version='${n}' \u2014 the catalog advertises a stale version; bump it in lockstep`})}}function mRe(t){let e=t.match(/TIER_STAGES[\s\S]*?\ball:\s*\[([^\]]*)\]/);return e?[...e[1].matchAll(/['"]([^'"]+)['"]/g)].map(r=>r[1]):[]}function hRe(t,e){let r=Ka(t,"src","cli","clad.ts"),n=Ka(t,"plugins","claude-code",".claude-plugin","plugin.json");if(!Jl(r)||!Jl(n))return;let i=mRe(iC(r,"utf8"));if(i.length===0)return;let s=Rp(n)?.ironclad?.current?.["stages-implemented"];if(!Array.isArray(s))return;let a=new Set(i),c=new Set(s),l=i.filter(f=>!c.has(f)),u=s.filter(f=>!a.has(f));if(l.length===0&&u.length===0)return;let d=[l.length?`missing [${l.join(", ")}]`:"",u.length?`unexpected [${u.join(", ")}]`:""].filter(Boolean).join("; ");e.push({detector:Eo,severity:"error",message:`plugins/claude-code/.claude-plugin/plugin.json stages-implemented disagrees with TIER_STAGES.all (src/cli/clad.ts): ${d} \u2014 run \`npm run build:plugin\` to re-derive`})}function gRe(t){let{cwd:e="."}=t,r=[];return dRe(e,r),hRe(e,r),fRe(e,r),pRe(e,r),r}var Eo,a5,c5,l5=y(()=>{"use strict";Ap();Eo="HARNESS_INTEGRITY",a5=[{host:"claude-code",path:"plugins/claude-code/.claude-plugin/plugin.json",required:["name","version"]},{host:"codex",path:"plugins/codex/.codex-plugin/plugin.json",required:["name","version","description"]},{host:"gemini-cli",path:"plugins/gemini-cli/gemini-extension.json",required:["name","version"]}];c5={name:Eo,run:gRe}});import{existsSync as yRe,readFileSync as _Re}from"node:fs";import{join as bRe}from"node:path";function SRe(t){let{cwd:e="."}=t;return ge(e,Qv,r=>xRe(r,e))}function wRe(t){let e=bRe(t,"spec/capabilities.yaml");if(!yRe(e))return!1;try{let r=u5.default.parse(_Re(e,"utf8"));if(!r||typeof r!="object")return!1;let n=r.capabilities;return!Array.isArray(n)||n.length===0}catch{return!1}}function xRe(t,e){let r=t.features.length;if(r{"use strict";u5=St(er(),1);wt();Qv="HOLLOW_GOVERNANCE",vRe=8;d5={name:Qv,run:SRe}});import{existsSync as p5,readFileSync as m5}from"node:fs";import{join as h5}from"node:path";function g5(t,e){let r=t.match(e);if(!r)return null;try{let n=JSON.parse(r[1]),i={};for(let[o,s]of Object.entries(n))typeof s=="string"&&(i[o]=s);return i}catch{return null}}function ERe(t){switch(t){case"fail":case"wiring-fail":return 0;case"wiring-ok":case"wiring-only":return 1;case"verified":return 2;default:return null}}function ARe(t){switch(t){case"wiring-only":return 1;case"verified":return 2;default:return null}}function TRe(t){let e=h5(t,"README.md"),r=h5(t,"docs","dogfood","matrix.md");if(!p5(e)||!p5(r))return[];let n=g5(m5(e,"utf8"),$Re),i=g5(m5(r,"utf8"),kRe);if(!n||!i)return[];let o=[];for(let[s,a]of Object.entries(n)){let c=ARe(a);if(c===null)continue;let l=i[s]??"not-run",u=ERe(l);u!==null&&c>u&&o.push({detector:y5,severity:"warn",path:"README.md",message:`README host-claims: '${s}' claims '${a}' but the newest matrix evidence is '${l}' \u2014 the claim exceeds the evidence. Re-run \`clad doctor --hosts\` (with consent) or lower the README claim for '${s}'.`})}return o}function ORe(t){let{cwd:e="."}=t;return TRe(e)}var y5,$Re,kRe,_5,b5=y(()=>{"use strict";y5="HOST_CLAIM_DRIFT",$Re=//,kRe=//;_5={name:y5,run:ORe}});function RRe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=[];return v5(r.features.map(i=>i.id),"feature","spec/features/",n),v5((r.scenarios??[]).map(i=>i.id),"scenario","spec/scenarios/",n),n}function v5(t,e,r,n){let i=new Map;for(let o of t)i.set(o,(i.get(o)??0)+1);for(let[o,s]of i)s>1&&n.push({detector:S5,severity:"error",message:`${e} id '${o}' appears ${s} times across ${r} \u2014 every ${e} must have a unique id; resolve the duplicate`})}var S5,w5,x5=y(()=>{"use strict";Ue();S5="ID_COLLISION";w5={name:S5,run:RRe}});import{existsSync as Ip,readFileSync as oC,readdirSync as sC,statSync as IRe,writeFileSync as k5}from"node:fs";import{join as Ao}from"node:path";function $5(t){if(!Ip(t))return 0;try{return sC(t).filter(e=>e.endsWith(".yaml")||e.endsWith(".yml")).length}catch{return 0}}function PRe(t){if(!Ip(t))return 0;let e=0,r=[t];for(;r.length>0;){let n=r.pop(),i;try{i=sC(n)}catch{continue}for(let o of i){if(o==="node_modules"||o===".cladding"||o.startsWith("."))continue;let s=Ao(n,o),a;try{a=IRe(s)}catch{continue}a.isDirectory()?r.push(s):(o.endsWith(".test.ts")||o.endsWith(".test.tsx"))&&e++}}return e}function CRe(t){let e=Ao(t,"spec","capabilities.yaml");if(!Ip(e))return 0;try{let r=eS.default.parse(oC(e,"utf8"));return Array.isArray(r?.capabilities)?r.capabilities.length:0}catch{return 0}}function bs(t="."){let e=$5(Ao(t,"spec","features")),r=$5(Ao(t,"spec","scenarios")),n=CRe(t),i=PRe(Ao(t,"tests"));return{features:e,scenarios:r,capabilities:n,test_files:i}}function Yl(t,e){let r=Ao(t,"spec.yaml");if(!Ip(r))return;let n=oC(r,"utf8"),i=DRe(n,e);i!==n&&k5(r,i)}function DRe(t,e){let r=t.includes(`\r + if (condition) { yield value; }`)}});import{Buffer as H0e}from"node:buffer";import{StringDecoder as B0e}from"node:string_decoder";var uv,G0e,Z0e,V0e,PI=y(()=>{an();uv=(t,e,r)=>{if(r)return;if(t)return{transform:G0e.bind(void 0,new TextEncoder)};let n=new B0e(e);return{transform:Z0e.bind(void 0,n),final:V0e.bind(void 0,n)}},G0e=function*(t,e){H0e.isBuffer(e)?yield vo(e):typeof e=="string"?yield t.encode(e):yield e},Z0e=function*(t,e){yield qt(e)?t.write(e):e},V0e=function*(t){let e=t.end();e!==""&&(yield e)}});import{callbackify as kK}from"node:util";var CI,dv,EK,W0e,AK,K0e,OK=y(()=>{CI=kK(async(t,e,r,n)=>{e.currentIterable=t(...r);try{for await(let i of e.currentIterable)n.push(i)}finally{delete e.currentIterable}}),dv=async function*(t,e,r){if(r===e.length){yield t;return}let{transform:n=K0e}=e[r];for await(let i of n(t))yield*dv(i,e,r+1)},EK=async function*(t){for(let[e,{final:r}]of Object.entries(t))yield*W0e(r,Number(e),t)},W0e=async function*(t,e,r){if(t!==void 0)for await(let n of t())yield*dv(n,r,e+1)},AK=kK(async({currentIterable:t},e)=>{if(t!==void 0){await(e?t.throw(e):t.return());return}if(e)throw e}),K0e=function*(t){yield t}});var DI,TK,Ua,hp,J0e,Y0e,NI=y(()=>{DI=(t,e,r,n)=>{try{for(let i of t(...e))r.push(i);n()}catch(i){n(i)}},TK=(t,e)=>[...e.flatMap(r=>[...Ua(r,t,0)]),...hp(t)],Ua=function*(t,e,r){if(r===e.length){yield t;return}let{transform:n=Y0e}=e[r];for(let i of n(t))yield*Ua(i,e,r+1)},hp=function*(t){for(let[e,{final:r}]of Object.entries(t))yield*J0e(r,Number(e),t)},J0e=function*(t,e,r){if(t!==void 0)for(let n of t())yield*Ua(n,r,e+1)},Y0e=function*(t){yield t}});import{Transform as X0e,getDefaultHighWaterMark as RK}from"node:stream";var jI,fv,IK,pv=y(()=>{$r();lv();$K();PI();OK();NI();jI=({value:t,value:{transform:e,final:r,writableObjectMode:n,readableObjectMode:i},optionName:o},{encoding:s})=>{let a={},c=IK(t,s,o),l=za(e),u=za(r),d=l?CI.bind(void 0,dv,a):DI.bind(void 0,Ua),f=l||u?CI.bind(void 0,EK,a):DI.bind(void 0,hp),p=l||u?AK.bind(void 0,a):void 0;return{stream:new X0e({writableObjectMode:n,writableHighWaterMark:RK(n),readableObjectMode:i,readableHighWaterMark:RK(i),transform(h,g,b){d([h,c,0],this,b)},flush(h){f([c],this,h)},destroy:p})}},fv=(t,e,r,n)=>{let i=e.filter(({type:s})=>s==="generator"),o=n?i.reverse():i;for(let{value:s,optionName:a}of o){let c=IK(s,r,a);t=TK(c,t)}return t},IK=({transform:t,final:e,binary:r,writableObjectMode:n,readableObjectMode:i,preserveNewlines:o},s,a)=>{let c={};return[{transform:SK(n,a)},uv(r,s,n),cv(r,o,n,c),{transform:t,final:e},{transform:wK(i,a)},vK({binary:r,preserveNewlines:o,readableObjectMode:i,state:c})].filter(Boolean)}});var PK,Q0e,e$e,t$e,r$e,CK=y(()=>{pv();an();$r();PK=(t,e)=>{for(let r of Q0e(t))e$e(t,r,e)},Q0e=t=>new Set(Object.entries(t).filter(([,{direction:e}])=>e==="input").map(([e])=>Number(e))),e$e=(t,e,r)=>{let{stdioItems:n}=t[e],i=n.filter(({contents:a})=>a!==void 0);if(i.length===0)return;if(e!==0){let[{type:a,optionName:c}]=i;throw new TypeError(`Only the \`stdin\` option, not \`${c}\`, can be ${ys[a]} with synchronous methods.`)}let s=i.map(({contents:a})=>a).map(a=>t$e(a,n));r.input=Qf(s)},t$e=(t,e)=>{let r=fv(t,e,"utf8",!0);return r$e(r),Qf(r)},r$e=t=>{let e=t.find(r=>typeof r!="string"&&!qt(r));if(e!==void 0)throw new TypeError(`The \`stdin\` option is invalid: when passing objects as input, a transform must be used to serialize them to strings or Uint8Arrays: ${e}.`)}});var mv,n$e,i$e,DK,NK,o$e,jK,MI=y(()=>{ja();$r();Pl();ps();mv=({stdioItems:t,encoding:e,verboseInfo:r,fdNumber:n})=>n!=="all"&&Il(r,n)&&!cn.has(e)&&n$e(n)&&(t.some(({type:i,value:o})=>i==="native"&&i$e.has(o))||t.every(({type:i})=>Cn.has(i))),n$e=t=>t===1||t===2,i$e=new Set(["pipe","overlapped"]),DK=async(t,e,r,n)=>{for await(let i of t)o$e(e)||jK(i,r,n)},NK=(t,e,r)=>{for(let n of t)jK(n,e,r)},o$e=t=>t._readableState.pipes.length>0,jK=(t,e,r)=>{let n=pb(t);Ci({type:"output",verboseMessage:n,fdNumber:e,verboseInfo:r})}});import{writeFileSync as s$e,appendFileSync as a$e}from"node:fs";var MK,c$e,l$e,u$e,d$e,f$e,FK=y(()=>{MI();pv();lv();an();$r();La();MK=({fileDescriptors:t,syncResult:{output:e},options:r,isMaxBuffer:n,verboseInfo:i})=>{if(e===null)return{output:Array.from({length:3})};let o={},s=new Set([]);return{output:e.map((c,l)=>c$e({result:c,fileDescriptors:t,fdNumber:l,state:o,outputFiles:s,isMaxBuffer:n,verboseInfo:i},r)),...o}},c$e=({result:t,fileDescriptors:e,fdNumber:r,state:n,outputFiles:i,isMaxBuffer:o,verboseInfo:s},{buffer:a,encoding:c,lines:l,stripFinalNewline:u,maxBuffer:d})=>{if(t===null)return;let f=wW(t,o,d),p=vo(f),{stdioItems:m,objectMode:h}=e[r],g=l$e([p],m,c,n),{serializedResult:b,finalResult:_=b}=u$e({chunks:g,objectMode:h,encoding:c,lines:l,stripFinalNewline:u,fdNumber:r});d$e({serializedResult:b,fdNumber:r,state:n,verboseInfo:s,encoding:c,stdioItems:m,objectMode:h});let S=a[r]?_:void 0;try{return n.error===void 0&&f$e(b,m,i),S}catch(x){return n.error=x,S}},l$e=(t,e,r,n)=>{try{return fv(t,e,r,!1)}catch(i){return n.error=i,t}},u$e=({chunks:t,objectMode:e,encoding:r,lines:n,stripFinalNewline:i,fdNumber:o})=>{if(e)return{serializedResult:t};if(r==="buffer")return{serializedResult:Qf(t)};let s=fZ(t,r);return n[o]?{serializedResult:s,finalResult:II(s,!i[o],e)}:{serializedResult:s}},d$e=({serializedResult:t,fdNumber:e,state:r,verboseInfo:n,encoding:i,stdioItems:o,objectMode:s})=>{if(!mv({stdioItems:o,encoding:i,verboseInfo:n,fdNumber:e}))return;let a=II(t,!1,s);try{NK(a,e,n)}catch(c){r.error??=c}},f$e=(t,e,r)=>{for(let{path:n,append:i}of e.filter(({type:o})=>ov.has(o))){let o=typeof n=="string"?n:n.toString();i||r.has(o)?a$e(n,t):(r.add(o),s$e(n,t))}}});var LK,zK=y(()=>{an();mp();LK=([,t,e],r)=>{if(r.all)return t===void 0?e:e===void 0?t:Array.isArray(t)?Array.isArray(e)?[...t,...e]:[...t,ko(e,r,"all")]:Array.isArray(e)?[ko(t,r,"all"),...e]:qt(t)&&qt(e)?ER([t,e]):`${t}${e}`}});import{once as FI}from"node:events";var UK,p$e,qK,HK,m$e,LI,zI=y(()=>{Da();UK=async(t,e)=>{let[r,n]=await p$e(t);return e.isForcefullyTerminated??=!1,[r,n]},p$e=async t=>{let[e,r]=await Promise.allSettled([FI(t,"spawn"),FI(t,"exit")]);return e.status==="rejected"?[]:r.status==="rejected"?qK(t):r.value},qK=async t=>{try{return await FI(t,"exit")}catch{return qK(t)}},HK=async t=>{let[e,r]=await t;if(!m$e(e,r)&&LI(e,r))throw new ni;return[e,r]},m$e=(t,e)=>t===void 0&&e===void 0,LI=(t,e)=>t!==0||e!==null});var BK,h$e,GK=y(()=>{Da();La();zI();BK=({error:t,status:e,signal:r,output:n},{maxBuffer:i})=>{let o=h$e(t,e,r),s=o?.code==="ETIMEDOUT",a=SW(o,n,i);return{resultError:o,exitCode:e,signal:r,timedOut:s,isMaxBuffer:a}},h$e=(t,e,r)=>t!==void 0?t:LI(e,r)?new ni:void 0});import{spawnSync as g$e}from"node:child_process";var ZK,y$e,_$e,b$e,hv,v$e,S$e,w$e,x$e,VK=y(()=>{NR();lI();uI();pp();rv();yK();mp();CK();FK();La();zK();GK();ZK=(t,e,r)=>{let{file:n,commandArguments:i,command:o,escapedCommand:s,startTime:a,verboseInfo:c,options:l,fileDescriptors:u}=y$e(t,e,r),d=v$e({file:n,commandArguments:i,options:l,command:o,escapedCommand:s,verboseInfo:c,fileDescriptors:u,startTime:a});return Hl(d,c,l)},y$e=(t,e,r)=>{let{command:n,escapedCommand:i,startTime:o,verboseInfo:s}=gb(t,e,r),a=_$e(r),{file:c,commandArguments:l,options:u}=Hb(t,e,a);b$e(u);let d=hK(u,s);return{file:c,commandArguments:l,command:n,escapedCommand:i,startTime:o,verboseInfo:s,options:u,fileDescriptors:d}},_$e=t=>t.node&&!t.ipc?{...t,ipc:!1}:t,b$e=({ipc:t,ipcInput:e,detached:r,cancelSignal:n})=>{e&&hv("ipcInput"),t&&hv("ipc: true"),r&&hv("detached: true"),n&&hv("cancelSignal")},hv=t=>{throw new TypeError(`The "${t}" option cannot be used with synchronous methods.`)},v$e=({file:t,commandArguments:e,options:r,command:n,escapedCommand:i,verboseInfo:o,fileDescriptors:s,startTime:a})=>{let c=S$e({file:t,commandArguments:e,options:r,command:n,escapedCommand:i,fileDescriptors:s,startTime:a});if(c.failed)return c;let{resultError:l,exitCode:u,signal:d,timedOut:f,isMaxBuffer:p}=BK(c,r),{output:m,error:h=l}=MK({fileDescriptors:s,syncResult:c,options:r,isMaxBuffer:p,verboseInfo:o}),g=m.map((_,S)=>ko(_,r,S)),b=ko(LK(m,r),r,"all");return x$e({error:h,exitCode:u,signal:d,timedOut:f,isMaxBuffer:p,stdio:g,all:b,options:r,command:n,escapedCommand:i,startTime:a})},S$e=({file:t,commandArguments:e,options:r,command:n,escapedCommand:i,fileDescriptors:o,startTime:s})=>{try{PK(o,r);let a=w$e(r);return g$e(...Bb(t,e,a))}catch(a){return ql({error:a,command:n,escapedCommand:i,fileDescriptors:o,options:r,startTime:s,isSync:!0})}},w$e=({encoding:t,maxBuffer:e,...r})=>({...r,encoding:"buffer",maxBuffer:ev(e)}),x$e=({error:t,exitCode:e,signal:r,timedOut:n,isMaxBuffer:i,stdio:o,all:s,options:a,command:c,escapedCommand:l,startTime:u})=>t===void 0?tv({command:c,escapedCommand:l,stdio:o,all:s,ipcOutput:[],options:a,startTime:u}):fp({error:t,command:c,escapedCommand:l,timedOut:n,isCanceled:!1,isGracefullyCanceled:!1,isMaxBuffer:i,isForcefullyTerminated:!1,exitCode:e,signal:r,stdio:o,all:s,ipcOutput:[],options:a,startTime:u,isSync:!0})});import{once as UI,on as $$e}from"node:events";var WK,k$e,E$e,A$e,O$e,KK=y(()=>{Ml();ap();sp();WK=({anyProcess:t,channel:e,isSubprocess:r,ipc:n},{reference:i=!0,filter:o}={})=>(Nl({methodName:"getOneMessage",isSubprocess:r,ipc:n,isConnected:jb(t)}),k$e({anyProcess:t,channel:e,isSubprocess:r,filter:o,reference:i})),k$e=async({anyProcess:t,channel:e,isSubprocess:r,filter:n,reference:i})=>{Tb(e,i);let o=gs(t,e,r),s=new AbortController;try{return await Promise.race([E$e(o,n,s),A$e(o,r,s),O$e(o,r,s)])}catch(a){throw jl(t),a}finally{s.abort(),Rb(e,i)}},E$e=async(t,e,{signal:r})=>{if(e===void 0){let[n]=await UI(t,"message",{signal:r});return n}for await(let[n]of $$e(t,"message",{signal:r}))if(e(n))return n},A$e=async(t,e,{signal:r})=>{await UI(t,"disconnect",{signal:r}),s9(e)},O$e=async(t,e,{signal:r})=>{let[n]=await UI(t,"strict:error",{signal:r});throw kb(n,e)}});import{once as YK,on as T$e}from"node:events";var XK,qI,R$e,I$e,P$e,JK,HI=y(()=>{Ml();ap();sp();XK=({anyProcess:t,channel:e,isSubprocess:r,ipc:n},{reference:i=!0}={})=>qI({anyProcess:t,channel:e,isSubprocess:r,ipc:n,shouldAwait:!r,reference:i}),qI=({anyProcess:t,channel:e,isSubprocess:r,ipc:n,shouldAwait:i,reference:o})=>{Nl({methodName:"getEachMessage",isSubprocess:r,ipc:n,isConnected:jb(t)}),Tb(e,o);let s=gs(t,e,r),a=new AbortController,c={};return R$e(t,s,a),I$e({ipcEmitter:s,isSubprocess:r,controller:a,state:c}),P$e({anyProcess:t,channel:e,ipcEmitter:s,isSubprocess:r,shouldAwait:i,controller:a,state:c,reference:o})},R$e=async(t,e,r)=>{try{await YK(e,"disconnect",{signal:r.signal}),r.abort()}catch{}},I$e=async({ipcEmitter:t,isSubprocess:e,controller:r,state:n})=>{try{let[i]=await YK(t,"strict:error",{signal:r.signal});n.error=kb(i,e),r.abort()}catch{}},P$e=async function*({anyProcess:t,channel:e,ipcEmitter:r,isSubprocess:n,shouldAwait:i,controller:o,state:s,reference:a}){try{for await(let[c]of T$e(r,"message",{signal:o.signal}))JK(s),yield c}catch{JK(s)}finally{o.abort(),Rb(e,a),n||jl(t),i&&await t}},JK=({error:t})=>{if(t)throw t}});import QK from"node:process";var e3,t3,r3,BI=y(()=>{Ub();KK();HI();Db();e3=(t,{ipc:e})=>{Object.assign(t,r3(t,!1,e))},t3=()=>{let t=QK,e=!0,r=QK.channel!==void 0;return{...r3(t,e,r),getCancelSignal:D9.bind(void 0,{anyProcess:t,channel:t.channel,isSubprocess:e,ipc:r})}},r3=(t,e,r)=>({sendMessage:zb.bind(void 0,{anyProcess:t,channel:t.channel,isSubprocess:e,ipc:r}),getOneMessage:WK.bind(void 0,{anyProcess:t,channel:t.channel,isSubprocess:e,ipc:r}),getEachMessage:XK.bind(void 0,{anyProcess:t,channel:t.channel,isSubprocess:e,ipc:r})})});import{ChildProcess as C$e}from"node:child_process";import{PassThrough as D$e,Readable as N$e,Writable as j$e,Duplex as M$e}from"node:stream";var n3,F$e,gp,L$e,z$e,U$e,q$e,i3=y(()=>{av();pp();rv();n3=({error:t,command:e,escapedCommand:r,fileDescriptors:n,options:i,startTime:o,verboseInfo:s})=>{OI(n);let a=new C$e;F$e(a,n),Object.assign(a,{readable:L$e,writable:z$e,duplex:U$e});let c=ql({error:t,command:e,escapedCommand:r,fileDescriptors:n,options:i,startTime:o,isSync:!1}),l=q$e(c,s,i);return{subprocess:a,promise:l}},F$e=(t,e)=>{let r=gp(),n=gp(),i=gp(),o=Array.from({length:e.length-3},gp),s=gp(),a=[r,n,i,...o];Object.assign(t,{stdin:r,stdout:n,stderr:i,all:s,stdio:a})},gp=()=>{let t=new D$e;return t.end(),t},L$e=()=>new N$e({read(){}}),z$e=()=>new j$e({write(){}}),U$e=()=>new M$e({read(){},write(){}}),q$e=async(t,e,r)=>Hl(t,e,r)});import{createReadStream as o3,createWriteStream as s3}from"node:fs";import{Buffer as H$e}from"node:buffer";import{Readable as yp,Writable as B$e,Duplex as G$e}from"node:stream";var c3,_p,a3,Z$e,l3=y(()=>{pv();av();$r();c3=(t,e)=>sv(Z$e,t,e,!1),_p=({type:t,optionName:e})=>{throw new TypeError(`The \`${e}\` option cannot be ${ys[t]}.`)},a3={fileNumber:_p,generator:jI,asyncGenerator:jI,nodeStream:({value:t})=>({stream:t}),webTransform({value:{transform:t,writableObjectMode:e,readableObjectMode:r}}){let n=e||r;return{stream:G$e.fromWeb(t,{objectMode:n})}},duplex:({value:{transform:t}})=>({stream:t}),native(){}},Z$e={input:{...a3,fileUrl:({value:t})=>({stream:o3(t)}),filePath:({value:{file:t}})=>({stream:o3(t)}),webStream:({value:t})=>({stream:yp.fromWeb(t)}),iterable:({value:t})=>({stream:yp.from(t)}),asyncIterable:({value:t})=>({stream:yp.from(t)}),string:({value:t})=>({stream:yp.from(t)}),uint8Array:({value:t})=>({stream:yp.from(H$e.from(t))})},output:{...a3,fileUrl:({value:t})=>({stream:s3(t)}),filePath:({value:{file:t,append:e}})=>({stream:s3(t,e?{flags:"a"}:{})}),webStream:({value:t})=>({stream:B$e.fromWeb(t)}),iterable:_p,asyncIterable:_p,string:_p,uint8Array:_p}}});import{on as V$e,once as u3}from"node:events";import{PassThrough as W$e,getDefaultHighWaterMark as K$e}from"node:stream";import{finished as p3}from"node:stream/promises";function qa(t){if(!Array.isArray(t))throw new TypeError(`Expected an array, got \`${typeof t}\`.`);for(let i of t)ZI(i);let e=t.some(({readableObjectMode:i})=>i),r=J$e(t,e),n=new GI({objectMode:e,writableHighWaterMark:r,readableHighWaterMark:r});for(let i of t)n.add(i);return n}var J$e,GI,Y$e,X$e,Q$e,ZI,eke,tke,rke,nke,ike,m3,h3,VI,g3,oke,gv,d3,f3,yv=y(()=>{J$e=(t,e)=>{if(t.length===0)return K$e(e);let r=t.filter(({readableObjectMode:n})=>n===e).map(({readableHighWaterMark:n})=>n);return Math.max(...r)},GI=class extends W$e{#t=new Set([]);#r=new Set([]);#e=new Set([]);#n;#o=Symbol("unpipe");#i=new WeakMap;add(e){if(ZI(e),this.#t.has(e))return;this.#t.add(e),this.#n??=Y$e(this,this.#t,this.#o);let r=eke({passThroughStream:this,stream:e,streams:this.#t,ended:this.#r,aborted:this.#e,onFinished:this.#n,unpipeEvent:this.#o});this.#i.set(e,r),e.pipe(this,{end:!1})}async remove(e){if(ZI(e),!this.#t.has(e))return!1;let r=this.#i.get(e);return r===void 0?!1:(this.#i.delete(e),e.unpipe(this),await r,!0)}},Y$e=async(t,e,r)=>{gv(t,d3);let n=new AbortController;try{await Promise.race([X$e(t,n),Q$e(t,e,r,n)])}finally{n.abort(),gv(t,-d3)}},X$e=async(t,{signal:e})=>{try{await p3(t,{signal:e,cleanup:!0})}catch(r){throw m3(t,r),r}},Q$e=async(t,e,r,{signal:n})=>{for await(let[i]of V$e(t,"unpipe",{signal:n}))e.has(i)&&i.emit(r)},ZI=t=>{if(typeof t?.pipe!="function")throw new TypeError(`Expected a readable stream, got: \`${typeof t}\`.`)},eke=async({passThroughStream:t,stream:e,streams:r,ended:n,aborted:i,onFinished:o,unpipeEvent:s})=>{gv(t,f3);let a=new AbortController;try{await Promise.race([tke(o,e,a),rke({passThroughStream:t,stream:e,streams:r,ended:n,aborted:i,controller:a}),nke({stream:e,streams:r,ended:n,aborted:i,unpipeEvent:s,controller:a})])}finally{a.abort(),gv(t,-f3)}r.size>0&&r.size===n.size+i.size&&(n.size===0&&i.size>0?VI(t):ike(t))},tke=async(t,e,{signal:r})=>{try{await t,r.aborted||VI(e)}catch(n){r.aborted||m3(e,n)}},rke=async({passThroughStream:t,stream:e,streams:r,ended:n,aborted:i,controller:{signal:o}})=>{try{await p3(e,{signal:o,cleanup:!0,readable:!0,writable:!1}),r.has(e)&&n.add(e)}catch(s){if(o.aborted||!r.has(e))return;h3(s)?i.add(e):g3(t,s)}},nke=async({stream:t,streams:e,ended:r,aborted:n,unpipeEvent:i,controller:{signal:o}})=>{if(await u3(t,i,{signal:o}),!t.readable)return u3(o,"abort",{signal:o});e.delete(t),r.delete(t),n.delete(t)},ike=t=>{t.writable&&t.end()},m3=(t,e)=>{h3(e)?VI(t):g3(t,e)},h3=t=>t?.code==="ERR_STREAM_PREMATURE_CLOSE",VI=t=>{(t.readable||t.writable)&&t.destroy()},g3=(t,e)=>{t.destroyed||(t.once("error",oke),t.destroy(e))},oke=()=>{},gv=(t,e)=>{let r=t.getMaxListeners();r!==0&&r!==Number.POSITIVE_INFINITY&&t.setMaxListeners(r+e)},d3=2,f3=1});import{finished as y3}from"node:stream/promises";var Gl,ske,WI,ake,KI,_v=y(()=>{So();Gl=(t,e)=>{t.pipe(e),ske(t,e),ake(t,e)},ske=async(t,e)=>{if(!(ri(t)||ri(e))){try{await y3(t,{cleanup:!0,readable:!0,writable:!1})}catch{}WI(e)}},WI=t=>{t.writable&&t.end()},ake=async(t,e)=>{if(!(ri(t)||ri(e))){try{await y3(e,{cleanup:!0,readable:!1,writable:!0})}catch{}KI(t)}},KI=t=>{t.readable&&t.destroy()}});var _3,cke,lke,uke,dke,fke,b3=y(()=>{yv();So();Ob();$r();_v();_3=(t,e,r)=>{let n=new Map;for(let[i,{stdioItems:o,direction:s}]of Object.entries(e)){for(let{stream:a}of o.filter(({type:c})=>Cn.has(c)))cke(t,a,s,i);for(let{stream:a}of o.filter(({type:c})=>!Cn.has(c)))uke({subprocess:t,stream:a,direction:s,fdNumber:i,pipeGroups:n,controller:r})}for(let[i,o]of n.entries()){let s=o.length===1?o[0]:qa(o);Gl(s,i)}},cke=(t,e,r,n)=>{r==="output"?Gl(t.stdio[n],e):Gl(e,t.stdio[n]);let i=lke[n];i!==void 0&&(t[i]=e),t.stdio[n]=e},lke=["stdin","stdout","stderr"],uke=({subprocess:t,stream:e,direction:r,fdNumber:n,pipeGroups:i,controller:o})=>{if(e===void 0)return;dke(e,o);let[s,a]=r==="output"?[e,t.stdio[n]]:[t.stdio[n],e],c=i.get(s)??[];i.set(s,[...c,a])},dke=(t,{signal:e})=>{ri(t)&&Na(t,fke,e)},fke=2});var Ha,v3=y(()=>{Ha=[];Ha.push("SIGHUP","SIGINT","SIGTERM");process.platform!=="win32"&&Ha.push("SIGALRM","SIGABRT","SIGVTALRM","SIGXCPU","SIGXFSZ","SIGUSR2","SIGTRAP","SIGSYS","SIGQUIT","SIGIOT");process.platform==="linux"&&Ha.push("SIGIO","SIGPOLL","SIGPWR","SIGSTKFLT")});var bv,JI,YI,pke,XI,vv,mke,QI,eP,tP,S3,plt,mlt,w3=y(()=>{v3();bv=t=>!!t&&typeof t=="object"&&typeof t.removeListener=="function"&&typeof t.emit=="function"&&typeof t.reallyExit=="function"&&typeof t.listeners=="function"&&typeof t.kill=="function"&&typeof t.pid=="number"&&typeof t.on=="function",JI=Symbol.for("signal-exit emitter"),YI=globalThis,pke=Object.defineProperty.bind(Object),XI=class{emitted={afterExit:!1,exit:!1};listeners={afterExit:[],exit:[]};count=0;id=Math.random();constructor(){if(YI[JI])return YI[JI];pke(YI,JI,{value:this,writable:!1,enumerable:!1,configurable:!1})}on(e,r){this.listeners[e].push(r)}removeListener(e,r){let n=this.listeners[e],i=n.indexOf(r);i!==-1&&(i===0&&n.length===1?n.length=0:n.splice(i,1))}emit(e,r,n){if(this.emitted[e])return!1;this.emitted[e]=!0;let i=!1;for(let o of this.listeners[e])i=o(r,n)===!0||i;return e==="exit"&&(i=this.emit("afterExit",r,n)||i),i}},vv=class{},mke=t=>({onExit(e,r){return t.onExit(e,r)},load(){return t.load()},unload(){return t.unload()}}),QI=class extends vv{onExit(){return()=>{}}load(){}unload(){}},eP=class extends vv{#t=tP.platform==="win32"?"SIGINT":"SIGHUP";#r=new XI;#e;#n;#o;#i={};#s=!1;constructor(e){super(),this.#e=e,this.#i={};for(let r of Ha)this.#i[r]=()=>{let n=this.#e.listeners(r),{count:i}=this.#r,o=e;if(typeof o.__signal_exit_emitter__=="object"&&typeof o.__signal_exit_emitter__.count=="number"&&(i+=o.__signal_exit_emitter__.count),n.length===i){this.unload();let s=this.#r.emit("exit",null,r),a=r==="SIGHUP"?this.#t:r;s||e.kill(e.pid,a)}};this.#o=e.reallyExit,this.#n=e.emit}onExit(e,r){if(!bv(this.#e))return()=>{};this.#s===!1&&this.load();let n=r?.alwaysLast?"afterExit":"exit";return this.#r.on(n,e),()=>{this.#r.removeListener(n,e),this.#r.listeners.exit.length===0&&this.#r.listeners.afterExit.length===0&&this.unload()}}load(){if(!this.#s){this.#s=!0,this.#r.count+=1;for(let e of Ha)try{let r=this.#i[e];r&&this.#e.on(e,r)}catch{}this.#e.emit=(e,...r)=>this.#c(e,...r),this.#e.reallyExit=e=>this.#a(e)}}unload(){this.#s&&(this.#s=!1,Ha.forEach(e=>{let r=this.#i[e];if(!r)throw new Error("Listener not defined for signal: "+e);try{this.#e.removeListener(e,r)}catch{}}),this.#e.emit=this.#n,this.#e.reallyExit=this.#o,this.#r.count-=1)}#a(e){return bv(this.#e)?(this.#e.exitCode=e||0,this.#r.emit("exit",this.#e.exitCode,null),this.#o.call(this.#e,this.#e.exitCode)):0}#c(e,...r){let n=this.#n;if(e==="exit"&&bv(this.#e)){typeof r[0]=="number"&&(this.#e.exitCode=r[0]);let i=n.call(this.#e,e,...r);return this.#r.emit("exit",this.#e.exitCode,null),i}else return n.call(this.#e,e,...r)}},tP=globalThis.process,{onExit:S3,load:plt,unload:mlt}=mke(bv(tP)?new eP(tP):new QI)});import{addAbortListener as hke}from"node:events";var x3,$3=y(()=>{w3();x3=(t,{cleanup:e,detached:r},{signal:n})=>{if(!e||r)return;let i=S3(()=>{t.kill()});hke(n,()=>{i()})}});var E3,gke,yke,k3,_ke,A3=y(()=>{kR();hb();hs();Tl();E3=({source:t,sourcePromise:e,boundOptions:r,createNested:n},...i)=>{let o=mb(),{destination:s,destinationStream:a,destinationError:c,from:l,unpipeSignal:u}=gke(r,n,i),{sourceStream:d,sourceError:f}=_ke(t,l),{options:p,fileDescriptors:m}=Ni.get(t);return{sourcePromise:e,sourceStream:d,sourceOptions:p,sourceError:f,destination:s,destinationStream:a,destinationError:c,unpipeSignal:u,fileDescriptors:m,startTime:o}},gke=(t,e,r)=>{try{let{destination:n,pipeOptions:{from:i,to:o,unpipeSignal:s}={}}=yke(t,e,...r),a=Ab(n,o);return{destination:n,destinationStream:a,from:i,unpipeSignal:s}}catch(n){return{destinationError:n}}},yke=(t,e,r,...n)=>{if(Array.isArray(r))return{destination:e(k3,t)(r,...n),pipeOptions:t};if(typeof r=="string"||r instanceof URL||xR(r)){if(Object.keys(t).length>0)throw new TypeError('Please use .pipe("file", ..., options) or .pipe(execa("file", ..., options)) instead of .pipe(options)("file", ...).');let[i,o,s]=nb(r,...n);return{destination:e(k3)(i,o,s),pipeOptions:s}}if(Ni.has(r)){if(Object.keys(t).length>0)throw new TypeError("Please use .pipe(options)`command` or .pipe($(options)`command`) instead of .pipe(options)($`command`).");return{destination:r,pipeOptions:n[0]}}throw new TypeError(`The first argument must be a template string, an options object, or an Execa subprocess: ${r}`)},k3=({options:t})=>({options:{...t,stdin:"pipe",piped:!0}}),_ke=(t,e)=>{try{return{sourceStream:Ll(t,e)}}catch(r){return{sourceError:r}}}});var T3,bke,rP,O3,nP=y(()=>{pp();_v();T3=({sourceStream:t,sourceError:e,destinationStream:r,destinationError:n,fileDescriptors:i,sourceOptions:o,startTime:s})=>{let a=bke({sourceStream:t,sourceError:e,destinationStream:r,destinationError:n});if(a!==void 0)throw rP({error:a,fileDescriptors:i,sourceOptions:o,startTime:s})},bke=({sourceStream:t,sourceError:e,destinationStream:r,destinationError:n})=>{if(e!==void 0&&n!==void 0)return n;if(n!==void 0)return KI(t),n;if(e!==void 0)return WI(r),e},rP=({error:t,fileDescriptors:e,sourceOptions:r,startTime:n})=>ql({error:t,command:O3,escapedCommand:O3,fileDescriptors:e,options:r,startTime:n,isSync:!1}),O3="source.pipe(destination)"});var R3,I3=y(()=>{R3=async t=>{let[{status:e,reason:r,value:n=r},{status:i,reason:o,value:s=o}]=await t;if(s.pipedFrom.includes(n)||s.pipedFrom.push(n),i==="rejected")throw s;if(e==="rejected")throw n;return s}});import{finished as vke}from"node:stream/promises";var P3,Ske,wke,xke,Sv,$ke,kke,C3=y(()=>{yv();Ob();_v();P3=(t,e,r)=>{let n=Sv.has(e)?wke(t,e):Ske(t,e);return Na(t,$ke,r.signal),Na(e,kke,r.signal),xke(e),n},Ske=(t,e)=>{let r=qa([t]);return Gl(r,e),Sv.set(e,r),r},wke=(t,e)=>{let r=Sv.get(e);return r.add(t),r},xke=async t=>{try{await vke(t,{cleanup:!0,readable:!1,writable:!0})}catch{}Sv.delete(t)},Sv=new WeakMap,$ke=2,kke=1});import{aborted as Eke}from"node:util";var D3,Ake,N3=y(()=>{nP();D3=(t,e)=>t===void 0?[]:[Ake(t,e)],Ake=async(t,{sourceStream:e,mergedStream:r,fileDescriptors:n,sourceOptions:i,startTime:o})=>{await Eke(t,e),await r.remove(e);let s=new Error("Pipe canceled by `unpipeSignal` option.");throw rP({error:s,fileDescriptors:n,sourceOptions:i,startTime:o})}});var wv,Oke,Tke,j3=y(()=>{bo();A3();nP();I3();C3();N3();wv=(t,...e)=>{if(Tt(e[0]))return wv.bind(void 0,{...t,boundOptions:{...t.boundOptions,...e[0]}});let{destination:r,...n}=E3(t,...e),i=Oke({...n,destination:r});return i.pipe=wv.bind(void 0,{...t,source:r,sourcePromise:i,boundOptions:{}}),i},Oke=async({sourcePromise:t,sourceStream:e,sourceOptions:r,sourceError:n,destination:i,destinationStream:o,destinationError:s,unpipeSignal:a,fileDescriptors:c,startTime:l})=>{let u=Tke(t,i);T3({sourceStream:e,sourceError:n,destinationStream:o,destinationError:s,fileDescriptors:c,sourceOptions:r,startTime:l});let d=new AbortController;try{let f=P3(e,o,d);return await Promise.race([R3(u),...D3(a,{sourceStream:e,mergedStream:f,sourceOptions:r,fileDescriptors:c,startTime:l})])}finally{d.abort()}},Tke=(t,e)=>Promise.allSettled([t,e])});import{on as Rke}from"node:events";import{getDefaultHighWaterMark as Ike}from"node:stream";var xv,Pke,iP,Cke,F3,oP,M3,Dke,Nke,$v=y(()=>{PI();lv();NI();xv=({subprocessStdout:t,subprocess:e,binary:r,shouldEncode:n,encoding:i,preserveNewlines:o})=>{let s=new AbortController;return Pke(e,s),F3({stream:t,controller:s,binary:r,shouldEncode:!t.readableObjectMode&&n,encoding:i,shouldSplit:!t.readableObjectMode,preserveNewlines:o})},Pke=async(t,e)=>{try{await t}catch{}finally{e.abort()}},iP=({stream:t,onStreamEnd:e,lines:r,encoding:n,stripFinalNewline:i,allMixed:o})=>{let s=new AbortController;Cke(e,s,t);let a=t.readableObjectMode&&!o;return F3({stream:t,controller:s,binary:n==="buffer",shouldEncode:!a,encoding:n,shouldSplit:!a&&r,preserveNewlines:!i})},Cke=async(t,e,r)=>{try{await t}catch{r.destroy()}finally{e.abort()}},F3=({stream:t,controller:e,binary:r,shouldEncode:n,encoding:i,shouldSplit:o,preserveNewlines:s})=>{let a=Rke(t,"data",{signal:e.signal,highWaterMark:M3,highWatermark:M3});return Dke({onStdoutChunk:a,controller:e,binary:r,shouldEncode:n,encoding:i,shouldSplit:o,preserveNewlines:s})},oP=Ike(!0),M3=oP,Dke=async function*({onStdoutChunk:t,controller:e,binary:r,shouldEncode:n,encoding:i,shouldSplit:o,preserveNewlines:s}){let a=Nke({binary:r,shouldEncode:n,encoding:i,shouldSplit:o,preserveNewlines:s});try{for await(let[c]of t)yield*Ua(c,a,0)}catch(c){if(!e.signal.aborted)throw c}finally{yield*hp(a)}},Nke=({binary:t,shouldEncode:e,encoding:r,shouldSplit:n,preserveNewlines:i})=>[uv(t,r,!e),cv(t,i,!n,{})].filter(Boolean)});import{setImmediate as jke}from"node:timers/promises";var L3,Mke,Fke,Lke,sP,z3,aP=y(()=>{Qb();an();MI();$v();La();mp();L3=async({stream:t,onStreamEnd:e,fdNumber:r,encoding:n,buffer:i,maxBuffer:o,lines:s,allMixed:a,stripFinalNewline:c,verboseInfo:l,streamInfo:u})=>{let d=Mke({stream:t,onStreamEnd:e,fdNumber:r,encoding:n,allMixed:a,verboseInfo:l,streamInfo:u});if(!i){await Promise.all([Fke(t),d]);return}let f=TI(c,r),p=iP({stream:t,onStreamEnd:e,lines:s,encoding:n,stripFinalNewline:f,allMixed:a}),[m]=await Promise.all([Lke({stream:t,iterable:p,fdNumber:r,encoding:n,maxBuffer:o,lines:s}),d]);return m},Mke=async({stream:t,onStreamEnd:e,fdNumber:r,encoding:n,allMixed:i,verboseInfo:o,streamInfo:{fileDescriptors:s}})=>{if(!mv({stdioItems:s[r]?.stdioItems,encoding:n,verboseInfo:o,fdNumber:r}))return;let a=iP({stream:t,onStreamEnd:e,lines:!0,encoding:n,stripFinalNewline:!0,allMixed:i});await DK(a,t,r,o)},Fke=async t=>{await jke(),t.readableFlowing===null&&t.resume()},Lke=async({stream:t,stream:{readableObjectMode:e},iterable:r,fdNumber:n,encoding:i,maxBuffer:o,lines:s})=>{try{return e||s?await Kb(r,{maxBuffer:o}):i==="buffer"?new Uint8Array(await Jb(r,{maxBuffer:o})):await Xb(r,{maxBuffer:o})}catch(a){return z3(_W({error:a,stream:t,readableObjectMode:e,lines:s,encoding:i,fdNumber:n}))}},sP=async t=>{try{return await t}catch(e){return z3(e)}},z3=({bufferedData:t})=>uZ(t)?new Uint8Array(t):t});import{finished as zke}from"node:stream/promises";var bp,Uke,qke,Hke,Bke,Gke,cP,kv,U3,Ev=y(()=>{bp=async(t,e,r,{isSameDirection:n,stopOnExit:i=!1}={})=>{let o=Uke(t,r),s=new AbortController;try{await Promise.race([...i?[r.exitPromise]:[],zke(t,{cleanup:!0,signal:s.signal})])}catch(a){o.stdinCleanedUp||Bke(a,e,r,n)}finally{s.abort()}},Uke=(t,{originalStreams:[e],subprocess:r})=>{let n={stdinCleanedUp:!1};return t===e&&qke(t,r,n),n},qke=(t,e,r)=>{let{_destroy:n}=t;t._destroy=(...i)=>{Hke(e,r),n.call(t,...i)}},Hke=({exitCode:t,signalCode:e},r)=>{(t!==null||e!==null)&&(r.stdinCleanedUp=!0)},Bke=(t,e,r,n)=>{if(!Gke(t,e,r,n))throw t},Gke=(t,e,r,n=!0)=>r.propagating?U3(t)||kv(t):(r.propagating=!0,cP(r,e)===n?U3(t):kv(t)),cP=({fileDescriptors:t},e)=>e!=="all"&&t[e].direction==="input",kv=t=>t?.code==="ERR_STREAM_PREMATURE_CLOSE",U3=t=>t?.code==="EPIPE"});var q3,lP,uP=y(()=>{aP();Ev();q3=({subprocess:t,encoding:e,buffer:r,maxBuffer:n,lines:i,stripFinalNewline:o,verboseInfo:s,streamInfo:a})=>t.stdio.map((c,l)=>lP({stream:c,fdNumber:l,encoding:e,buffer:r[l],maxBuffer:n[l],lines:i[l],allMixed:!1,stripFinalNewline:o,verboseInfo:s,streamInfo:a})),lP=async({stream:t,fdNumber:e,encoding:r,buffer:n,maxBuffer:i,lines:o,allMixed:s,stripFinalNewline:a,verboseInfo:c,streamInfo:l})=>{if(!t)return;let u=bp(t,e,l);if(cP(l,e)){await u;return}let[d]=await Promise.all([L3({stream:t,onStreamEnd:u,fdNumber:e,encoding:r,buffer:n,maxBuffer:i,lines:o,allMixed:s,stripFinalNewline:a,verboseInfo:c,streamInfo:l}),u]);return d}});var H3,B3,Zke,Vke,dP=y(()=>{yv();uP();H3=({stdout:t,stderr:e},{all:r})=>r&&(t||e)?qa([t,e].filter(Boolean)):void 0,B3=({subprocess:t,encoding:e,buffer:r,maxBuffer:n,lines:i,stripFinalNewline:o,verboseInfo:s,streamInfo:a})=>lP({...Zke(t,r),fdNumber:"all",encoding:e,maxBuffer:n[1]+n[2],lines:i[1]||i[2],allMixed:Vke(t),stripFinalNewline:o,verboseInfo:s,streamInfo:a}),Zke=({stdout:t,stderr:e,all:r},[,n,i])=>{let o=n||i;return o?n?i?{stream:r,buffer:o}:{stream:t,buffer:o}:{stream:e,buffer:o}:{stream:r,buffer:o}},Vke=({all:t,stdout:e,stderr:r})=>t&&e&&r&&e.readableObjectMode!==r.readableObjectMode});var G3,Z3,V3=y(()=>{Pl();ps();G3=t=>Il(t,"ipc"),Z3=(t,e)=>{let r=pb(t);Ci({type:"ipc",verboseMessage:r,fdNumber:"ipc",verboseInfo:e})}});var W3,K3,J3=y(()=>{La();V3();xo();HI();W3=async({subprocess:t,buffer:e,maxBuffer:r,ipc:n,ipcOutput:i,verboseInfo:o})=>{if(!n)return i;let s=G3(o),a=wo(e,"ipc"),c=wo(r,"ipc");for await(let l of qI({anyProcess:t,channel:t.channel,isSubprocess:!1,ipc:n,shouldAwait:!1,reference:!0}))a&&(bW(t,i,c),i.push(l)),s&&Z3(l,o);return i},K3=async(t,e)=>(await Promise.allSettled([t]),e)});import{once as Wke}from"node:events";var Y3,Kke,Jke,Yke,X3=y(()=>{Fa();iI();KR();nI();So();$r();aP();J3();sI();dP();uP();zI();Ev();Y3=async({subprocess:t,options:{encoding:e,buffer:r,maxBuffer:n,lines:i,timeoutDuration:o,cancelSignal:s,gracefulCancel:a,forceKillAfterDelay:c,stripFinalNewline:l,ipc:u,ipcInput:d},context:f,verboseInfo:p,fileDescriptors:m,originalStreams:h,onInternalError:g,controller:b})=>{let _=UK(t,f),S={originalStreams:h,fileDescriptors:m,subprocess:t,exitPromise:_,propagating:!1},x=q3({subprocess:t,encoding:e,buffer:r,maxBuffer:n,lines:i,stripFinalNewline:l,verboseInfo:p,streamInfo:S}),w=B3({subprocess:t,encoding:e,buffer:r,maxBuffer:n,lines:i,stripFinalNewline:l,verboseInfo:p,streamInfo:S}),R=[],A=W3({subprocess:t,buffer:r,maxBuffer:n,ipc:u,ipcOutput:R,verboseInfo:p}),O=Kke(h,t,S),D=Jke(m,S);try{return await Promise.race([Promise.all([{},HK(_),Promise.all(x),w,A,B9(t,d),...O,...D]),g,Yke(t,b),...L9(t,o,f,b),...o9({subprocess:t,cancelSignal:s,gracefulCancel:a,context:f,controller:b}),...M9({subprocess:t,cancelSignal:s,gracefulCancel:a,forceKillAfterDelay:c,context:f,controller:b})])}catch(E){return f.terminationReason??="other",Promise.all([{error:E},_,Promise.all(x.map(ae=>sP(ae))),sP(w),K3(A,R),Promise.allSettled(O),Promise.allSettled(D)])}},Kke=(t,e,r)=>t.map((n,i)=>n===e.stdio[i]?void 0:bp(n,i,r)),Jke=(t,e)=>t.flatMap(({stdioItems:r},n)=>r.filter(({value:i,stream:o=i})=>oi(o,{checkOpen:!1})&&!ri(o)).map(({type:i,value:o,stream:s=o})=>bp(s,n,e,{isSameDirection:Cn.has(i),stopOnExit:i==="native"}))),Yke=async(t,{signal:e})=>{let[r]=await Wke(t,"error",{signal:e});throw r}});var Q3,vp,Zl,Av=y(()=>{Fl();Q3=()=>({readableDestroy:new WeakMap,writableFinal:new WeakMap,writableDestroy:new WeakMap}),vp=(t,e,r)=>{let n=t[r];n.has(e)||n.set(e,[]);let i=n.get(e),o=Di();return i.push(o),{resolve:o.resolve.bind(o),promises:i}},Zl=async({resolve:t,promises:e},r)=>{t();let[n]=await Promise.race([Promise.allSettled([!0,r]),Promise.all([!1,...e])]);return!n}});import{finished as eJ}from"node:stream/promises";var fP,tJ,pP,mP,Ov,Tv,hP=y(()=>{Ev();fP=async t=>{if(t!==void 0)try{await pP(t)}catch{}},tJ=async t=>{if(t!==void 0)try{await mP(t)}catch{}},pP=async t=>{await eJ(t,{cleanup:!0,readable:!1,writable:!0})},mP=async t=>{await eJ(t,{cleanup:!0,readable:!0,writable:!1})},Ov=async(t,e)=>{if(await t,e)throw e},Tv=(t,e,r)=>{r&&!kv(r)?t.destroy(r):e&&t.destroy()}});import{Readable as Xke}from"node:stream";import{callbackify as Qke}from"node:util";var rJ,gP,yP,_P,eEe,bP,vP,nJ,SP=y(()=>{ja();hs();$v();Fl();Av();hP();rJ=({subprocess:t,concurrentStreams:e,encoding:r},{from:n,binary:i=!0,preserveNewlines:o=!0}={})=>{let s=i||cn.has(r),{subprocessStdout:a,waitReadableDestroy:c}=gP(t,n,e),{readableEncoding:l,readableObjectMode:u,readableHighWaterMark:d}=yP(a,s),{read:f,onStdoutDataDone:p}=_P({subprocessStdout:a,subprocess:t,binary:s,encoding:r,preserveNewlines:o}),m=new Xke({read:f,destroy:Qke(vP.bind(void 0,{subprocessStdout:a,subprocess:t,waitReadableDestroy:c})),highWaterMark:d,objectMode:u,encoding:l});return bP({subprocessStdout:a,onStdoutDataDone:p,readable:m,subprocess:t}),m},gP=(t,e,r)=>{let n=Ll(t,e),i=vp(r,n,"readableDestroy");return{subprocessStdout:n,waitReadableDestroy:i}},yP=({readableEncoding:t,readableObjectMode:e,readableHighWaterMark:r},n)=>n?{readableEncoding:t,readableObjectMode:e,readableHighWaterMark:r}:{readableEncoding:t,readableObjectMode:!0,readableHighWaterMark:oP},_P=({subprocessStdout:t,subprocess:e,binary:r,encoding:n,preserveNewlines:i})=>{let o=Di(),s=xv({subprocessStdout:t,subprocess:e,binary:r,shouldEncode:!r,encoding:n,preserveNewlines:i});return{read(){eEe(this,s,o)},onStdoutDataDone:o}},eEe=async(t,e,r)=>{try{let{value:n,done:i}=await e.next();i?r.resolve():t.push(n)}catch{}},bP=async({subprocessStdout:t,onStdoutDataDone:e,readable:r,subprocess:n,subprocessStdin:i})=>{try{await mP(t),await n,await fP(i),await e,r.readable&&r.push(null)}catch(o){await fP(i),nJ(r,o)}},vP=async({subprocessStdout:t,subprocess:e,waitReadableDestroy:r},n)=>{await Zl(r,e)&&(nJ(t,n),await Ov(e,n))},nJ=(t,e)=>{Tv(t,t.readable,e)}});import{Writable as tEe}from"node:stream";import{callbackify as iJ}from"node:util";var oJ,wP,xP,rEe,nEe,$P,kP,sJ,EP=y(()=>{hs();Av();hP();oJ=({subprocess:t,concurrentStreams:e},{to:r}={})=>{let{subprocessStdin:n,waitWritableFinal:i,waitWritableDestroy:o}=wP(t,r,e),s=new tEe({...xP(n,t,i),destroy:iJ(kP.bind(void 0,{subprocessStdin:n,subprocess:t,waitWritableFinal:i,waitWritableDestroy:o})),highWaterMark:n.writableHighWaterMark,objectMode:n.writableObjectMode});return $P(n,s),s},wP=(t,e,r)=>{let n=Ab(t,e),i=vp(r,n,"writableFinal"),o=vp(r,n,"writableDestroy");return{subprocessStdin:n,waitWritableFinal:i,waitWritableDestroy:o}},xP=(t,e,r)=>({write:rEe.bind(void 0,t),final:iJ(nEe.bind(void 0,t,e,r))}),rEe=(t,e,r,n)=>{t.write(e,r)?n():t.once("drain",n)},nEe=async(t,e,r)=>{await Zl(r,e)&&(t.writable&&t.end(),await e)},$P=async(t,e,r)=>{try{await pP(t),e.writable&&e.end()}catch(n){await tJ(r),sJ(e,n)}},kP=async({subprocessStdin:t,subprocess:e,waitWritableFinal:r,waitWritableDestroy:n},i)=>{await Zl(r,e),await Zl(n,e)&&(sJ(t,i),await Ov(e,i))},sJ=(t,e)=>{Tv(t,t.writable,e)}});import{Duplex as iEe}from"node:stream";import{callbackify as oEe}from"node:util";var aJ,sEe,cJ=y(()=>{ja();SP();EP();aJ=({subprocess:t,concurrentStreams:e,encoding:r},{from:n,to:i,binary:o=!0,preserveNewlines:s=!0}={})=>{let a=o||cn.has(r),{subprocessStdout:c,waitReadableDestroy:l}=gP(t,n,e),{subprocessStdin:u,waitWritableFinal:d,waitWritableDestroy:f}=wP(t,i,e),{readableEncoding:p,readableObjectMode:m,readableHighWaterMark:h}=yP(c,a),{read:g,onStdoutDataDone:b}=_P({subprocessStdout:c,subprocess:t,binary:a,encoding:r,preserveNewlines:s}),_=new iEe({read:g,...xP(u,t,d),destroy:oEe(sEe.bind(void 0,{subprocessStdout:c,subprocessStdin:u,subprocess:t,waitReadableDestroy:l,waitWritableFinal:d,waitWritableDestroy:f})),readableHighWaterMark:h,writableHighWaterMark:u.writableHighWaterMark,readableObjectMode:m,writableObjectMode:u.writableObjectMode,encoding:p});return bP({subprocessStdout:c,onStdoutDataDone:b,readable:_,subprocess:t,subprocessStdin:u}),$P(u,_,c),_},sEe=async({subprocessStdout:t,subprocessStdin:e,subprocess:r,waitReadableDestroy:n,waitWritableFinal:i,waitWritableDestroy:o},s)=>{await Promise.all([vP({subprocessStdout:t,subprocess:r,waitReadableDestroy:n},s),kP({subprocessStdin:e,subprocess:r,waitWritableFinal:i,waitWritableDestroy:o},s)])}});var AP,aEe,lJ=y(()=>{ja();hs();$v();AP=(t,e,{from:r,binary:n=!1,preserveNewlines:i=!1}={})=>{let o=n||cn.has(e),s=Ll(t,r),a=xv({subprocessStdout:s,subprocess:t,binary:o,shouldEncode:!0,encoding:e,preserveNewlines:i});return aEe(a,s,t)},aEe=async function*(t,e,r){try{yield*t}finally{e.readable&&e.destroy(),await r}}});var uJ,dJ=y(()=>{Av();SP();EP();cJ();lJ();uJ=(t,{encoding:e})=>{let r=Q3();t.readable=rJ.bind(void 0,{subprocess:t,concurrentStreams:r,encoding:e}),t.writable=oJ.bind(void 0,{subprocess:t,concurrentStreams:r}),t.duplex=aJ.bind(void 0,{subprocess:t,concurrentStreams:r,encoding:e}),t.iterable=AP.bind(void 0,t,e),t[Symbol.asyncIterator]=AP.bind(void 0,t,e,{})}});var fJ,cEe,lEe,pJ=y(()=>{fJ=(t,e)=>{for(let[r,n]of lEe){let i=n.value.bind(e);Reflect.defineProperty(t,r,{...n,value:i})}},cEe=(async()=>{})().constructor.prototype,lEe=["then","catch","finally"].map(t=>[t,Reflect.getOwnPropertyDescriptor(cEe,t)])});import{setMaxListeners as uEe}from"node:events";import{spawn as dEe}from"node:child_process";var mJ,fEe,pEe,mEe,hEe,gEe,hJ=y(()=>{Qb();NR();lI();hs();uI();BI();pp();rv();i3();l3();mp();b3();xb();$3();j3();dP();X3();dJ();Fl();pJ();mJ=(t,e,r,n)=>{let{file:i,commandArguments:o,command:s,escapedCommand:a,startTime:c,verboseInfo:l,options:u,fileDescriptors:d}=fEe(t,e,r),{subprocess:f,promise:p}=mEe({file:i,commandArguments:o,options:u,startTime:c,verboseInfo:l,command:s,escapedCommand:a,fileDescriptors:d});return f.pipe=wv.bind(void 0,{source:f,sourcePromise:p,boundOptions:{},createNested:n}),fJ(f,p),Ni.set(f,{options:u,fileDescriptors:d}),f},fEe=(t,e,r)=>{let{command:n,escapedCommand:i,startTime:o,verboseInfo:s}=gb(t,e,r),{file:a,commandArguments:c,options:l}=Hb(t,e,r),u=pEe(l),d=c3(u,s);return{file:a,commandArguments:c,command:n,escapedCommand:i,startTime:o,verboseInfo:s,options:u,fileDescriptors:d}},pEe=({timeout:t,signal:e,...r})=>{if(e!==void 0)throw new TypeError('The "signal" option has been renamed to "cancelSignal" instead.');return{...r,timeoutDuration:t}},mEe=({file:t,commandArguments:e,options:r,startTime:n,verboseInfo:i,command:o,escapedCommand:s,fileDescriptors:a})=>{let c;try{c=dEe(...Bb(t,e,r))}catch(m){return n3({error:m,command:o,escapedCommand:s,fileDescriptors:a,options:r,startTime:n,verboseInfo:i})}let l=new AbortController;uEe(Number.POSITIVE_INFINITY,l.signal);let u=[...c.stdio];_3(c,a,l),x3(c,r,l);let d={},f=Di();c.kill=n9.bind(void 0,{kill:c.kill.bind(c),options:r,onInternalError:f,context:d,controller:l}),c.all=H3(c,r),uJ(c,r),e3(c,r);let p=hEe({subprocess:c,options:r,startTime:n,verboseInfo:i,fileDescriptors:a,originalStreams:u,command:o,escapedCommand:s,context:d,onInternalError:f,controller:l});return{subprocess:c,promise:p}},hEe=async({subprocess:t,options:e,startTime:r,verboseInfo:n,fileDescriptors:i,originalStreams:o,command:s,escapedCommand:a,context:c,onInternalError:l,controller:u})=>{let[d,[f,p],m,h,g]=await Y3({subprocess:t,options:e,context:c,verboseInfo:n,fileDescriptors:i,originalStreams:o,onInternalError:l,controller:u});u.abort(),l.resolve();let b=m.map((x,w)=>ko(x,e,w)),_=ko(h,e,"all"),S=gEe({errorInfo:d,exitCode:f,signal:p,stdio:b,all:_,ipcOutput:g,context:c,options:e,command:s,escapedCommand:a,startTime:r});return Hl(S,n,e)},gEe=({errorInfo:t,exitCode:e,signal:r,stdio:n,all:i,ipcOutput:o,context:s,options:a,command:c,escapedCommand:l,startTime:u})=>"error"in t?fp({error:t.error,command:c,escapedCommand:l,timedOut:s.terminationReason==="timeout",isCanceled:s.terminationReason==="cancel"||s.terminationReason==="gracefulCancel",isGracefullyCanceled:s.terminationReason==="gracefulCancel",isMaxBuffer:t.error instanceof ji,isForcefullyTerminated:s.isForcefullyTerminated,exitCode:e,signal:r,stdio:n,all:i,ipcOutput:o,options:a,startTime:u,isSync:!1}):tv({command:c,escapedCommand:l,stdio:n,all:i,ipcOutput:o,options:a,startTime:u})});var Rv,yEe,_Ee,gJ=y(()=>{bo();xo();Rv=(t,e)=>{let r=Object.fromEntries(Object.entries(e).map(([n,i])=>[n,yEe(n,t[n],i)]));return{...t,...r}},yEe=(t,e,r)=>_Ee.has(t)&&Tt(e)&&Tt(r)?{...e,...r}:r,_Ee=new Set(["env",...RR])});var _s,bEe,vEe,yJ=y(()=>{bo();kR();_Z();VK();hJ();gJ();_s=(t,e,r,n)=>{let i=(s,a,c)=>_s(s,a,r,c),o=(...s)=>bEe({mapArguments:t,deepOptions:r,boundOptions:e,setBoundExeca:n,createNested:i},...s);return n!==void 0&&n(o,i,e),o},bEe=({mapArguments:t,deepOptions:e={},boundOptions:r={},setBoundExeca:n,createNested:i},o,...s)=>{if(Tt(o))return i(t,Rv(r,o),n);let{file:a,commandArguments:c,options:l,isSync:u}=vEe({mapArguments:t,firstArgument:o,nextArguments:s,deepOptions:e,boundOptions:r});return u?ZK(a,c,l):mJ(a,c,l,i)},vEe=({mapArguments:t,firstArgument:e,nextArguments:r,deepOptions:n,boundOptions:i})=>{let o=gZ(e)?yZ(e,r):[e,...r],[s,a,c]=nb(...o),l=Rv(Rv(n,i),c),{file:u=s,commandArguments:d=a,options:f=l,isSync:p=!1}=t({file:s,commandArguments:a,options:l});return{file:u,commandArguments:d,options:f,isSync:p}}});var _J,bJ,vJ,SEe,wEe,SJ=y(()=>{_J=({file:t,commandArguments:e})=>vJ(t,e),bJ=({file:t,commandArguments:e})=>({...vJ(t,e),isSync:!0}),vJ=(t,e)=>{if(e.length>0)throw new TypeError(`The command and its arguments must be passed as a single string: ${t} ${e}.`);let[r,...n]=SEe(t);return{file:r,commandArguments:n}},SEe=t=>{if(typeof t!="string")throw new TypeError(`The command must be a string: ${String(t)}.`);let e=t.trim();if(e==="")return[];let r=[];for(let n of e.split(wEe)){let i=r.at(-1);i&&i.endsWith("\\")?r[r.length-1]=`${i.slice(0,-1)} ${n}`:r.push(n)}return r},wEe=/ +/g});var wJ,xJ,xEe,$J,$Ee,kJ,EJ=y(()=>{wJ=(t,e,r)=>{t.sync=e(xEe,r),t.s=t.sync},xJ=({options:t})=>$J(t),xEe=({options:t})=>({...$J(t),isSync:!0}),$J=t=>({options:{...$Ee(t),...t}}),$Ee=({input:t,inputFile:e,stdio:r})=>t===void 0&&e===void 0&&r===void 0?{stdin:"inherit"}:{},kJ={preferLocal:!0}});var nft,Ke,ift,oft,sft,aft,cft,lft,uft,dft,zr=y(()=>{yJ();SJ();oI();EJ();BI();nft=_s(()=>({})),Ke=_s(()=>({isSync:!0})),ift=_s(_J),oft=_s(bJ),sft=_s(U9),aft=_s(xJ,{},kJ,wJ),{sendMessage:cft,getOneMessage:lft,getEachMessage:uft,getCancelSignal:dft}=t3()});import{existsSync as Iv,statSync as kEe}from"node:fs";import{dirname as OP,extname as EEe,isAbsolute as AJ,join as TP,relative as RP,resolve as Pv,sep as AEe}from"node:path";function Cv(t){return t==="./gradlew"||t==="gradle"}function OEe(t){return(Iv(TP(t,"build.gradle.kts"))||Iv(TP(t,"build.gradle")))&&Iv(TP(t,"gradle.properties"))}function TEe(t,e){let n=RP(t,e).split(AEe).filter(Boolean);return n.length===0?":":`:${n.join(":")}`}function bs(t,e){return t===":"?`:${e}`:`${t}:${e}`}function REe(t,e){let r=Pv(t,e),n=r;Iv(r)?kEe(r).isFile()&&(n=OP(r)):EEe(r)!==""&&(n=OP(r));let i=RP(t,n);if(i.startsWith("..")||AJ(i))return null;let o=n;for(;;){if(OEe(o))return o;if(Pv(o)===Pv(t))return null;let s=OP(o);if(s===o)return null;let a=RP(t,s);if(a.startsWith("..")||AJ(a))return null;o=s}}function Dv(t,e){let r=Pv(t),n=new Map,i=[];for(let o of e){let s=REe(r,o);if(!s){i.push(o);continue}let a=TEe(r,s);n.has(a)||n.set(a,{path:a,dir:s})}if(i.length>0)throw new Error(`cannot map module(s) to a Gradle project (no build.gradle[.kts] + gradle.properties ancestor under ${r}): ${i.join(", ")}`);return[...n.values()].sort((o,s)=>o.paths.path?1:0)}var Nv=y(()=>{"use strict"});import{existsSync as PP,readFileSync as IEe}from"node:fs";import{join as Vl}from"node:path";function Wl(t="."){let e=Vl(t,".cladding","config.yaml");if(!PP(e))return IP;try{let n=(0,OJ.parse)(IEe(e,"utf8"))?.gate;if(!n)return IP;let i=n.scope==="repo"?"repo":"feature",o=n.coverage==="kover"||n.coverage==="jacoco"?n.coverage:void 0,s=typeof n.test_report=="string"?n.test_report:void 0,a={};if(n.commands&&typeof n.commands=="object")for(let l of PEe){let u=n.commands[l];Array.isArray(u)&&u.every(d=>typeof d=="string")&&(a[l]=u)}let c={scope:i};return Object.keys(a).length>0&&(c.commands=a),o&&(c.coverage=o),s&&(c.testReport=s),c}catch{return IP}}function TJ(t="."){let e=Wl(t).testReport,r=e?[e,...CP]:CP;return[...new Set(r.map(n=>Vl(t,n)))]}function RJ(t="."){let e=Wl(t).testReport;if(e){let r=Vl(t,e);return PP(r)?r:null}return CP.map(r=>Vl(t,r)).find(r=>PP(r))??null}function IJ(t,e){let r=[],n=!1;for(let i of t){let o=CEe.exec(i);if(o){n=!0;for(let s of e)r.push(bs(s.path,o[1]))}else r.push(i)}return n&&e.length===0||r.length===0?null:{cmd:r[0],args:r.slice(1)}}var OJ,PEe,IP,CP,CEe,Sp=y(()=>{"use strict";OJ=wt(tr(),1);Nv();PEe=["type","lint","test","coverage"],IP={scope:"feature"},CP=["test-report.junit.xml",Vl("coverage","junit.xml"),Vl(".cladding","test-report.junit.xml")];CEe=/^\{modules:([A-Za-z0-9_.:-]+)\}$/});import{existsSync as NP,readFileSync as PJ,readdirSync as DEe,statSync as NEe}from"node:fs";import{join as jv}from"node:path";function FP(t){for(let e of["build.gradle.kts","build.gradle","gradle.properties"]){let r=jv(t,e);if(NP(r))try{if(CJ.test(PJ(r,"utf8")))return!0}catch{}}return!1}function DJ(t){try{return NP(t)&&CJ.test(PJ(t,"utf8"))}catch{return!1}}function NJ(t,e=0){if(e>4||!NP(t))return!1;let r;try{r=DEe(t)}catch{return!1}for(let n of r){let i=jv(t,n),o=!1;try{o=NEe(i).isDirectory()}catch{continue}if(o){if(n==="build"||n===".gradle"||n==="node_modules")continue;if(NJ(i,e+1))return!0}else if(/\.(kts|gradle|toml)$/.test(n)&&DJ(i))return!0}return!1}function FEe(t){if(FP(t))return!0;for(let e of jEe)if(DJ(jv(t,e)))return!0;for(let e of MEe)if(NJ(jv(t,e)))return!0;return!1}function jJ(t="."){let e=Wl(t).coverage;return e||(FEe(t)?"kover":"jacoco")}function MJ(t="."){return jP[jJ(t)]}function FJ(t="."){return DP[jJ(t)]}var jP,DP,MP,CJ,jEe,MEe,Mv=y(()=>{"use strict";Sp();jP={kover:"koverXmlReport",jacoco:"jacocoTestReport"},DP={kover:"build/reports/kover/report.xml",jacoco:"build/reports/jacoco/test/jacocoTestReport.xml"},MP=[DP.kover,DP.jacoco],CJ=/kover/i;jEe=["build.gradle.kts","build.gradle","settings.gradle.kts","settings.gradle","gradle/libs.versions.toml"],MEe=["buildSrc","build-logic"]});import{existsSync as xp,readFileSync as zP,readdirSync as zJ,statSync as LEe}from"node:fs";import{dirname as zEe,join as kr,resolve as UEe}from"node:path";import Kl from"node:process";function UP(t){return xp(kr(t,"gradlew"))?"./gradlew":"gradle"}function qEe(t){let e=UP(t);return{type:{cmd:e,args:["compileKotlin","compileTestKotlin"]},lint:{cmd:e,args:["ktlintCheck"]},test:{cmd:e,args:["test"]},coverage:{cmd:e,args:[MJ(t)]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}}function HEe(t){let e=!1;try{e=/(^|\n)\s*flutter\s*:|sdk:\s*flutter/.test(zP(kr(t,"pubspec.yaml"),"utf8"))}catch{}let r={cmd:"dart",args:["format","--output=none","--set-exit-if-changed","."]},n={cmd:"gitleaks",args:["detect","--no-banner"]};return e?{type:{cmd:"flutter",args:["analyze"]},lint:r,test:{cmd:"flutter",args:["test"]},coverage:{cmd:"flutter",args:["test","--coverage"]},secret:n}:{type:{cmd:"dart",args:["analyze"]},lint:r,test:{cmd:"dart",args:["test"]},coverage:{cmd:"dart",args:["test","--coverage=coverage"]},secret:n}}function GEe(t,e){let r=[t],n=0,i=4e3;for(;r.length>0&&na.name.endsWith(c)))return!0}return!1}function WEe(t,e){for(let r of e)if(xp(kr(t,r)))return r}function KEe(t,e){try{return zJ(t).find(n=>n.endsWith(e))}catch{return}}function QEe(t){let e=[],r=Kl.platform==="win32";r||e.push(kr("/etc","madge","config"),kr("/etc","madgerc"));let n=r?Kl.env.USERPROFILE:Kl.env.HOME;n&&e.push(kr(n,".config","madge","config"),kr(n,".config","madge"),kr(n,".madge","config"),kr(n,".madgerc"));for(let o=UEe(t);;){e.push(kr(o,".madgerc"));let s=zEe(o);if(s===o)break;o=s}let i=Kl.env.MADGE_config??Kl.env.madge_config;return i&&e.push(i),e}function eAe(){for(let[t,e]of Object.entries(Kl.env))if(/^madge_excluderegexp/i.test(t)&&typeof e=="string"&&e.trim().length>0)return!0;return!1}function UJ(t){return Array.isArray(t)?t.length>0:typeof t=="string"&&t.trim().length>0}function rAe(t){try{return LEe(t).isFile()}catch{return!1}}function nAe(t){let e;try{e=zP(t,"utf8")}catch{return!0}try{return UJ(JSON.parse(e).excludeRegExp)}catch{return tAe.test(e)}}function iAe(t,e){let r=e.madge;return r&&typeof r=="object"&&UJ(r.excludeRegExp)||eAe()?!0:QEe(t).some(n=>rAe(n)&&nAe(n))}function oAe(t){try{return JSON.parse(zP(kr(t,"package.json"),"utf8").replace(/^\uFEFF/,""))}catch{return{}}}function wp(t,e){let r=t.scripts?.[e];return typeof r=="string"&&r.trim().length>0?r.trim():void 0}function LJ(t,e){return[t.dependencies,t.devDependencies,t.optionalDependencies,t.peerDependencies].some(r=>r?.[e]!==void 0)}function sAe(t,e,r){if(iAe(t,r))return e;let n=[...e.args];return n.splice(n.length-1,0,"--exclude",XEe),{...e,args:n}}function aAe(t,e,r){if(wp(r,"lint"))return{cmd:"npm",args:["run","--silent","lint"]};for(let n of JEe)if(n.configs.some(i=>xp(kr(t,i))))return n.gate;if(YEe.some(n=>xp(kr(t,n)))||r.eslintConfig!==void 0)return e}function lAe(t,e){return cAe.some(r=>xp(kr(t,r)))?!0:e.jest!==void 0}function uAe(t){if(/^(?:(?:npx|npm exec)\s+(?:--offline\s+)?(?:--no-install\s+)?(?:--\s+)?)?vitest(?:\s+run)?$/i.test(t))return"vitest";if(/^(?:(?:npx|npm exec)\s+(?:--offline\s+)?(?:--no-install\s+)?(?:--\s+)?)?jest$/i.test(t))return"jest"}function LP(t,e){let r={...t};return e==="lint"?delete r.lint:delete r.coverage,r}function dAe(t,e){let r=oAe(t),n=e.lint?aAe(t,e.lint,r):void 0,i=e.arch?{...e,arch:sAe(t,e.arch,r)}:e,o=n?{...i,lint:n}:LP(i,"lint"),s=wp(r,"test"),a=s?uAe(s):void 0;return s&&!a?(o=LP(o,"coverage"),{...o,test:{cmd:"npm",args:["test"]},...wp(r,"coverage")?{coverage:{cmd:"npm",args:["run","--silent","coverage"]}}:{}}):a==="jest"||!s&&lAe(t,r)?{...o,test:{cmd:"npx",args:[...Fi,"jest"]},coverage:{cmd:"npx",args:[...Fi,"jest","--coverage"]}}:(a==="vitest"&&!wp(r,"coverage")&&!LJ(r,"@vitest/coverage-v8")&&!LJ(r,"@vitest/coverage-istanbul")?o=LP(o,"coverage"):a==="vitest"&&wp(r,"coverage")&&(o={...o,coverage:{cmd:"npm",args:["run","--silent","coverage"]}}),o)}function _t(t="."){for(let e of ZEe){let r;for(let o of e.manifests)if(o.startsWith(".")?r=KEe(t,o):r=WEe(t,[o]),r)break;if(!r||e.requiresSource&&!GEe(t,e.requiresSource))continue;let n=typeof e.gates=="function"?e.gates(t):e.gates,i=e.language==="typescript"?dAe(t,n):n;return{language:e.language,manifest:r,gates:i}}return VEe}var Fi,BEe,ZEe,VEe,JEe,YEe,XEe,tAe,cAe,Dn=y(()=>{"use strict";Mv();Fi=["--offline","--no-install"];BEe=new Set(["node_modules",".git",".gradle",".idea","build","target","dist","out",".cladding"]);ZEe=[{language:"typescript",manifests:["package.json"],gates:{type:{cmd:"npx",args:[...Fi,"tsc","--noEmit"]},lint:{cmd:"npx",args:[...Fi,"eslint","."]},test:{cmd:"npx",args:[...Fi,"vitest","run"]},coverage:{cmd:"npx",args:[...Fi,"vitest","run","--coverage"]},secret:{cmd:"npx",args:[...Fi,"secretlint","**/*"]},arch:{cmd:"npx",args:[...Fi,"madge","--circular","--extensions","ts,tsx,js,jsx","."]},smoke:{cmd:"npm",args:["run","--silent","smoke"]},perf:{cmd:"npm",args:["run","--silent","perf"]},visual:{cmd:"npm",args:["run","--silent","visual"]}}},{language:"python",manifests:["pyproject.toml","setup.py","requirements.txt"],gates:{type:{cmd:"mypy",args:["."]},lint:{cmd:"ruff",args:["check","."]},test:{cmd:"pytest",args:[]},coverage:{cmd:"coverage",args:["run","-m","pytest"]},secret:{cmd:"detect-secrets",args:["scan"]},arch:{cmd:"lint-imports",args:[]}}},{language:"rust",manifests:["Cargo.toml"],gates:{type:{cmd:"cargo",args:["check"]},lint:{cmd:"cargo",args:["clippy","--","-D","warnings"]},test:{cmd:"cargo",args:["test"]},coverage:{cmd:"cargo",args:["llvm-cov"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"go",manifests:["go.mod"],gates:{type:{cmd:"go",args:["vet","./..."]},lint:{cmd:"golangci-lint",args:["run"]},test:{cmd:"go",args:["test","./..."]},coverage:{cmd:"go",args:["test","-cover","./..."]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"kotlin",manifests:["build.gradle.kts","build.gradle","pom.xml"],requiresSource:[".kt",".kts"],gates:qEe},{language:"java",manifests:["pom.xml","build.gradle","build.gradle.kts"],gates:{type:{cmd:"mvn",args:["compile","-q"]},lint:{cmd:"mvn",args:["checkstyle:check","-q"]},test:{cmd:"mvn",args:["test","-q"]},coverage:{cmd:"mvn",args:["jacoco:report","-q"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"php",manifests:["composer.json"],gates:{type:{cmd:"phpstan",args:["analyse"]},lint:{cmd:"phpcs",args:[]},test:{cmd:"phpunit",args:[]},coverage:{cmd:"phpunit",args:["--coverage-text"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"ruby",manifests:["Gemfile"],gates:{type:{cmd:"srb",args:["tc"]},lint:{cmd:"rubocop",args:[]},test:{cmd:"bundle",args:["exec","rspec"]},coverage:{cmd:"bundle",args:["exec","rspec","--format","documentation"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"elixir",manifests:["mix.exs"],gates:{type:{cmd:"mix",args:["dialyzer"]},lint:{cmd:"mix",args:["credo"]},test:{cmd:"mix",args:["test"]},coverage:{cmd:"mix",args:["coveralls"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"dotnet",manifests:[".csproj",".sln",".fsproj"],gates:{type:{cmd:"dotnet",args:["build","--nologo","-v","q"]},lint:{cmd:"dotnet",args:["format","--verify-no-changes"]},test:{cmd:"dotnet",args:["test","--nologo"]},coverage:{cmd:"dotnet",args:["test",'--collect:"XPlat Code Coverage"']},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"swift",manifests:["Package.swift"],gates:{type:{cmd:"swift",args:["build"]},lint:{cmd:"swiftlint",args:["lint"]},test:{cmd:"swift",args:["test"]},coverage:{cmd:"swift",args:["test","--enable-code-coverage"]},secret:{cmd:"gitleaks",args:["detect","--no-banner"]}}},{language:"dart",manifests:["pubspec.yaml"],gates:HEe}],VEe={language:"unknown",manifest:"",gates:{}};JEe=[{configs:["biome.json","biome.jsonc"],gate:{cmd:"npx",args:[...Fi,"biome","lint","."]}},{configs:[".oxlintrc.json",".oxlintrc.jsonc","oxlint.config.ts"],gate:{cmd:"npx",args:[...Fi,"oxlint"]}}],YEe=["eslint.config.js","eslint.config.mjs","eslint.config.cjs","eslint.config.ts","eslint.config.mts","eslint.config.cts",".eslintrc",".eslintrc.js",".eslintrc.cjs",".eslintrc.json",".eslintrc.yaml",".eslintrc.yml"],XEe="(^|/)(dist|coverage|\\.next|\\.nuxt|\\.output|\\.svelte-kit|\\.vite)/|^(build|out|target)/";tAe=/^[ \t]*excludeRegExp[ \t]*(?:\[[^\]]*\])?[ \t]*=[ \t]*(\S.*?)[ \t]*$/m;cAe=["jest.config.js","jest.config.ts","jest.config.mjs","jest.config.cjs","jest.config.json"]});import{existsSync as fAe,readFileSync as pAe}from"node:fs";import{join as mAe}from"node:path";function Ba(t){return t.code==="ENOENT"}function Fv(t,e,r,n){let i=t.exitCode??1;if(i===0)return[];let o=(t.stderr??"").toString().trim(),s=(t.stdout??"").toString().trim(),a=[s,o].filter(c=>c.length>0).join(` +`).slice(0,2e3)||`exit ${i}`;return qJ.test(o)||qJ.test(s)?[{detector:e,severity:"info",message:n(a)}]:[{detector:e,severity:"error",message:r(a)}]}function Nt(t,e,r,n=[]){if(Ba(r))return{stage:t,pass:!1,exitCode:2,stderr:`'${e}' not installed`,skipReason:"tool-missing"};let i=`${String(r.stderr??"")} +${String(r.stdout??"")}`,o=/ENOTCACHED|ENOTFOUND|EAI_AGAIN|canceled due to missing packages|could not determine executable/i.test(i),a=n.find(l=>l!=="--"&&!l.startsWith("-"))?.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),c=r.exitCode===127&&a!==void 0&&new RegExp(`(?:^|[\\s:])${a}: (?:command )?not found\\b`,"i").test(i);return e==="npx"&&(o||c)?{stage:t,pass:!1,exitCode:2,stderr:"setup gap: 'npx' could not resolve the configured tool without installing it; the inferred tool is not installed or unavailable offline",skipReason:"tool-missing"}:null}function Xt(t,e){if((e.exitCode??1)===0)return{stage:t,pass:!0,exitCode:0};let n=[String(e.stdout??"").trim(),String(e.stderr??"").trim()].filter(i=>i.length>0).join(` +`);return n?{stage:t,pass:!1,exitCode:1,stderr:n}:{stage:t,pass:!1,exitCode:1}}function Jl(t,e){let r=mAe(t,"package.json");if(!fAe(r))return!1;try{return!!JSON.parse(pAe(r,"utf8")).scripts?.[e]}catch{return!1}}var qJ,Nn=y(()=>{"use strict";qJ=/config (is |file )?not found|no such file|ENOENT|ENOTCACHED|ENOTFOUND|EAI_AGAIN|cannot find (a |the )?(config|module|package|preset)|require[sd]?\b.{0,40}\bconfig|canceled due to missing packages|could not determine executable/i});function hAe(t){let{cwd:e="."}=t,r=_t(e),n=r.gates.arch;if(!n)return[{detector:Lv,severity:"info",message:`no architecture validator registered for language '${r.language}' (compiler may already enforce acyclic imports)`}];let i=Ke(n.cmd,[...n.args],{cwd:e,reject:!1});return Ba(i)?[{detector:Lv,severity:"info",message:`architecture validator '${n.cmd}' not installed`}]:Fv(i,Lv,o=>`${n.cmd} reported architecture violations: ${o}`,o=>`${n.cmd} could not validate (config/setup gap, not a violation): ${o}`)}var Lv,Ga,zv=y(()=>{"use strict";zr();Dn();Nn();Lv="ARCHITECTURE_VIOLATION";Ga={name:Lv,subprocess:!0,run:hAe}});function gAe(t){let{cwd:e="."}=t,r=_t(e),n=r.gates.secret;if(!n)return[{detector:Uv,severity:"info",message:`no secret scanner registered for language '${r.language}'`}];let i=Ke(n.cmd,[...n.args],{cwd:e,reject:!1});return Ba(i)?[{detector:Uv,severity:"info",message:`secret scanner '${n.cmd}' not installed`}]:Fv(i,Uv,o=>`${n.cmd} reported secrets: ${o}`,o=>`${n.cmd} could not scan (config/setup gap, not a secret): ${o}`)}var Uv,Za,qv=y(()=>{"use strict";zr();Dn();Nn();Uv="HARDCODED_SECRET";Za={name:Uv,subprocess:!0,run:gAe}});import{existsSync as qP,readdirSync as HJ}from"node:fs";import{join as Hv}from"node:path";function _Ae(t,e){let r=Hv(t,e.path);if(!qP(r))return!0;if(e.isDirectory)try{return HJ(r).filter(i=>i.endsWith(".yaml")||i.endsWith(".yml")).length===0}catch{return!0}return!1}function bAe(t){let{cwd:e="."}=t,r=[];for(let i of yAe)_Ae(e,i)&&r.push({detector:$p,severity:i.severity,path:i.path,message:`${i.path} is absent \u2014 cladding scaffold incomplete (${i.purpose}). Run \`clad init --intent ""\` to populate it.`});let n=Hv(e,"spec.yaml");if(qP(n)){let i=wAe(n),o=i?null:vAe(e);if(i)r.push({detector:$p,severity:"error",path:"spec.yaml",message:`spec.yaml is present but unreadable (${i}) \u2014 cladding is governing nothing. Fix the SSoT root, then \`clad sync\` to validate.`});else if(o)r.push({detector:$p,severity:"error",path:o.path,message:`spec shard '${o.path}' is present but unparseable (${o.reason}) \u2014 loadSpec throws on it, so every spec-gated detector silently passes. Fix it, then \`clad sync\`.`});else{let s=SAe(e);s&&r.push({detector:$p,severity:"error",path:"spec.yaml",message:`spec.yaml is present and parses, but the assembled spec does not load (${s}) \u2014 every spec-gated detector then degrades to non-blocking info, so the gate would pass GREEN on an unloadable SSoT. Fix it, then \`clad sync\` to validate.`})}}return r}function vAe(t){for(let e of["spec/features","spec/scenarios"]){let r=Hv(t,e);if(!qP(r))continue;let n;try{n=HJ(r).filter(i=>i.endsWith(".yaml")||i.endsWith(".yml"))}catch{continue}for(let i of[...n].sort())try{Ri(Hv(r,i))}catch(o){return{path:`${e}/${i}`,reason:o.message}}}return null}function SAe(t){try{return q(t),null}catch(e){return e.message}}function wAe(t){let e;try{e=Ri(t)}catch(r){return`unparseable: ${r.message}`}return e===null||typeof e!="object"||Array.isArray(e)?"empty or not a YAML mapping":null}var $p,yAe,BJ,GJ=y(()=>{"use strict";Ue();V_();$p="ABSENCE_OF_GOVERNANCE",yAe=[{path:"spec.yaml",severity:"error",purpose:"SSoT root \u2014 every spec-gated detector needs it"},{path:"spec/architecture.yaml",severity:"warn",purpose:"architecture invariants (layers + forbidden_imports)"},{path:"spec/capabilities.yaml",severity:"warn",purpose:"capability \u2194 feature traceability"},{path:"docs/project-context.md",severity:"warn",purpose:"intent narrative + decision history"},{path:"docs/conventions.md",severity:"info",purpose:"project style guide (recommended)"},{path:"spec/scenarios",severity:"info",purpose:"user-journey scenarios (recommended)",isDirectory:!0}];BJ={name:$p,run:bAe}});function Bv(t){let e=t.trim().match(/^(\S+)/);return e?e[1].toLowerCase():""}function HP(t,e){let r=e?.trim()??"";if(!t)return r.length>0?"condition is present but ears pattern is not declared":null;if(t==="ubiquitous")return r.length>0?`ears='ubiquitous' but condition is present ('${r.slice(0,40)}\u2026')`:null;if(t==="complex"){if(r.length===0)return"ears='complex' requires a 'while' precondition and a 'when' trigger \u2014 empty";let i=Bv(r)==="while",o=$Ae.test(r);return i?o?null:"ears='complex' requires a 'when' trigger clause after the 'while' precondition \u2014 none found":`ears='complex' requires the condition to start with 'while' (precondition) \u2014 got '${Bv(r)}'`}let n=xAe[t];return r.length===0?`ears='${t}' requires condition starting with '${n}' \u2014 empty`:Bv(r)!==n?`ears='${t}' requires condition to start with '${n}' \u2014 got '${Bv(r)}'`:null}function kAe(t,e){let r=HP(e.ears,e.condition);return r?[{featureId:t.id,acId:e.id,pattern:e.ears??"unspecified",message:r}]:[]}function ZJ(t){let e=[];for(let r of t)for(let n of r.acceptance_criteria??[])e.push(...kAe(r,n));return e}var xAe,$Ae,BP=y(()=>{"use strict";xAe={event:"when",state:"while",optional:"where",unwanted:"if"},$Ae=/\bwhen\b/i});function ye(t,e,r){let n;try{n=q(t)}catch(i){return[{detector:e,severity:"info",message:`spec.yaml not loaded: ${i.message}`}]}return r(n)}var xt=y(()=>{"use strict";Ue()});function EAe(t){let{cwd:e="."}=t;return ye(e,Gv,AAe)}function AAe(t){let e=[];for(let r of t.features)for(let n of r.acceptance_criteria??[]){let i=!!n.text?.trim(),o=!!(n.condition?.trim()||n.action?.trim()||n.response?.trim());!i&&!o&&e.push({detector:Gv,severity:"error",message:`${r.id}.${n.id} has neither rendered text nor any EARS field (condition/action/response) \u2014 structurally empty AC`})}for(let r of ZJ(t.features))e.push({detector:Gv,severity:"error",message:`${r.featureId}.${r.acId} EARS: ${r.message}`});return e}var Gv,VJ,WJ=y(()=>{"use strict";BP();xt();Gv="AC_DRIFT";VJ={name:Gv,run:EAe}});function Li(t=".",e){let n=(e??"").trim().toLowerCase()||_t(t).language;return JJ[n]??KJ}var OAe,TAe,RAe,KJ,IAe,PAe,JJ,CAe,YJ,Va=y(()=>{"use strict";Dn();OAe=/(?:import\s+(?:[\s\S]*?\sfrom\s+)?|import\s*\()['"]([^'"]+)['"]\)?/g,TAe=/^[ \t]*import\s+([\w.]+)/gm,RAe=/^[ \t]*(?:from|import)\s+([\w.]+)/gm,KJ={ext:"ts",extensions:[".ts",".tsx"],sourceRoots:["src"],mainRoot:"src",testGlobs:["tests/**/*.test.ts"],coverageSummary:"coverage/coverage-summary.json",coverageFormat:"istanbul-json",importMatcher:OAe,importStyle:"relative"},IAe={ext:"kt",extensions:[".kt",".kts"],sourceRoots:["src/main/kotlin","src/test/kotlin"],mainRoot:"src/main/kotlin",testGlobs:["src/test/kotlin/**/*Test.kt","src/test/kotlin/**/*Tests.kt"],coverageSummary:"build/reports/jacoco/test/jacocoTestReport.xml",coverageFormat:"jacoco-xml",importMatcher:TAe,importStyle:"dotted"},PAe={ext:"py",extensions:[".py"],sourceRoots:["."],mainRoot:"src",testGlobs:["tests/test_*.py","tests/**/test_*.py","tests/**/*_test.py"],coverageSummary:"coverage.xml",coverageFormat:"cobertura-xml",importMatcher:RAe,importStyle:"dotted"},JJ={typescript:KJ,kotlin:IAe,python:PAe},CAe=[".js",".jsx",".mts",".cts",".rs",".go",".java",".rb",".php",".cs",".fs",".ex",".exs"],YJ=new Set([...Object.values(JJ).flatMap(t=>t?.extensions??[]),...CAe].map(t=>t.toLowerCase()))});import{existsSync as DAe,readFileSync as NAe,readdirSync as jAe,statSync as MAe}from"node:fs";import{join as QJ,relative as XJ}from"node:path";function FAe(t,e){if(!DAe(t))return[];let r=[],n=[t];for(;n.length>0;){let i=n.pop(),o;try{o=jAe(i)}catch{continue}for(let s of o){if(s==="node_modules"||s===".cladding"||s.startsWith("."))continue;let a=QJ(i,s),c;try{c=MAe(a)}catch{continue}c.isDirectory()?n.push(a):e.some(l=>s.endsWith(l))&&r.push(a)}}return r}function LAe(t){let e=t.trim();return e.startsWith("//")||e.startsWith("/*")||e.startsWith("*")}function UAe(t){return zAe.test(t)}function qAe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=r.project.ai_hints?.forbidden_patterns;if(!n||n.length===0)return[];let i=Li(e,r.project?.language),o=i.sourceRoots.flatMap(a=>FAe(QJ(e,a),i.extensions));if(o.length===0)return[];let s=[];for(let a of o){let c;try{c=NAe(a,"utf8")}catch{continue}let l=c.split(` +`);for(let u=0;u{"use strict";Ue();Va();e8="AI_HINTS_FORBIDDEN_PATTERN";zAe=/\/\/\s*cladding-disable[:\s]+AI_HINTS_FORBIDDEN_PATTERN\b/;t8={name:e8,run:qAe}});function HAe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=[];for(let i of r.features){let o=(i.acceptance_criteria??[]).map(a=>a.id),s=new Map;for(let a of o)s.set(a,(s.get(a)??0)+1);for(let[a,c]of s)c>1&&n.push({detector:n8,severity:"error",message:`${i.id}.${a} appears ${c} times \u2014 AC ids must be unique within a feature`})}return n}var n8,i8,o8=y(()=>{"use strict";Ue();n8="AC_DUPLICATE_WITHIN_FEATURE";i8={name:n8,run:HAe}});import{createRequire as BAe}from"module";import{basename as GAe,dirname as ZP,normalize as ZAe,relative as VAe,resolve as WAe,sep as c8}from"path";import*as KAe from"fs";function JAe(t){let e=ZAe(t);return e.length>1&&e[e.length-1]===c8&&(e=e.substring(0,e.length-1)),e}function l8(t,e){return t.replace(YAe,e)}function QAe(t){return t==="/"||XAe.test(t)}function GP(t,e){let{resolvePaths:r,normalizePath:n,pathSeparator:i}=e,o=process.platform==="win32"&&t.includes("/")||t.startsWith(".");if(r&&(t=WAe(t)),(n||o)&&(t=JAe(t)),t===".")return"";let s=t[t.length-1]!==i;return l8(s?t+i:t,i)}function u8(t,e){return e+t}function eOe(t,e){return function(r,n){return n.startsWith(t)?n.slice(t.length)+r:l8(VAe(t,n),e.pathSeparator)+e.pathSeparator+r}}function tOe(t){return t}function rOe(t,e,r){return e+t+r}function nOe(t,e){let{relativePaths:r,includeBasePath:n}=e;return r&&t?eOe(t,e):n?u8:tOe}function iOe(t){return function(e,r){r.push(e.substring(t.length)||".")}}function oOe(t){return function(e,r,n){let i=e.substring(t.length)||".";n.every(o=>o(i,!0))&&r.push(i)}}function lOe(t,e){let{includeDirs:r,filters:n,relativePaths:i}=e;return r?i?n&&n.length?oOe(t):iOe(t):n&&n.length?aOe:sOe:cOe}function hOe(t){let{excludeFiles:e,filters:r,onlyCounts:n}=t;return e?mOe:r&&r.length?n?uOe:dOe:n?fOe:pOe}function _Oe(t){return t.group?yOe:gOe}function SOe(t){return t.group?bOe:vOe}function $Oe(t,e){return!t.resolveSymlinks||t.excludeSymlinks?null:e?xOe:wOe}function d8(t,e,r){if(r.options.useRealPaths)return kOe(e,r);let n=ZP(t),i=1;for(;n!==r.root&&i<2;){let o=r.symlinks.get(n);!!o&&(o===e||o.startsWith(e)||e.startsWith(o))?i++:n=ZP(n)}return r.symlinks.set(t,e),i>1}function kOe(t,e){return e.visited.includes(t+e.options.pathSeparator)}function Zv(t,e,r,n){e(t&&!n?t:null,r)}function DOe(t,e){let{onlyCounts:r,group:n,maxFiles:i}=t;return r?e?EOe:ROe:n?e?AOe:COe:i?e?TOe:POe:e?OOe:IOe}function MOe(t){return t?jOe:NOe}function UOe(t,e){return new Promise((r,n)=>{m8(t,e,(i,o)=>{if(i)return n(i);r(o)})})}function m8(t,e,r){new p8(t,e,r).start()}function qOe(t,e){return new p8(t,e).start()}var s8,YAe,XAe,sOe,aOe,cOe,uOe,dOe,fOe,pOe,mOe,gOe,yOe,bOe,vOe,wOe,xOe,EOe,AOe,OOe,TOe,ROe,IOe,POe,COe,f8,NOe,jOe,FOe,LOe,zOe,p8,a8,h8,g8,y8=y(()=>{s8=BAe(import.meta.url);YAe=/[\\/]/g;XAe=/^[a-z]:[\\/]$/i;sOe=(t,e)=>{e.push(t||".")},aOe=(t,e,r)=>{let n=t||".";r.every(i=>i(n,!0))&&e.push(n)},cOe=()=>{};uOe=(t,e,r,n)=>{n.every(i=>i(t,!1))&&r.files++},dOe=(t,e,r,n)=>{n.every(i=>i(t,!1))&&e.push(t)},fOe=(t,e,r,n)=>{r.files++},pOe=(t,e)=>{e.push(t)},mOe=()=>{};gOe=t=>t,yOe=()=>[""].slice(0,0);bOe=(t,e,r)=>{t.push({directory:e,files:r,dir:e})},vOe=()=>{};wOe=function(t,e,r){let{queue:n,fs:i,options:{suppressErrors:o}}=e;n.enqueue(),i.realpath(t,(s,a)=>{if(s)return n.dequeue(o?null:s,e);i.stat(a,(c,l)=>{if(c)return n.dequeue(o?null:c,e);if(l.isDirectory()&&d8(t,a,e))return n.dequeue(null,e);r(l,a),n.dequeue(null,e)})})},xOe=function(t,e,r){let{queue:n,fs:i,options:{suppressErrors:o}}=e;n.enqueue();try{let s=i.realpathSync(t),a=i.statSync(s);if(a.isDirectory()&&d8(t,s,e))return;r(a,s)}catch(s){if(!o)throw s}};EOe=t=>t.counts,AOe=t=>t.groups,OOe=t=>t.paths,TOe=t=>t.paths.slice(0,t.options.maxFiles),ROe=(t,e,r)=>(Zv(e,r,t.counts,t.options.suppressErrors),null),IOe=(t,e,r)=>(Zv(e,r,t.paths,t.options.suppressErrors),null),POe=(t,e,r)=>(Zv(e,r,t.paths.slice(0,t.options.maxFiles),t.options.suppressErrors),null),COe=(t,e,r)=>(Zv(e,r,t.groups,t.options.suppressErrors),null);f8={withFileTypes:!0},NOe=(t,e,r,n,i)=>{if(t.queue.enqueue(),n<0)return t.queue.dequeue(null,t);let{fs:o}=t;t.visited.push(e),t.counts.directories++,o.readdir(e||".",f8,(s,a=[])=>{i(a,r,n),t.queue.dequeue(t.options.suppressErrors?null:s,t)})},jOe=(t,e,r,n,i)=>{let{fs:o}=t;if(n<0)return;t.visited.push(e),t.counts.directories++;let s=[];try{s=o.readdirSync(e||".",f8)}catch(a){if(!t.options.suppressErrors)throw a}i(s,r,n)};FOe=class{count=0;constructor(t){this.onQueueEmpty=t}enqueue(){return this.count++,this.count}dequeue(t,e){this.onQueueEmpty&&(--this.count<=0||t)&&(this.onQueueEmpty(t,e),t&&(e.controller.abort(),this.onQueueEmpty=void 0))}},LOe=class{_files=0;_directories=0;set files(t){this._files=t}get files(){return this._files}set directories(t){this._directories=t}get directories(){return this._directories}get dirs(){return this._directories}},zOe=class{aborted=!1;abort(){this.aborted=!0}},p8=class{root;isSynchronous;state;joinPath;pushDirectory;pushFile;getArray;groupFiles;resolveSymlink;walkDirectory;callbackInvoker;constructor(t,e,r){this.isSynchronous=!r,this.callbackInvoker=DOe(e,this.isSynchronous),this.root=GP(t,e),this.state={root:QAe(this.root)?this.root:this.root.slice(0,-1),paths:[""].slice(0,0),groups:[],counts:new LOe,options:e,queue:new FOe((n,i)=>this.callbackInvoker(i,n,r)),symlinks:new Map,visited:[""].slice(0,0),controller:new zOe,fs:e.fs||KAe},this.joinPath=nOe(this.root,e),this.pushDirectory=lOe(this.root,e),this.pushFile=hOe(e),this.getArray=_Oe(e),this.groupFiles=SOe(e),this.resolveSymlink=$Oe(e,this.isSynchronous),this.walkDirectory=MOe(this.isSynchronous)}start(){return this.pushDirectory(this.root,this.state.paths,this.state.options.filters),this.walkDirectory(this.state,this.root,this.root,this.state.options.maxDepth,this.walk),this.isSynchronous?this.callbackInvoker(this.state,null):null}walk=(t,e,r)=>{let{paths:n,options:{filters:i,resolveSymlinks:o,excludeSymlinks:s,exclude:a,maxFiles:c,signal:l,useRealPaths:u,pathSeparator:d},controller:f}=this.state;if(f.aborted||l&&l.aborted||c&&n.length>c)return;let p=this.getArray(this.state.paths);for(let m=0;m{if(b.isDirectory()){if(_=GP(_,this.state.options),a&&a(h.name,u?_:g+d))return;this.walkDirectory(this.state,_,u?_:g+d,r-1,this.walk)}else{_=u?_:g;let S=GAe(_),x=GP(ZP(_),this.state.options);_=this.joinPath(S,x),this.pushFile(_,p,this.state.counts,i)}})}}this.groupFiles(this.state.groups,e,p)}};a8=class{constructor(t,e){this.root=t,this.options=e}withPromise(){return UOe(this.root,this.options)}withCallback(t){m8(this.root,this.options,t)}sync(){return qOe(this.root,this.options)}},h8=null;try{s8.resolve("picomatch"),h8=s8("picomatch")}catch{}g8=class{globCache={};options={maxDepth:1/0,suppressErrors:!0,pathSeparator:c8,filters:[]};globFunction;constructor(t){this.options={...this.options,...t},this.globFunction=this.options.globFunction}group(){return this.options.group=!0,this}withPathSeparator(t){return this.options.pathSeparator=t,this}withBasePath(){return this.options.includeBasePath=!0,this}withRelativePaths(){return this.options.relativePaths=!0,this}withDirs(){return this.options.includeDirs=!0,this}withMaxDepth(t){return this.options.maxDepth=t,this}withMaxFiles(t){return this.options.maxFiles=t,this}withFullPaths(){return this.options.resolvePaths=!0,this.options.includeBasePath=!0,this}withErrors(){return this.options.suppressErrors=!1,this}withSymlinks({resolvePaths:t=!0}={}){return this.options.resolveSymlinks=!0,this.options.useRealPaths=t,this.withFullPaths()}withAbortSignal(t){return this.options.signal=t,this}normalize(){return this.options.normalizePath=!0,this}filter(t){return this.options.filters.push(t),this}onlyDirs(){return this.options.excludeFiles=!0,this.options.includeDirs=!0,this}exclude(t){return this.options.exclude=t,this}onlyCounts(){return this.options.onlyCounts=!0,this}crawl(t){return new a8(t||".",this.options)}withGlobFunction(t){return this.globFunction=t,this}crawlWithOptions(t,e){return this.options={...this.options,...e},new a8(t||".",this.options)}glob(...t){return this.globFunction?this.globWithOptions(t):this.globWithOptions(t,{dot:!0})}globWithOptions(t,...e){let r=this.globFunction||h8;if(!r)throw new Error("Please specify a glob function to use glob matching.");var n=this.globCache[t.join("\0")];return n||(n=r(t,...e),this.globCache[t.join("\0")]=n),this.options.filters.push(i=>n(i)),this}}});var kp=v((hpt,w8)=>{"use strict";var _8="[^\\\\/]",HOe="(?=.)",b8="[^/]",VP="(?:\\/|$)",v8="(?:^|\\/)",WP=`\\.{1,2}${VP}`,BOe="(?!\\.)",GOe=`(?!${v8}${WP})`,ZOe=`(?!\\.{0,1}${VP})`,VOe=`(?!${WP})`,WOe="[^.\\/]",KOe=`${b8}*?`,JOe="/",S8={DOT_LITERAL:"\\.",PLUS_LITERAL:"\\+",QMARK_LITERAL:"\\?",SLASH_LITERAL:"\\/",ONE_CHAR:HOe,QMARK:b8,END_ANCHOR:VP,DOTS_SLASH:WP,NO_DOT:BOe,NO_DOTS:GOe,NO_DOT_SLASH:ZOe,NO_DOTS_SLASH:VOe,QMARK_NO_DOT:WOe,STAR:KOe,START_ANCHOR:v8,SEP:JOe},YOe={...S8,SLASH_LITERAL:"[\\\\/]",QMARK:_8,STAR:`${_8}*?`,DOTS_SLASH:"\\.{1,2}(?:[\\\\/]|$)",NO_DOT:"(?!\\.)",NO_DOTS:"(?!(?:^|[\\\\/])\\.{1,2}(?:[\\\\/]|$))",NO_DOT_SLASH:"(?!\\.{0,1}(?:[\\\\/]|$))",NO_DOTS_SLASH:"(?!\\.{1,2}(?:[\\\\/]|$))",QMARK_NO_DOT:"[^.\\\\/]",START_ANCHOR:"(?:^|[\\\\/])",END_ANCHOR:"(?:[\\\\/]|$)",SEP:"\\"},XOe={__proto__:null,alnum:"a-zA-Z0-9",alpha:"a-zA-Z",ascii:"\\x00-\\x7F",blank:" \\t",cntrl:"\\x00-\\x1F\\x7F",digit:"0-9",graph:"\\x21-\\x7E",lower:"a-z",print:"\\x20-\\x7E ",punct:"\\-!\"#$%&'()\\*+,./:;<=>?@[\\]^_`{|}~",space:" \\t\\r\\n\\v\\f",upper:"A-Z",word:"A-Za-z0-9_",xdigit:"A-Fa-f0-9"};w8.exports={DEFAULT_MAX_EXTGLOB_RECURSION:0,MAX_LENGTH:1024*64,POSIX_REGEX_SOURCE:XOe,REGEX_BACKSLASH:/\\(?![*+?^${}(|)[\]])/g,REGEX_NON_SPECIAL_CHARS:/^[^@![\].,$*+?^{}()|\\/]+/,REGEX_SPECIAL_CHARS:/[-*+?.^${}(|)[\]]/,REGEX_SPECIAL_CHARS_BACKREF:/(\\?)((\W)(\3*))/g,REGEX_SPECIAL_CHARS_GLOBAL:/([-*+?.^${}(|)[\]])/g,REGEX_REMOVE_BACKSLASH:/(?:\[.*?[^\\]\]|\\(?=.))/g,REPLACEMENTS:{__proto__:null,"***":"*","**/**":"**","**/**/**":"**"},CHAR_0:48,CHAR_9:57,CHAR_UPPERCASE_A:65,CHAR_LOWERCASE_A:97,CHAR_UPPERCASE_Z:90,CHAR_LOWERCASE_Z:122,CHAR_LEFT_PARENTHESES:40,CHAR_RIGHT_PARENTHESES:41,CHAR_ASTERISK:42,CHAR_AMPERSAND:38,CHAR_AT:64,CHAR_BACKWARD_SLASH:92,CHAR_CARRIAGE_RETURN:13,CHAR_CIRCUMFLEX_ACCENT:94,CHAR_COLON:58,CHAR_COMMA:44,CHAR_DOT:46,CHAR_DOUBLE_QUOTE:34,CHAR_EQUAL:61,CHAR_EXCLAMATION_MARK:33,CHAR_FORM_FEED:12,CHAR_FORWARD_SLASH:47,CHAR_GRAVE_ACCENT:96,CHAR_HASH:35,CHAR_HYPHEN_MINUS:45,CHAR_LEFT_ANGLE_BRACKET:60,CHAR_LEFT_CURLY_BRACE:123,CHAR_LEFT_SQUARE_BRACKET:91,CHAR_LINE_FEED:10,CHAR_NO_BREAK_SPACE:160,CHAR_PERCENT:37,CHAR_PLUS:43,CHAR_QUESTION_MARK:63,CHAR_RIGHT_ANGLE_BRACKET:62,CHAR_RIGHT_CURLY_BRACE:125,CHAR_RIGHT_SQUARE_BRACKET:93,CHAR_SEMICOLON:59,CHAR_SINGLE_QUOTE:39,CHAR_SPACE:32,CHAR_TAB:9,CHAR_UNDERSCORE:95,CHAR_VERTICAL_LINE:124,CHAR_ZERO_WIDTH_NOBREAK_SPACE:65279,extglobChars(t){return{"!":{type:"negate",open:"(?:(?!(?:",close:`))${t.STAR})`},"?":{type:"qmark",open:"(?:",close:")?"},"+":{type:"plus",open:"(?:",close:")+"},"*":{type:"star",open:"(?:",close:")*"},"@":{type:"at",open:"(?:",close:")"}}},globChars(t){return t===!0?YOe:S8}}});var Ep=v(Ur=>{"use strict";var{REGEX_BACKSLASH:QOe,REGEX_REMOVE_BACKSLASH:eTe,REGEX_SPECIAL_CHARS:tTe,REGEX_SPECIAL_CHARS_GLOBAL:rTe}=kp();Ur.isObject=t=>t!==null&&typeof t=="object"&&!Array.isArray(t);Ur.hasRegexChars=t=>tTe.test(t);Ur.isRegexChar=t=>t.length===1&&Ur.hasRegexChars(t);Ur.escapeRegex=t=>t.replace(rTe,"\\$1");Ur.toPosixSlashes=t=>t.replace(QOe,"/");Ur.isWindows=()=>{if(typeof navigator<"u"&&navigator.platform){let t=navigator.platform.toLowerCase();return t==="win32"||t==="windows"}return typeof process<"u"&&process.platform?process.platform==="win32":!1};Ur.removeBackslashes=t=>t.replace(eTe,e=>e==="\\"?"":e);Ur.escapeLast=(t,e,r)=>{let n=t.lastIndexOf(e,r);return n===-1?t:t[n-1]==="\\"?Ur.escapeLast(t,e,n-1):`${t.slice(0,n)}\\${t.slice(n)}`};Ur.removePrefix=(t,e={})=>{let r=t;return r.startsWith("./")&&(r=r.slice(2),e.prefix="./"),r};Ur.wrapOutput=(t,e={},r={})=>{let n=r.contains?"":"^",i=r.contains?"":"$",o=`${n}(?:${t})${i}`;return e.negated===!0&&(o=`(?:^(?!${o}).*$)`),o};Ur.basename=(t,{windows:e}={})=>{let r=t.split(e?/[\\/]/:"/"),n=r[r.length-1];return n===""?r[r.length-2]:n}});var R8=v((ypt,T8)=>{"use strict";var x8=Ep(),{CHAR_ASTERISK:KP,CHAR_AT:nTe,CHAR_BACKWARD_SLASH:Ap,CHAR_COMMA:iTe,CHAR_DOT:JP,CHAR_EXCLAMATION_MARK:YP,CHAR_FORWARD_SLASH:O8,CHAR_LEFT_CURLY_BRACE:XP,CHAR_LEFT_PARENTHESES:QP,CHAR_LEFT_SQUARE_BRACKET:oTe,CHAR_PLUS:sTe,CHAR_QUESTION_MARK:$8,CHAR_RIGHT_CURLY_BRACE:aTe,CHAR_RIGHT_PARENTHESES:k8,CHAR_RIGHT_SQUARE_BRACKET:cTe}=kp(),E8=t=>t===O8||t===Ap,A8=t=>{t.isPrefix!==!0&&(t.depth=t.isGlobstar?1/0:1)},lTe=(t,e)=>{let r=e||{},n=t.length-1,i=r.parts===!0||r.scanToEnd===!0,o=[],s=[],a=[],c=t,l=-1,u=0,d=0,f=!1,p=!1,m=!1,h=!1,g=!1,b=!1,_=!1,S=!1,x=!1,w=!1,R=0,A,O,D={value:"",depth:0,isGlob:!1},E=()=>l>=n,ae=()=>c.charCodeAt(l+1),X=()=>(A=O,c.charCodeAt(++l));for(;l0&&(P=c.slice(0,u),c=c.slice(u),d-=u),J&&m===!0&&d>0?(J=c.slice(0,d),C=c.slice(d)):m===!0?(J="",C=c):J=c,J&&J!==""&&J!=="/"&&J!==c&&E8(J.charCodeAt(J.length-1))&&(J=J.slice(0,-1)),r.unescape===!0&&(C&&(C=x8.removeBackslashes(C)),J&&_===!0&&(J=x8.removeBackslashes(J)));let dr={prefix:P,input:t,start:u,base:J,glob:C,isBrace:f,isBracket:p,isGlob:m,isExtglob:h,isGlobstar:g,negated:S,negatedExtglob:x};if(r.tokens===!0&&(dr.maxDepth=0,E8(O)||s.push(D),dr.tokens=s),r.parts===!0||r.tokens===!0){let se;for(let Ce=0;Ce{"use strict";var Op=kp(),ln=Ep(),{MAX_LENGTH:Vv,POSIX_REGEX_SOURCE:uTe,REGEX_NON_SPECIAL_CHARS:dTe,REGEX_SPECIAL_CHARS_BACKREF:fTe,REPLACEMENTS:I8}=Op,pTe=(t,e)=>{if(typeof e.expandRange=="function")return e.expandRange(...t,e);t.sort();let r=`[${t.join("-")}]`;try{new RegExp(r)}catch{return t.map(i=>ln.escapeRegex(i)).join("..")}return r},Yl=(t,e)=>`Missing ${t}: "${e}" - use "\\\\${e}" to match literal characters`,P8=t=>{let e=[],r=0,n=0,i=0,o="",s=!1;for(let a of t){if(s===!0){o+=a,s=!1;continue}if(a==="\\"){o+=a,s=!0;continue}if(a==='"'){i=i===1?0:1,o+=a;continue}if(i===0){if(a==="[")r++;else if(a==="]"&&r>0)r--;else if(r===0){if(a==="(")n++;else if(a===")"&&n>0)n--;else if(a==="|"&&n===0){e.push(o),o="";continue}}}o+=a}return e.push(o),e},mTe=t=>{let e=!1;for(let r of t){if(e===!0){e=!1;continue}if(r==="\\"){e=!0;continue}if(/[?*+@!()[\]{}]/.test(r))return!1}return!0},tC=t=>{let e=t.trim(),r=!0;for(;r===!0;)r=!1,/^@\([^\\()[\]{}|]+\)$/.test(e)&&(e=e.slice(2,-1),r=!0);if(mTe(e))return e.replace(/\\(.)/g,"$1")},hTe=t=>{let e=t.map(tC).filter(Boolean);for(let r=0;r{if(t[0]!=="+"&&t[0]!=="*"||t[1]!=="(")return;let r=0,n=0,i=0,o=!1;for(let s=1;s0){r--;continue}if(!(r>0)){if(a==="("){n++;continue}if(a===")"&&(n--,n===0))return e===!0&&s!==t.length-1?void 0:{type:t[0],body:t.slice(2,s),end:s}}}}},gTe=t=>`${t.length===1?ln.escapeRegex(t[0]):`[${t.map(r=>ln.escapeRegex(r)).join("")}]`}*`,yTe=t=>{let e=0,r=[];for(;es.trim());if(i.length!==1)return;let o=tC(i[0]);if(!o||o.length!==1)return;r.push(o),e+=n.end+1}if(!(r.length<1))return r},_Te=t=>{let e=0,r=t.trim(),n=eC(r);for(;n;)e++,r=n.body.trim(),n=eC(r);return e},bTe=(t,e)=>{if(e.maxExtglobRecursion===!1)return{risky:!1};let r=typeof e.maxExtglobRecursion=="number"?e.maxExtglobRecursion:Op.DEFAULT_MAX_EXTGLOB_RECURSION,n=P8(t).map(a=>a.trim());if(n.length>1&&(n.some(a=>a==="")||n.some(a=>/^[*?]+$/.test(a))||hTe(n)))return{risky:!0};let i=[],o=!1,s=!0;for(let a of n){let c=yTe(a);if(c){o=!0,i.push(...c);continue}let l=tC(a);if(l&&l.length===1){i.push(l);continue}if(s=!1,_Te(a)>r)return{risky:!0}}return o?s?{risky:!0,safeOutput:gTe([...new Set(i)])}:{risky:!0}:{risky:!1}},rC=(t,e)=>{if(typeof t!="string")throw new TypeError("Expected a string");t=I8[t]||t;let r={...e},n=typeof r.maxLength=="number"?Math.min(Vv,r.maxLength):Vv,i=t.length;if(i>n)throw new SyntaxError(`Input length: ${i}, exceeds maximum allowed length: ${n}`);let o={type:"bos",value:"",output:r.prepend||""},s=[o],a=r.capture?"":"?:",c=Op.globChars(r.windows),l=Op.extglobChars(c),{DOT_LITERAL:u,PLUS_LITERAL:d,SLASH_LITERAL:f,ONE_CHAR:p,DOTS_SLASH:m,NO_DOT:h,NO_DOT_SLASH:g,NO_DOTS_SLASH:b,QMARK:_,QMARK_NO_DOT:S,STAR:x,START_ANCHOR:w}=c,R=G=>`(${a}(?:(?!${w}${G.dot?m:u}).)*?)`,A=r.dot?"":h,O=r.dot?_:S,D=r.bash===!0?R(r):x;r.capture&&(D=`(${D})`),typeof r.noext=="boolean"&&(r.noextglob=r.noext);let E={input:t,index:-1,start:0,dot:r.dot===!0,consumed:"",output:"",prefix:"",backtrack:!1,negated:!1,brackets:0,braces:0,parens:0,quotes:0,globstar:!1,tokens:s};t=ln.removePrefix(t,E),i=t.length;let ae=[],X=[],J=[],P=o,C,dr=()=>E.index===i-1,se=E.peek=(G=1)=>t[E.index+G],Ce=E.advance=()=>t[++E.index]||"",Kt=()=>t.slice(E.index+1),fr=(G="",ht=0)=>{E.consumed+=G,E.index+=ht},Qt=G=>{E.output+=G.output!=null?G.output:G.value,fr(G.value)},fo=()=>{let G=1;for(;se()==="!"&&(se(2)!=="("||se(3)==="?");)Ce(),E.start++,G++;return G%2===0?!1:(E.negated=!0,E.start++,!0)},ki=G=>{E[G]++,J.push(G)},tn=G=>{E[G]--,J.pop()},fe=G=>{if(P.type==="globstar"){let ht=E.braces>0&&(G.type==="comma"||G.type==="brace"),B=G.extglob===!0||ae.length&&(G.type==="pipe"||G.type==="paren");G.type!=="slash"&&G.type!=="paren"&&!ht&&!B&&(E.output=E.output.slice(0,-P.output.length),P.type="star",P.value="*",P.output=D,E.output+=P.output)}if(ae.length&&G.type!=="paren"&&(ae[ae.length-1].inner+=G.value),(G.value||G.output)&&Qt(G),P&&P.type==="text"&&G.type==="text"){P.output=(P.output||P.value)+G.value,P.value+=G.value;return}G.prev=P,s.push(G),P=G},po=(G,ht)=>{let B={...l[ht],conditions:1,inner:""};B.prev=P,B.parens=E.parens,B.output=E.output,B.startIndex=E.index,B.tokensIndex=s.length;let Te=(r.capture?"(":"")+B.open;ki("parens"),fe({type:G,value:ht,output:E.output?"":p}),fe({type:"paren",extglob:!0,value:Ce(),output:Te}),ae.push(B)},Nfe=G=>{let ht=t.slice(G.startIndex,E.index+1),B=t.slice(G.startIndex+2,E.index),Te=bTe(B,r);if((G.type==="plus"||G.type==="star")&&Te.risky){let ut=Te.safeOutput?(G.output?"":p)+(r.capture?`(${Te.safeOutput})`:Te.safeOutput):void 0,Ei=s[G.tokensIndex];Ei.type="text",Ei.value=ht,Ei.output=ut||ln.escapeRegex(ht);for(let Ai=G.tokensIndex+1;Ai1&&G.inner.includes("/")&&(ut=R(r)),(ut!==D||dr()||/^\)+$/.test(Kt()))&&(dt=G.close=`)$))${ut}`),G.inner.includes("*")&&(zt=Kt())&&/^\.[^\\/.]+$/.test(zt)){let Ei=rC(zt,{...e,fastpaths:!1}).output;dt=G.close=`)${Ei})${ut})`}G.prev.type==="bos"&&(E.negatedExtglob=!0)}fe({type:"paren",extglob:!0,value:C,output:dt}),tn("parens")};if(r.fastpaths!==!1&&!/(^[*!]|[/()[\]{}"])/.test(t)){let G=!1,ht=t.replace(fTe,(B,Te,dt,zt,ut,Ei)=>zt==="\\"?(G=!0,B):zt==="?"?Te?Te+zt+(ut?_.repeat(ut.length):""):Ei===0?O+(ut?_.repeat(ut.length):""):_.repeat(dt.length):zt==="."?u.repeat(dt.length):zt==="*"?Te?Te+zt+(ut?D:""):D:Te?B:`\\${B}`);return G===!0&&(r.unescape===!0?ht=ht.replace(/\\/g,""):ht=ht.replace(/\\+/g,B=>B.length%2===0?"\\\\":B?"\\":"")),ht===t&&r.contains===!0?(E.output=t,E):(E.output=ln.wrapOutput(ht,E,e),E)}for(;!dr();){if(C=Ce(),C==="\0")continue;if(C==="\\"){let B=se();if(B==="/"&&r.bash!==!0||B==="."||B===";")continue;if(!B){C+="\\",fe({type:"text",value:C});continue}let Te=/^\\+/.exec(Kt()),dt=0;if(Te&&Te[0].length>2&&(dt=Te[0].length,E.index+=dt,dt%2!==0&&(C+="\\")),r.unescape===!0?C=Ce():C+=Ce(),E.brackets===0){fe({type:"text",value:C});continue}}if(E.brackets>0&&(C!=="]"||P.value==="["||P.value==="[^")){if(r.posix!==!1&&C===":"){let B=P.value.slice(1);if(B.includes("[")&&(P.posix=!0,B.includes(":"))){let Te=P.value.lastIndexOf("["),dt=P.value.slice(0,Te),zt=P.value.slice(Te+2),ut=uTe[zt];if(ut){P.value=dt+ut,E.backtrack=!0,Ce(),!o.output&&s.indexOf(P)===1&&(o.output=p);continue}}}(C==="["&&se()!==":"||C==="-"&&se()==="]")&&(C=`\\${C}`),C==="]"&&(P.value==="["||P.value==="[^")&&(C=`\\${C}`),r.posix===!0&&C==="!"&&P.value==="["&&(C="^"),P.value+=C,Qt({value:C});continue}if(E.quotes===1&&C!=='"'){C=ln.escapeRegex(C),P.value+=C,Qt({value:C});continue}if(C==='"'){E.quotes=E.quotes===1?0:1,r.keepQuotes===!0&&fe({type:"text",value:C});continue}if(C==="("){ki("parens"),fe({type:"paren",value:C});continue}if(C===")"){if(E.parens===0&&r.strictBrackets===!0)throw new SyntaxError(Yl("opening","("));let B=ae[ae.length-1];if(B&&E.parens===B.parens+1){Nfe(ae.pop());continue}fe({type:"paren",value:C,output:E.parens?")":"\\)"}),tn("parens");continue}if(C==="["){if(r.nobracket===!0||!Kt().includes("]")){if(r.nobracket!==!0&&r.strictBrackets===!0)throw new SyntaxError(Yl("closing","]"));C=`\\${C}`}else ki("brackets");fe({type:"bracket",value:C});continue}if(C==="]"){if(r.nobracket===!0||P&&P.type==="bracket"&&P.value.length===1){fe({type:"text",value:C,output:`\\${C}`});continue}if(E.brackets===0){if(r.strictBrackets===!0)throw new SyntaxError(Yl("opening","["));fe({type:"text",value:C,output:`\\${C}`});continue}tn("brackets");let B=P.value.slice(1);if(P.posix!==!0&&B[0]==="^"&&!B.includes("/")&&(C=`/${C}`),P.value+=C,Qt({value:C}),r.literalBrackets===!1||ln.hasRegexChars(B))continue;let Te=ln.escapeRegex(P.value);if(E.output=E.output.slice(0,-P.value.length),r.literalBrackets===!0){E.output+=Te,P.value=Te;continue}P.value=`(${a}${Te}|${P.value})`,E.output+=P.value;continue}if(C==="{"&&r.nobrace!==!0){ki("braces");let B={type:"brace",value:C,output:"(",outputIndex:E.output.length,tokensIndex:E.tokens.length};X.push(B),fe(B);continue}if(C==="}"){let B=X[X.length-1];if(r.nobrace===!0||!B){fe({type:"text",value:C,output:C});continue}let Te=")";if(B.dots===!0){let dt=s.slice(),zt=[];for(let ut=dt.length-1;ut>=0&&(s.pop(),dt[ut].type!=="brace");ut--)dt[ut].type!=="dots"&&zt.unshift(dt[ut].value);Te=pTe(zt,r),E.backtrack=!0}if(B.comma!==!0&&B.dots!==!0){let dt=E.output.slice(0,B.outputIndex),zt=E.tokens.slice(B.tokensIndex);B.value=B.output="\\{",C=Te="\\}",E.output=dt;for(let ut of zt)E.output+=ut.output||ut.value}fe({type:"brace",value:C,output:Te}),tn("braces"),X.pop();continue}if(C==="|"){ae.length>0&&ae[ae.length-1].conditions++,fe({type:"text",value:C});continue}if(C===","){let B=C,Te=X[X.length-1];Te&&J[J.length-1]==="braces"&&(Te.comma=!0,B="|"),fe({type:"comma",value:C,output:B});continue}if(C==="/"){if(P.type==="dot"&&E.index===E.start+1){E.start=E.index+1,E.consumed="",E.output="",s.pop(),P=o;continue}fe({type:"slash",value:C,output:f});continue}if(C==="."){if(E.braces>0&&P.type==="dot"){P.value==="."&&(P.output=u);let B=X[X.length-1];P.type="dots",P.output+=C,P.value+=C,B.dots=!0;continue}if(E.braces+E.parens===0&&P.type!=="bos"&&P.type!=="slash"){fe({type:"text",value:C,output:u});continue}fe({type:"dot",value:C,output:u});continue}if(C==="?"){if(!(P&&P.value==="(")&&r.noextglob!==!0&&se()==="("&&se(2)!=="?"){po("qmark",C);continue}if(P&&P.type==="paren"){let Te=se(),dt=C;(P.value==="("&&!/[!=<:]/.test(Te)||Te==="<"&&!/<([!=]|\w+>)/.test(Kt()))&&(dt=`\\${C}`),fe({type:"text",value:C,output:dt});continue}if(r.dot!==!0&&(P.type==="slash"||P.type==="bos")){fe({type:"qmark",value:C,output:S});continue}fe({type:"qmark",value:C,output:_});continue}if(C==="!"){if(r.noextglob!==!0&&se()==="("&&(se(2)!=="?"||!/[!=<:]/.test(se(3)))){po("negate",C);continue}if(r.nonegate!==!0&&E.index===0){fo();continue}}if(C==="+"){if(r.noextglob!==!0&&se()==="("&&se(2)!=="?"){po("plus",C);continue}if(P&&P.value==="("||r.regex===!1){fe({type:"plus",value:C,output:d});continue}if(P&&(P.type==="bracket"||P.type==="paren"||P.type==="brace")||E.parens>0){fe({type:"plus",value:C});continue}fe({type:"plus",value:d});continue}if(C==="@"){if(r.noextglob!==!0&&se()==="("&&se(2)!=="?"){fe({type:"at",extglob:!0,value:C,output:""});continue}fe({type:"text",value:C});continue}if(C!=="*"){(C==="$"||C==="^")&&(C=`\\${C}`);let B=dTe.exec(Kt());B&&(C+=B[0],E.index+=B[0].length),fe({type:"text",value:C});continue}if(P&&(P.type==="globstar"||P.star===!0)){P.type="star",P.star=!0,P.value+=C,P.output=D,E.backtrack=!0,E.globstar=!0,fr(C);continue}let G=Kt();if(r.noextglob!==!0&&/^\([^?]/.test(G)){po("star",C);continue}if(P.type==="star"){if(r.noglobstar===!0){fr(C);continue}let B=P.prev,Te=B.prev,dt=B.type==="slash"||B.type==="bos",zt=Te&&(Te.type==="star"||Te.type==="globstar");if(r.bash===!0&&(!dt||G[0]&&G[0]!=="/")){fe({type:"star",value:C,output:""});continue}let ut=E.braces>0&&(B.type==="comma"||B.type==="brace"),Ei=ae.length&&(B.type==="pipe"||B.type==="paren");if(!dt&&B.type!=="paren"&&!ut&&!Ei){fe({type:"star",value:C,output:""});continue}for(;G.slice(0,3)==="/**";){let Ai=t[E.index+4];if(Ai&&Ai!=="/")break;G=G.slice(3),fr("/**",3)}if(B.type==="bos"&&dr()){P.type="globstar",P.value+=C,P.output=R(r),E.output=P.output,E.globstar=!0,fr(C);continue}if(B.type==="slash"&&B.prev.type!=="bos"&&!zt&&dr()){E.output=E.output.slice(0,-(B.output+P.output).length),B.output=`(?:${B.output}`,P.type="globstar",P.output=R(r)+(r.strictSlashes?")":"|$)"),P.value+=C,E.globstar=!0,E.output+=B.output+P.output,fr(C);continue}if(B.type==="slash"&&B.prev.type!=="bos"&&G[0]==="/"){let Ai=G[1]!==void 0?"|$":"";E.output=E.output.slice(0,-(B.output+P.output).length),B.output=`(?:${B.output}`,P.type="globstar",P.output=`${R(r)}${f}|${f}${Ai})`,P.value+=C,E.output+=B.output+P.output,E.globstar=!0,fr(C+Ce()),fe({type:"slash",value:"/",output:""});continue}if(B.type==="bos"&&G[0]==="/"){P.type="globstar",P.value+=C,P.output=`(?:^|${f}|${R(r)}${f})`,E.output=P.output,E.globstar=!0,fr(C+Ce()),fe({type:"slash",value:"/",output:""});continue}E.output=E.output.slice(0,-P.output.length),P.type="globstar",P.output=R(r),P.value+=C,E.output+=P.output,E.globstar=!0,fr(C);continue}let ht={type:"star",value:C,output:D};if(r.bash===!0){ht.output=".*?",(P.type==="bos"||P.type==="slash")&&(ht.output=A+ht.output),fe(ht);continue}if(P&&(P.type==="bracket"||P.type==="paren")&&r.regex===!0){ht.output=C,fe(ht);continue}(E.index===E.start||P.type==="slash"||P.type==="dot")&&(P.type==="dot"?(E.output+=g,P.output+=g):r.dot===!0?(E.output+=b,P.output+=b):(E.output+=A,P.output+=A),se()!=="*"&&(E.output+=p,P.output+=p)),fe(ht)}for(;E.brackets>0;){if(r.strictBrackets===!0)throw new SyntaxError(Yl("closing","]"));E.output=ln.escapeLast(E.output,"["),tn("brackets")}for(;E.parens>0;){if(r.strictBrackets===!0)throw new SyntaxError(Yl("closing",")"));E.output=ln.escapeLast(E.output,"("),tn("parens")}for(;E.braces>0;){if(r.strictBrackets===!0)throw new SyntaxError(Yl("closing","}"));E.output=ln.escapeLast(E.output,"{"),tn("braces")}if(r.strictSlashes!==!0&&(P.type==="star"||P.type==="bracket")&&fe({type:"maybe_slash",value:"",output:`${f}?`}),E.backtrack===!0){E.output="";for(let G of E.tokens)E.output+=G.output!=null?G.output:G.value,G.suffix&&(E.output+=G.suffix)}return E};rC.fastpaths=(t,e)=>{let r={...e},n=typeof r.maxLength=="number"?Math.min(Vv,r.maxLength):Vv,i=t.length;if(i>n)throw new SyntaxError(`Input length: ${i}, exceeds maximum allowed length: ${n}`);t=I8[t]||t;let{DOT_LITERAL:o,SLASH_LITERAL:s,ONE_CHAR:a,DOTS_SLASH:c,NO_DOT:l,NO_DOTS:u,NO_DOTS_SLASH:d,STAR:f,START_ANCHOR:p}=Op.globChars(r.windows),m=r.dot?u:l,h=r.dot?d:l,g=r.capture?"":"?:",b={negated:!1,prefix:""},_=r.bash===!0?".*?":f;r.capture&&(_=`(${_})`);let S=A=>A.noglobstar===!0?_:`(${g}(?:(?!${p}${A.dot?c:o}).)*?)`,x=A=>{switch(A){case"*":return`${m}${a}${_}`;case".*":return`${o}${a}${_}`;case"*.*":return`${m}${_}${o}${a}${_}`;case"*/*":return`${m}${_}${s}${a}${h}${_}`;case"**":return m+S(r);case"**/*":return`(?:${m}${S(r)}${s})?${h}${a}${_}`;case"**/*.*":return`(?:${m}${S(r)}${s})?${h}${_}${o}${a}${_}`;case"**/.*":return`(?:${m}${S(r)}${s})?${o}${a}${_}`;default:{let O=/^(.*?)\.(\w+)$/.exec(A);if(!O)return;let D=x(O[1]);return D?D+o+O[2]:void 0}}},w=ln.removePrefix(t,b),R=x(w);return R&&r.strictSlashes!==!0&&(R+=`${s}?`),R};C8.exports=rC});var M8=v((bpt,j8)=>{"use strict";var vTe=R8(),nC=D8(),N8=Ep(),STe=kp(),wTe=t=>t&&typeof t=="object"&&!Array.isArray(t),Rt=(t,e,r=!1)=>{if(Array.isArray(t)){let u=t.map(f=>Rt(f,e,r));return f=>{for(let p of u){let m=p(f);if(m)return m}return!1}}let n=wTe(t)&&t.tokens&&t.input;if(t===""||typeof t!="string"&&!n)throw new TypeError("Expected pattern to be a non-empty string");let i=e||{},o=i.windows,s=n?Rt.compileRe(t,e):Rt.makeRe(t,e,!1,!0),a=s.state;delete s.state;let c=()=>!1;if(i.ignore){let u={...e,ignore:null,onMatch:null,onResult:null};c=Rt(i.ignore,u,r)}let l=(u,d=!1)=>{let{isMatch:f,match:p,output:m}=Rt.test(u,s,e,{glob:t,posix:o}),h={glob:t,state:a,regex:s,posix:o,input:u,output:m,match:p,isMatch:f};return typeof i.onResult=="function"&&i.onResult(h),f===!1?(h.isMatch=!1,d?h:!1):c(u)?(typeof i.onIgnore=="function"&&i.onIgnore(h),h.isMatch=!1,d?h:!1):(typeof i.onMatch=="function"&&i.onMatch(h),d?h:!0)};return r&&(l.state=a),l};Rt.test=(t,e,r,{glob:n,posix:i}={})=>{if(typeof t!="string")throw new TypeError("Expected input to be a string");if(t==="")return{isMatch:!1,output:""};let o=r||{},s=o.format||(i?N8.toPosixSlashes:null),a=t===n,c=a&&s?s(t):t;return a===!1&&(c=s?s(t):t,a=c===n),(a===!1||o.capture===!0)&&(o.matchBase===!0||o.basename===!0?a=Rt.matchBase(t,e,r,i):a=e.exec(c)),{isMatch:!!a,match:a,output:c}};Rt.matchBase=(t,e,r,n=r&&r.windows)=>(e instanceof RegExp?e:Rt.makeRe(e,r)).test(N8.basename(t,{windows:n}));Rt.isMatch=(t,e,r)=>Rt(e,r)(t);Rt.parse=(t,e)=>Array.isArray(t)?t.map(r=>Rt.parse(r,e)):nC(t,{...e,fastpaths:!1});Rt.scan=(t,e)=>vTe(t,e);Rt.compileRe=(t,e,r=!1,n=!1)=>{if(r===!0)return t.output;let i=e||{},o=i.contains?"":"^",s=i.contains?"":"$",a=`${o}(?:${t.output})${s}`;t&&t.negated===!0&&(a=`^(?!${a}).*$`);let c=Rt.toRegex(a,e);return n===!0&&(c.state=t),c};Rt.makeRe=(t,e={},r=!1,n=!1)=>{if(!t||typeof t!="string")throw new TypeError("Expected a non-empty string");let i={negated:!1,fastpaths:!0};return e.fastpaths!==!1&&(t[0]==="."||t[0]==="*")&&(i.output=nC.fastpaths(t,e)),i.output||(i=nC(t,e)),Rt.compileRe(i,e,r,n)};Rt.toRegex=(t,e)=>{try{let r=e||{};return new RegExp(t,r.flags||(r.nocase?"i":""))}catch(r){if(e&&e.debug===!0)throw r;return/$^/}};Rt.constants=STe;j8.exports=Rt});var U8=v((vpt,z8)=>{"use strict";var F8=M8(),xTe=Ep();function L8(t,e,r=!1){return e&&(e.windows===null||e.windows===void 0)&&(e={...e,windows:xTe.isWindows()}),F8(t,e,r)}Object.assign(L8,F8);z8.exports=L8});import{readdir as $Te,readdirSync as kTe,realpath as ETe,realpathSync as ATe,stat as OTe,statSync as TTe}from"fs";import{isAbsolute as RTe,posix as Wa,resolve as ITe}from"path";import{fileURLToPath as PTe}from"url";function jTe(t,e={}){let r=t.length,n=Array(r),i=Array(r),o,s;for(o=0;o{let c=a.split("/");if(c[0]===".."&&NTe.test(a))return!0;for(o=0;oo.slice(i,s?-1:void 0)||"."}let n=e.slice(t.length+1);return n?(i,o)=>{if(i===".")return n;let s=`${n}/${i}`;return o?s.slice(0,-1):s}:(i,o)=>o&&i!=="."?i.slice(0,-1):i}return r?n=>Wa.relative(t,n)||".":n=>Wa.relative(t,`${e}/${n}`)||"."}function LTe(t,e){if(e.startsWith(`${t}/`)){let r=e.slice(t.length+1);return n=>`${r}/${n}`}return r=>{let n=Wa.relative(t,`${e}/${r}`);return r[r.length-1]==="/"&&n!==""?`${n}/`:n||"."}}function H8(t){return t.replace(DTe,e=>`${e}/`)}function V8(t){var e;let r=Xl.default.scan(t,zTe);return!((e=r.parts)===null||e===void 0)&&e.length?r.parts:[t]}function ZTe(t,e){if(e?.caseSensitiveMatch===!1)return!0;let r=Xl.default.scan(t);return r.isGlob||r.negated}function Tp(...t){console.log(`[tinyglobby ${new Date().toLocaleTimeString("es")}]`,...t)}function W8(t){return typeof t=="string"?[t]:t??[]}function iC(t,e,r,n){var i;let o=e.cwd,s=t;t[t.length-1]==="/"&&(s=t.slice(0,-1)),s[s.length-1]!=="*"&&e.expandDirectories&&(s+="/**");let a=GTe(o);s=RTe(s.replace(WTe,""))?Wa.relative(a,s):Wa.normalize(s);let c=(i=VTe.exec(s))===null||i===void 0?void 0:i[0],l=V8(s);if(c){let d=(c.length+1)/3,f=0,p=a.split("/");for(;fm.length&&(r.root=H8(m),r.depthOffset=-d+f)}if(!n&&r.depthOffset>=0){var u;(u=r.commonPath)!==null&&u!==void 0||(r.commonPath=l);let d=[],f=Math.min(r.commonPath.length,l.length);for(let p=0;p0?Wa.join(o,...d):o)}return s}function KTe(t,e,r){let n=[],i=[];for(let o of t.ignore)o&&(o[0]!=="!"||o[1]==="(")&&i.push(iC(o,t,r,!0));for(let o of e)o&&(o[0]!=="!"||o[1]==="("?n.push(iC(o,t,r,!1)):(o[1]!=="!"||o[2]==="(")&&i.push(iC(o.slice(1),t,r,!0)));return{match:n,ignore:i}}function JTe(t,e){let r=t.cwd,n={root:r,depthOffset:0},i=KTe(t,e,n);t.debug&&Tp("internal processing patterns:",i);let{absolute:o,caseSensitiveMatch:s,debug:a,dot:c,followSymbolicLinks:l,onlyDirectories:u}=t,d=n.root.replace(G8,""),f={dot:c,nobrace:t.braceExpansion===!1,nocase:!s,noextglob:t.extglob===!1,noglobstar:t.globstar===!1,posix:!0},p=(0,Xl.default)(i.match,f),m=(0,Xl.default)(i.ignore,f),h=jTe(i.match,f),g=q8(r,d,o),b=o?g:q8(r,d,!0),_=(w,R)=>{let A=b(R,!0);return A!=="."&&!h(A)||m(A)},S;t.deep!==void 0&&(S=Math.round(t.deep-n.depthOffset));let x=new g8({filters:[a?(w,R)=>{let A=g(w,R),O=p(A)&&!m(A);return O&&Tp(`matched ${A}`),O}:(w,R)=>{let A=g(w,R);return p(A)&&!m(A)}],exclude:a?(w,R)=>{let A=_(w,R);return Tp(`${A?"skipped":"crawling"} ${R}`),A}:_,fs:t.fs,pathSeparator:"/",relativePaths:!o,resolvePaths:o,includeBasePath:o,resolveSymlinks:l,excludeSymlinks:!l,excludeFiles:u,includeDirs:u||!t.onlyFiles,maxDepth:S,signal:t.signal}).crawl(d);return t.debug&&Tp("internal properties:",{...n,root:d}),[x,r!==d&&!o&<e(r,d)]}function YTe(t,e){if(e)for(let r=t.length-1;r>=0;r--)t[r]=e(t[r]);return t}function XTe(t){let e=Object.assign({},t);for(let r in B8)e[r]===void 0&&Object.assign(e,{[r]:B8[r]});return e.cwd=(e.cwd instanceof URL?PTe(e.cwd):ITe(e.cwd||process.cwd())).replace(G8,"/"),e.ignore=W8(e.ignore),e.fs&&(e.fs={readdir:e.fs.readdir||$Te,readdirSync:e.fs.readdirSync||kTe,realpath:e.fs.realpath||ETe,realpathSync:e.fs.realpathSync||ATe,stat:e.fs.stat||OTe,statSync:e.fs.statSync||TTe}),e.debug&&Tp("globbing with options:",e),e}function QTe(t,e={}){var r;if(t&&e?.patterns)throw new Error("Cannot pass patterns as both an argument and an option");let n=CTe(t)||typeof t=="string",i=W8((r=n?t:t.patterns)!==null&&r!==void 0?r:"**/*"),o=XTe(n?e:t);return i.length>0?JTe(o,i):[]}function vs(t,e){let[r,n]=QTe(t,e);return r?YTe(r.sync(),n):[]}var Xl,CTe,G8,DTe,Z8,NTe,MTe,FTe,zTe,UTe,qTe,HTe,BTe,GTe,VTe,WTe,B8,Rp=y(()=>{y8();Xl=wt(U8(),1),CTe=Array.isArray,G8=/\\/g,DTe=/^[A-Za-z]:$/,Z8=process.platform==="win32",NTe=/^(\/?\.\.)+$/;MTe=/^[A-Z]:\/$/i,FTe=Z8?t=>MTe.test(t):t=>t==="/";zTe={parts:!0};UTe=/(?t.replace(UTe,"\\$&"),BTe=t=>t.replace(qTe,"\\$&"),GTe=Z8?BTe:HTe;VTe=/^(\/?\.\.)+/,WTe=/\\(?=[()[\]{}!*+?@|])/g;B8={caseSensitiveMatch:!0,debug:!!process.env.TINYGLOBBY_DEBUG,expandDirectories:!0,followSymbolicLinks:!0,onlyFiles:!0}});import{existsSync as Ip,readFileSync as eRe,readdirSync as tRe,statSync as K8}from"node:fs";import{join as Ka}from"node:path";function rRe(t){let{cwd:e="."}=t,r,n;try{let c=q(e);r=c.architecture,n=c.project?.language}catch{return[]}if(!r)return[];let i=Li(e,n),o=[],{layers:s,forbiddenImports:a}=oC(r);return(s.size>0||a.length>0)&&!Ip(Ka(e,i.mainRoot))?[{detector:Pp,severity:"info",path:`${i.mainRoot}/`,message:`architecture layers declared but ${i.mainRoot}/ not found \u2014 layer checks skipped (flat layout not yet supported)`}]:(s.size>0&&(nRe(e,i,s,o),iRe(e,i,s,o)),a.length>0&&oRe(e,i,a,o),o)}function oC(t){let e=new Set,r=[];for(let i of t.layers??[])if(Array.isArray(i))for(let o of i)e.add(o);else{let o=i;if(typeof o.name=="string"&&o.name.length>0){e.add(o.name);for(let s of o.forbidden_imports??[])typeof s=="string"&&r.push({from:o.name,to:s})}}let n=t.forbidden_imports??[];return{layers:e,forbiddenImports:[...n,...r]}}function nRe(t,e,r,n){let i=e.mainRoot,o=Ka(t,i);if(Ip(o))for(let s of tRe(o)){let a=Ka(o,s);K8(a).isDirectory()&&(r.has(s)||n.push({detector:Pp,severity:"warn",path:`${i}/${s}/`,message:`${i}/${s}/ is not declared in spec/architecture.yaml layers \u2014 add it or remove the directory`}))}}function iRe(t,e,r,n){let i=e.mainRoot,o=Ka(t,i);if(Ip(o))for(let s of r){let a=Ka(o,s);Ip(a)&&K8(a).isDirectory()||n.push({detector:Pp,severity:"warn",path:`${i}/${s}/`,message:`spec/architecture.yaml declares layer '${s}' but ${i}/${s}/ does not exist \u2014 fix the spec or create the directory`})}}function oRe(t,e,r,n){let i=e.mainRoot,o=e.importMatcher;for(let s of r){let a=Ka(t,i,s.from);if(!Ip(a))continue;let c=vs([`**/*.${e.ext}`],{cwd:a,dot:!1});for(let l of c){let u=Ka(a,l),d;try{d=eRe(u,"utf8")}catch{continue}let f;for(o.lastIndex=0;(f=o.exec(d))!==null;){let p=f[1];sRe(p,s.to,e.importStyle)&&n.push({detector:Pp,severity:"error",path:`${i}/${s.from}/${l}`,message:`${i}/${s.from}/${l} imports from '${p}' which crosses into the '${s.to}' layer \u2014 spec/architecture.yaml forbids imports from '${s.from}' to '${s.to}'`})}}}}function sRe(t,e,r){return r==="dotted"?t.split(".").includes(e):t.startsWith(".")?t.split("/").includes(e):!1}var Pp,J8,sC=y(()=>{"use strict";Rp();Ue();Va();Pp="ARCHITECTURE_FROM_SPEC";J8={name:Pp,run:rRe}});import{existsSync as aRe,readFileSync as cRe}from"node:fs";import{join as lRe}from"node:path";function dRe(t){let{cwd:e="."}=t,r=lRe(e,"spec/capabilities.yaml");if(!aRe(r))return[];let n;try{let u=cRe(r,"utf8"),d=Y8.default.parse(u);if(!d||typeof d!="object")return[];n=d}catch{return[]}let i=n.capabilities??[];if(i.length===0)return[];let o,s=!1;try{let u=q(e);o=new Set(u.features.map(d=>d.id)),s=u.project.onboarding_seeded===!0}catch{return[]}let a=[],c=new Set,l=s&&o.size{"use strict";Y8=wt(tr(),1);Ue();Wv="CAPABILITIES_FEATURE_MAPPING",uRe=8;X8={name:Wv,run:dRe}});import{existsSync as fRe,readFileSync as pRe}from"node:fs";import{join as mRe}from"node:path";function hRe(t){let e=t.trimStart();return e.startsWith("//")||e.startsWith("/*")||e.startsWith("#")||e.startsWith('"""')||e.startsWith("'''")}function gRe(t){let{cwd:e="."}=t;return ye(e,aC,r=>yRe(r,e))}function yRe(t,e){let r=Li(e,t.project?.language),n=[];for(let i of t.features)for(let o of i.modules??[]){if(!r.extensions.some(c=>o.endsWith(c)))continue;let s=mRe(e,o);if(!fRe(s))continue;let a=pRe(s,"utf8");hRe(a)||n.push({detector:aC,severity:"warn",path:o,message:`${o} has no file-header comment \u2014 Why>What guardrail recommends a one-line intent`})}return n}var aC,e5,t5=y(()=>{"use strict";Va();xt();aC="CONVENTION_DRIFT";e5={name:aC,run:gRe}});import{existsSync as cC,readFileSync as r5}from"node:fs";import{join as Kv}from"node:path";function _Re(t){return JSON.parse(t).total?.lines?.pct??0}function n5(t){let e=/]*\bline-rate="([0-9]*\.?[0-9]+)"/.exec(t);return e?Number(e[1])*100:null}function SRe(t,e){if(!Cv(_t(t).gates.coverage?.cmd))return null;let r;try{r=Dv(t,e)}catch(c){return[{detector:Eo,severity:"error",message:c.message}]}let n=0,i=0,o=0,s=[];for(let c of r){let l=MP.find(d=>cC(Kv(c.dir,d)));if(!l){s.push(c.path);continue}let u=n5(r5(Kv(c.dir,l),"utf8"));u&&(n+=u.missed,i+=u.covered,o++)}if(o===0)return[{detector:Eo,severity:"info",message:`no module coverage report present for ${r.map(c=>c.path).join(", ")} \u2014 run stage_2.2 first`}];let a=i5(n,i);return a0?[{detector:Eo,severity:"info",message:`module coverage ${a.toFixed(1)}% OK; no report yet for ${s.join(", ")}`}]:[]}function wRe(t){let{cwd:e="."}=t;if(t.focusModules&&t.focusModules.length>0){let a=SRe(e,t.focusModules);if(a)return a}let r;try{r=q(e).project?.language}catch{}let n=Li(e,r),i=_t(e).language==="kotlin"?MP.find(a=>cC(Kv(e,a)))??FJ(e):n.coverageSummary,o=Kv(e,i);if(!cC(o))return[{detector:Eo,severity:"info",message:`${i} not present \u2014 run stage_2.2 first`}];let s;try{let a=r5(o,"utf8");s=n.coverageFormat==="jacoco-xml"?bRe(a):n.coverageFormat==="cobertura-xml"?vRe(a):_Re(a)}catch(a){return[{detector:Eo,severity:"warn",message:`${i} unparseable: ${a.message}`}]}return s===null?n.coverageFormat==="cobertura-xml"?[]:[{detector:Eo,severity:"warn",message:`${i} contained no line-coverage counter`}]:s>=Jv?[]:[{detector:Eo,severity:"warn",message:`line coverage ${s.toFixed(1)}% < floor ${Jv}%`}]}var Eo,Jv,o5,s5=y(()=>{"use strict";Ue();Mv();Va();Nv();Dn();Eo="COVERAGE_DROP",Jv=70;o5={name:Eo,run:wRe}});import{existsSync as xRe}from"node:fs";import{join as $Re}from"node:path";function ERe(t){let{cwd:e="."}=t;return ye(e,Yv,r=>ARe(r,e))}function ARe(t,e){let r=t.project.deliverable,n=t.features.filter(i=>i.status==="done"&&(i.modules?.length??0)>0);if(!r){if(n.length===0)return[];let i=t.project.onboarding_seeded===!0&&t.features.length{"use strict";xt();Yv="DELIVERABLE_INTEGRITY",kRe=8;a5={name:Yv,run:ERe}});function ORe(t){let e=new Set((t.features??[]).map(n=>n.id)),r=[];for(let n of t.project?.smoke??[]){let i=n.feature;if(i===void 0||e.has(i))continue;let o=(n.run??[]).join(" ")||`kind:${n.kind}`;r.push({detector:Xv,severity:"warn",path:"spec.yaml",message:`smoke probe '${o}' binds feature ${i}, which is not in the spec \u2014 a dangling binding is annotation drift (the bound feature was renamed, archived, or never existed). Fix the id or drop the binding.`})}return r}function TRe(t){let e=ORe(t),r=(t.features??[]).filter(o=>o.status==="done");return r.length===0||!!!t.project?.deliverable||(t.project?.smoke??[]).length>0?e:[...e,{detector:Xv,severity:"warn",path:"spec.yaml",message:`${r.length} feature(s) are done and the project ships a runnable deliverable, but no functional smoke probe is declared (project.smoke) \u2014 an exit-only deliverable is liveness, not AC-verification. Declare a smoke probe with an expect.token so the gate re-executes the shipped entry against its AC result.`}]}function RRe(t){let{cwd:e="."}=t;return ye(e,Xv,r=>TRe(r))}var Xv,l5,u5=y(()=>{"use strict";xt();Xv="SMOKE_PROBE_DEMAND";l5={name:Xv,run:RRe}});function IRe(t){let{cwd:e="."}=t;return ye(e,Qv,r=>PRe(r,e))}function PRe(t,e){let r=(t.features??[]).filter(o=>o.status==="done"&&(o.modules??[]).length>0);if(r.length===0)return[];let n=ds(e);if(n===null)return[{detector:Qv,severity:"info",path:"spec/attestation.yaml",message:"no verification attestation \u2014 when this tree was last verified is unknown. Run `clad check --tier=pre-push --strict` GREEN once to attest (the gate writes spec/attestation.yaml)."}];let i=[];for(let o of r){let s=Q_(n,e,o);s.state!=="fresh"&&i.push({detector:Qv,severity:"warn",path:"spec/attestation.yaml",message:s.state==="unattested"?`${o.id} is done but has no attestation entry \u2014 its modules were never verified by an attested gate. Run \`clad check --tier=pre-push --strict\` to attest.`:s.module?`${o.id}'s module ${s.module} changed since the last attested verification \u2014 shipped code is running ahead of its verification. Run \`clad check --tier=pre-push --strict\` to re-verify and re-attest.`:`${o.id}'s modules changed since the last attested verification \u2014 shipped code is running ahead of its verification. Run \`clad check --tier=pre-push --strict\` to re-verify and re-attest.`})}return i}var Qv,eS,lC=y(()=>{"use strict";El();xt();Qv="STALE_ATTESTATION";eS={name:Qv,run:IRe}});function CRe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}return DRe(r)}function DRe(t){let e=new Set(t.features.map(d=>d.id)),r=new Map;for(let d of t.features)r.set(d.id,(d.depends_on??[]).filter(f=>e.has(f)));let n=0,i=1,o=2,s=new Map;for(let d of r.keys())s.set(d,n);let a=[],c=new Set,l=[];function u(d){s.set(d,i),l.push(d);for(let f of r.get(d)??[]){let p=s.get(f);if(p===i){let m=l.indexOf(f),h=l.slice(m).concat(f),g=[...h].sort().join(",");c.has(g)||(c.add(g),a.push({detector:d5,severity:"error",path:"spec.yaml",message:`circular depends_on cycle: ${h.join(" \u2192 ")} \u2014 these features can never all become ready, so the drive loop deadlocks. Break the cycle by removing one edge.`}))}else p===n&&u(f)}l.pop(),s.set(d,o)}for(let d of r.keys())s.get(d)===n&&u(d);return a}var d5,tS,uC=y(()=>{"use strict";Ue();d5="DEPENDENCY_CYCLE";tS={name:d5,run:CRe}});import{appendFileSync as NRe,existsSync as f5,mkdirSync as jRe,readFileSync as MRe}from"node:fs";import{dirname as FRe,join as LRe}from"node:path";function p5(t){return LRe(t,zRe,URe)}function m5(t){return dC.add(t),()=>dC.delete(t)}function Ja(t,e){let r=p5(t),n=FRe(r);f5(n)||jRe(n,{recursive:!0}),NRe(r,`${JSON.stringify(e)} +`,"utf8");for(let i of dC)try{i(t,e)}catch{}}function pr(t){let e=p5(t);if(!f5(e))return[];let r=MRe(e,"utf8").trim();return r.length===0?[]:r.split(` +`).filter(n=>n.length>0).map(n=>JSON.parse(n))}var zRe,URe,dC,un=y(()=>{"use strict";zRe=".cladding",URe="audit.log.jsonl";dC=new Set});import{existsSync as qRe}from"node:fs";import{join as HRe}from"node:path";function BRe(t){let{cwd:e="."}=t,r=pr(e);if(r.length===0)return[{detector:fC,severity:"info",message:"no audit log present \u2014 detector is opt-in on prior stage_4 runs"}];let n=[];for(let i of r)i.artifact&&(qRe(HRe(e,i.artifact))||n.push({detector:fC,severity:"error",path:i.artifact,message:`evidence ${i.id} references missing artifact '${i.artifact}'`}));return n}var fC,h5,g5=y(()=>{"use strict";un();fC="EVIDENCE_MISMATCH";h5={name:fC,run:BRe}});import{existsSync as GRe,readFileSync as ZRe}from"node:fs";import{join as VRe}from"node:path";function WRe(t){let e=VRe(t,v5);if(!GRe(e))return null;try{let n=((0,b5.parse)(ZRe(e,"utf8"))?.fixtures??[]).map(i=>i.name).filter(Boolean);return new Set(n)}catch{return null}}function*_5(t,e){for(let r of t??[])r.startsWith(y5)&&(yield{ref:r,name:r.slice(y5.length),field:e})}function KRe(t){let{cwd:e="."}=t,r=WRe(e);if(r===null)return[];let n;try{n=q(e)}catch(o){return[{detector:pC,severity:"info",message:`spec.yaml not loaded: ${o.message}`}]}let i=[];for(let o of n.features)for(let s of o.acceptance_criteria??[]){let a=[..._5(s.evidence_refs,"evidence_refs"),..._5(s.test_refs,"test_refs")];for(let{ref:c,name:l,field:u}of a)r.has(l)||i.push({detector:pC,severity:"warn",path:v5,message:`${o.id}.${s.id} cites '${c}' in ${u} but no fixture named '${l}' is registered in conformance/fixtures.yaml`})}return i}var b5,pC,y5,v5,S5,w5=y(()=>{"use strict";b5=wt(tr(),1);Ue();pC="FIXTURE_REFERENCE_INVALID",y5="fixture:",v5="conformance/fixtures.yaml";S5={name:pC,run:KRe}});import{existsSync as Ql,readFileSync as mC}from"node:fs";import{join as Ya}from"node:path";function JRe(t){return vs(["src/stages/detectors/*.ts"],{cwd:t,dot:!1}).filter(r=>!/[/\\](index|with-spec|spec-first-window)\.ts$/.test(r)).length}function Cp(t){if(!Ql(t))return null;try{return JSON.parse(mC(t,"utf8"))}catch{return null}}function YRe(t,e){let r=Ya(t,"plugins","claude-code",".claude-plugin","plugin.json"),n;try{n=JSON.parse(mC(r,"utf8"))}catch(c){e.push({detector:Ao,severity:"info",message:`plugin.json not loaded: ${c.message}`});return}let i=n.ironclad?.current?.detectors;if(!i)return;let o=i.match(/^(\d+)\/(\d+)$/);if(!o){e.push({detector:Ao,severity:"warn",message:`plugin.json current.detectors='${i}' is not in 'N/M' form`});return}let s=Number(o[1]),a=JRe(t);s!==a&&e.push({detector:Ao,severity:"error",message:`plugin.json current.detectors='${i}' but stages/detectors/contains ${a} non-index .ts file(s)`})}function XRe(t,e){for(let r of x5){let n=Ya(t,r.path);if(!Ql(n))continue;let i=Cp(n);if(!i){e.push({detector:Ao,severity:"warn",message:`${r.host}: ${r.path} could not be parsed as JSON`});continue}for(let o of r.required)(i[o]===void 0||i[o]===null||i[o]==="")&&e.push({detector:Ao,severity:"error",message:`${r.host}: ${r.path} is missing required field '${String(o)}'`})}}function QRe(t,e){let r=Cp(Ya(t,"package.json"));if(!r?.version)return;let n=r.version;for(let o of x5){let s=Ya(t,o.path);if(!Ql(s))continue;let a=Cp(s);a?.version&&a.version!==n&&e.push({detector:Ao,severity:"error",message:`${o.host}: ${o.path} version='${a.version}' but package.json version='${n}' \u2014 bump them in lockstep`})}let i=Ya(t,".claude-plugin","marketplace.json");if(Ql(i)){let o=Cp(i);for(let s of o?.plugins??[])s?.version&&s.version!==n&&e.push({detector:Ao,severity:"error",message:`marketplace: .claude-plugin/marketplace.json plugin '${s.name??"?"}' version='${s.version}' but package.json version='${n}' \u2014 the catalog advertises a stale version; bump it in lockstep`})}}function eIe(t){let e=t.match(/TIER_STAGES[\s\S]*?\ball:\s*\[([^\]]*)\]/);return e?[...e[1].matchAll(/['"]([^'"]+)['"]/g)].map(r=>r[1]):[]}function tIe(t,e){let r=Ya(t,"src","cli","clad.ts"),n=Ya(t,"plugins","claude-code",".claude-plugin","plugin.json");if(!Ql(r)||!Ql(n))return;let i=eIe(mC(r,"utf8"));if(i.length===0)return;let s=Cp(n)?.ironclad?.current?.["stages-implemented"];if(!Array.isArray(s))return;let a=new Set(i),c=new Set(s),l=i.filter(f=>!c.has(f)),u=s.filter(f=>!a.has(f));if(l.length===0&&u.length===0)return;let d=[l.length?`missing [${l.join(", ")}]`:"",u.length?`unexpected [${u.join(", ")}]`:""].filter(Boolean).join("; ");e.push({detector:Ao,severity:"error",message:`plugins/claude-code/.claude-plugin/plugin.json stages-implemented disagrees with TIER_STAGES.all (src/cli/clad.ts): ${d} \u2014 run \`npm run build:plugin\` to re-derive`})}function rIe(t){let{cwd:e="."}=t,r=[];return YRe(e,r),tIe(e,r),XRe(e,r),QRe(e,r),r}var Ao,x5,$5,k5=y(()=>{"use strict";Rp();Ao="HARNESS_INTEGRITY",x5=[{host:"claude-code",path:"plugins/claude-code/.claude-plugin/plugin.json",required:["name","version"]},{host:"codex",path:"plugins/codex/.codex-plugin/plugin.json",required:["name","version","description"]},{host:"gemini-cli",path:"plugins/gemini-cli/gemini-extension.json",required:["name","version"]}];$5={name:Ao,run:rIe}});import{existsSync as nIe,readFileSync as iIe}from"node:fs";import{join as oIe}from"node:path";function aIe(t){let{cwd:e="."}=t;return ye(e,rS,r=>lIe(r,e))}function cIe(t){let e=oIe(t,"spec/capabilities.yaml");if(!nIe(e))return!1;try{let r=E5.default.parse(iIe(e,"utf8"));if(!r||typeof r!="object")return!1;let n=r.capabilities;return!Array.isArray(n)||n.length===0}catch{return!1}}function lIe(t,e){let r=t.features.length;if(r{"use strict";E5=wt(tr(),1);xt();rS="HOLLOW_GOVERNANCE",sIe=8;A5={name:rS,run:aIe}});function uIe(t,e){let r=t.slice(0,e).split(/\r\n|\n|\r/g);return[r.length,r.pop().length+1]}function dIe(t,e,r){let n=t.split(/\r\n|\n|\r/g),i="",o=(Math.log10(e+1)|0)+1;for(let s=e-1;s<=e+1;s++){let a=n[s-1];a&&(i+=s.toString().padEnd(o," "),i+=": ",i+=a,i+=` +`,s===e&&(i+=" ".repeat(o+r+2),i+=`^ +`))}return i}var ge,Xa=y(()=>{ge=class extends Error{line;column;codeblock;constructor(e,r){let[n,i]=uIe(r.toml,r.ptr),o=dIe(r.toml,n,i);super(`Invalid TOML document: ${e} + +${o}`,r),this.line=n,this.column=i,this.codeblock=o}}});function fIe(t,e){let r=0;for(;t[e-++r]==="\\";);return--r&&r%2}function nS(t,e=0,r=t.length){let n=t.indexOf(` +`,e);return t[n-1]==="\r"&&n--,n<=r?n:-1}function eu(t,e){for(let r=e;r-1&&r!=="'"&&fIe(t,e));return e>-1&&(e+=n.length,n.length>1&&(t[e]===r&&e++,t[e]===r&&e++)),e}var Dp=y(()=>{Xa();});var pIe,Qa,hC=y(()=>{pIe=/^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|[-+]\d{2}:\d{2})?$/i,Qa=class t extends Date{#t=!1;#r=!1;#e=null;constructor(e){let r=!0,n=!0,i="Z";if(typeof e=="string"){let o=e.match(pIe);o?(o[1]||(r=!1,e=`0000-01-01T${e}`),n=!!o[2],n&&e[10]===" "&&(e=e.replace(" ","T")),o[2]&&+o[2]>23?e="":(i=o[3]||null,e=e.toUpperCase(),!i&&n&&(e+="Z"))):e=""}super(e),isNaN(this.getTime())||(this.#t=r,this.#r=n,this.#e=i)}isDateTime(){return this.#t&&this.#r}isLocal(){return!this.#t||!this.#r||!this.#e}isDate(){return this.#t&&!this.#r}isTime(){return this.#r&&!this.#t}isValid(){return this.#t||this.#r}toISOString(){let e=super.toISOString();if(this.isDate())return e.slice(0,10);if(this.isTime())return e.slice(11,23);if(this.#e===null)return e.slice(0,-1);if(this.#e==="Z")return e;let r=+this.#e.slice(1,3)*60+ +this.#e.slice(4,6);return r=this.#e[0]==="-"?r:-r,new Date(this.getTime()-r*6e4).toISOString().slice(0,-1)+this.#e}static wrapAsOffsetDateTime(e,r="Z"){let n=new t(e);return n.#e=r,n}static wrapAsLocalDateTime(e){let r=new t(e);return r.#e=null,r}static wrapAsLocalDate(e){let r=new t(e);return r.#r=!1,r.#e=null,r}static wrapAsLocalTime(e){let r=new t(e);return r.#t=!1,r.#e=null,r}}});function oS(t,e=0,r=t.length){let n=t[e]==="'",i=t[e++]===t[e]&&t[e]===t[e+1];i&&(r-=2,t[e+=2]==="\r"&&e++,t[e]===` +`&&e++);let o=0,s,a="",c=e;for(;e{Dp();hC();Xa();mIe=/^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/,hIe=/^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/,gIe=/^[+-]?0[0-9_]/,yIe=/^[0-9a-f]{2,8}$/i,R5={b:"\b",t:" ",n:` +`,f:"\f",r:"\r",e:"\x1B",'"':'"',"\\":"\\"}});function _Ie(t,e,r){let n=t.slice(e,r),i=n.indexOf("#");return i>-1&&(eu(t,i),n=n.slice(0,i)),[n.trimEnd(),i]}function Np(t,e,r,n,i){if(n===0)throw new ge("document contains excessively nested structures. aborting.",{toml:t,ptr:e});let o=t[e];if(o==="["||o==="{"){let[c,l]=o==="["?C5(t,e,n,i):P5(t,e,n,i);if(r){if(l=dn(t,l),t[l]===",")l++;else if(t[l]!==r)throw new ge("expected comma or end of structure",{toml:t,ptr:l})}return[c,l]}let s;if(o==='"'||o==="'"){s=iS(t,e);let c=oS(t,e,s);if(r){if(s=dn(t,s),t[s]&&t[s]!==","&&t[s]!==r&&t[s]!==` +`&&t[s]!=="\r")throw new ge("unexpected character encountered",{toml:t,ptr:s});s+=+(t[s]===",")}return[c,s]}s=T5(t,e,",",r);let a=_Ie(t,e,s-+(t[s-1]===","));if(!a[0])throw new ge("incomplete key-value declaration: no value specified",{toml:t,ptr:e});return r&&a[1]>-1&&(s=dn(t,e+a[1]),s+=+(t[s]===",")),[I5(a[0],t,e,i),s]}var yC=y(()=>{gC();_C();Dp();Xa();});function sS(t,e,r="="){let n=e-1,i=[],o=t.indexOf(r,e);if(o<0)throw new ge("incomplete key-value: cannot find end of key",{toml:t,ptr:e});do{let s=t[e=++n];if(s!==" "&&s!==" ")if(s==='"'||s==="'"){if(s===t[e+1]&&s===t[e+2])throw new ge("multiline strings are not allowed in keys",{toml:t,ptr:e});let a=iS(t,e);if(a<0)throw new ge("unfinished string encountered",{toml:t,ptr:e});n=t.indexOf(".",a);let c=t.slice(a,n<0||n>o?o:n),l=nS(c);if(l>-1)throw new ge("newlines are not allowed in keys",{toml:t,ptr:e+n+l});if(c.trimStart())throw new ge("found extra tokens after the string part",{toml:t,ptr:a});if(oo?o:n);if(!bIe.test(a))throw new ge("only letter, numbers, dashes and underscores are allowed in keys",{toml:t,ptr:e});i.push(a.trimEnd())}}while(n+1&&n{gC();yC();Dp();Xa();bIe=/^[a-zA-Z0-9-_]+[ \t]*$/});function D5(t,e,r,n){let i=e,o=r,s,a=!1,c;for(let l=0;l{_C();yC();Dp();Xa();});function jp(t){let e=typeof t;if(e==="object"){if(Array.isArray(t))return"array";if(t instanceof Date)return"date"}return e}function vIe(t){for(let e=0;e{j5=/^[a-z0-9-_]+$/i});var $C={};Nr($C,{TomlDate:()=>Qa,TomlError:()=>ge,default:()=>$Ie,parse:()=>bC,stringify:()=>xC});var $Ie,kC=y(()=>{N5();M5();hC();Xa();$Ie={parse:bC,stringify:xC,TomlDate:Qa,TomlError:ge}});import{cpSync as kIe,existsSync as jn,lstatSync as EIe,mkdirSync as AIe,readFileSync as uS,readlinkSync as OIe,readdirSync as TIe,rmSync as L5,writeFileSync as ec}from"node:fs";import{homedir as z5,platform as U5}from"node:os";import{basename as RIe,dirname as Ss,isAbsolute as IIe,join as he,relative as PIe,resolve as ws}from"node:path";import{fileURLToPath as CIe}from"node:url";import{spawnSync as q5}from"node:child_process";function aS(t){AIe(t,{recursive:!0})}function si(t){try{return uS(t,"utf8")}catch{return null}}function tc(t,e){let r=si(t);return r===e?"unchanged":(aS(Ss(t)),ec(t,e,"utf8"),r==null?"created":"rewired")}function cS(t){try{return EIe(t).isSymbolicLink()}catch{return!1}}function jIe(t){try{return ws(Ss(t),OIe(t))}catch{return null}}function H5(t,e){let r=PIe(ws(e),ws(t));return r===""||!r.startsWith("..")&&!IIe(r)}function MIe(t,e){let r=[ws(e)],n=si(he(t,".cladding",AC));if(n)try{let i=JSON.parse(n);typeof i.cladding_root=="string"&&r.push(ws(i.cladding_root))}catch{}return[...new Set(r)]}function lS(t,e){if(!jn(t)&&!cS(t))return"unchanged";if(!cS(t))return"skipped-different";let r=jIe(t);if(!r||!e.some(n=>H5(r,n)))return"skipped-different";try{return L5(t,{force:!0}),"removed"}catch{return"failed"}}function FIe(t,e){let r=he(t,".agents","skills");if(!jn(r))return"unchanged";let n=0,i=0;for(let o of TIe(r)){if(!o.startsWith("cladding-"))continue;let s=lS(he(r,o),e);s==="removed"&&n++,s==="skipped-different"&&i++}return i>0?"skipped-different":n>0?"removed":"unchanged"}function Lp(t,e){if(!t||typeof t!="object")return!1;let r=t,n=Array.isArray(r.args)?r.args:[];return r.command==="clad"&&n[0]==="serve"||typeof r.description=="string"&&r.description.includes("wired by `clad setup`")||typeof r.description=="string"&&r.description.includes("project-scoped by `clad setup`")||r.command==="node"&&n[0]===OC?!0:r.command==="node"&&typeof n[0]=="string"&&e.some(i=>H5(n[0],i))}function LIe(t,e){let r=t.split(` +`),n=r.findIndex(s=>s.trim()===e);if(n===-1)return null;let i=r.length;for(let s=n+1;s0&&r[o-1].trim()==="";)o--;return[...r.slice(0,o),...r.slice(i)].join(` +`)}async function zIe(t,e){let r=he(t,".codex","config.toml"),n=si(r);if(n==null)return"unchanged";try{let{parse:i,stringify:o}=await Promise.resolve().then(()=>(kC(),$C)),s=i(n),a=s.mcp_servers;if(!a?.cladding)return"unchanged";if(!Lp(a.cladding,e))return"skipped-different";delete a.cladding,Object.keys(a).length===0&&delete s.mcp_servers;let c=LIe(n,"[mcp_servers.cladding]");if(c!=null)try{if(JSON.stringify(i(c))===JSON.stringify(s))return ec(r,c,"utf8"),"removed"}catch{}return ec(r,o(s),"utf8"),"removed"}catch{return"failed"}}function UIe(t,e){let r=he(t,".cursor","mcp.json"),n=si(r);if(n==null)return"unchanged";try{let i=JSON.parse(n),o=i.mcpServers;return o?.cladding?Lp(o.cladding,e)?(delete o.cladding,Object.keys(o).length===0&&delete i.mcpServers,ec(r,`${JSON.stringify(i,null,2)} +`,"utf8"),"removed"):"skipped-different":"unchanged"}catch{return"failed"}}function qIe(t,e,r){let n=he(t,".gemini","config","plugins","cladding");if(cS(n))return"skipped-different";let i={command:"node",args:[he(e,"dist","clad.js"),"serve"]},o=Fp(he(n,"mcp_config.json"),i,r);if(o==="skipped-different"||o==="failed")return o;let s=`${JSON.stringify({$schema:"https://antigravity.google/schemas/v1/plugin.json",name:"cladding",description:"Spec-driven verification and onboarding for Antigravity CLI (machine-wide MCP wire; the project is resolved from each session\u2019s working directory)."},null,2)} +`;return tu([o,tc(he(n,"plugin.json"),s)])}function HIe(t,e){let r=he(t,".gemini","config","plugins","cladding");if(cS(r))return lS(r,e);let n=si(he(r,"mcp_config.json"));if(n==null)return"unchanged";try{let i=JSON.parse(n).mcpServers;return i?.cladding&&!Lp(i.cladding,e)?"skipped-different":"unchanged"}catch{return"skipped-different"}}function BIe(t){let e=U5()==="win32"?"where":"which";return q5(e,[t],{stdio:"ignore"}).status===0}function GIe(t){if(!t||!BIe("claude"))return"manual-required";let e=q5("claude",["plugin","uninstall","claude-code@cladding","--scope","user","--keep-data"],{encoding:"utf8",timeout:3e4,shell:U5()==="win32"});if(e.status===0)return"removed";let r=`${e.stdout??""} +${e.stderr??""}`;return/not installed|not found/i.test(r)?"unchanged":"manual-required"}function ZIe(t){let e=he(t,"dist","clad.js");return["'use strict';","const {spawn} = require('node:child_process');",`const engine = ${JSON.stringify(e)};`,"const requested = process.argv.slice(2);","const args = requested.length > 0 ? requested : ['serve'];","const child = spawn(process.execPath, [engine, ...args], {cwd: process.cwd(), stdio: 'inherit'});","for (const signal of ['SIGINT', 'SIGTERM']) process.on(signal, () => child.kill(signal));","child.on('error', (error) => { console.error(`cladding project launcher: ${error.message}`); process.exitCode = 1; });","child.on('exit', (code, signal) => { process.exitCode = code ?? (signal ? 1 : 0); });",""].join(` +`)}function VIe(){return["[[rule]]",'mcpName = "cladding"','toolName = "*"','decision = "deny"',"priority = 100",'modes = ["plan"]',"interactive = false","","[[rule]]",'mcpName = "cladding"','toolName = ["clad_list_features", "clad_get_feature", "clad_run_check"]',"toolAnnotations = { readOnlyHint = true }",'decision = "allow"',"priority = 200",'modes = ["plan"]',"interactive = false","","[[rule]]",'toolName = "exit_plan_mode"','decision = "deny"',"priority = 200",'modes = ["plan"]',"interactive = false",""].join(` +`)}function WIe(t){let e=he(t,".git","info","exclude");if(!jn(Ss(e)))return;let r=["/.cladding/host/","/.cladding/setup-status.json"],n=si(e)??"",i=n.split(/\r?\n/),o=r.filter(a=>!i.includes(a));if(o.length===0)return;let s=n.length>0&&!n.endsWith(` +`)?` +`:"";ec(e,`${n}${s}${o.join(` +`)} +`,"utf8")}function KIe(){return{command:"node",args:[OC]}}function EC(t,e,r){if(!jn(t))return"failed";let n=si(he(t,"SKILL.md"));if(n==null||!n.startsWith(`--- +`))return"failed";let i=RIe(e),o=/^name:\s*.*$/m.test(n)?n.replace(/^name:\s*.*$/m,`name: ${i}`):n.replace(/^---\n/,`--- +name: ${i} +`);if(jn(e)){let s=si(he(e,"SKILL.md"));if(s===o)return"unchanged";if(!r&&s!=null&&!s.includes("# Cladding init"))return"skipped-different";L5(e,{recursive:!0,force:!0})}return aS(Ss(e)),kIe(t,e,{recursive:!0,dereference:!0}),ec(he(e,"SKILL.md"),o,"utf8"),"created"}function Fp(t,e,r){try{let n=si(t),i=n==null?{}:JSON.parse(n);(!i.mcpServers||typeof i.mcpServers!="object")&&(i.mcpServers={});let o=i.mcpServers,s=o.cladding,a={command:e.command,args:e.args};return JSON.stringify(s)===JSON.stringify(a)?"unchanged":s&&!r&&!Lp(s,[])?"skipped-different":(o.cladding=a,tc(t,`${JSON.stringify(i,null,2)} +`))}catch{return"failed"}}function JIe(t){try{let e=si(t),r=e==null?{}:JSON.parse(e),n=r.permissions;if(n!==void 0&&(typeof n!="object"||n===null||Array.isArray(n)))return"skipped-different";let i=n??{},o=i.allow;if(o!==void 0&&(!Array.isArray(o)||o.some(u=>typeof u!="string")))return"skipped-different";let s=i.deny;if(s!==void 0&&(!Array.isArray(s)||s.some(u=>typeof u!="string")))return"skipped-different";let a=o??[],c=s??[],l=[...a];for(let u of NIe)l.includes(u)||l.push(u);return l.length===a.length&&s!==void 0?"unchanged":(i.allow=l,i.deny=c,r.permissions=i,tc(t,`${JSON.stringify(r,null,2)} +`))}catch{return"failed"}}async function YIe(t,e,r){try{let{parse:n,stringify:i}=await Promise.resolve().then(()=>(kC(),$C)),o=si(t),s=o==null?{}:n(o);(!s.mcp_servers||typeof s.mcp_servers!="object")&&(s.mcp_servers={});let a=s.mcp_servers,c=a.cladding,l={command:e.command,args:e.args,description:"cladding MCP server (project-scoped by `clad setup`)",default_tools_approval_mode:"writes"};return JSON.stringify(c)===JSON.stringify(l)?"unchanged":c&&!r&&!Lp(c,[])?"skipped-different":(a.cladding=l,tc(t,i(s)))}catch{return"failed"}}function XIe(t){let e=["---","description: Cladding bootstrap boundary","alwaysApply: true","---","","Cladding is available only in this project. Do not initialize or invoke Cladding for ordinary work.","Use the cladding-init skill only when the user explicitly names Cladding and asks to initialize, adopt, or refresh it.",""].join(` +`);return tc(he(t,".cursor","rules","cladding-bootstrap.mdc"),e)}function tu(t){return t.includes("failed")?"failed":t.includes("skipped-different")?"skipped-different":t.includes("manual-required")?"manual-required":t.includes("removed")?"removed":t.includes("rewired")?"rewired":t.includes("created")?"created":"unchanged"}function B5(t){try{return JSON.parse(uS(t,"utf8")).cladding_version??null}catch{return null}}function F5(t,e,r,n){t==="failed"&&r.push({step:e,message:"project wiring failed"}),t==="skipped-different"&&n.push({step:e,message:"existing non-Cladding configuration was preserved; use --force to replace only the cladding entry"}),t==="manual-required"&&n.push({step:e,message:"run `claude plugin uninstall claude-code@cladding --scope user --keep-data` to remove the legacy user plugin"})}async function RC(t={}){let e=t.home??z5(),r=ws(t.projectRoot??process.cwd()),n=t.pkgRoot??G5(),i=t.version??Z5(n),o=ePe(e),s=new Set(t.hosts??DIe.filter(X=>o[X])),a=t.force??!1,c=he(r,".cladding",AC),l=B5(c),u=[],d=[];aS(r),WIe(r);let f=[tc(he(r,OC),ZIe(n))];s.has("gemini")&&f.push(tc(he(r,TC),VIe()));let p=tu(f),m=he(n,"plugins","codex","skills","init"),h=s.has("codex")||s.has("gemini")||s.has("antigravity")?EC(m,he(r,".agents","skills","cladding-init"),a):"unchanged",g=KIe(),b=MIe(e,n),_=lS(he(e,".claude","plugins","cladding"),b),S=_==="removed"?GIe(t.activate??!0):"unchanged",x={claude_plugin:tu([_,S]),gemini_extension:lS(he(e,".gemini","extensions","cladding"),b),antigravity_plugin:HIe(e,b),codex_skills:FIe(e,b),codex_mcp:await zIe(e,b),cursor_mcp:UIe(e,b)},w=s.has("codex")?await YIe(he(r,".codex","config.toml"),g,a):"skipped-not-selected",R=s.has("gemini")?Fp(he(r,".gemini","settings.json"),g,a):"skipped-not-selected",A=s.has("antigravity")?tu([Fp(he(r,".agents","mcp_config.json"),g,a),qIe(e,n,a)]):"skipped-not-selected",O=s.has("claude")?tu([EC(m,he(r,".claude","skills","cladding-init"),a),Fp(he(r,".mcp.json"),g,a)]):"skipped-not-selected",D=s.has("cursor")?tu([EC(m,he(r,".cursor","skills","cladding-init"),a),Fp(he(r,".cursor","mcp.json"),g,a),JIe(he(r,".cursor","cli.json")),XIe(r)]):"skipped-not-selected",E={runtime:p,shared_init_skill:h,claude:O,codex:w,gemini:R,antigravity:A,cursor:D};s.size===0&&d.push({step:"hosts",message:"no supported AI host detected on this machine \u2014 only the shared runtime was written; use `clad setup --host ` to wire explicitly"});for(let[X,J]of Object.entries(E))F5(J,X,u,d);for(let[X,J]of Object.entries(x))F5(J,`legacy:${X}`,u,d);aS(Ss(c)),ec(c,`${JSON.stringify({project_root:r,cladding_root:n,cladding_version:i,last_run:new Date().toISOString()},null,2)} +`,"utf8");let ae={projectRoot:r,wiring:E,legacyCleanup:x,errors:u,warnings:d,statusFile:c,cladding_root:n,cladding_version:i,last_setup_version:l};return t.quiet||process.stdout.write(`${QIe(ae)} +`),ae}function Mp(t){switch(t){case"created":return"wired";case"rewired":return"updated";case"unchanged":return"already ready";case"removed":return"legacy global removed";case"skipped-not-selected":return"not selected";case"skipped-different":return"preserved conflict";case"manual-required":return"manual cleanup required";default:return"failed"}}function QIe(t,e){let r=[`cladding setup \u2014 project activation: ${t.projectRoot}`,"",` Claude Code \u2192 ${Mp(t.wiring.claude)}`,` Codex \u2192 ${Mp(t.wiring.codex)}`,` Gemini CLI \u2192 ${Mp(t.wiring.gemini)}`,` Antigravity \u2192 ${Mp(t.wiring.antigravity)}`,` Cursor \u2192 ${Mp(t.wiring.cursor)}`];(t.wiring.antigravity==="created"||t.wiring.antigravity==="rewired")&&r.push(""," Note: Antigravity reads MCP config machine-wide only, so its wire lives in ~/.gemini/config/plugins/cladding (each session still resolves the project from its working directory).");let n=Object.values(t.legacyCleanup).filter(i=>i==="removed").length;n>0&&r.push("",`Removed ${n} legacy global Cladding wire(s).`);for(let i of t.warnings)r.push(` ! ${i.step}: ${i.message}`);return r.push("","Next steps:"," 1. Start a new AI session in this project directory",' 2. Ask: "Apply Cladding to this project"'," 3. Review the preview and reply with its exact approval phrase"," 4. After initialization, develop normally in natural language"),r.join(` +`)}function G5(){let t=CIe(import.meta.url),e=Ss(t);for(let r=0;r<7;r++){try{if(JSON.parse(uS(he(e,"package.json"),"utf8")).name==="cladding")return e}catch{}e=Ss(e)}return ws(Ss(t),"..")}function Z5(t){for(let e of["package.json",he(".claude-plugin","plugin.json")])try{let r=JSON.parse(uS(he(t,e),"utf8")).version;if(typeof r=="string"&&r.length>0)return r}catch{}return"unknown"}function fn(t=G5()){let e=Z5(t);return e==="unknown"?null:e}function V5(t=process.cwd()){return B5(he(ws(t),".cladding",AC))}function ePe(t=z5()){return{claude:jn(he(t,".claude")),gemini:jn(he(t,".gemini")),antigravity:jn(he(t,".gemini","config"))||jn(he(t,".gemini","antigravity-cli")),codex:jn(he(t,".codex")),agents:jn(he(t,".agents")),cursor:jn(he(t,".cursor"))}}var AC,OC,TC,DIe,NIe,ru=y(()=>{"use strict";AC="setup-status.json",OC=he(".cladding","host","serve.cjs"),TC=".cladding/host/gemini-doctor-policy.toml",DIe=["claude","codex","gemini","antigravity","cursor"],NIe=["Mcp(cladding:clad_list_features)","Mcp(cladding:clad_get_feature)","Mcp(cladding:clad_run_check)"]});import{existsSync as W5,readFileSync as K5}from"node:fs";import{join as J5}from"node:path";function Y5(t,e){let r=t.match(e);if(!r)return null;try{let n=JSON.parse(r[1]),i={};for(let[o,s]of Object.entries(n))typeof s=="string"&&(i[o]=s);return i}catch{return null}}function sPe(t){switch(t){case"fail":case"wiring-fail":return 0;case"wiring-ok":case"wiring-only":return 1;case"verified":return 2;default:return null}}function X5(t){switch(t){case"wiring-only":return 1;case"verified":return 2;default:return null}}function Q5(t){let e=t.match(/^(\d+)\.(\d+)\.(\d+)(?:[-+]|$)/);return e?[Number(e[1]),Number(e[2]),Number(e[3])]:null}function aPe(t,e){let r=Q5(t),n=Q5(e);if(!r||!n)return!1;for(let i=0;ioPe&&r.push(`generated ${n}, more than 30 days ago`);let o=t.match(nPe)?.[1],s=fn();return o!==void 0&&s!==null&&aPe(o,s)&&r.push(`generated by cladding v${o}, before the current v${s}`),r}function lPe(t){let e=J5(t,"README.md"),r=J5(t,"docs","dogfood","matrix.md");if(!W5(e)||!W5(r))return[];let n=K5(e,"utf8"),i=K5(r,"utf8"),o=Y5(n,tPe),s=Y5(i,rPe);if(!o||!s)return[];let a=[];for(let[u,d]of Object.entries(o)){let f=X5(d);if(f===null)continue;let p=s[u]??"not-run",m=sPe(p);m!==null&&f>m&&a.push({detector:IC,severity:"warn",path:"README.md",message:`README host-claims: '${u}' claims '${d}' but the newest matrix evidence is '${p}' \u2014 the claim exceeds the evidence. Re-run \`clad doctor --hosts\` (with consent) or lower the README claim for '${u}'.`})}let l=Object.values(o).some(u=>X5(u)!==null)?cPe(i,Date.now()):[];return l.length>0&&a.push({detector:IC,severity:"info",path:"docs/dogfood/matrix.md",message:`Host support evidence needs a fresh receipt: ${l.join("; ")}. Re-run \`clad doctor --hosts\` with consent; existing contradictory-claim warnings are unchanged.`}),a}function uPe(t){let{cwd:e="."}=t;return lPe(e)}var IC,tPe,rPe,nPe,iPe,oPe,eY,tY=y(()=>{"use strict";ru();IC="HOST_CLAIM_DRIFT",tPe=//,rPe=//,nPe=/^- Cladding version:\s*`([^`]+)`\s*$/m,iPe=/^- Generated:\s*(\S+)\s*$/m,oPe=720*60*60*1e3;eY={name:IC,run:uPe}});function dPe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=[];return rY(r.features.map(i=>i.id),"feature","spec/features/",n),rY((r.scenarios??[]).map(i=>i.id),"scenario","spec/scenarios/",n),n}function rY(t,e,r,n){let i=new Map;for(let o of t)i.set(o,(i.get(o)??0)+1);for(let[o,s]of i)s>1&&n.push({detector:nY,severity:"error",message:`${e} id '${o}' appears ${s} times across ${r} \u2014 every ${e} must have a unique id; resolve the duplicate`})}var nY,iY,oY=y(()=>{"use strict";Ue();nY="ID_COLLISION";iY={name:nY,run:dPe}});import{existsSync as zp,readFileSync as PC,readdirSync as CC,statSync as fPe,writeFileSync as aY}from"node:fs";import{join as Oo}from"node:path";function sY(t){if(!zp(t))return 0;try{return CC(t).filter(e=>e.endsWith(".yaml")||e.endsWith(".yml")).length}catch{return 0}}function pPe(t){if(!zp(t))return 0;let e=0,r=[t];for(;r.length>0;){let n=r.pop(),i;try{i=CC(n)}catch{continue}for(let o of i){if(o==="node_modules"||o===".cladding"||o.startsWith("."))continue;let s=Oo(n,o),a;try{a=fPe(s)}catch{continue}a.isDirectory()?r.push(s):(o.endsWith(".test.ts")||o.endsWith(".test.tsx"))&&e++}}return e}function mPe(t){let e=Oo(t,"spec","capabilities.yaml");if(!zp(e))return 0;try{let r=dS.default.parse(PC(e,"utf8"));return Array.isArray(r?.capabilities)?r.capabilities.length:0}catch{return 0}}function xs(t="."){let e=sY(Oo(t,"spec","features")),r=sY(Oo(t,"spec","scenarios")),n=mPe(t),i=pPe(Oo(t,"tests"));return{features:e,scenarios:r,capabilities:n,test_files:i}}function nu(t,e){let r=Oo(t,"spec.yaml");if(!zp(r))return;let n=PC(r,"utf8"),i=hPe(n,e);i!==n&&aY(r,i)}function hPe(t,e){let r=t.includes(`\r `)?`\r `:` `,n=t.split(/\r?\n/),i=n.findIndex(d=>/^inventory:\s*$/.test(d)),o=["# Auto-maintained by `clad sync` (F-5b9f9f). Do not edit by hand.","inventory:",` features: ${e.features??0}`,` scenarios: ${e.scenarios??0}`,` capabilities: ${e.capabilities??0}`,` test_files: ${e.test_files??0}`],s=d=>r===`\r @@ -273,51 +330,21 @@ ${o.join(` `)}let a=i;a>0&&/Auto-maintained by `clad sync`/.test(n[a-1])&&(a-=1);let c=i+1;for(;ci+1);)c++;let l=n.slice(0,a),u=n.slice(c);for(;l.length>0&&l[l.length-1].trim()==="";)l.pop();return l.push(""),s([...l,...o,"",...u.filter((d,f)=>!(f===0&&d.trim()===""))].join(` `).replace(/\n{3,}/g,` -`))}function Ja(t="."){let e=Ao(t,"spec","features");if(!Ip(e))return!1;let r=[];for(let i of sC(e).sort())if(!(!i.endsWith(".yaml")&&!i.endsWith(".yml")))try{let o=(0,eS.parse)(oC(Ao(e,i),"utf8"));if(!o?.id)continue;let s=o.slug??i.replace(/\.(ya?ml)$/,"");r.push(` ${o.id}: {slug: ${s}, status: ${o.status??"planned"}, modules: ${(o.modules??[]).length}}`)}catch{continue}r.sort();let n="# Cladding \xB7 Tier C \u2014 generated feature index (`clad sync`). Do not edit by hand.\n# One line per feature \u2192 1-file lookup + line-independent merges\n# (suggested .gitattributes: `spec/index.yaml merge=union`).\nfeatures:\n"+r.join(` +`))}function rc(t="."){let e=Oo(t,"spec","features");if(!zp(e))return!1;let r=[];for(let i of CC(e).sort())if(!(!i.endsWith(".yaml")&&!i.endsWith(".yml")))try{let o=(0,dS.parse)(PC(Oo(e,i),"utf8"));if(!o?.id)continue;let s=o.slug??i.replace(/\.(ya?ml)$/,"");r.push(` ${o.id}: {slug: ${s}, status: ${o.status??"planned"}, modules: ${(o.modules??[]).length}}`)}catch{continue}r.sort();let n="# Cladding \xB7 Tier C \u2014 generated feature index (`clad sync`). Do not edit by hand.\n# One line per feature \u2192 1-file lookup + line-independent merges\n# (suggested .gitattributes: `spec/index.yaml merge=union`).\nfeatures:\n"+r.join(` `)+` -`;return k5(Ao(t,"spec","index.yaml"),n,"utf8"),!0}var eS,Pp=y(()=>{"use strict";eS=St(er(),1)});import{existsSync as E5,readFileSync as A5,readdirSync as NRe}from"node:fs";import{join as aC}from"node:path";function jRe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=bs(e),i=r.inventory;if(!i){let s=T5.filter(([c])=>(n[c]??0)>0);if(s.length===0)return cC(e);let a=s.map(([c,l])=>`${n[c]??0} ${l}`).join(", ");return[...cC(e),{detector:Cp,severity:"warn",path:"spec.yaml",message:`spec.yaml has no inventory: block, but the project has ${a} on disk \u2014 run \`clad sync\` to record the inventory so anyone reading spec.yaml sees its real scale.`}]}let o=[];for(let[s,a]of T5){let c=i[s]??0,l=n[s]??0;c!==l&&o.push({detector:Cp,severity:"error",path:"spec.yaml",message:`spec.yaml inventory.${s} declares ${c} but the project has ${l} ${a} on disk \u2014 run \`clad sync\` (a stale inventory hides created/deleted shards from anyone reading spec.yaml).`})}return o.push(...cC(e)),o}function cC(t){let e=aC(t,"spec","index.yaml"),r=aC(t,"spec","features");if(!E5(e)||!E5(r))return[];let n=new Map;try{for(let l of A5(e,"utf8").split(` -`)){let u=l.match(/^ (F-[\w-]+):.*\bstatus:\s*['"]?([\w-]+)['"]?/);if(u){n.set(u[1],u[2]);continue}let d=l.match(/^ (F-[\w-]+):/);d&&n.set(d[1],"planned")}}catch{return[]}let i=new Map;try{for(let l of NRe(r)){if(!l.endsWith(".yaml")&&!l.endsWith(".yml"))continue;let u=A5(aC(r,l),"utf8"),d=u.match(/^id:\s*['"]?(F-[\w-]+)['"]?/m);if(!d)continue;let f=u.match(/^status:\s*['"]?([\w-]+)['"]?/m);i.set(d[1],f?f[1]:"planned")}}catch{return[]}let o=[],s=[...i.keys()].filter(l=>!n.has(l)).sort(),a=[...n.keys()].filter(l=>!i.has(l)).sort();if(s.length>0||a.length>0){let l=[];s.length>0&&l.push(`missing from index: ${s.join(", ")}`),a.length>0&&l.push(`in index but not on disk: ${a.join(", ")}`),o.push({detector:Cp,severity:"error",path:"spec/index.yaml",message:`spec/index.yaml disagrees with spec/features/ (${l.join("; ")}) \u2014 run \`clad sync\` to regenerate (a stale index silently misleads agents that trust it for lookup).`})}let c=[...i.keys()].filter(l=>n.has(l)&&n.get(l)!==i.get(l)).sort().map(l=>`${l} (index: ${n.get(l)}, shard: ${i.get(l)})`);return c.length>0&&o.push({detector:Cp,severity:"error",path:"spec/index.yaml",message:`spec/index.yaml status disagrees with spec/features/ for ${c.join("; ")} \u2014 run \`clad sync\` to regenerate (a stale status silently misleads agents that trust the index).`}),o}var Cp,T5,O5,R5=y(()=>{"use strict";Pp();Ue();Cp="INVENTORY_DRIFT",T5=[["features","feature shard(s)"],["scenarios","scenario shard(s)"],["capabilities","capabilit(ies)"],["test_files","test file(s)"]];O5={name:Cp,run:jRe}});import{existsSync as MRe,readFileSync as FRe}from"node:fs";import{join as LRe}from"node:path";function URe(t){let{cwd:e="."}=t,r=LRe(e,"src","spec","schema.json"),n=[];if(MRe(r)){let i;try{i=JSON.parse(FRe(r,"utf8"))}catch(o){n.push({detector:Dp,severity:"error",message:`spec/schema.json unreadable or invalid JSON: ${o.message}`})}if(i)for(let o of zRe)i.required?.includes(o)||n.push({detector:Dp,severity:"error",message:`spec/schema.json does not require root key '${o}'`}),i.properties?.[o]||n.push({detector:Dp,severity:"error",message:`spec/schema.json does not declare property '${o}'`})}try{let i=q(e);i.schema!==I5&&n.push({detector:Dp,severity:"error",message:`spec.yaml schema='${i.schema}' but supported version is '${I5}'`})}catch{}return n}var Dp,zRe,I5,P5,C5=y(()=>{"use strict";Ue();Dp="META_INTEGRITY",zRe=["schema","project","features"],I5="0.1";P5={name:Dp,run:URe}});function qRe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=[];return D5(r.features.map(i=>({id:i.id,slug:i.slug})),"features",n),D5((r.scenarios??[]).map(i=>({id:i.id,slug:i.slug})),"scenarios",n),n}function D5(t,e,r){let n=new Map;for(let i of t){if(!i.slug)continue;let o=n.get(i.slug);o?r.push({detector:N5,severity:"error",message:`slug '${i.slug}' is used by both ${o} and ${i.id} in ${e}/ \u2014 two items in the same namespace cannot share a slug; pick a different slug for one`}):n.set(i.slug,i.id)}}var N5,j5,M5=y(()=>{"use strict";Ue();N5="SLUG_CONFLICT";j5={name:N5,run:qRe}});function Xl(t){return t==="planned"||t==="in_progress"}var tS=y(()=>{"use strict"});import{existsSync as BRe}from"node:fs";import{join as HRe}from"node:path";function GRe(t){let{cwd:e="."}=t;return ge(e,rS,r=>ZRe(r,e))}function ZRe(t,e){let r=[];for(let n of t.features)for(let i of n.modules??[]){let o=HRe(e,i);BRe(o)||r.push(VRe(n.id,i,n.status))}return r}function VRe(t,e,r){return Xl(r)?{detector:rS,severity:"info",path:e,message:`feature ${t}'s module '${e}' is not built yet \u2014 the normal state between authoring the spec entry and implementing it`}:{detector:rS,severity:"error",path:e,message:`feature ${t} declares module '${e}' but the file does not exist`}}var rS,nS,lC=y(()=>{"use strict";tS();wt();rS="MISSING_IMPLEMENTATION";nS={name:rS,run:GRe}});function WRe(t){let{cwd:e="."}=t;return ge(e,uC,KRe)}function KRe(t){let e=[];for(let r of t.features)if(r.status==="done")for(let n of r.acceptance_criteria??[]){let o=(n.test_refs??[]).filter(c=>!c.startsWith("derived:")).length>0,s=(n.evidence_refs?.length??0)>0,a=!o&&!s&&(n.test_refs?.length??0)>0;!o&&!s&&e.push({detector:uC,severity:"error",message:`${r.id}.${n.id} declares no test_refs or evidence_refs \u2014 AC is unverified`+(a?" (a 'derived:' candidate exists \u2014 confirm it by removing the prefix, or author a real ref)":"")})}return e}var uC,iS,dC=y(()=>{"use strict";wt();uC="MISSING_TESTS";iS={name:uC,run:WRe}});import{existsSync as JRe,readFileSync as YRe}from"node:fs";import{join as F5}from"node:path";function L5(t){if(JRe(t))try{return JSON.parse(YRe(t,"utf8"))}catch{return}}function tIe(t){let{cwd:e="."}=t,r=L5(F5(e,XRe)),n=L5(F5(e,QRe));if(!r||!n)return[{detector:fC,severity:"info",message:"perf baseline or current missing \u2014 run stage_3.2 with --record first"}];let i=[];for(let[o,s]of Object.entries(r.metrics??{})){let a=n.metrics?.[o];if(!a||typeof s.value!="number"||typeof a.value!="number"||s.value===0)continue;let c=(a.value-s.value)/s.value*100;c>eIe&&i.push({detector:fC,severity:"warn",message:`${o} regressed ${c.toFixed(1)}% (baseline ${s.value}${s.unit??""} \u2192 current ${a.value}${a.unit??""})`})}return i}var fC,XRe,QRe,eIe,z5,U5=y(()=>{"use strict";fC="PERFORMANCE_DRIFT",XRe="perf/baseline.json",QRe="perf/current.json",eIe=10;z5={name:fC,run:tIe}});import{existsSync as rIe}from"node:fs";import{join as nIe}from"node:path";function oIe(t){let{cwd:e="."}=t;return ge(e,pC,r=>aIe(r,e))}function sIe(t,e){return(t.modules??[]).some(r=>rIe(nIe(e,r)))}function aIe(t,e){let r=[];for(let s of t.features)s.status!=="planned"&&s.status!=="in_progress"||sIe(s,e)||r.push(s.id);let n=iIe;if(r.length<=n)return[];let i=r.slice(0,q5).join(", "),o=r.length>q5?", \u2026":"";return[{detector:pC,severity:"warn",message:`${r.length} planned/in_progress features have NO code on disk (> ${n} tolerated) \u2014 the spec has raced ahead of the code. Work one feature end-to-end before authoring the next (docs/feature-cycle.md). Stalled: ${i}${o}`}]}var pC,iIe,q5,B5,H5=y(()=>{"use strict";wt();pC="PLANNED_BACKLOG",iIe=5,q5=8;B5={name:pC,run:oIe}});import{existsSync as cIe,readFileSync as lIe}from"node:fs";import{join as uIe}from"node:path";function pIe(t){let{cwd:e="."}=t;return ge(e,mC,r=>mIe(r,e))}function mIe(t,e){if(t.features.lengthn.includes(i))?[{detector:mC,severity:"warn",path:"docs/project-context.md",message:`${t.features.length} features but docs/project-context.md is still the unrefined init template (it still carries the placeholder prompts) \u2014 the Why/What/Purpose narrative was never filled in. Fill it in with \`clad clarify\` or by hand.`}]:[]}var mC,dIe,fIe,G5,Z5=y(()=>{"use strict";wt();mC="PROJECT_CONTEXT_DRIFT",dIe=8,fIe=["Refine by hand or re-run with LLM available","What gap or pain led to this project","What does success look like"];G5={name:mC,run:pIe}});function V5(t,e,r){return e?e.filter(n=>!t.has(n)).map(n=>({detector:oS,severity:"error",message:`${r} references unknown id '${n}'`})):[]}function hIe(t){let{cwd:e="."}=t;return ge(e,oS,gIe)}function gIe(t){let e=new Set(t.features.map(n=>n.id)),r=[];for(let n of t.features)r.push(...V5(e,n.depends_on,`feature ${n.id}.depends_on`)),n.superseded_by&&!e.has(n.superseded_by)&&r.push({detector:oS,severity:"error",message:`feature ${n.id}.superseded_by references unknown id '${n.superseded_by}'`});for(let n of t.scenarios??[])r.push(...V5(e,n.features,`scenario ${n.id}.features`));return r}var oS,sS,hC=y(()=>{"use strict";wt();oS="REFERENCE_INTEGRITY";sS={name:oS,run:hIe}});function Np(t=""){return new RegExp(yIe,t)}var yIe,gC=y(()=>{"use strict";yIe=String.raw`\bF-(?:\d{3,}|[0-9a-f]{6,8})\b`});import{existsSync as _Ie,readdirSync as bIe,readFileSync as vIe,statSync as SIe,writeFileSync as wIe}from"node:fs";import{dirname as xIe,join as jp,normalize as $Ie,relative as kIe}from"node:path";function RIe(t){let e=[];for(let r of t.matchAll(OIe))if(!r[1].trim().startsWith("ignore"))for(let n of r[1].match(Np("g"))??[])e.push(n);return[...new Set(e)].sort()}function IIe(t){return t.replace(/```[\s\S]*?```/g," ").replace(/~~~[\s\S]*?~~~/g," ").replace(/`[^`\n]*`/g," ")}function W5(t){return t.split("\\").join("/")}function PIe(t){return EIe.some(e=>t===e||t.startsWith(`${e}/`))}function CIe(t){let e=jp(t,"docs");if(!_Ie(e))return[];let r=[],n=[e];for(;n.length>0;){let i=n.pop(),o;try{o=bIe(i)}catch{continue}for(let s of o){if(s.startsWith("."))continue;let a=jp(i,s),c;try{c=SIe(a)}catch{continue}let l=W5(kIe(t,a));c.isDirectory()?n.push(a):s.endsWith(".md")&&r.push(l)}}return r.sort()}function DIe(t,e){if(/^[a-z]+:/i.test(e))return null;let r=$Ie(jp(xIe(t),e));return W5(r)}function Mp(t="."){let e=[];for(let r of CIe(t)){let n;try{n=vIe(jp(t,r),"utf8")}catch{continue}let i=IIe(n),o=RIe(i);if(PIe(r)){if(o.length===0)continue;e.push({doc:r,features:o,doc_links:[]});continue}let a=n.includes(AIe)?[]:i.match(Np("g"))??[],c=[...new Set([...a,...o])].sort(),l=new Set;for(let u of i.matchAll(TIe)){let d=DIe(r,u[1]);d&&l.add(d)}e.push({doc:r,features:c,doc_links:[...l].sort()})}return{docs:e}}function K5(t="."){let e=Mp(t);if(e.docs.length===0)return!1;let r=["# Cladding \xB7 Tier C \u2014 generated doc\u2192spec / doc\u2192doc link index (`clad sync`). Do not edit by hand.","# Source of truth is the docs themselves; DOC_LINK_INTEGRITY validates resolution.",'schema: "0.1"',"docs:"];for(let n of e.docs)n.features.length===0&&n.doc_links.length===0||(r.push(` ${JSON.stringify(n.doc)}:`),n.features.length>0&&r.push(` features: [${n.features.join(", ")}]`),n.doc_links.length>0&&r.push(` doc_links: [${n.doc_links.map(i=>JSON.stringify(i)).join(", ")}]`));return wIe(jp(t,"spec","_doc-links.yaml"),`${r.join(` +`;return aY(Oo(t,"spec","index.yaml"),n,"utf8"),!0}var dS,Up=y(()=>{"use strict";dS=wt(tr(),1)});import{existsSync as cY,readFileSync as lY,readdirSync as gPe}from"node:fs";import{join as DC}from"node:path";function yPe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=xs(e),i=r.inventory;if(!i){let s=uY.filter(([c])=>(n[c]??0)>0);if(s.length===0)return NC(e);let a=s.map(([c,l])=>`${n[c]??0} ${l}`).join(", ");return[...NC(e),{detector:qp,severity:"warn",path:"spec.yaml",message:`spec.yaml has no inventory: block, but the project has ${a} on disk \u2014 run \`clad sync\` to record the inventory so anyone reading spec.yaml sees its real scale.`}]}let o=[];for(let[s,a]of uY){let c=i[s]??0,l=n[s]??0;c!==l&&o.push({detector:qp,severity:"error",path:"spec.yaml",message:`spec.yaml inventory.${s} declares ${c} but the project has ${l} ${a} on disk \u2014 run \`clad sync\` (a stale inventory hides created/deleted shards from anyone reading spec.yaml).`})}return o.push(...NC(e)),o}function NC(t){let e=DC(t,"spec","index.yaml"),r=DC(t,"spec","features");if(!cY(e)||!cY(r))return[];let n=new Map;try{for(let l of lY(e,"utf8").split(` +`)){let u=l.match(/^ (F-[\w-]+):.*\bstatus:\s*['"]?([\w-]+)['"]?/);if(u){n.set(u[1],u[2]);continue}let d=l.match(/^ (F-[\w-]+):/);d&&n.set(d[1],"planned")}}catch{return[]}let i=new Map;try{for(let l of gPe(r)){if(!l.endsWith(".yaml")&&!l.endsWith(".yml"))continue;let u=lY(DC(r,l),"utf8"),d=u.match(/^id:\s*['"]?(F-[\w-]+)['"]?/m);if(!d)continue;let f=u.match(/^status:\s*['"]?([\w-]+)['"]?/m);i.set(d[1],f?f[1]:"planned")}}catch{return[]}let o=[],s=[...i.keys()].filter(l=>!n.has(l)).sort(),a=[...n.keys()].filter(l=>!i.has(l)).sort();if(s.length>0||a.length>0){let l=[];s.length>0&&l.push(`missing from index: ${s.join(", ")}`),a.length>0&&l.push(`in index but not on disk: ${a.join(", ")}`),o.push({detector:qp,severity:"error",path:"spec/index.yaml",message:`spec/index.yaml disagrees with spec/features/ (${l.join("; ")}) \u2014 run \`clad sync\` to regenerate (a stale index silently misleads agents that trust it for lookup).`})}let c=[...i.keys()].filter(l=>n.has(l)&&n.get(l)!==i.get(l)).sort().map(l=>`${l} (index: ${n.get(l)}, shard: ${i.get(l)})`);return c.length>0&&o.push({detector:qp,severity:"error",path:"spec/index.yaml",message:`spec/index.yaml status disagrees with spec/features/ for ${c.join("; ")} \u2014 run \`clad sync\` to regenerate (a stale status silently misleads agents that trust the index).`}),o}var qp,uY,dY,fY=y(()=>{"use strict";Up();Ue();qp="INVENTORY_DRIFT",uY=[["features","feature shard(s)"],["scenarios","scenario shard(s)"],["capabilities","capabilit(ies)"],["test_files","test file(s)"]];dY={name:qp,run:yPe}});import{existsSync as _Pe,readFileSync as bPe}from"node:fs";import{join as vPe}from"node:path";function wPe(t){let{cwd:e="."}=t,r=vPe(e,"src","spec","schema.json"),n=[];if(_Pe(r)){let i;try{i=JSON.parse(bPe(r,"utf8"))}catch(o){n.push({detector:Hp,severity:"error",message:`spec/schema.json unreadable or invalid JSON: ${o.message}`})}if(i)for(let o of SPe)i.required?.includes(o)||n.push({detector:Hp,severity:"error",message:`spec/schema.json does not require root key '${o}'`}),i.properties?.[o]||n.push({detector:Hp,severity:"error",message:`spec/schema.json does not declare property '${o}'`})}try{let i=q(e);i.schema!==pY&&n.push({detector:Hp,severity:"error",message:`spec.yaml schema='${i.schema}' but supported version is '${pY}'`})}catch{}return n}var Hp,SPe,pY,mY,hY=y(()=>{"use strict";Ue();Hp="META_INTEGRITY",SPe=["schema","project","features"],pY="0.1";mY={name:Hp,run:wPe}});function xPe(t){let{cwd:e="."}=t,r;try{r=q(e)}catch{return[]}let n=[];return gY(r.features.map(i=>({id:i.id,slug:i.slug})),"features",n),gY((r.scenarios??[]).map(i=>({id:i.id,slug:i.slug})),"scenarios",n),n}function gY(t,e,r){let n=new Map;for(let i of t){if(!i.slug)continue;let o=n.get(i.slug);o?r.push({detector:yY,severity:"error",message:`slug '${i.slug}' is used by both ${o} and ${i.id} in ${e}/ \u2014 two items in the same namespace cannot share a slug; pick a different slug for one`}):n.set(i.slug,i.id)}}var yY,_Y,bY=y(()=>{"use strict";Ue();yY="SLUG_CONFLICT";_Y={name:yY,run:xPe}});function iu(t){return t==="planned"||t==="in_progress"}var fS=y(()=>{"use strict"});import{existsSync as $Pe}from"node:fs";import{join as kPe}from"node:path";function EPe(t){let{cwd:e="."}=t;return ye(e,pS,r=>APe(r,e))}function APe(t,e){let r=[];for(let n of t.features)for(let i of n.modules??[]){let o=kPe(e,i);$Pe(o)||r.push(OPe(n.id,i,n.status))}return r}function OPe(t,e,r){return iu(r)?{detector:pS,severity:"info",path:e,message:`feature ${t}'s module '${e}' is not built yet \u2014 the normal state between authoring the spec entry and implementing it`}:{detector:pS,severity:"error",path:e,message:`feature ${t} declares module '${e}' but the file does not exist`}}var pS,mS,jC=y(()=>{"use strict";fS();xt();pS="MISSING_IMPLEMENTATION";mS={name:pS,run:EPe}});function TPe(t){let{cwd:e="."}=t;return ye(e,MC,RPe)}function RPe(t){let e=[];for(let r of t.features)if(r.status==="done")for(let n of r.acceptance_criteria??[]){let o=(n.test_refs??[]).filter(c=>!c.startsWith("derived:")).length>0,s=(n.evidence_refs?.length??0)>0,a=!o&&!s&&(n.test_refs?.length??0)>0;!o&&!s&&e.push({detector:MC,severity:"error",message:`${r.id}.${n.id} declares no test_refs or evidence_refs \u2014 AC is unverified`+(a?" (a 'derived:' candidate exists \u2014 confirm it by removing the prefix, or author a real ref)":"")})}return e}var MC,hS,FC=y(()=>{"use strict";xt();MC="MISSING_TESTS";hS={name:MC,run:TPe}});import{existsSync as IPe,readFileSync as PPe}from"node:fs";import{join as vY}from"node:path";function SY(t){if(IPe(t))try{return JSON.parse(PPe(t,"utf8"))}catch{return}}function jPe(t){let{cwd:e="."}=t,r=SY(vY(e,CPe)),n=SY(vY(e,DPe));if(!r||!n)return[{detector:LC,severity:"info",message:"perf baseline or current missing \u2014 run stage_3.2 with --record first"}];let i=[];for(let[o,s]of Object.entries(r.metrics??{})){let a=n.metrics?.[o];if(!a||typeof s.value!="number"||typeof a.value!="number"||s.value===0)continue;let c=(a.value-s.value)/s.value*100;c>NPe&&i.push({detector:LC,severity:"warn",message:`${o} regressed ${c.toFixed(1)}% (baseline ${s.value}${s.unit??""} \u2192 current ${a.value}${a.unit??""})`})}return i}var LC,CPe,DPe,NPe,wY,xY=y(()=>{"use strict";LC="PERFORMANCE_DRIFT",CPe="perf/baseline.json",DPe="perf/current.json",NPe=10;wY={name:LC,run:jPe}});import{existsSync as MPe}from"node:fs";import{join as FPe}from"node:path";function zPe(t){let{cwd:e="."}=t;return ye(e,zC,r=>qPe(r,e))}function UPe(t,e){return(t.modules??[]).some(r=>MPe(FPe(e,r)))}function qPe(t,e){let r=[];for(let s of t.features)s.status!=="planned"&&s.status!=="in_progress"||UPe(s,e)||r.push(s.id);let n=LPe;if(r.length<=n)return[];let i=r.slice(0,$Y).join(", "),o=r.length>$Y?", \u2026":"";return[{detector:zC,severity:"warn",message:`${r.length} planned/in_progress features have NO code on disk (> ${n} tolerated) \u2014 the spec has raced ahead of the code. Work one feature end-to-end before authoring the next (docs/feature-cycle.md). Stalled: ${i}${o}`}]}var zC,LPe,$Y,kY,EY=y(()=>{"use strict";xt();zC="PLANNED_BACKLOG",LPe=5,$Y=8;kY={name:zC,run:zPe}});import{existsSync as HPe,readFileSync as BPe}from"node:fs";import{join as GPe}from"node:path";function WPe(t){let{cwd:e="."}=t;return ye(e,UC,r=>KPe(r,e))}function KPe(t,e){if(t.features.lengthn.includes(i))?[{detector:UC,severity:"warn",path:"docs/project-context.md",message:`${t.features.length} features but docs/project-context.md is still the unrefined init template (it still carries the placeholder prompts) \u2014 the Why/What/Purpose narrative was never filled in. Fill it in with \`clad clarify\` or by hand.`}]:[]}var UC,ZPe,VPe,AY,OY=y(()=>{"use strict";xt();UC="PROJECT_CONTEXT_DRIFT",ZPe=8,VPe=["Refine by hand or re-run with LLM available","What gap or pain led to this project","What does success look like"];AY={name:UC,run:WPe}});function TY(t,e,r){return e?e.filter(n=>!t.has(n)).map(n=>({detector:gS,severity:"error",message:`${r} references unknown id '${n}'`})):[]}function JPe(t){let{cwd:e="."}=t;return ye(e,gS,YPe)}function YPe(t){let e=new Set(t.features.map(n=>n.id)),r=[];for(let n of t.features)r.push(...TY(e,n.depends_on,`feature ${n.id}.depends_on`)),n.superseded_by&&!e.has(n.superseded_by)&&r.push({detector:gS,severity:"error",message:`feature ${n.id}.superseded_by references unknown id '${n.superseded_by}'`});for(let n of t.scenarios??[])r.push(...TY(e,n.features,`scenario ${n.id}.features`));return r}var gS,yS,qC=y(()=>{"use strict";xt();gS="REFERENCE_INTEGRITY";yS={name:gS,run:JPe}});function Bp(t=""){return new RegExp(XPe,t)}var XPe,HC=y(()=>{"use strict";XPe=String.raw`\bF-(?:\d{3,}|[0-9a-f]{6,8})\b`});import{existsSync as QPe,readdirSync as eCe,readFileSync as tCe,statSync as rCe,writeFileSync as nCe}from"node:fs";import{dirname as iCe,join as Gp,normalize as oCe,relative as sCe}from"node:path";function dCe(t){let e=[];for(let r of t.matchAll(uCe))if(!r[1].trim().startsWith("ignore"))for(let n of r[1].match(Bp("g"))??[])e.push(n);return[...new Set(e)].sort()}function fCe(t){return t.replace(/```[\s\S]*?```/g," ").replace(/~~~[\s\S]*?~~~/g," ").replace(/`[^`\n]*`/g," ")}function RY(t){return t.split("\\").join("/")}function pCe(t){return aCe.some(e=>t===e||t.startsWith(`${e}/`))}function mCe(t){let e=Gp(t,"docs");if(!QPe(e))return[];let r=[],n=[e];for(;n.length>0;){let i=n.pop(),o;try{o=eCe(i)}catch{continue}for(let s of o){if(s.startsWith("."))continue;let a=Gp(i,s),c;try{c=rCe(a)}catch{continue}let l=RY(sCe(t,a));c.isDirectory()?n.push(a):s.endsWith(".md")&&r.push(l)}}return r.sort()}function hCe(t,e){if(/^[a-z]+:/i.test(e))return null;let r=oCe(Gp(iCe(t),e));return RY(r)}function Zp(t="."){let e=[];for(let r of mCe(t)){let n;try{n=tCe(Gp(t,r),"utf8")}catch{continue}let i=fCe(n),o=dCe(i);if(pCe(r)){if(o.length===0)continue;e.push({doc:r,features:o,doc_links:[]});continue}let a=n.includes(cCe)?[]:i.match(Bp("g"))??[],c=[...new Set([...a,...o])].sort(),l=new Set;for(let u of i.matchAll(lCe)){let d=hCe(r,u[1]);d&&l.add(d)}e.push({doc:r,features:c,doc_links:[...l].sort()})}return{docs:e}}function IY(t="."){let e=Zp(t);if(e.docs.length===0)return!1;let r=["# Cladding \xB7 Tier C \u2014 generated doc\u2192spec / doc\u2192doc link index (`clad sync`). Do not edit by hand.","# Source of truth is the docs themselves; DOC_LINK_INTEGRITY validates resolution.",'schema: "0.1"',"docs:"];for(let n of e.docs)n.features.length===0&&n.doc_links.length===0||(r.push(` ${JSON.stringify(n.doc)}:`),n.features.length>0&&r.push(` features: [${n.features.join(", ")}]`),n.doc_links.length>0&&r.push(` doc_links: [${n.doc_links.map(i=>JSON.stringify(i)).join(", ")}]`));return nCe(Gp(t,"spec","_doc-links.yaml"),`${r.join(` `)} -`,"utf8"),!0}var EIe,AIe,TIe,OIe,aS=y(()=>{"use strict";gC();EIe=["docs/ab-evaluation","docs/ab-evaluation-extended","docs/dogfood","docs/benchmarks"],AIe="clad-doc-links: ignore",TIe=/\]\(\s*([^)\s]+?\.md)(?:#[^)]*)?\s*\)/g,OIe=/clad-doc-links:[ \t]*([^\n>]*)/g});import{existsSync as NIe}from"node:fs";import{join as jIe}from"node:path";function MIe(t){let{cwd:e="."}=t;return ge(e,cS,r=>FIe(r,e))}function FIe(t,e){let r=new Set((t.features??[]).map(i=>i.id)),n=[];for(let i of Mp(e).docs){for(let o of i.doc_links)NIe(jIe(e,o))||n.push({detector:cS,severity:"error",path:i.doc,message:`doc '${i.doc}' links to missing file '${o}'`});for(let o of i.features)r.has(o)||n.push({detector:cS,severity:"warn",path:i.doc,message:`doc '${i.doc}' references unknown feature '${o}' \u2014 archived/renamed? If it is an illustrative example, add a \`clad-doc-links: ignore\` marker to the doc.`})}return n}var cS,lS,yC=y(()=>{"use strict";aS();wt();cS="DOC_LINK_INTEGRITY";lS={name:cS,run:MIe}});function LIe(t){let{cwd:e="."}=t;return ge(e,Fp,r=>zIe(r))}function zIe(t){let e=[],r=t.features.length,n=t.scenarios??[],i=r>=J5,o=t.project.onboarding_seeded===!0&&!i;r>=J5&&n.length===0&&e.push({detector:Fp,severity:"warn",path:"spec/scenarios/",message:`${r} features but no scenarios declared \u2014 cross-feature user-journey flows are not captured. Author at least one with \`clad_create_scenario\`.`});for(let a of n)(a.features??[]).length===0&&e.push({detector:Fp,severity:o?"info":"warn",path:"spec/scenarios/",message:o?`scenario ${a.id} binds no features yet \u2014 retained as future onboarding intent; bind it when a matching feature lands.`:`scenario ${a.id} binds no features (features: []) \u2014 a scenario must cover at least one feature's flow, or it should be removed.`});let s=new Map(t.features.filter(a=>typeof a.slug=="string"&&a.slug.length>0).map(a=>[a.slug,a.id]));for(let a of n){if(!a.flow)continue;let c=new Set(a.features??[]),l=new Map;for(let u of a.flow.matchAll(/\(([^)]+)\)/g))for(let d of u[1].split(/[,/·]/)){let f=d.trim(),p=s.get(f);p&&!c.has(p)&&l.set(f,p)}if(l.size>0){let u=[...l].map(([d,f])=>`${d} (${f})`).join(", ");e.push({detector:Fp,severity:"warn",path:"spec/scenarios/",message:`scenario ${a.id} flow references ${u} but features[] does not bind ${l.size===1?"it":"them"} \u2014 bind every feature the flow walks, or trim the flow so coverage is not under-stated.`})}}return e}var Fp,J5,Y5,X5=y(()=>{"use strict";wt();Fp="SCENARIO_COVERAGE",J5=8;Y5={name:Fp,run:LIe}});import{createHash as UIe}from"node:crypto";function qIe(t){return!Number.isFinite(t)||t<=0?0:t>=1?1:t}function Lp(t,e=0){if(t.oracle_policy){let r=t.oracle_policy;return{mandateActive:!0,reportOnly:!1,exhaustive:!1,alwaysEars:new Set(r.always_ears??Q5),sample:qIe(r.sample??0)}}return t.require_oracles===!0?{mandateActive:!0,reportOnly:!1,exhaustive:!0,alwaysEars:new Set,sample:1}:t.require_oracles===void 0&&e>=8?{mandateActive:!0,reportOnly:!0,exhaustive:!1,alwaysEars:new Set(Q5),sample:0}:{mandateActive:!1,reportOnly:!1,exhaustive:!1,alwaysEars:new Set,sample:0}}function zp(t){return(t.features??[]).filter(e=>e.status==="done").length}function BIe(t,e){return e<=0?!1:e>=1?!0:parseInt(UIe("sha256").update(t).digest("hex").slice(0,8),16)%1e40})}return r}var Q5,uS=y(()=>{"use strict";Q5=["unwanted"]});import{chmodSync as HIe,existsSync as tY,readFileSync as GIe,readdirSync as ZIe,statSync as rY,unlinkSync as VIe,utimesSync as WIe,writeFileSync as KIe}from"node:fs";import{join as nY}from"node:path";import iY from"node:process";function JIe(t){return mJ(t).map(e=>{try{let r=rY(e);return r.isFile()?{path:e,body:GIe(e),mode:r.mode,atime:r.atime,mtime:r.mtime}:{path:e,nonFile:!0}}catch(r){if(r.code==="ENOENT")return{path:e};throw r}})}function YIe(t){let e=[];for(let r of t)if(!r.nonFile)try{if(r.body===void 0){if(!tY(r.path))continue;if(!rY(r.path).isFile()){e.push(`${r.path}: scoped oracle run created a non-file report candidate`);continue}VIe(r.path);continue}KIe(r.path,r.body),r.mode!==void 0&&HIe(r.path,r.mode),r.atime&&r.mtime&&WIe(r.path,r.atime,r.mtime)}catch(n){e.push(`${r.path}: ${n.message}`)}return e}function XIe(t){let e=!1,r=n=>{for(let i of ZIe(n,{withFileTypes:!0})){if(e)return;let o=nY(n,i.name);i.isDirectory()?r(o):(/\.(test|spec)\.[cm]?[jt]sx?$/.test(i.name)||/_test\.py$/.test(i.name))&&(e=!0)}};try{r(t)}catch{}return e}function _C(t={}){let{cwd:e="."}=t,r=nY(e,vs);if(!tY(r)||!XIe(r))return{stage:Ya,pass:!1,exitCode:2,stderr:`no spec-conformance oracles under ${vs}/ \u2014 skipped`};let n=dt(e),i=n.gates.test;if(!i?.cmd||!i.args)return{stage:Ya,pass:!1,exitCode:2,stderr:`no test runner registered for language '${n.language}'`};let o;try{o=JIe(e)}catch(d){return{stage:Ya,pass:!1,exitCode:1,stderr:`could not preserve the full test report before the scoped oracle run: ${d.message}`}}let s,a,c=[...i.args,vs];try{s=We(i.cmd,c,{cwd:e,reject:!1})}catch(d){a=d}let l=YIe(o);if(l.length>0)return{stage:Ya,pass:!1,exitCode:1,stderr:`could not restore the full test report after the scoped oracle run: ${l.join("; ")}`};if(a||!s)return{stage:Ya,pass:!1,exitCode:1,stderr:`oracle runner failed to start: ${a?.message??"unknown error"}`};let u=Nt(Ya,i.cmd,s,c);return u||Yt(Ya,s)}var Ya,vs,QIe,bC=y(()=>{"use strict";Lr();cn();_p();Cn();Ya="stage_2.3",vs="tests/oracle";QIe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${iY.argv[1]}`;if(QIe){let t=_C();console.log(JSON.stringify(t)),iY.exit(t.exitCode)}});import{existsSync as ePe}from"node:fs";import{join as tPe}from"node:path";function rPe(t){let{cwd:e="."}=t;return ge(e,oi,r=>nPe(r,e))}function nPe(t,e){let r=[],n=Lp(t.project,zp(t)),i=n.reportOnly?"info":"error",o=n.mandateActive?fr(e):[],s=o.filter(l=>l.kind==="oracle"),a=new Set(["agent:developer","agent:specialists"]),c=l=>o.find(u=>u.featureId===l&&a.has(u.stage))?.identity.name;for(let l of t.features)if(l.status==="done")for(let u of l.acceptance_criteria??[]){let d=u.oracle_refs??[];if(Up(n,l.id,u)&&d.length===0){let f=n.exhaustive?"project.require_oracles is set":u.ears&&n.alwaysEars.has(u.ears)?`oracle_policy.always_ears includes '${u.ears}'`:"selected by oracle_policy.sample";r.push({detector:oi,severity:i,message:`${l.id}.${u.id} done AC lacks a spec-conformance oracle (${f}; declare oracle_refs under ${vs}/)`+(n.reportOnly?" [report-only \u2014 the graduated default enforces in 0.7]":"")})}for(let f of d){if(!ePe(tPe(e,f))){r.push({detector:oi,severity:"error",path:f,message:`${l.id}.${u.id} oracle_ref '${f}' resolves to nothing on disk`});continue}if(f.startsWith(`${vs}/`)||r.push({detector:oi,severity:"warn",path:f,message:`${l.id}.${u.id} oracle_ref '${f}' lives outside ${vs}/ \u2014 stage_2.3 only runs ${vs}/, so this oracle will not execute`}),!n.mandateActive)continue;let p=s.find(g=>g.featureId===l.id&&g.acId===u.id&&g.artifact===f);if(!p){r.push({detector:oi,severity:"error",path:f,message:`${l.id}.${u.id} oracle '${f}' has no authoring-provenance record \u2014 author it via 'clad oracle' (or clad_author_oracle) so impl-blindness can be verified`});continue}let m=c(l.id);m&&p.identity.name===m?r.push({detector:oi,severity:"error",path:f,message:`${l.id}.${u.id} oracle '${f}' is NOT impl-blind: authored by the implementer ('${m}')`}):m||r.push({detector:oi,severity:"info",message:`${l.id}.${u.id} oracle author\u2260implementer not verified \u2014 no implementer identity recorded (no clad run history to compare)`});let h=(p.readManifest??[]).filter(g=>(l.modules??[]).includes(g));h.length>0&&r.push({detector:oi,severity:"error",path:f,message:`${l.id}.${u.id} oracle '${f}' is NOT impl-blind: author read implementation file(s) the feature owns (${h.join(", ")})`}),p.blind===!1&&r.push({detector:oi,severity:"info",message:`${l.id}.${u.id} oracle '${f}' provenance is self-reported (host-protocol), not cladding-controlled \u2014 manifest checked, blindness unproven`})}}if(n.mandateActive&&!n.exhaustive){let l=t.features.filter(u=>u.status==="done").flatMap(u=>u.acceptance_criteria??[]).filter(u=>!u.ears).length;l>0&&r.push({detector:oi,severity:"info",message:`${l} done AC(s) carry no EARS tag and are invisible to the risk-weighted oracle mandate \u2014 tag them (ubiquitous/event/state/optional/unwanted/complex) for the mandate to mean anything.`})}return r}var oi,oY,sY=y(()=>{"use strict";un();uS();bC();wt();oi="SPEC_CONFORMANCE";oY={name:oi,run:rPe}});function iPe(t){let{cwd:e="."}=t,r=fr(e);if(r.length===0)return[{detector:vC,severity:"info",message:"no audit log present \u2014 detector is opt-in on prior stage_4 runs"}];let n=Date.now(),i=[];for(let o of r){let s=Date.parse(o.identity.timestamp);if(Number.isNaN(s))continue;let a=(n-s)/(1e3*60*60*24);a>aY&&i.push({detector:vC,severity:"warn",message:`evidence ${o.id} is ${Math.round(a)} days old (floor ${aY})`})}return i}var vC,aY,cY,lY=y(()=>{"use strict";un();vC="STALE_EVIDENCE",aY=90;cY={name:vC,run:iPe}});import{existsSync as uY}from"node:fs";import{join as dY}from"node:path";function oPe(t){let{cwd:e="."}=t;return ge(e,Ql,r=>sPe(r,e))}function sPe(t,e){let r=[];for(let n of t.features){if(n.archived_at&&n.status!=="archived"&&r.push({detector:Ql,severity:"warn",message:`feature ${n.id} has archived_at but status='${n.status}' (expected 'archived')`,suggestion:{action:"propose-archive",args:{featureId:n.id,reason:`archived_at already set but status is '${n.status}'`}}}),n.superseded_by&&!n.archived_at&&r.push({detector:Ql,severity:"warn",message:`feature ${n.id} has superseded_by but no archived_at`,suggestion:{action:"propose-archive",args:{featureId:n.id,reason:`superseded by ${n.superseded_by} but missing archived_at`}}}),n.status==="archived"){let i=(n.modules??[]).filter(o=>uY(dY(e,o)));i.length>0&&r.push({detector:Ql,severity:"warn",message:`feature ${n.id} is archived but ${i.length} module(s) still exist: ${i.join(", ")}`})}Xl(n.status)&&(n.modules?.length??0)>0&&!(n.modules??[]).some(i=>uY(dY(e,i)))&&r.push({detector:Ql,severity:"info",message:`feature ${n.id} (status='${n.status}') declares ${n.modules?.length??0} module(s) that aren't built yet \u2014 the normal state while implementing (not stale)`})}return r}var Ql,dS,SC=y(()=>{"use strict";tS();wt();Ql="STALE_SPECIFICATION";dS={name:Ql,run:oPe}});import{existsSync as fY,statSync as pY}from"node:fs";import{join as mY}from"node:path";function cPe(t,e){let r=0;for(let n of e){let i=mY(t,n);if(!fY(i))continue;let o=pY(i).mtimeMs;o>r&&(r=o)}return r}function lPe(t){let{cwd:e="."}=t;return ge(e,wC,r=>uPe(r,e))}function uPe(t,e){let r=Li(e,t.project?.language),n=t.features.flatMap(a=>a.modules??[]),i=cPe(e,n);if(i===0)return[];let o=_s([...r.testGlobs],{cwd:e,dot:!1});if(o.length===0)return[];let s=[];for(let a of o){let c=mY(e,a);if(!fY(c))continue;let l=pY(c).mtimeMs,u=(i-l)/(1e3*60*60*24);u>aPe&&s.push({detector:wC,severity:"warn",path:a,message:`${a} is ${Math.round(u)} days older than newest source module`})}return s}var wC,aPe,fS,xC=y(()=>{"use strict";Ap();Ga();wt();wC="STALE_TESTS",aPe=30;fS={name:wC,run:lPe}});import{existsSync as dPe}from"node:fs";import{join as fPe}from"node:path";function pPe(t){let{cwd:e="."}=t;return ge(e,qp,r=>mPe(r,e))}function mPe(t,e){let r=[];for(let n of t.features){let i=n.modules??[],o=n.acceptance_criteria??[];if(n.status==="done"&&i.length===0&&o.length===0){r.push({detector:qp,severity:"error",message:`feature ${n.id} status='done' but declares no modules and no acceptance_criteria \u2014 nothing to verify (hollow completion)`});continue}if(i.length===0)continue;let s=i.filter(a=>!dPe(fPe(e,a)));s.length!==0&&(n.status==="done"?r.push({detector:qp,severity:"error",message:`feature ${n.id} status='done' but ${s.length}/${i.length} module(s) missing: ${s.join(", ")}`}):n.status==="in_progress"&&s.length===i.length&&r.push({detector:qp,severity:Xl(n.status)?"info":"warn",message:`feature ${n.id} is in progress and none of its declared modules are built yet \u2014 the normal state while implementing`}))}return r}var qp,pS,$C=y(()=>{"use strict";tS();wt();qp="STATUS_DRIFT";pS={name:qp,run:pPe}});function hPe(t){let{cwd:e="."}=t;return ge(e,mS,r=>gPe(r,e))}function gPe(t,e){let r=dt(e).language;return r==="unknown"?[{detector:mS,severity:"info",message:"no manifest matched \u2014 language cannot be cross-checked"}]:t.project.language===r?[]:[{detector:mS,severity:"warn",message:`spec.project.language='${t.project.language}' but the manifest chain detects '${r}'`}]}var mS,hY,gY=y(()=>{"use strict";cn();wt();mS="TECH_STACK_MISMATCH";hY={name:mS,run:hPe}});function vPe(t){if((t.features??[]).length`${i}/${o}/**/*.${n}`)}function SPe(t){let{cwd:e="."}=t;return ge(e,kC,r=>wPe(r,e))}function wPe(t,e){let r=new Set;for(let o of t.features)for(let s of o.modules??[])r.add(s);let n=_s([...vPe(t)],{cwd:e,dot:!1}),i=[];for(let o of n)r.has(o)||i.push({detector:kC,severity:"error",path:o,message:`file '${o}' is not claimed by any feature in spec.yaml`});return i}var kC,yY,yPe,_Pe,bPe,hS,EC=y(()=>{"use strict";Ap();JP();wt();kC="UNMAPPED_ARTIFACT",yY=["src/stages/**/*.ts","src/spec/**/*.ts"],yPe={typescript:"ts",javascript:"js",python:"py",rust:"rs",go:"go",kotlin:"kt"},_Pe={kotlin:"src/main/kotlin"},bPe=8;hS={name:kC,run:SPe}});import{existsSync as _Y}from"node:fs";import{join as bY}from"node:path";function $Pe(t){return xPe.some(e=>t.startsWith(e))}function kPe(t){let{cwd:e="."}=t;return ge(e,AC,r=>EPe(r,e))}function EPe(t,e){let r=[];for(let n of t.features)if(n.status==="done")for(let i of n.acceptance_criteria??[])for(let o of i.test_refs??[]){if($Pe(o))continue;let s=o.split("#",1)[0];_Y(bY(e,o))||s&&_Y(bY(e,s))||r.push({detector:AC,severity:"error",path:o,message:`${n.id}.${i.id} test_ref '${o}' resolves to nothing on disk \u2014 a test_ref must be a real file path (e.g. 'tests/x.test.ts', optionally with a '#' anchor) or a 'self-dogfood: +`}function Kx(t){return`${JSON.stringify(t,null,2)} +`}function ire(t){let e=new Map(t.nodes.map(s=>[s.id,s])),r=new Map,n=new Map;for(let s of t.edges)(r.get(s.from)??r.set(s.from,[]).get(s.from)).push({other:s.to,kind:s.kind}),(n.get(s.to)??n.set(s.to,[]).get(s.to)).push({other:s.from,kind:s.kind});let i=s=>{let a=e.get(s);return a?`[[${ere(a)}|${a.label.replace(/[[\]|]/g," ")}]]`:`[[${s.replace(/[[\]|]/g," ")}]]`},o=new Map;for(let s of t.nodes){let a=["---",`kind: ${s.kind}`,...s.tier?[`tier: ${s.tier}`]:[],...s.status?[`status: ${s.status}`]:[],`id: ${JSON.stringify(s.id)}`,"---",`# ${s.label}`,""],c=(r.get(s.id)??[]).slice().sort(tre);if(c.length>0){a.push("## Links");for(let u of c)a.push(`- ${u.kind} \u2192 ${i(u.other)}`);a.push("")}let l=(n.get(s.id)??[]).slice().sort(tre);if(l.length>0){a.push("## Backlinks");for(let u of l)a.push(`- ${i(u.other)} \u2192 ${u.kind}`);a.push("")}o.set(`${s.kind}/${ere(s)}.md`,`${a.join(` +`)}`)}return o}function tre(t,e){return t.kind.localeCompare(e.kind)||t.other.localeCompare(e.other)}import{readFileSync as W4e}from"node:fs";import{dirname as K4e,join as Vj}from"node:path";import{fileURLToPath as J4e}from"node:url";var Wj=K4e(J4e(import.meta.url));function ore(t){for(let e of[Vj(Wj,"viewer",t),Vj(Wj,"..","graph","viewer",t),Vj(Wj,"..","..","dist","viewer",t)])try{return W4e(e,"utf8")}catch{}throw new Error(`cladding: viewer asset not found: ${t}`)}function sre(t){return JSON.stringify(t).replace(/0?` `:"";return` @@ -903,61 +927,63 @@ ${n.report.remainingQuestions} question(s) left. continue with \`clad clarify ${n} -`}eC();yC();lC();dC();hC();QP();xC();$C();EC();TC();rh();gC();Ue();var kqe=[iS,gS,nS,hS,sS,lS,Xv,pS,fS,Yv];function Eqe(t,e){if(t.path){let n=t.path.split("#")[0].trim(),i=[qe.module(n),qe.test(n),qe.doc(n)].filter(o=>e.has(o));if(i.length>0)return i}let r=Np().exec(t.message??"");return r&&e.has(qe.feature(r[0]))?[qe.feature(r[0])]:[]}function Hx(t,e="."){let r=new Set(t.nodes.map(o=>o.id)),n={};try{Ea(e,q(e))}catch{}try{for(let o of kqe){let s=[];try{s=o.run({cwd:e})}catch{continue}for(let a of s)if(!(a.severity!=="error"&&a.severity!=="warn"))for(let c of Eqe(a,r)){let l=n[c]??(n[c]={severity:"warn",count:0,detectors:new Set});l.count+=1,l.detectors.add(a.detector),a.severity==="error"&&(l.severity="error")}}}finally{Ea(e,null)}let i={};for(let o of Object.keys(n).sort()){let s=n[o];i[o]={severity:s.severity,count:s.count,detectors:[...s.detectors].sort()}}return i}Dj();Ue();Pi();var Tqe=new Set(["mermaid","dot","json","obsidian","html"]);function wte(t={}){try{let e=t.format??"mermaid";if(!Tqe.has(e)){L("fail","graph",`unknown --format '${e}' \u2014 use mermaid | dot | json | obsidian | html`),process.exit(1);return}let r=e,n=q(),i=$c(n,".");if(t.focus){let s=Fx(n,i,t.focus);if(s.length===0){L("fail","graph",`no node matches '${t.focus}' \u2014 try a feature id (F-\u2026), slug, or module path`),process.exit(1);return}let a=t.depth!==void 0?Number(t.depth):1/0;if(Number.isNaN(a)||a<0){L("fail","graph",`--depth must be a non-negative number, got '${t.depth}'`),process.exit(1);return}i=Mx(i,s,a)}if(r==="obsidian"){let s=t.out??".cladding/graph",a=_te(i);for(let[c,l]of a){let u=Aqe(s,c);Nj(Mj(u),{recursive:!0}),jj(u,l,"utf8")}L("pass","graph",`wrote ${a.size} note(s) to ${s} \u2014 open it as an Obsidian vault`),process.exit(0);return}if(r==="html"){if(!t.out){L("fail","graph","--format html requires --out (a single self-contained .html file)"),process.exit(1);return}let s=Bx(i,Hx(i,"."));Nj(Mj(t.out),{recursive:!0}),jj(t.out,s,"utf8"),L("pass","graph",`wrote a self-contained viewer to ${t.out} \u2014 open it in a browser (offline)`),process.exit(0);return}let o=r==="dot"?yte(i):r==="json"?qx(i):gte(i);t.out?(Nj(Mj(t.out),{recursive:!0}),jj(t.out,o,"utf8"),L("pass","graph",`wrote ${r} graph to ${t.out}`),process.exit(0)):process.stdout.write(o,()=>process.exit(0))}catch(e){L("fail","graph",e.message),process.exit(1)}}function xte(){try{let t=$c(q(),".");process.stdout.write(Ste(Gx(t)),()=>process.exit(0))}catch(t){L("fail","graph",t.message),process.exit(1)}}rh();import{createServer as Oqe}from"node:http";import{existsSync as Rqe,watch as Iqe}from"node:fs";import{join as Pqe}from"node:path";Ue();Pi();function Cqe(t={}){let e=t.cwd??".",r=new Set,n=()=>$c(q(e),e),i=()=>{for(let u of r)try{u.write(`data: refresh +`}uC();BC();jC();FC();qC();lC();JC();YC();XC();eD();oh();HC();Ue();var Y4e=[hS,TS,mS,OS,yS,vS,tS,$S,xS,eS];function X4e(t,e){if(t.path){let n=t.path.split("#")[0].trim(),i=[qe.module(n),qe.test(n),qe.doc(n)].filter(o=>e.has(o));if(i.length>0)return i}let r=Bp().exec(t.message??"");return r&&e.has(qe.feature(r[0]))?[qe.feature(r[0])]:[]}function Yx(t,e="."){let r=new Set(t.nodes.map(o=>o.id)),n={};try{Oa(e,q(e))}catch{}try{for(let o of Y4e){let s=[];try{s=o.run({cwd:e})}catch{continue}for(let a of s)if(!(a.severity!=="error"&&a.severity!=="warn"))for(let c of X4e(a,r)){let l=n[c]??(n[c]={severity:"warn",count:0,detectors:new Set});l.count+=1,l.detectors.add(a.detector),a.severity==="error"&&(l.severity="error")}}}finally{Oa(e,null)}let i={};for(let o of Object.keys(n).sort()){let s=n[o];i[o]={severity:s.severity,count:s.count,detectors:[...s.detectors].sort()}}return i}Kj();Ue();Pi();var eHe=new Set(["mermaid","dot","json","obsidian","html"]);function cre(t={}){try{let e=t.format??"mermaid";if(!eHe.has(e)){L("fail","graph",`unknown --format '${e}' \u2014 use mermaid | dot | json | obsidian | html`),process.exit(1);return}let r=e,n=q(),i=Ac(n,".");if(t.focus){let s=Gx(n,i,t.focus);if(s.length===0){L("fail","graph",`no node matches '${t.focus}' \u2014 try a feature id (F-\u2026), slug, or module path`),process.exit(1);return}let a=t.depth!==void 0?Number(t.depth):1/0;if(Number.isNaN(a)||a<0){L("fail","graph",`--depth must be a non-negative number, got '${t.depth}'`),process.exit(1);return}i=Bx(i,s,a)}if(r==="obsidian"){let s=t.out??".cladding/graph",a=ire(i);for(let[c,l]of a){let u=Q4e(s,c);Jj(Xj(u),{recursive:!0}),Yj(u,l,"utf8")}L("pass","graph",`wrote ${a.size} note(s) to ${s} \u2014 open it as an Obsidian vault`),process.exit(0);return}if(r==="html"){if(!t.out){L("fail","graph","--format html requires --out (a single self-contained .html file)"),process.exit(1);return}let s=Jx(i,Yx(i,"."));Jj(Xj(t.out),{recursive:!0}),Yj(t.out,s,"utf8"),L("pass","graph",`wrote a self-contained viewer to ${t.out} \u2014 open it in a browser (offline)`),process.exit(0);return}let o=r==="dot"?nre(i):r==="json"?Kx(i):rre(i);t.out?(Jj(Xj(t.out),{recursive:!0}),Yj(t.out,o,"utf8"),L("pass","graph",`wrote ${r} graph to ${t.out}`),process.exit(0)):process.stdout.write(o,()=>process.exit(0))}catch(e){L("fail","graph",e.message),process.exit(1)}}function lre(){try{let t=Ac(q(),".");process.stdout.write(are(Xx(t)),()=>process.exit(0))}catch(t){L("fail","graph",t.message),process.exit(1)}}oh();import{createServer as tHe}from"node:http";import{existsSync as rHe,watch as nHe}from"node:fs";import{join as iHe}from"node:path";Ue();Pi();function oHe(t={}){let e=t.cwd??".",r=new Set,n=()=>Ac(q(e),e),i=()=>{for(let u of r)try{u.write(`data: refresh -`)}catch{r.delete(u)}},o=Oqe((u,d)=>{let f=(u.url??"/").split("?")[0],p=(u.headers.host??"").split(":")[0];if(p&&p!=="localhost"&&p!=="127.0.0.1"&&p!=="[::1]"&&p!=="::1"){d.writeHead(403,{"Content-Type":"text/plain"}),d.end("forbidden host");return}try{if(f==="/graph.json"){let m=qx(n());d.writeHead(200,{"Content-Type":"application/json","Cache-Control":"no-store"}),d.end(m);return}if(f==="/health.json"){let m=JSON.stringify(Hx(n(),e));d.writeHead(200,{"Content-Type":"application/json","Cache-Control":"no-store"}),d.end(m);return}if(f==="/events"){d.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),d.write(`: connected +`)}catch{r.delete(u)}},o=tHe((u,d)=>{let f=(u.url??"/").split("?")[0],p=(u.headers.host??"").split(":")[0];if(p&&p!=="localhost"&&p!=="127.0.0.1"&&p!=="[::1]"&&p!=="::1"){d.writeHead(403,{"Content-Type":"text/plain"}),d.end("forbidden host");return}try{if(f==="/graph.json"){let m=Kx(n());d.writeHead(200,{"Content-Type":"application/json","Cache-Control":"no-store"}),d.end(m);return}if(f==="/health.json"){let m=JSON.stringify(Yx(n(),e));d.writeHead(200,{"Content-Type":"application/json","Cache-Control":"no-store"}),d.end(m);return}if(f==="/events"){d.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache",Connection:"keep-alive"}),d.write(`: connected -`),r.add(d),u.on("close",()=>r.delete(d));return}if(f==="/"||f==="/index.html"){let m=Bx(n());d.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),d.end(m);return}d.writeHead(404,{"Content-Type":"text/plain"}),d.end("not found")}catch(m){if(d.headersSent)try{d.end()}catch{}else{d.writeHead(503,{"Content-Type":"application/json","Cache-Control":"no-store"});try{d.end(JSON.stringify({error:m.message}))}catch{}}}}),s=null,a=()=>{s&&clearTimeout(s),s=setTimeout(i,400)},c=[];for(let u of["spec","docs"]){let d=Pqe(e,u);if(Rqe(d))try{let f=Iqe(d,{recursive:!0},a);f.on("error",()=>{try{f.close()}catch{}}),c.push(f)}catch{}}let l=setInterval(()=>{for(let u of r)try{u.write(`: keep-alive +`),r.add(d),u.on("close",()=>r.delete(d));return}if(f==="/"||f==="/index.html"){let m=Jx(n());d.writeHead(200,{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}),d.end(m);return}d.writeHead(404,{"Content-Type":"text/plain"}),d.end("not found")}catch(m){if(d.headersSent)try{d.end()}catch{}else{d.writeHead(503,{"Content-Type":"application/json","Cache-Control":"no-store"});try{d.end(JSON.stringify({error:m.message}))}catch{}}}}),s=null,a=()=>{s&&clearTimeout(s),s=setTimeout(i,400)},c=[];for(let u of["spec","docs"]){let d=iHe(e,u);if(rHe(d))try{let f=nHe(d,{recursive:!0},a);f.on("error",()=>{try{f.close()}catch{}}),c.push(f)}catch{}}let l=setInterval(()=>{for(let u of r)try{u.write(`: keep-alive -`)}catch{r.delete(u)}},3e4);return typeof l.unref=="function"&&l.unref(),new Promise((u,d)=>{o.on("error",d),o.listen(t.port??0,"127.0.0.1",()=>{let f=o.address(),p=typeof f=="object"&&f?f.port:t.port??0;u({port:p,broadcast:i,close:()=>new Promise(m=>{s&&clearTimeout(s),clearInterval(l);for(let h of c)try{h.close()}catch{}for(let h of r)try{h.end()}catch{}r.clear(),o.close(()=>m()),typeof o.closeAllConnections=="function"&&o.closeAllConnections()})})})})}async function $te(t={}){let e=t.port!==void 0?Number(t.port):3e3;try{let r=await Cqe({port:e,cwd:t.cwd??"."});L("pass","graph",`live graph at http://localhost:${r.port} \u2014 edit spec/ or docs/ and the view auto-reloads (Ctrl-C to stop)`)}catch(r){L("fail","graph",r.message),process.exit(1)}}var Dqe=["stage_1.1","stage_2.1","stage_2.3"];function Nqe(t){return(t.features??[]).filter(e=>e.status==="done")}function jqe(t,e){let r=Nqe(t);switch(e){case"stage_1.1":return!t.project?.language||r.length===0?null:`project.language is '${t.project.language}' and ${r.length} feature(s) are done, but the type checker did not run (skipped) \u2014 type safety of shipped code was never verified. Install the language toolchain; under --strict, an unverifiable 'done' is not GREEN.`;case"stage_2.1":{let n=r.filter(i=>(i.acceptance_criteria??[]).some(o=>(o.test_refs??[]).length>0)).length;return n===0?null:`${n} done feature(s) declare tests but the test runner did not run (skipped) \u2014 the implementation was never verified. Install the test framework; under --strict, an unverifiable 'done' is not GREEN.`}case"stage_2.3":{let n=r.flatMap(i=>i.acceptance_criteria??[]).filter(i=>(i.oracle_refs??[]).length>0).length;return n===0?null:`${n} done AC(s) declare oracle_refs but the conformance runner did not run (skipped) \u2014 the declared oracles never executed. Under --strict, declared-but-unrun verification is not GREEN.`}}}function kte(t,e){let r=[];for(let n of Dqe){if(!e.some(s=>s.stage===n&&s.status==="skip"))continue;let o=jqe(t,n);o&&r.push({stage:n,label:"Verification",message:o})}return r}TS();import Ete from"node:process";function Mqe(t,e){let r=e.filter(i=>i.acId===t),n=r.filter(i=>i.identity.author==="human");return n.length===0?{acId:t,pass:!1,totalEvidence:r.length,humanEvidence:0,reason:r.length===0?"no evidence at all":`${r.length} tool/LLM evidence but 0 human \u2014 anti-self-cert guard blocks`}:{acId:t,pass:!0,totalEvidence:r.length,humanEvidence:n.length}}function Zx(t){let e=new Set;for(let n of t)n.acId&&e.add(n.acId);let r=[];for(let n of e){let i=Mqe(n,t);i.pass||r.push(i)}return r}un();var Fj="stage_4.1";function Lj(t={}){let{cwd:e="."}=t,r=fr(e);if(r.length===0)return{stage:Fj,pass:!1,exitCode:2,stderr:"no audit log present \u2014 record evidence before running stage_4.1"};let n=Zx(r);if(n.length===0)return{stage:Fj,pass:!0,exitCode:0};let i=n.map(o=>`${o.acId}: ${o.reason}`).join("; ");return{stage:Fj,pass:!1,exitCode:1,stderr:`anti-self-cert guard: ${i}`}}var Fqe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${Ete.argv[1]}`;if(Fqe){let t=Lj();console.log(JSON.stringify(t)),Ete.exit(t.exitCode)}$l();import{randomBytes as Lqe}from"node:crypto";import{unlinkSync as zqe}from"node:fs";import{tmpdir as Uqe}from"node:os";import{join as qqe,resolve as zj}from"node:path";import Bqe from"node:process";var Hr=null;function Ate(t){Hr={cwd:zj(t),run:null,jsonFile:null}}function Uj(){return Hr!==null}function qj(t,e){if(!Hr||Hr.cwd!==zj(t))return null;if(Hr.run)return Hr.run;let r=qqe(Uqe(),`clad-shared-vitest-${Bqe.pid}-${Lqe(6).toString("hex")}.json`);Hr.jsonFile=r;let n=e(r);return Hr.run={proc:n,jsonFile:r},Hr.run}function Tte(t){return!Hr||Hr.cwd!==zj(t)?null:Hr.run}function Bj(t){return t.pass&&t.exitCode===0?"reuse-pass":"fallback"}function Ote(){let t=Hr?.jsonFile;if(Hr=null,t)try{zqe(t)}catch{}}Lr();import Rte from"node:process";var Vx="stage_1.4";function Hj(t={}){let{cwd:e="."}=t,r;try{r=We("git",["status","--porcelain"],{cwd:e,reject:!1})}catch(i){if(i.code==="ENOENT")return{stage:Vx,pass:!1,exitCode:2,stderr:"git binary not found"};throw i}if(r.exitCode!==0){let i=(r.stderr??"").toString().trim()||"not a git repository";return{stage:Vx,pass:!1,exitCode:2,stderr:i}}let n=(r.stdout??"").toString().trim();return n.length===0?{stage:Vx,pass:!0,exitCode:0}:{stage:Vx,pass:!1,exitCode:1,stderr:`working tree dirty: -${n}`}}var Hqe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${Rte.argv[1]}`;if(Hqe){let t=Hj();console.log(JSON.stringify(t)),Rte.exit(t.exitCode)}Lr();import Ite from"node:process";nh();Cn();var Wx="stage_2.2";function Gj(t={}){let{cwd:e="."}=t,r,n,i;try{({cmd:r,args:n,language:i}=Xi("coverage",t))}catch(c){return{stage:Wx,pass:!1,exitCode:1,stderr:c.message}}if(!r||!n)return{stage:Wx,pass:!1,exitCode:2,stderr:`no coverage runner registered for language '${i}'`};let o=Tte(e),s=o?o.proc:We(r,[...n],{cwd:e,reject:!1}),a=Nt(Wx,r,s,n);return a||Yt(Wx,s)}var Vqe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${Ite.argv[1]}`;if(Vqe){let t=Gj();console.log(JSON.stringify(t)),Ite.exit(t.exitCode)}Hp();Zj();Lr();cn();Cn();import Cte from"node:process";var Yx="stage_3.2";function Vj(t={}){let{cwd:e="."}=t,r=dt(e),n=r.gates.perf,i=t.cmd??n?.cmd,o=t.args??n?.args;if(!i||!o)return{stage:Yx,pass:!1,exitCode:2,stderr:`no perf runner registered for language '${r.language}'`};if(i==="npm"&&o[0]==="run"&&!Vl(e,o[o.length-1]))return{stage:Yx,pass:!1,exitCode:2,stderr:"perf npm script not defined"};let s=We(i,[...o],{cwd:e,reject:!1}),a=Nt(Yx,i,s,o);return a||Yt(Yx,s)}var p4e=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${Cte.argv[1]}`;if(p4e){let t=Vj();console.log(JSON.stringify(t)),Cte.exit(t.exitCode)}Lr();Ue();Cn();import{existsSync as m4e}from"node:fs";import{resolve as Nte}from"node:path";import jte from"node:process";var fi="stage_2.4",Wj=5e3,h4e=3e4;function Kj(t={}){let{cwd:e="."}=t,r,n=[],i=!1,o=new Map;try{let p=q(e);r=p.project.deliverable,n=p.project.smoke??[],i=p.features.some(m=>m.status==="done"),o=new Map(p.features.map(m=>[m.id,m.status]))}catch{return{stage:fi,pass:!1,exitCode:2,stderr:"spec.yaml not loaded \u2014 deliverable smoke skipped"}}if(n.length>0)return y4e(e,n,{anyDone:i,featureStatus:o});if(!r)return{stage:fi,pass:!1,exitCode:2,stderr:"no project.deliverable declared \u2014 skipped"};if(r.is_safe_to_smoke!==!0)return{stage:fi,pass:!1,exitCode:2,stderr:`deliverable '${r.path}' not marked is_safe_to_smoke \u2014 skipped`};if(!i)return{stage:fi,pass:!1,exitCode:2,stderr:"no done feature yet \u2014 deliverable smoke skipped"};let s=Nte(e,r.path);if(!m4e(s))return{stage:fi,pass:!1,exitCode:2,stderr:`deliverable '${r.path}' not found \u2014 see DELIVERABLE_INTEGRITY`};let a=r.timeout_ms??Wj,c;try{c=We(s,[...r.smoke_args??[]],{cwd:e,reject:!1,timeout:a})}catch(p){c=p}let l=Nt(fi,r.path,c);if(l)return l;if(c.timedOut)return{stage:fi,pass:!1,exitCode:1,stderr:`deliverable '${r.path}' timed out after ${a}ms (hung or too slow)`};let u=r.expect_exit??0,d=c.exitCode??1;if(d===u)return{stage:fi,pass:!0,exitCode:0,disposition:"liveness"};let f=String(c.stderr??"").trim()||String(c.stdout??"").trim();return{stage:fi,pass:!1,exitCode:1,stderr:`deliverable '${r.path}' exited ${d}, expected ${u}${f?` \u2014 ${f.slice(0,200)}`:""}`}}var Dte={fail:5,advisory:4,pending_env:4,liveness:3,pass:2,na:1,skip:0},g4e={pass:"\u2713",fail:"\u2717",liveness:"liveness",na:"na",pending_env:"pending_env",advisory:"advisory",skip:"skip"};function y4e(t,e,r){let n=Math.min(e.length*Wj,h4e),i=Date.now(),o=[];for(let s of e){if(Date.now()-i>=n){o.push({argv:(s.run??[]).join(" ")||"(none)",kind:s.kind,disposition:"pending_env",detail:"stage time ceiling \u2014 not started",feature:s.feature,why:s.why});continue}o.push(_4e(t,s,r))}return b4e(o)}function _4e(t,e,r){let n=(e.run??[]).join(" ")||"(none)",i=e.why;if(e.kind==="none")return{argv:"(kind:none)",kind:"none",disposition:"na",detail:"nothing to run (library/static)",why:i};let o=e.feature;if(o!==void 0){let h=r.featureStatus.get(o);if(h!=="done"){let g=h===void 0?`bound feature ${o} not found in spec \u2014 not executed`:`bound feature ${o} is ${h}, not done \u2014 not executed`;return{argv:n,kind:"cli",disposition:"na",detail:g,feature:o,why:i}}}else if(!r.anyDone)return{argv:n,kind:"cli",disposition:"skip",detail:"no done feature yet \u2014 smoke probe skipped",why:i};let s=e.run??[];if(s.length===0)return{argv:"(none)",kind:"cli",disposition:"skip",detail:"cli smoke probe has no run argv \u2014 skipped",feature:o,why:i};let[a,...c]=s,l=a.startsWith(".")||a.startsWith("/")?Nte(t,a):a,u=Wj,d;try{d=We(l,[...c],{cwd:t,reject:!1,timeout:u})}catch(h){d=h}if(qa(d))return{argv:n,kind:"cli",disposition:"skip",detail:`'${a}' not installed`,feature:o,why:i};if(d.timedOut)return{argv:n,kind:"cli",disposition:"fail",detail:`timed out after ${u}ms`,feature:o,why:i};let f=e.expect?.exit??0,p=d.exitCode??1;if(p!==f){let h=String(d.stderr??"").trim()||String(d.stdout??"").trim();return{argv:n,kind:"cli",disposition:"fail",detail:`exited ${p}, expected ${f}${h?` \u2014 ${h.slice(0,200)}`:""}`,feature:o,why:i}}let m=e.expect?.token;return m?String(d.stdout??"").includes(m)?{argv:n,kind:"cli",disposition:"pass",detail:`ran clean (exit ${p}), stdout contains ${JSON.stringify(m)}`,feature:o,why:i}:{argv:n,kind:"cli",disposition:"fail",detail:`ran (exit ${p}) but stdout did not contain the AC token ${JSON.stringify(m)}`,feature:o,why:i}:{argv:n,kind:"cli",disposition:"liveness",detail:`ran clean (exit ${p}), no token declared \u2014 exit-only`,feature:o,why:i}}function b4e(t){let e="skip";for(let o of t)Dte[o.disposition]>Dte[e]&&(e=o.disposition);let r=t.map(o=>{let s=o.why?` \xB7 ${o.why}`:"";return`${g4e[o.disposition]} ${o.argv} \xB7 ${o.detail}${s}`}).join(` -`),n=t.map((o,s)=>({id:`probe_${s+1}`,kind:o.kind,disposition:o.disposition==="skip"?"na":o.disposition,bindsFeature:o.feature,why:o.why,detail:o.detail}));if(e==="skip")return{stage:fi,pass:!1,exitCode:2,stderr:r,probes:n};let i=e==="fail"||e==="pending_env"||e==="advisory";return{stage:fi,pass:!i,exitCode:i?1:0,disposition:e,stderr:r,probes:n}}var v4e=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${jte.argv[1]}`;if(v4e){let t=Kj();console.log(JSON.stringify(t)),jte.exit(t.exitCode)}Lr();cn();Cn();import Mte from"node:process";var Xx="stage_3.1";function Jj(t={}){let{cwd:e="."}=t,r=dt(e),n=r.gates.smoke,i=t.cmd??n?.cmd,o=t.args??n?.args;if(!i||!o)return{stage:Xx,pass:!1,exitCode:2,stderr:`no smoke runner registered for language '${r.language}'`};if(i==="npm"&&o[0]==="run"&&!Vl(e,o[o.length-1]))return{stage:Xx,pass:!1,exitCode:2,stderr:"smoke npm script not defined"};let s=We(i,[...o],{cwd:e,reject:!1}),a=Nt(Xx,i,s,o);return a||Yt(Xx,s)}var S4e=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${Mte.argv[1]}`;if(S4e){let t=Jj();console.log(JSON.stringify(t)),Mte.exit(t.exitCode)}bC();Yj();Xj();Lr();Kx();import{randomBytes as T4e}from"node:crypto";import{unlinkSync as O4e}from"node:fs";import{tmpdir as R4e}from"node:os";import{join as I4e}from"node:path";import eM from"node:process";nh();Cn();Ue();import{readFileSync as $4e}from"node:fs";import{resolve as zte}from"node:path";function k4e(t){let e=t.trim();if(!e.startsWith("{"))return null;let r;try{r=JSON.parse(e)}catch{return null}let n=r.testResults;if(!Array.isArray(n))return null;let i=new Map;for(let o of n){if(typeof o.name!="string"||!o.name)continue;let s=zte(o.name),a=i.get(s)??0;for(let c of o.assertionResults??[])c.status==="passed"&&(a+=1);i.set(s,a)}return i}function E4e(t){let e=t.indexOf("#");return(e===-1?t:t.slice(0,e)).trim()}function A4e(t,e,r){let n=[];for(let i of t.features??[]){if(i.status!=="done")continue;let o=[],s=new Set;for(let u of i.acceptance_criteria??[])for(let d of u.test_refs??[]){let f=E4e(d);f&&!s.has(f)&&(s.add(f),o.push(f))}if(o.length===0)continue;let a=!0,c=!1;for(let u of o){let d=e.get(zte(r,u));if(d===void 0){a=!1;break}if(d>0){c=!0;break}}if(c||!a)continue;let l=i.title||i.id;n.push({detector:"VACUOUS_TESTS",severity:"warn",path:o[0],message:`Done feature "${l}" declares tests, but none of its test files executed a passing test (all skipped / todo / empty) \u2014 its behavioral proof never actually ran`})}return n}function Qj(t,e){try{let r=k4e($4e(t,"utf8"));return r?A4e(q(e),r,e):[]}catch{return[]}}var Gr="stage_2.1";function Ute(t,e){return t==="vitest"||t.endsWith("/vitest")||e.includes("vitest")}function qte(t,e){return[t,...e].some(r=>r==="pytest"||r.endsWith("/pytest"))}function Bte(t){let e=`${String(t.stdout??"")} -${String(t.stderr??"")}`,r=[],n=[/^\s*#\s*tests\s+(\d+)\s*$/gim,/^\s*ℹ\s+tests\s+(\d+)\s*$/gim,/^\s*Tests:\s+.*?\b(\d+)\s+total\b.*$/gim,/^\s*collected\s+(\d+)\s+items?\b.*$/gim];for(let i of n)for(let o of e.matchAll(i))r.push(Number(o[1]));return r.length>0&&r.every(i=>i===0)}function P4e(t,e,r){let n,i;try{({cmd:n,args:i}=Xi("coverage",t))}catch{return null}if(!n||!i||!Ute(n,i))return null;let o=n,s=i,a=qj(e,d=>We(o,[...s,"--reporter=default","--reporter=json",`--outputFile=${d}`],{cwd:e,reject:!1}));if(!a)return null;let{proc:c,jsonFile:l}=a;if(Nt(Gr,n,c,s))return null;let u=Yt(Gr,c);if(Bj(u)==="fallback")return null;if(r){let d=Qj(l,e);if(d.length>0)return{stage:Gr,pass:!1,exitCode:1,findings:d,stderr:d[0].message}}return{stage:Gr,pass:!0,exitCode:0}}function C4e(t,e){let{strict:r=!1}=t,n,i;try{({cmd:n,args:i}=Xi("coverage",t))}catch{return null}if(!n||!i||!qte(n,i))return null;let o=n,s=i,a=qj(e,()=>We(o,[...s],{cwd:e,reject:!1}));if(!a||Nt(Gr,o,a.proc,s))return null;let c=Yt(Gr,a.proc);if(Bj(c)==="fallback")return null;if(r&&Bte(a.proc)){let l={detector:"VACUOUS_TESTS",severity:"error",message:"The unit test command exited successfully but reported zero executed tests."};return{stage:Gr,pass:!1,exitCode:1,findings:[l],stderr:l.message}}return{stage:Gr,pass:!0,exitCode:0}}function tM(t={}){let{cwd:e=".",strict:r=!1}=t,n,i,o;try{({cmd:n,args:i,language:o}=Xi("test",t))}catch(d){return{stage:Gr,pass:!1,exitCode:1,stderr:d.message}}if(!n||!i)return{stage:Gr,pass:!1,exitCode:2,stderr:`no unit test runner registered for language '${o}'`};let s=Ute(n,i),a=qte(n,i),c=r&&s;if(Uj()&&s){let d=P4e(t,e,c);if(d)return d}if(Uj()&&a){let d=C4e(t,e);if(d)return d}let l,u=i;c&&(l=I4e(R4e(),`clad-vitest-${eM.pid}-${T4e(6).toString("hex")}.json`),u=[...i,"--reporter=default","--reporter=json",`--outputFile=${l}`]);try{let d=We(n,[...u],{cwd:e,reject:!1}),f=Nt(Gr,n,d,u);if(f)return f;let p=ju("unit",Yt(Gr,d),d);if(r&&p.pass&&Bte(d)){let m={detector:"VACUOUS_TESTS",severity:"error",message:"The unit test command exited successfully but reported zero executed tests."};return{stage:Gr,pass:!1,exitCode:1,findings:[m],stderr:m.message}}if(c&&p.pass&&l){let m=Qj(l,e);if(m.length>0)return{stage:Gr,pass:!1,exitCode:1,findings:m,stderr:m[0].message}}return p}finally{if(l)try{O4e(l)}catch{}}}var D4e=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${eM.argv[1]}`;if(D4e){let t=tM();console.log(JSON.stringify(t)),eM.exit(t.exitCode)}Lr();cn();Cn();import Hte from"node:process";var t0="stage_3.3";function rM(t={}){let{cwd:e="."}=t,r=dt(e),n=r.gates.visual,i=t.cmd??n?.cmd,o=t.args??n?.args;if(!i||!o)return{stage:t0,pass:!1,exitCode:2,stderr:`no visual runner registered for language '${r.language}'`};if(i==="npm"&&o[0]==="run"&&!Vl(e,o[o.length-1]))return{stage:t0,pass:!1,exitCode:2,stderr:"visual npm script not defined"};let s=We(i,[...o],{cwd:e,reject:!1}),a=Nt(t0,i,s,o);return a||Yt(t0,s)}var N4e=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${Hte.argv[1]}`;if(N4e){let t=rM();console.log(JSON.stringify(t)),Hte.exit(t.exitCode)}SC();Bf();ba();iM();Pp();aS();var Yte=St(er(),1);import{existsSync as oM,readFileSync as Z4e,readdirSync as Jte,statSync as V4e,writeFileSync as W4e}from"node:fs";import{basename as ch,join as lh,relative as Kte}from"node:path";var K4e=["self-dogfood:","fixture:","derived:"],Xte=/\.(test|spec)\.[jt]sx?$/;function Qte(t,e=t,r=[]){let n;try{n=Jte(e)}catch{return r}for(let i of n){if(i.startsWith("."))continue;let o=lh(e,i);try{V4e(o).isDirectory()?Qte(t,o,r):Xte.test(i)&&r.push(o)}catch{continue}}return r}function ere(t="."){let e=lh(t,"spec","features"),r=lh(t,"tests"),n=[],i=[];if(!oM(e)||!oM(r))return{repaired:n,suggested:i};let o=Qte(r),s=new Map;for(let a of o){let c=Kte(t,a).split("\\").join("/"),l=s.get(ch(a))??[];l.push(c),s.set(ch(a),l)}for(let a of Jte(e)){if(!a.endsWith(".yaml")&&!a.endsWith(".yml"))continue;let c=lh(e,a),l,u;try{l=Z4e(c,"utf8"),u=(0,Yte.parse)(l)}catch{continue}if(!u||u.status!=="done")continue;let d=!1;for(let h of u.acceptance_criteria??[])for(let g of h.test_refs??[]){if(K4e.some(x=>g.startsWith(x)))continue;let b=g.split("#",1)[0];if(oM(lh(t,b)))continue;let _=s.get(ch(b))??[];if(_.length!==1)continue;let S=g.replace(b,_[0]);S!==g&&l.includes(g)&&(l=l.split(g).join(S),n.push({shard:a,from:g,to:S}),d=!0)}let f=u.slug??"",p=(u.modules??[]).map(h=>ch(h).replace(/\.[jt]sx?$/,"")),m=o.map(h=>Kte(t,h).split("\\").join("/")).find(h=>{let g=ch(h).replace(Xte,"");return f!==""&&g===f||p.includes(g)});if(m)for(let h of u.acceptance_criteria??[]){if((h.test_refs?.length??0)>0||(h.evidence_refs?.length??0)>0||!h.id)continue;let g=new RegExp(`^(([ ]+)- id: ${h.id}\\b.*)$`,"m"),b=l.match(g);if(!b)continue;let _=b[2]+" ";l=l.replace(g,`$1 +`)}catch{r.delete(u)}},3e4);return typeof l.unref=="function"&&l.unref(),new Promise((u,d)=>{o.on("error",d),o.listen(t.port??0,"127.0.0.1",()=>{let f=o.address(),p=typeof f=="object"&&f?f.port:t.port??0;u({port:p,broadcast:i,close:()=>new Promise(m=>{s&&clearTimeout(s),clearInterval(l);for(let h of c)try{h.close()}catch{}for(let h of r)try{h.end()}catch{}r.clear(),o.close(()=>m()),typeof o.closeAllConnections=="function"&&o.closeAllConnections()})})})})}async function ure(t={}){let e=t.port!==void 0?Number(t.port):3e3;try{let r=await oHe({port:e,cwd:t.cwd??"."});L("pass","graph",`live graph at http://localhost:${r.port} \u2014 edit spec/ or docs/ and the view auto-reloads (Ctrl-C to stop)`)}catch(r){L("fail","graph",r.message),process.exit(1)}}var sHe=["stage_1.1","stage_2.1","stage_2.3"];function aHe(t){return(t.features??[]).filter(e=>e.status==="done")}function cHe(t,e){let r=aHe(t);switch(e){case"stage_1.1":return!t.project?.language||r.length===0?null:`project.language is '${t.project.language}' and ${r.length} feature(s) are done, but the type checker did not run (skipped) \u2014 type safety of shipped code was never verified. Install the language toolchain; under --strict, an unverifiable 'done' is not GREEN.`;case"stage_2.1":{let n=r.filter(i=>(i.acceptance_criteria??[]).some(o=>(o.test_refs??[]).length>0)).length;return n===0?null:`${n} done feature(s) declare tests but the test runner did not run (skipped) \u2014 the implementation was never verified. Install the test framework; under --strict, an unverifiable 'done' is not GREEN.`}case"stage_2.3":{let n=r.flatMap(i=>i.acceptance_criteria??[]).filter(i=>(i.oracle_refs??[]).length>0).length;return n===0?null:`${n} done AC(s) declare oracle_refs but the conformance runner did not run (skipped) \u2014 the declared oracles never executed. Under --strict, declared-but-unrun verification is not GREEN.`}}}function dre(t,e){let r=[];for(let n of sHe){if(!e.some(s=>s.stage===n&&s.status==="skip"))continue;let o=cHe(t,n);o&&r.push({stage:n,label:"Verification",message:o})}return r}NS();import fre from"node:process";function lHe(t,e){let r=e.filter(i=>i.acId===t),n=r.filter(i=>i.identity.author==="human");return n.length===0?{acId:t,pass:!1,totalEvidence:r.length,humanEvidence:0,reason:r.length===0?"no evidence at all":`${r.length} tool/LLM evidence but 0 human \u2014 anti-self-cert guard blocks`}:{acId:t,pass:!0,totalEvidence:r.length,humanEvidence:n.length}}function Qx(t){let e=new Set;for(let n of t)n.acId&&e.add(n.acId);let r=[];for(let n of e){let i=lHe(n,t);i.pass||r.push(i)}return r}un();var Qj="stage_4.1";function eM(t={}){let{cwd:e="."}=t,r=pr(e);if(r.length===0)return{stage:Qj,pass:!1,exitCode:2,stderr:"no audit log present \u2014 record evidence before running stage_4.1"};let n=Qx(r);if(n.length===0)return{stage:Qj,pass:!0,exitCode:0};let i=n.map(o=>`${o.acId}: ${o.reason}`).join("; ");return{stage:Qj,pass:!1,exitCode:1,stderr:`anti-self-cert guard: ${i}`}}var uHe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${fre.argv[1]}`;if(uHe){let t=eM();console.log(JSON.stringify(t)),fre.exit(t.exitCode)}Al();import{randomBytes as dHe}from"node:crypto";import{unlinkSync as fHe}from"node:fs";import{tmpdir as pHe}from"node:os";import{join as mHe,resolve as tM}from"node:path";import hHe from"node:process";var Gr=null;function pre(t){Gr={cwd:tM(t),run:null,jsonFile:null}}function rM(){return Gr!==null}function nM(t,e){if(!Gr||Gr.cwd!==tM(t))return null;if(Gr.run)return Gr.run;let r=mHe(pHe(),`clad-shared-vitest-${hHe.pid}-${dHe(6).toString("hex")}.json`);Gr.jsonFile=r;let n=e(r);return Gr.run={proc:n,jsonFile:r},Gr.run}function mre(t){return!Gr||Gr.cwd!==tM(t)?null:Gr.run}function iM(t){return t.pass&&t.exitCode===0?"reuse-pass":"fallback"}function hre(){let t=Gr?.jsonFile;if(Gr=null,t)try{fHe(t)}catch{}}zr();import gre from"node:process";var e0="stage_1.4";function oM(t={}){let{cwd:e="."}=t,r;try{r=Ke("git",["status","--porcelain"],{cwd:e,reject:!1})}catch(i){if(i.code==="ENOENT")return{stage:e0,pass:!1,exitCode:2,stderr:"git binary not found"};throw i}if(r.exitCode!==0){let i=(r.stderr??"").toString().trim()||"not a git repository";return{stage:e0,pass:!1,exitCode:2,stderr:i}}let n=(r.stdout??"").toString().trim();return n.length===0?{stage:e0,pass:!0,exitCode:0}:{stage:e0,pass:!1,exitCode:1,stderr:`working tree dirty: +${n}`}}var gHe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${gre.argv[1]}`;if(gHe){let t=oM();console.log(JSON.stringify(t)),gre.exit(t.exitCode)}zr();import yre from"node:process";sh();Nn();var t0="stage_2.2";function sM(t={}){let{cwd:e="."}=t,r,n,i;try{({cmd:r,args:n,language:i}=Xi("coverage",t))}catch(c){return{stage:t0,pass:!1,exitCode:1,stderr:c.message}}if(!r||!n)return{stage:t0,pass:!1,exitCode:2,stderr:`no coverage runner registered for language '${i}'`,skipReason:"no-runner"};let o=mre(e),s=o?o.proc:Ke(r,[...n],{cwd:e,reject:!1}),a=Nt(t0,r,s,n);return a||Xt(t0,s)}var bHe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${yre.argv[1]}`;if(bHe){let t=sM();console.log(JSON.stringify(t)),yre.exit(t.exitCode)}Qp();aD();aM();zr();Dn();Nn();import bre from"node:process";var i0="stage_3.2";function cM(t={}){let{cwd:e="."}=t,r=_t(e),n=r.gates.perf,i=t.cmd??n?.cmd,o=t.args??n?.args;if(!i||!o)return{stage:i0,pass:!1,exitCode:2,stderr:`no perf runner registered for language '${r.language}'`};if(i==="npm"&&o[0]==="run"&&!Jl(e,o[o.length-1]))return{stage:i0,pass:!1,exitCode:2,stderr:"perf npm script not defined"};let s=Ke(i,[...o],{cwd:e,reject:!1}),a=Nt(i0,i,s,o);return a||Xt(i0,s)}var LHe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${bre.argv[1]}`;if(LHe){let t=cM();console.log(JSON.stringify(t)),bre.exit(t.exitCode)}zr();Ue();Nn();import{existsSync as zHe}from"node:fs";import{resolve as Sre}from"node:path";import wre from"node:process";var fi="stage_2.4",lM=5e3,UHe=3e4;function uM(t={}){let{cwd:e="."}=t,r,n=[],i=!1,o=new Map;try{let p=q(e);r=p.project.deliverable,n=p.project.smoke??[],i=p.features.some(m=>m.status==="done"),o=new Map(p.features.map(m=>[m.id,m.status]))}catch{return{stage:fi,pass:!1,exitCode:2,stderr:"spec.yaml not loaded \u2014 deliverable smoke skipped"}}if(n.length>0)return HHe(e,n,{anyDone:i,featureStatus:o});if(!r)return{stage:fi,pass:!1,exitCode:2,stderr:"no project.deliverable declared \u2014 skipped"};if(r.is_safe_to_smoke!==!0)return{stage:fi,pass:!1,exitCode:2,stderr:`deliverable '${r.path}' not marked is_safe_to_smoke \u2014 skipped`};if(!i)return{stage:fi,pass:!1,exitCode:2,stderr:"no done feature yet \u2014 deliverable smoke skipped"};let s=Sre(e,r.path);if(!zHe(s))return{stage:fi,pass:!1,exitCode:2,stderr:`deliverable '${r.path}' not found \u2014 see DELIVERABLE_INTEGRITY`};let a=r.timeout_ms??lM,c;try{c=Ke(s,[...r.smoke_args??[]],{cwd:e,reject:!1,timeout:a})}catch(p){c=p}let l=Nt(fi,r.path,c);if(l)return l;if(c.timedOut)return{stage:fi,pass:!1,exitCode:1,stderr:`deliverable '${r.path}' timed out after ${a}ms (hung or too slow)`};let u=r.expect_exit??0,d=c.exitCode??1;if(d===u)return{stage:fi,pass:!0,exitCode:0,disposition:"liveness"};let f=String(c.stderr??"").trim()||String(c.stdout??"").trim();return{stage:fi,pass:!1,exitCode:1,stderr:`deliverable '${r.path}' exited ${d}, expected ${u}${f?` \u2014 ${f.slice(0,200)}`:""}`}}var vre={fail:5,advisory:4,pending_env:4,liveness:3,pass:2,na:1,skip:0},qHe={pass:"\u2713",fail:"\u2717",liveness:"liveness",na:"na",pending_env:"pending_env",advisory:"advisory",skip:"skip"};function HHe(t,e,r){let n=Math.min(e.length*lM,UHe),i=Date.now(),o=[];for(let s of e){if(Date.now()-i>=n){o.push({argv:(s.run??[]).join(" ")||"(none)",kind:s.kind,disposition:"pending_env",detail:"stage time ceiling \u2014 not started",feature:s.feature,why:s.why});continue}o.push(BHe(t,s,r))}return GHe(o)}function BHe(t,e,r){let n=(e.run??[]).join(" ")||"(none)",i=e.why;if(e.kind==="none")return{argv:"(kind:none)",kind:"none",disposition:"na",detail:"nothing to run (library/static)",why:i};let o=e.feature;if(o!==void 0){let h=r.featureStatus.get(o);if(h!=="done"){let g=h===void 0?`bound feature ${o} not found in spec \u2014 not executed`:`bound feature ${o} is ${h}, not done \u2014 not executed`;return{argv:n,kind:"cli",disposition:"na",detail:g,feature:o,why:i}}}else if(!r.anyDone)return{argv:n,kind:"cli",disposition:"skip",detail:"no done feature yet \u2014 smoke probe skipped",why:i};let s=e.run??[];if(s.length===0)return{argv:"(none)",kind:"cli",disposition:"skip",detail:"cli smoke probe has no run argv \u2014 skipped",feature:o,why:i};let[a,...c]=s,l=a.startsWith(".")||a.startsWith("/")?Sre(t,a):a,u=lM,d;try{d=Ke(l,[...c],{cwd:t,reject:!1,timeout:u})}catch(h){d=h}if(Ba(d))return{argv:n,kind:"cli",disposition:"skip",detail:`'${a}' not installed`,feature:o,why:i};if(d.timedOut)return{argv:n,kind:"cli",disposition:"fail",detail:`timed out after ${u}ms`,feature:o,why:i};let f=e.expect?.exit??0,p=d.exitCode??1;if(p!==f){let h=String(d.stderr??"").trim()||String(d.stdout??"").trim();return{argv:n,kind:"cli",disposition:"fail",detail:`exited ${p}, expected ${f}${h?` \u2014 ${h.slice(0,200)}`:""}`,feature:o,why:i}}let m=e.expect?.token;return m?String(d.stdout??"").includes(m)?{argv:n,kind:"cli",disposition:"pass",detail:`ran clean (exit ${p}), stdout contains ${JSON.stringify(m)}`,feature:o,why:i}:{argv:n,kind:"cli",disposition:"fail",detail:`ran (exit ${p}) but stdout did not contain the AC token ${JSON.stringify(m)}`,feature:o,why:i}:{argv:n,kind:"cli",disposition:"liveness",detail:`ran clean (exit ${p}), no token declared \u2014 exit-only`,feature:o,why:i}}function GHe(t){let e="skip";for(let o of t)vre[o.disposition]>vre[e]&&(e=o.disposition);let r=t.map(o=>{let s=o.why?` \xB7 ${o.why}`:"";return`${qHe[o.disposition]} ${o.argv} \xB7 ${o.detail}${s}`}).join(` +`),n=t.map((o,s)=>({id:`probe_${s+1}`,kind:o.kind,disposition:o.disposition==="skip"?"na":o.disposition,bindsFeature:o.feature,why:o.why,detail:o.detail}));if(e==="skip")return{stage:fi,pass:!1,exitCode:2,stderr:r,probes:n};let i=e==="fail"||e==="pending_env"||e==="advisory";return{stage:fi,pass:!i,exitCode:i?1:0,disposition:e,stderr:r,probes:n}}var ZHe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${wre.argv[1]}`;if(ZHe){let t=uM();console.log(JSON.stringify(t)),wre.exit(t.exitCode)}zr();Dn();Nn();import xre from"node:process";var o0="stage_3.1";function dM(t={}){let{cwd:e="."}=t,r=_t(e),n=r.gates.smoke,i=t.cmd??n?.cmd,o=t.args??n?.args;if(!i||!o)return{stage:o0,pass:!1,exitCode:2,stderr:`no smoke runner registered for language '${r.language}'`};if(i==="npm"&&o[0]==="run"&&!Jl(e,o[o.length-1]))return{stage:o0,pass:!1,exitCode:2,stderr:"smoke npm script not defined"};let s=Ke(i,[...o],{cwd:e,reject:!1}),a=Nt(o0,i,s,o);return a||Xt(o0,s)}var VHe=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${xre.argv[1]}`;if(VHe){let t=dM();console.log(JSON.stringify(t)),xre.exit(t.exitCode)}ZC();fM();pM();zr();r0();import{randomBytes as e6e}from"node:crypto";import{unlinkSync as t6e}from"node:fs";import{tmpdir as r6e}from"node:os";import{join as n6e}from"node:path";import hM from"node:process";sh();Nn();Ue();import{readFileSync as JHe}from"node:fs";import{resolve as Ere}from"node:path";function YHe(t){let e=t.trim();if(!e.startsWith("{"))return null;let r;try{r=JSON.parse(e)}catch{return null}let n=r.testResults;if(!Array.isArray(n))return null;let i=new Map;for(let o of n){if(typeof o.name!="string"||!o.name)continue;let s=Ere(o.name),a=i.get(s)??0;for(let c of o.assertionResults??[])c.status==="passed"&&(a+=1);i.set(s,a)}return i}function XHe(t){let e=t.indexOf("#");return(e===-1?t:t.slice(0,e)).trim()}function QHe(t,e,r){let n=[];for(let i of t.features??[]){if(i.status!=="done")continue;let o=[],s=new Set;for(let u of i.acceptance_criteria??[])for(let d of u.test_refs??[]){let f=XHe(d);f&&!s.has(f)&&(s.add(f),o.push(f))}if(o.length===0)continue;let a=!0,c=!1;for(let u of o){let d=e.get(Ere(r,u));if(d===void 0){a=!1;break}if(d>0){c=!0;break}}if(c||!a)continue;let l=i.title||i.id;n.push({detector:"VACUOUS_TESTS",severity:"warn",path:o[0],message:`Done feature "${l}" declares tests, but none of its test files executed a passing test (all skipped / todo / empty) \u2014 its behavioral proof never actually ran`})}return n}function mM(t,e){try{let r=YHe(JHe(t,"utf8"));return r?QHe(q(e),r,e):[]}catch{return[]}}var Zr="stage_2.1";function Are(t,e){return t==="vitest"||t.endsWith("/vitest")||e.includes("vitest")}function Ore(t,e){return[t,...e].some(r=>r==="pytest"||r.endsWith("/pytest"))}function Tre(t){let e=`${String(t.stdout??"")} +${String(t.stderr??"")}`,r=[],n=[/^\s*#\s*tests\s+(\d+)\s*$/gim,/^\s*ℹ\s+tests\s+(\d+)\s*$/gim,/^\s*Tests:\s+.*?\b(\d+)\s+total\b.*$/gim,/^\s*collected\s+(\d+)\s+items?\b.*$/gim];for(let i of n)for(let o of e.matchAll(i))r.push(Number(o[1]));return r.length>0&&r.every(i=>i===0)}function i6e(t,e,r){let n,i;try{({cmd:n,args:i}=Xi("coverage",t))}catch{return null}if(!n||!i||!Are(n,i))return null;let o=n,s=i,a=nM(e,d=>Ke(o,[...s,"--reporter=default","--reporter=json",`--outputFile=${d}`],{cwd:e,reject:!1}));if(!a)return null;let{proc:c,jsonFile:l}=a;if(Nt(Zr,n,c,s))return null;let u=Xt(Zr,c);if(iM(u)==="fallback")return null;if(r){let d=mM(l,e);if(d.length>0)return{stage:Zr,pass:!1,exitCode:1,findings:d,stderr:d[0].message}}return{stage:Zr,pass:!0,exitCode:0}}function o6e(t,e){let{strict:r=!1}=t,n,i;try{({cmd:n,args:i}=Xi("coverage",t))}catch{return null}if(!n||!i||!Ore(n,i))return null;let o=n,s=i,a=nM(e,()=>Ke(o,[...s],{cwd:e,reject:!1}));if(!a||Nt(Zr,o,a.proc,s))return null;let c=Xt(Zr,a.proc);if(iM(c)==="fallback")return null;if(r&&Tre(a.proc)){let l={detector:"VACUOUS_TESTS",severity:"error",message:"The unit test command exited successfully but reported zero executed tests."};return{stage:Zr,pass:!1,exitCode:1,findings:[l],stderr:l.message}}return{stage:Zr,pass:!0,exitCode:0}}function gM(t={}){let{cwd:e=".",strict:r=!1}=t,n,i,o;try{({cmd:n,args:i,language:o}=Xi("test",t))}catch(d){return{stage:Zr,pass:!1,exitCode:1,stderr:d.message}}if(!n||!i)return{stage:Zr,pass:!1,exitCode:2,stderr:`no unit test runner registered for language '${o}'`,skipReason:"no-runner"};let s=Are(n,i),a=Ore(n,i),c=r&&s;if(rM()&&s){let d=i6e(t,e,c);if(d)return d}if(rM()&&a){let d=o6e(t,e);if(d)return d}let l,u=i;c&&(l=n6e(r6e(),`clad-vitest-${hM.pid}-${e6e(6).toString("hex")}.json`),u=[...i,"--reporter=default","--reporter=json",`--outputFile=${l}`]);try{let d=Ke(n,[...u],{cwd:e,reject:!1}),f=Nt(Zr,n,d,u);if(f)return f;let p=Lu("unit",Xt(Zr,d),d);if(r&&p.pass&&Tre(d)){let m={detector:"VACUOUS_TESTS",severity:"error",message:"The unit test command exited successfully but reported zero executed tests."};return{stage:Zr,pass:!1,exitCode:1,findings:[m],stderr:m.message}}if(c&&p.pass&&l){let m=mM(l,e);if(m.length>0)return{stage:Zr,pass:!1,exitCode:1,findings:m,stderr:m[0].message}}return p}finally{if(l)try{t6e(l)}catch{}}}var s6e=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${hM.argv[1]}`;if(s6e){let t=gM();console.log(JSON.stringify(t)),hM.exit(t.exitCode)}zr();Dn();Nn();import Rre from"node:process";var c0="stage_3.3";function yM(t={}){let{cwd:e="."}=t,r=_t(e),n=r.gates.visual,i=t.cmd??n?.cmd,o=t.args??n?.args;if(!i||!o)return{stage:c0,pass:!1,exitCode:2,stderr:`no visual runner registered for language '${r.language}'`};if(i==="npm"&&o[0]==="run"&&!Jl(e,o[o.length-1]))return{stage:c0,pass:!1,exitCode:2,stderr:"visual npm script not defined"};let s=Ke(i,[...o],{cwd:e,reject:!1}),a=Nt(c0,i,s,o);return a||Xt(c0,s)}var a6e=!globalThis.__CLADDING_BUNDLED&&import.meta.url===`file://${Rre.argv[1]}`;if(a6e){let t=yM();console.log(JSON.stringify(t)),Rre.exit(t.exitCode)}WC();Zf();wa();bM();Up();_S();var Mre=wt(tr(),1);import{existsSync as vM,readFileSync as _6e,readdirSync as jre,statSync as b6e,writeFileSync as v6e}from"node:fs";import{basename as dh,join as fh,relative as Nre}from"node:path";var S6e=["self-dogfood:","fixture:","derived:"],Fre=/\.(test|spec)\.[jt]sx?$/;function Lre(t,e=t,r=[]){let n;try{n=jre(e)}catch{return r}for(let i of n){if(i.startsWith("."))continue;let o=fh(e,i);try{b6e(o).isDirectory()?Lre(t,o,r):Fre.test(i)&&r.push(o)}catch{continue}}return r}function zre(t="."){let e=fh(t,"spec","features"),r=fh(t,"tests"),n=[],i=[];if(!vM(e)||!vM(r))return{repaired:n,suggested:i};let o=Lre(r),s=new Map;for(let a of o){let c=Nre(t,a).split("\\").join("/"),l=s.get(dh(a))??[];l.push(c),s.set(dh(a),l)}for(let a of jre(e)){if(!a.endsWith(".yaml")&&!a.endsWith(".yml"))continue;let c=fh(e,a),l,u;try{l=_6e(c,"utf8"),u=(0,Mre.parse)(l)}catch{continue}if(!u||u.status!=="done")continue;let d=!1;for(let h of u.acceptance_criteria??[])for(let g of h.test_refs??[]){if(S6e.some(x=>g.startsWith(x)))continue;let b=g.split("#",1)[0];if(vM(fh(t,b)))continue;let _=s.get(dh(b))??[];if(_.length!==1)continue;let S=g.replace(b,_[0]);S!==g&&l.includes(g)&&(l=l.split(g).join(S),n.push({shard:a,from:g,to:S}),d=!0)}let f=u.slug??"",p=(u.modules??[]).map(h=>dh(h).replace(/\.[jt]sx?$/,"")),m=o.map(h=>Nre(t,h).split("\\").join("/")).find(h=>{let g=dh(h).replace(Fre,"");return f!==""&&g===f||p.includes(g)});if(m)for(let h of u.acceptance_criteria??[]){if((h.test_refs?.length??0)>0||(h.evidence_refs?.length??0)>0||!h.id)continue;let g=new RegExp(`^(([ ]+)- id: ${h.id}\\b.*)$`,"m"),b=l.match(g);if(!b)continue;let _=b[2]+" ";l=l.replace(g,`$1 ${_}test_refs: -${_} - "derived:${m}"`),i.push({shard:a,ref:`derived:${m}`}),d=!0}d&&W4e(c,l,"utf8")}return{repaired:n,suggested:i}}xl();import{existsSync as J4e,readFileSync as Y4e}from"node:fs";import{join as X4e}from"node:path";function Q4e(t,e){let r=X4e(t,e);if(!J4e(r))return[];let n=[];for(let i of Y4e(r,"utf8").split(/\r?\n/)){let o=i.trim();if(!/^export\s+(?:async\s+)?(?:abstract\s+)?(?:function|const|let|class|interface|type|enum)\b/.test(o))continue;let s=o.replace(/\s*[{=].*$/s,"").trim();s&&n.push(s)}return n}function tre(t,e,r,n){let i=t.features.find(c=>c.id===e);if(!i)return null;let o=(i.acceptance_criteria??[]).filter(c=>!r||c.id===r),s=i.modules??[],a=s.flatMap(c=>Q4e(n,c).map(l=>`${c}: ${l}`));return{featureId:e,featureTitle:i.title,acs:o.map(c=>({id:c.id,ears:c.ears,condition:c.condition,action:c.action,response:c.response,text:c.text})),modules:s,signatures:a,readManifest:[...s.map(c=>`signatures-of:${c}`),"spec:acceptance_criteria"]}}function rre(t){let e=[];e.push(`# Impl-blind oracle brief \u2014 ${t.featureId}: ${t.featureTitle}`),e.push("#"),e.push("# Author a conformance TEST SUITE from THIS SPECIFICATION ONLY. You have NOT been"),e.push("# shown the implementation and MUST NOT read it. Assert ONLY what the acceptance"),e.push("# criteria literally require; when the spec is silent on an edge, write a WEAKER"),e.push("# assertion, not a stronger guess (an over-strict oracle falsely fails correct code)."),e.push(""),e.push("## Acceptance criteria (the spec)");for(let r of t.acs)e.push(`- ${r.id}${r.ears?` [${r.ears}]`:""}: ${r.text??""}`.trimEnd()),r.condition&&e.push(` when: ${r.condition}`),r.action&&e.push(` system shall: ${r.action}`),r.response&&e.push(` so that: ${r.response}`);e.push(""),e.push("## Public surface to call (signatures only \u2014 NO implementation shown)"),t.signatures.length===0&&e.push(" (no export signatures extracted \u2014 call the API exactly as the criteria describe)");for(let r of t.signatures)e.push(` ${r}`);return e.push(""),e.push("## Write the suite under tests/oracle/ (the dir stage_2.3 runs), then record it with"),e.push("## the clad_author_oracle MCP tool so its impl-blind provenance is gate-verified."),e.join(` -`)}uS();Ue();un();Pi();un();xl();var sM=["stage_1.1","stage_1.2","stage_1.3","stage_1.4","stage_1.5","stage_1.6","stage_2.1","stage_2.2","stage_3.1","stage_3.2","stage_3.3","stage_4.1","stage_4.2"],e6e=[...sM,"att"];function t6e(t,e,r){if(e.startsWith("stage_4")){let n=fr(r);if(n.length===0)return"\xB7";let i=(t.acceptance_criteria??[]).map(s=>s.id);return Zx(n).filter(s=>i.includes(s.acId)).length>0?"\u2717":"\u2713"}return"-"}function r6e(t,e,r){let n=t.modules??[];return t.status!=="done"||n.length===0?"\xB7":e===null?"-":J_(e,r,t).state==="fresh"?"\u2713":"!"}function o0(t,e="."){let r=ls(e),n=t.features.map(i=>({featureId:i.id,title:i.title||i.id,status:i.status,cells:[...sM.map(o=>t6e(i,o,e)),r6e(i,r,e)]}));return{columns:e6e,rows:n}}function nre(t,e=".",r={}){let n=r.internal??!1,i=o0(t,e),o=[...sM.map(c=>n?c.replace("stage_",""):n6e(c)),"att"],s=n?`feature ${o.join(" ")}`:`feature${" ".repeat(28)}${o.join(" ")}`,a=i.rows.map(c=>{let l=c.cells.join(" ");return n?`${c.featureId.padEnd(12)} ${l} ${c.title}`:`${c.title.padEnd(35).slice(0,35)} ${l}`});return[s,...a].join(` -`)}function n6e(t){return Ta(t).slice(0,3)}async function R5e(t){let[{buildServer:e},{StdioServerTransport:r},{setHostMcpServer:n}]=await Promise.all([Promise.resolve().then(()=>(_de(),yde)),Promise.resolve().then(()=>(xde(),wde)),Promise.resolve().then(()=>(om(),C7))]),i=e({cwd:t.cwd,onboarding:{renderDraft:s=>cte(s),prepareInit:({cwd:s,mode:a,intent:c})=>ste(s,a,c),initialize:Sj,prepareClarify:(s,{cwd:a})=>ate(a,s),clarify:kj,resolveReview:(s,{cwd:a})=>rte(s,{cwd:a})}});n(i.server);let o=new r;B.stderr.write(`\xB7 serve stdio transport \xB7 cwd=${t.cwd??"."} -`),await i.connect(o)}async function I5e(t,e){let r=t&&t.length>0?t.join(" ").trim():void 0,n=await Sj({projectName:e.name,force:e.force,scan:e.scan,noLlm:e.noLlm,roots:e.roots?e.roots.split(",").map(o=>o.trim()).filter(Boolean):void 0,intent:r,withHook:e.withHook,withCi:e.withCi});if(e.json){B.stdout.write(`${JSON.stringify(n,null,2)} -`),B.exit(0);return}for(let o of n.created)L("pass",`created ${o}`);for(let o of n.skipped)L("skip",o);for(let o of n.proposals??[])L("note","proposal",o);let i=n.onboardingMode?`language: ${n.language} \xB7 mode: ${n.onboardingMode}`:`language: ${n.language}`;if(L("note","init done",i),n.clarifyingQuestions&&n.clarifyingQuestions.length>0){B.stdout.write(` +${_} - "derived:${m}"`),i.push({shard:a,ref:`derived:${m}`}),d=!0}d&&v6e(c,l,"utf8")}return{repaired:n,suggested:i}}El();import{existsSync as w6e,readFileSync as x6e}from"node:fs";import{join as $6e}from"node:path";function k6e(t,e){let r=$6e(t,e);if(!w6e(r))return[];let n=[];for(let i of x6e(r,"utf8").split(/\r?\n/)){let o=i.trim();if(!/^export\s+(?:async\s+)?(?:abstract\s+)?(?:function|const|let|class|interface|type|enum)\b/.test(o))continue;let s=o.replace(/\s*[{=].*$/s,"").trim();s&&n.push(s)}return n}function Ure(t,e,r,n){let i=t.features.find(c=>c.id===e);if(!i)return null;let o=(i.acceptance_criteria??[]).filter(c=>!r||c.id===r),s=i.modules??[],a=s.flatMap(c=>k6e(n,c).map(l=>`${c}: ${l}`));return{featureId:e,featureTitle:i.title,acs:o.map(c=>({id:c.id,ears:c.ears,condition:c.condition,action:c.action,response:c.response,text:c.text})),modules:s,signatures:a,readManifest:[...s.map(c=>`signatures-of:${c}`),"spec:acceptance_criteria"]}}function qre(t){let e=[];e.push(`# Impl-blind oracle brief \u2014 ${t.featureId}: ${t.featureTitle}`),e.push("#"),e.push("# Author a conformance TEST SUITE from THIS SPECIFICATION ONLY. You have NOT been"),e.push("# shown the implementation and MUST NOT read it. Assert ONLY what the acceptance"),e.push("# criteria literally require; when the spec is silent on an edge, write a WEAKER"),e.push("# assertion, not a stronger guess (an over-strict oracle falsely fails correct code)."),e.push(""),e.push("## Acceptance criteria (the spec)");for(let r of t.acs)e.push(`- ${r.id}${r.ears?` [${r.ears}]`:""}: ${r.text??""}`.trimEnd()),r.condition&&e.push(` when: ${r.condition}`),r.action&&e.push(` system shall: ${r.action}`),r.response&&e.push(` so that: ${r.response}`);e.push(""),e.push("## Public surface to call (signatures only \u2014 NO implementation shown)"),t.signatures.length===0&&e.push(" (no export signatures extracted \u2014 call the API exactly as the criteria describe)");for(let r of t.signatures)e.push(` ${r}`);return e.push(""),e.push("## Write the suite under tests/oracle/ (the dir stage_2.3 runs), then record it with"),e.push("## the clad_author_oracle MCP tool so its impl-blind provenance is gate-verified."),e.join(` +`)}SS();Ue();un();Pi();un();El();var SM=["stage_1.1","stage_1.2","stage_1.3","stage_1.4","stage_1.5","stage_1.6","stage_2.1","stage_2.2","stage_3.1","stage_3.2","stage_3.3","stage_4.1","stage_4.2"],E6e=[...SM,"att"];function A6e(t,e,r){if(e.startsWith("stage_4")){let n=pr(r);if(n.length===0)return"\xB7";let i=(t.acceptance_criteria??[]).map(s=>s.id);return Qx(n).filter(s=>i.includes(s.acId)).length>0?"\u2717":"\u2713"}return"-"}function O6e(t,e,r){let n=t.modules??[];return t.status!=="done"||n.length===0?"\xB7":e===null?"-":Q_(e,r,t).state==="fresh"?"\u2713":"!"}function f0(t,e="."){let r=ds(e),n=t.features.map(i=>({featureId:i.id,title:i.title||i.id,status:i.status,cells:[...SM.map(o=>A6e(i,o,e)),O6e(i,r,e)]}));return{columns:E6e,rows:n}}function Hre(t,e=".",r={}){let n=r.internal??!1,i=f0(t,e),o=[...SM.map(c=>n?c.replace("stage_",""):T6e(c)),"att"],s=n?`feature ${o.join(" ")}`:`feature${" ".repeat(28)}${o.join(" ")}`,a=i.rows.map(c=>{let l=c.cells.join(" ");return n?`${c.featureId.padEnd(12)} ${l} ${c.title}`:`${c.title.padEnd(35).slice(0,35)} ${l}`});return[s,...a].join(` +`)}function T6e(t){return Ra(t).slice(0,3)}async function sXe(t){let[{buildServer:e},{StdioServerTransport:r},{setHostMcpServer:n}]=await Promise.all([Promise.resolve().then(()=>(nfe(),rfe)),Promise.resolve().then(()=>(cfe(),afe)),Promise.resolve().then(()=>(lm(),_Q))]),i=e({cwd:t.cwd,onboarding:{renderDraft:s=>Wte(s),prepareInit:({cwd:s,mode:a,intent:c})=>Zte(s,a,c),initialize:jj,prepareClarify:(s,{cwd:a})=>Vte(a,s),clarify:zj,resolveReview:(s,{cwd:a})=>qte(s,{cwd:a})}});n(i.server);let o=new r;H.stderr.write(`\xB7 serve stdio transport \xB7 cwd=${t.cwd??"."} +`),await i.connect(o)}async function aXe(t,e){let r=t&&t.length>0?t.join(" ").trim():void 0,n=await jj({projectName:e.name,force:e.force,scan:e.scan,noLlm:e.noLlm,roots:e.roots?e.roots.split(",").map(o=>o.trim()).filter(Boolean):void 0,intent:r,withHook:e.withHook,withCi:e.withCi});if(e.json){H.stdout.write(`${JSON.stringify(n,null,2)} +`),H.exit(0);return}for(let o of n.created)L("pass",`created ${o}`);for(let o of n.skipped)L("skip",o);for(let o of n.proposals??[])L("note","proposal",o);let i=n.onboardingMode?`language: ${n.language} \xB7 mode: ${n.onboardingMode}`:`language: ${n.language}`;if(L("note","init done",i),n.clarifyingQuestions&&n.clarifyingQuestions.length>0){H.stdout.write(` \u{1F4A1} A few more details would sharpen the spec: -`);for(let[o,s]of n.clarifyingQuestions.entries())B.stdout.write(` ${o+1}. ${s} -`);B.stdout.write(` -`)}else r||n.created.some(s=>s==="docs/conventions.md")&&(B.stdout.write(` +`);for(let[o,s]of n.clarifyingQuestions.entries())H.stdout.write(` ${o+1}. ${s} +`);H.stdout.write(` +`)}else r||n.created.some(s=>s==="docs/conventions.md")&&(H.stdout.write(` \u{1F4A1} Tip: for a more precise scaffold, describe the project: -`),B.stdout.write(` clad init -`),B.stdout.write(` e.g. clad init payment SaaS for B2B -`),B.stdout.write(` The existing seeds divert to .cladding/scan/*.proposal. - -`));B.exit(0)}async function P5e(t,e){L("note","run","EXPERIMENTAL \u2014 prefer the host-delegated path (clad serve + your AI host). See docs/feature-cycle.md \xA7 Execution surface.");let{runDriveLoop:r}=await Promise.resolve().then(()=>(Wde(),Vde)),n=await r({cwd:e.cwd,goal:t,budget:{maxIterations:Number(e.maxIterations),maxWallClockMs:Number(e.maxWallClockMs),maxRetriesPerFeature:Number(e.maxRetries)}}),i=n.halt.class==="ALL_FEATURES_DONE"?"pass":"note";if(e.json)L(i,"run",`halt=${n.halt.class} iter=${n.iterations} features=${n.featuresTouched.length} stubs=${n.stubsCreated.length} gates=${n.gateRuns}`),B.stdout.write(`${JSON.stringify(n,null,2)} -`);else{let s=q(e.cwd??"."),a=n.featuresTouched.map(l=>uR(l,s)),c=`${wG(n.halt,s)} iter=${n.iterations} features=${a.length} stubs=${n.stubsCreated.length} gates=${n.gateRuns}`;L(i,"run",c),a.length>0&&B.stdout.write(`Touched: ${a.join(", ")} -`)}let o=n.stubsCreated.length>0;o&&L("fail","run",`produced ${n.stubsCreated.length} empty auto-stub(s) and implemented nothing \u2014 the headless code-author needs a real LLM transport (set ANTHROPIC_API_KEY) or use the host-delegated path (clad serve + your AI host). This run did NOT do the work.`),B.exit(n.halt.class==="ALL_FEATURES_DONE"&&!o?0:1)}function C5e(t={}){try{let e=q();if(_a("."))L("note","sync","derived-file writes deferred \u2014 git operation in progress; re-run after the merge/rebase completes.");else{let r=bs(".");Yl(".",r),Ja("."),K5(".");let n=su(".");n==="created"?L("note","agents.md","wrote a spec-driven AGENTS.md so non-Claude agents share the same guidance."):n==="updated"&&L("note","agents.md","refreshed the AGENTS.md managed block from the current spec.");let i=ere(".");for(let s of i.repaired)L("note","test_refs",`repaired ${s.from} \u2192 ${s.to} (${s.shard})`);for(let s of i.suggested)L("note","test_refs",`suggested ${s.ref} (${s.shard}) \u2014 confirm by removing the 'derived:' prefix`);let o=i0(".");o&&L("note","deliverable",`auto-detected entry '${o.path}' \u2014 the gate now smoke-tests it. Opt out with is_safe_to_smoke: false.`)}if(t.proposeArchive){let n=dS.run({cwd:"."}).filter(i=>i.suggestion?.action==="propose-archive");if(n.length===0){L("pass","sync",`${e.features.length} features \xB7 0 archive candidates`),B.exit(0);return}for(let i of n){let o=i.suggestion?.args??{},s=String(o.featureId??"?"),a=String(o.reason??i.message);L("note",`propose-archive \xB7 ${s}`,a)}L("pass","sync",`${e.features.length} features \xB7 ${n.length} archive candidate(s)`),B.exit(0);return}L("pass","sync",`${e.features.length} features valid`),B.exit(0)}catch(e){L("fail","sync",e.message),B.exit(1)}}function D5e(t){if(!t){L("fail","checkpoint","feature id required (e.g. clad checkpoint F-001)"),B.exit(2);return}let e=C_(".",t),r=e.gitHead?e.gitHead.slice(0,12):"(no git)";L("pass",`checkpoint \xB7 ${t}`,`head=${r} digest=${e.specDigest.slice(0,12)}`),B.exit(0)}function N5e(t,e={}){if(!t){L("fail","rollback","feature id required (e.g. clad rollback F-001)"),B.exit(2);return}let r=D_(".",t);if(!r){L("fail",`rollback \xB7 ${t}`,"no prior checkpoint recorded"),B.exit(1);return}N_(".",t,r,e.reason);let n=r.gitHead?r.gitHead.slice(0,12):"(no git)";L("note",`rollback \xB7 ${t}`,`recorded \u2014 run the printed command to apply (cladding does not execute git) \xB7 target head=${n} ts=${r.timestamp}`),r.gitHead?B.stdout.write(`Run: git checkout ${r.gitHead} -`):B.stdout.write(`No git head pinned \u2014 restore spec.yaml manually from VCS history. -`),B.exit(0)}async function j5e(t){let e=t.host?t.host==="all"?["claude","codex","gemini","antigravity","cursor"].slice():[t.host]:void 0,r=await eD({force:t.force,quiet:t.quiet,projectRoot:t.project,hosts:e});B.exit(r.errors.length>0?1:0)}async function M5e(){L("note","update","reconciling the current project after the engine upgrade");let t=await n7(".",{wireHosts:async()=>(await eD({quiet:!0,projectRoot:"."})).errors.length});if(!t.isProject){L("skip","update","no spec.yaml here \u2014 nothing re-wired. Run `clad update` inside a cladding project, or `clad init` to start one."),B.exit(t.code);return}L(t.wiringErrors>0?"fail":"pass","hosts",t.wiringErrors>0?`${t.wiringErrors} wiring error(s)`:"re-wired"),t.inventoryDeferred?L("note","spec",`inventory + index writes deferred \u2014 git operation in progress; re-run \`clad update\` after it completes (${t.features} features seen).`):L("pass","spec",`inventory synced \xB7 ${t.features} features`),L(t.claudeMd==="refreshed-stale"?"note":"pass","CLAUDE.md",t.claudeMd),L(t.agentsMd==="refreshed-stale"?"note":"pass","AGENTS.md",t.agentsMd);for(let r of t.deprecations)L("note","deprecated",r);B.stdout.write(` +`),H.stdout.write(` clad init +`),H.stdout.write(` e.g. clad init payment SaaS for B2B +`),H.stdout.write(` The existing seeds divert to .cladding/scan/*.proposal. + +`));H.exit(0)}async function cXe(t,e){L("note","run","EXPERIMENTAL \u2014 prefer the host-delegated path (clad serve + your AI host). See docs/feature-cycle.md \xA7 Execution surface.");let{runDriveLoop:r}=await Promise.resolve().then(()=>(Cfe(),Pfe)),n=await r({cwd:e.cwd,goal:t,budget:{maxIterations:Number(e.maxIterations),maxWallClockMs:Number(e.maxWallClockMs),maxRetriesPerFeature:Number(e.maxRetries)}}),i=n.halt.class==="ALL_FEATURES_DONE"?"pass":"note";if(e.json)L(i,"run",`halt=${n.halt.class} iter=${n.iterations} features=${n.featuresTouched.length} stubs=${n.stubsCreated.length} gates=${n.gateRuns}`),H.stdout.write(`${JSON.stringify(n,null,2)} +`);else{let s=q(e.cwd??"."),a=n.featuresTouched.map(l=>_R(l,s)),c=`${MG(n.halt,s)} iter=${n.iterations} features=${a.length} stubs=${n.stubsCreated.length} gates=${n.gateRuns}`;L(i,"run",c),a.length>0&&H.stdout.write(`Touched: ${a.join(", ")} +`)}let o=n.stubsCreated.length>0;o&&L("fail","run",`produced ${n.stubsCreated.length} empty auto-stub(s) and implemented nothing \u2014 the headless code-author needs a real LLM transport (set ANTHROPIC_API_KEY) or use the host-delegated path (clad serve + your AI host). This run did NOT do the work.`),H.exit(n.halt.class==="ALL_FEATURES_DONE"&&!o?0:1)}function lXe(t={}){try{let e=q();if(Sa("."))L("note","sync","derived-file writes deferred \u2014 git operation in progress; re-run after the merge/rebase completes.");else{let r=xs(".");nu(".",r),rc("."),IY(".");let n=lu(".");n==="created"?L("note","agents.md","wrote a spec-driven AGENTS.md so non-Claude agents share the same guidance."):n==="updated"&&L("note","agents.md","refreshed the AGENTS.md managed block from the current spec.");let i=zre(".");for(let s of i.repaired)L("note","test_refs",`repaired ${s.from} \u2192 ${s.to} (${s.shard})`);for(let s of i.suggested)L("note","test_refs",`suggested ${s.ref} (${s.shard}) \u2014 confirm by removing the 'derived:' prefix`);let o=d0(".");o&&L("note","deliverable",`auto-detected entry '${o.path}' \u2014 the gate now smoke-tests it. Opt out with is_safe_to_smoke: false.`)}if(t.proposeArchive){let n=wS.run({cwd:"."}).filter(i=>i.suggestion?.action==="propose-archive");if(n.length===0){L("pass","sync",`${e.features.length} features \xB7 0 archive candidates`),H.exit(0);return}for(let i of n){let o=i.suggestion?.args??{},s=String(o.featureId??"?"),a=String(o.reason??i.message);L("note",`propose-archive \xB7 ${s}`,a)}L("pass","sync",`${e.features.length} features \xB7 ${n.length} archive candidate(s)`),H.exit(0);return}L("pass","sync",`${e.features.length} features valid`),H.exit(0)}catch(e){L("fail","sync",e.message),H.exit(1)}}function uXe(t){if(!t){L("fail","checkpoint","feature id required (e.g. clad checkpoint F-001)"),H.exit(2);return}let e=j_(".",t),r=e.gitHead?e.gitHead.slice(0,12):"(no git)";L("pass",`checkpoint \xB7 ${t}`,`head=${r} digest=${e.specDigest.slice(0,12)}`),H.exit(0)}function dXe(t,e={}){if(!t){L("fail","rollback","feature id required (e.g. clad rollback F-001)"),H.exit(2);return}let r=M_(".",t);if(!r){L("fail",`rollback \xB7 ${t}`,"no prior checkpoint recorded"),H.exit(1);return}F_(".",t,r,e.reason);let n=r.gitHead?r.gitHead.slice(0,12):"(no git)";L("note",`rollback \xB7 ${t}`,`recorded \u2014 run the printed command to apply (cladding does not execute git) \xB7 target head=${n} ts=${r.timestamp}`),r.gitHead?H.stdout.write(`Run: git checkout ${r.gitHead} +`):H.stdout.write(`No git head pinned \u2014 restore spec.yaml manually from VCS history. +`),H.exit(0)}async function fXe(t){let e=t.host?t.host==="all"?["claude","codex","gemini","antigravity","cursor"].slice():[t.host]:void 0,r=await RC({force:t.force,quiet:t.quiet,projectRoot:t.project,hosts:e});H.exit(r.errors.length>0?1:0)}async function pXe(){L("note","update","reconciling the current project after the engine upgrade");let t=await H7(".",{wireHosts:async()=>(await RC({quiet:!0,projectRoot:"."})).errors.length});if(!t.isProject){L("skip","update","no spec.yaml here \u2014 nothing re-wired. Run `clad update` inside a cladding project, or `clad init` to start one."),H.exit(t.code);return}L(t.wiringErrors>0?"fail":"pass","hosts",t.wiringErrors>0?`${t.wiringErrors} wiring error(s)`:"re-wired"),t.inventoryDeferred?L("note","spec",`inventory + index writes deferred \u2014 git operation in progress; re-run \`clad update\` after it completes (${t.features} features seen).`):L("pass","spec",`inventory synced \xB7 ${t.features} features`),L(t.claudeMd==="refreshed-stale"?"note":"pass","CLAUDE.md",t.claudeMd),L(t.agentsMd==="refreshed-stale"?"note":"pass","AGENTS.md",t.agentsMd);for(let r of t.deprecations)L("note","deprecated",r);H.stdout.write(` \u2192 drift check (report-only \xB7 does not block, does not edit your spec): -`),IA({tier:"pre-commit",strict:!0}).anyFailed?B.stdout.write("\n\u2139 The findings above are the bar this upgrade raised \u2014 not a failed update. Reconcile them in YOUR spec when ready (`clad check --strict` for the full gate).\n"):L("pass","drift","clean against the stricter detectors"),B.exit(t.code)}var F5e={"pre-commit":["stage_1.3","stage_1.5","stage_1.6"],"pre-push":["stage_1.1","stage_1.2","stage_1.3","stage_1.5","stage_1.6","stage_2.1","stage_2.2","stage_2.3","stage_2.4"],all:["stage_1.1","stage_1.2","stage_1.3","stage_1.4","stage_1.5","stage_1.6","stage_2.1","stage_2.2","stage_2.3","stage_2.4","stage_3.1","stage_3.2","stage_3.3","stage_4.1","stage_4.2"]};function IA(t){let e=t.tier??"all",r=t.silent===!0,n=F5e[e];if(!n)return t.json&&!r?B.stdout.write(`${JSON.stringify({tier:e,error:`unknown tier '${e}'`,worst:2,anyFailed:!0,stages:[]},null,2)} -`):r||L("fail","check",`unknown --tier '${e}' (expected: pre-commit | pre-push | all)`),{worst:2,anyFailed:!0,stages:[]};let i={focusModules:t.focusModules},s=[["stage_1.1",()=>sh(i)],["stage_1.2",()=>oh(i)],["stage_1.3",()=>si({...i,strict:t.strict})],["stage_1.4",Hj],["stage_1.5",ic],["stage_1.6",Qp],["stage_2.1",()=>tM({...i,strict:t.strict})],["stage_2.2",()=>Gj(i)],["stage_2.3",_C],["stage_2.4",Kj],["stage_3.1",Jj],["stage_3.2",Vj],["stage_3.3",rM],["stage_4.1",Lj],["stage_4.2",ah]].filter(([d])=>n.includes(d)),a=0,c=!1,l=d=>d==="pass"?"pass":d==="liveness"?"note":d==="na"?"skip":li(d)?"fail":"skip",u=[];Y_("."),Ate(".");try{for(let[d,f]of s){let p=f({}),m=t.internal?d:Ta(d),h=HX(p);li(h)&&(c=!0,a=Math.max(a,GX(p,h))),u.push({stage:d,label:m,status:h,exitCode:p.exitCode,stderr:p.stderr,findings:p.findings}),!t.json&&!r&&(L(l(h),m),li(h)&&Z5e(p))}}finally{Q_(),Ote()}if(t.strict)try{let d=q();for(let f of kte(d,u))a=Math.max(a,1),c=!0,u.push({stage:f.stage,label:f.label,status:"fail",exitCode:1,stderr:f.message}),!t.json&&!r&&L("fail",f.label,f.message)}catch{}if(t.strict&&(e==="pre-push"||e==="all")){let d=u.find(h=>h.stage==="stage_1.3"),f=(d?.findings??[]).filter(h=>h.severity==="error"||h.severity==="warn"),p=d?.status==="fail"&&f.length>0&&f.every(h=>h.detector==="STALE_ATTESTATION"),m=u.every(h=>h.stage==="stage_1.3"||!li(h.status));if(p&&m&&d&&(d.status="pass",d.exitCode=0,d.stderr="stale attestation exempted \u2014 this run re-verified and re-attests",c=u.some(h=>li(h.status)),a=c?Math.max(1,a):0,!t.json&&!r&&L("note","attestation","stale entries re-verified by this run \u2014 re-attesting")),!c&&!r)if(_a("."))t.json||L("note","attestation","deferred \u2014 git operation in progress; run the gate again after the merge/rebase completes.");else try{ZG(".",q())&&(t.json||L("note","attestation","spec/attestation.yaml refreshed (verified tree stamped)"))}catch{}}return t.json&&!r?B.stdout.write(`${JSON.stringify({tier:e,worst:a,anyFailed:c,stages:u},null,2)} -`):c&&!r&&B.stdout.write("\n\u2139 Run `clad doctor` for the event log, or `clad sync` to check the spec. The findings above say what drifted and why.\n"),tr(".","gate_run",{tier:e,strict:t.strict===!0,worst:a,anyFailed:c}),{worst:a,anyFailed:c,stages:u}}function L5e(t){try{let e=q(),r=gl(e,t);B.stdout.write(`${JSON.stringify(r,null,2)} -`),B.exit("not_found"in r?1:0)}catch(e){L("fail","context",e.message),B.exit(1)}}function z5e(t,e={}){try{let r=q(),n=e.depth!==void 0?Number(e.depth):void 0,i=Sr(r,t,{depth:n});B.stdout.write(`${JSON.stringify(i,null,2)} -`),B.exit("not_found"in i?1:0)}catch(r){L("fail","impact",r.message),B.exit(1)}}function U5e(t={}){try{let e=q(),r=t.ambiguity!==void 0?Number(t.ambiguity):void 0,i=yS(e,o=>{try{return Kde(o,"utf8")}catch{return null}},r!==void 0?{maxOwnerAmbiguity:r}:{});B.stdout.write(`${JSON.stringify({suggestions:i.suggestions,new_edges:i.edges.length,already_declared:i.alreadyDeclared.length,dynamic_import_files:i.dynamicImportFiles},null,2)} -`),B.exit(0)}catch(e){L("fail","infer-deps",e.message),B.exit(1)}}function q5e(t={}){try{if(t.sessions){dte(t);return}if(t.trend!==void 0&&t.trend!==!1){fte(t);return}let e=q(),n=UH(e,o=>{try{return Kde(o,"utf8")}catch{return null}},"."),i=BH(".",n);if(t.json)B.stdout.write(`${JSON.stringify(n,null,2)} -`);else{let o=n.context,s=o.truncatedCount>0?`budget enforces ${o.medianShrinkTruncated}x on ${o.truncatedCount} capped feature(s) (cap-driven)`:"no feature hit the budget cap",a=o.fitsCount>0?`${o.medianShrinkFit}x on ${o.fitsCount} fitting`:"none fit untruncated",c=[`graph efficiency \xB7 ${n.measured}/${n.featureCount} features`,` context: working-set ${o.medianSliceTokens} tok vs naive ${o.medianNaiveTokens} tok \u2014 ${s}, ${a}`,` uncapped structural slice = ${o.medianStructuralRatio}x of naive \u2014 the value is the guaranteed budget + wired needs/breaks/verify, not raw shrink`,` search: median ${n.search.medianDepth} hop(s) resolved (p95 ${n.search.p95Depth}), median ${n.search.medianEdges} edge(s)/feature (max hub ${n.search.maxEdges})`,` stability: median blast-radius coverage ${n.stability.medianCoverage}, median ${n.stability.medianRegressionTests} regression test(s) surfaced; stops ${JSON.stringify(n.stability.byStopReason)}`,` ${yl}`];B.stdout.write(`${c.join(` +`),LA({tier:"pre-commit",strict:!0}).anyFailed?H.stdout.write("\n\u2139 The findings above are the bar this upgrade raised \u2014 not a failed update. Reconcile them in YOUR spec when ready (`clad check --strict` for the full gate).\n"):L("pass","drift","clean against the stricter detectors"),H.exit(t.code)}var mXe={"pre-commit":["stage_1.3","stage_1.5","stage_1.6"],"pre-push":["stage_1.1","stage_1.2","stage_1.3","stage_1.5","stage_1.6","stage_2.1","stage_2.2","stage_2.3","stage_2.4"],all:["stage_1.1","stage_1.2","stage_1.3","stage_1.4","stage_1.5","stage_1.6","stage_2.1","stage_2.2","stage_2.3","stage_2.4","stage_3.1","stage_3.2","stage_3.3","stage_4.1","stage_4.2"]};function hXe(t){return t.length===0?"":`${t.join(", ")} skipped \u2014 no runner is known for this project. Declare commands in .cladding/config.yaml (gate: \u2192 commands: \u2192 e.g. test: ["zig","test"]) to run them; the file is committable, so CI runs the same gate you do.`}function LA(t){let e=t.tier??"all",r=t.silent===!0,n=mXe[e];if(!n)return t.json&&!r?H.stdout.write(`${JSON.stringify({tier:e,error:`unknown tier '${e}'`,worst:2,anyFailed:!0,stages:[]},null,2)} +`):r||L("fail","check",`unknown --tier '${e}' (expected: pre-commit | pre-push | all)`),{worst:2,anyFailed:!0,stages:[]};let i={focusModules:t.focusModules},s=[["stage_1.1",()=>lh(i)],["stage_1.2",()=>ch(i)],["stage_1.3",()=>ci({...i,strict:t.strict})],["stage_1.4",oM],["stage_1.5",ac],["stage_1.6",nm],["stage_2.1",()=>gM({...i,strict:t.strict})],["stage_2.2",()=>sM(i)],["stage_2.3",GC],["stage_2.4",uM],["stage_3.1",dM],["stage_3.2",cM],["stage_3.3",yM],["stage_4.1",eM],["stage_4.2",uh]].filter(([d])=>n.includes(d)),a=0,c=!1,l=d=>d==="pass"?"pass":d==="liveness"?"note":d==="na"?"skip":mr(d)?"fail":"skip",u=[];eb("."),pre(".");try{for(let[d,f]of s){let p=f({}),m=t.internal?d:Ra(d),h=SX(p);mr(h)&&(c=!0,a=Math.max(a,wX(p,h))),u.push({stage:d,label:m,status:h,exitCode:p.exitCode,stderr:p.stderr,findings:p.findings,skipReason:p.skipReason}),!t.json&&!r&&(L(l(h),m),mr(h)&&xXe(p))}}finally{rb(),hre()}if(t.strict)try{let d=q();for(let f of dre(d,u))a=Math.max(a,1),c=!0,u.push({stage:f.stage,label:f.label,status:"fail",exitCode:1,stderr:f.message}),!t.json&&!r&&L("fail",f.label,f.message)}catch{}if(t.strict&&(e==="pre-push"||e==="all")){let d=u.find(h=>h.stage==="stage_1.3"),f=(d?.findings??[]).filter(h=>h.severity==="error"||h.severity==="warn"),p=d?.status==="fail"&&f.length>0&&f.every(h=>h.detector==="STALE_ATTESTATION"),m=u.every(h=>h.stage==="stage_1.3"||!mr(h.status));if(p&&m&&d&&(d.status="pass",d.exitCode=0,d.stderr="stale attestation exempted \u2014 this run re-verified and re-attests",c=u.some(h=>mr(h.status)),a=c?Math.max(1,a):0,!t.json&&!r&&L("note","attestation","stale entries re-verified by this run \u2014 re-attesting")),!c&&!r)if(Sa("."))t.json||L("note","attestation","deferred \u2014 git operation in progress; run the gate again after the merge/rebase completes.");else try{aZ(".",q(),{cladding:fn()??"unknown",blocking:"strict",detectorsSha256:oZ(IS)})&&(t.json||L("note","attestation","spec/attestation.yaml refreshed (verified tree stamped)"))}catch{}}if(t.json&&!r?H.stdout.write(`${JSON.stringify({tier:e,worst:a,anyFailed:c,stages:u},null,2)} +`):c&&!r&&H.stdout.write("\n\u2139 Run `clad doctor` for the event log, or `clad sync` to check the spec. The findings above say what drifted and why.\n"),!t.json&&!r){let d=hXe(u.filter(f=>f.skipReason==="no-runner").map(f=>f.label));d&&H.stdout.write(` +\u2139 ${d} +`)}return Jt(".","gate_run",{tier:e,strict:t.strict===!0,worst:a,anyFailed:c,blockers:PS(u),stopFingerprint:xX(u)}),{worst:a,anyFailed:c,stages:u}}function gXe(t){try{let e=q(),r=bl(e,t);H.stdout.write(`${JSON.stringify(r,null,2)} +`),H.exit("not_found"in r?1:0)}catch(e){L("fail","context",e.message),H.exit(1)}}function yXe(t,e={}){try{let r=q(),n=e.depth!==void 0?Number(e.depth):void 0,i=xr(r,t,{depth:n});H.stdout.write(`${JSON.stringify(i,null,2)} +`),H.exit("not_found"in i?1:0)}catch(r){L("fail","impact",r.message),H.exit(1)}}function _Xe(t={}){try{let e=q(),r=t.ambiguity!==void 0?Number(t.ambiguity):void 0,i=RS(e,o=>{try{return Dfe(o,"utf8")}catch{return null}},r!==void 0?{maxOwnerAmbiguity:r}:{});H.stdout.write(`${JSON.stringify({suggestions:i.suggestions,new_edges:i.edges.length,already_declared:i.alreadyDeclared.length,dynamic_import_files:i.dynamicImportFiles},null,2)} +`),H.exit(0)}catch(e){L("fail","infer-deps",e.message),H.exit(1)}}function bXe(t={}){try{if(t.sessions){Yte(t);return}if(t.trend!==void 0&&t.trend!==!1){Xte(t);return}let e=q(),n=rG(e,o=>{try{return Dfe(o,"utf8")}catch{return null}},"."),i=iG(".",n);if(t.json)H.stdout.write(`${JSON.stringify(n,null,2)} +`);else{let o=n.context,s=o.truncatedCount>0?`budget enforces ${o.medianShrinkTruncated}x on ${o.truncatedCount} capped feature(s) (cap-driven)`:"no feature hit the budget cap",a=o.fitsCount>0?`${o.medianShrinkFit}x on ${o.fitsCount} fitting`:"none fit untruncated",c=[`graph efficiency \xB7 ${n.measured}/${n.featureCount} features`,` context: working-set ${o.medianSliceTokens} tok vs naive ${o.medianNaiveTokens} tok \u2014 ${s}, ${a}`,` uncapped structural slice = ${o.medianStructuralRatio}x of naive \u2014 the value is the guaranteed budget + wired needs/breaks/verify, not raw shrink`,` search: median ${n.search.medianDepth} hop(s) resolved (p95 ${n.search.p95Depth}), median ${n.search.medianEdges} edge(s)/feature (max hub ${n.search.maxEdges})`,` stability: median blast-radius coverage ${n.stability.medianCoverage}, median ${n.stability.medianRegressionTests} regression test(s) surfaced; stops ${JSON.stringify(n.stability.byStopReason)}`,` ${vl}`];H.stdout.write(`${c.join(` `)} -`),i.appended?L("note","measure","snapshot recorded to .cladding/measure.jsonl \u2014 see `clad measure --trend`"):i.reason==="deduped"?L("note","measure","commit+spec state unchanged since last snapshot \u2014 not recorded"):i.reason==="no_head"&&L("note","measure","no git HEAD \u2014 snapshot not recorded (commit first; a head-less line has no reproduce target)")}B.exit(0)}catch(e){L("fail","measure",e.message),B.exit(1)}}function B5e(t){let e;if(t.feature)try{let i=(q().features??[]).find(o=>o.id===t.feature||o.slug===t.feature);i||(L("fail","check",`no feature '${t.feature}' in spec \u2014 cannot scope gate`),B.exit(1)),e=i.modules}catch(n){L("fail","check",n.message),B.exit(1)}let r=IA({...t,focusModules:e});if(!t.json){let n=$X(".");n&&B.stdout.write(`\u2139 ${n} -`)}B.exitCode=r.worst}function H5e(t){let e;try{e={policy:q(".").project.independence_policy??"label",evidence:fr(".")}}catch{e=void 0}let r=mX(".",t,{checkStages:IA,onIndex:Ja,gitOpInProgress:PO,independence:e});if(L(r.ok?"pass":"fail",`done \xB7 ${t}`,r.reason),r.independence){let n=r.independence==="independent"?"independence: independent \u2014 backed by human or independent review":"independence: self-certified \u2014 no independent or human review yet";L("note",`done \xB7 ${t}`,n)}B.exit(r.code)}function G5e(t,e={}){let r=e.cwd??".",n;try{n=q(r)}catch(o){L("fail","oracle",`spec not loaded: ${o.message}`),B.exit(1);return}if(e.required){t&&B.stdout.write(`(note: --required lists the whole-project worklist; ignoring '${t}') -`);let o=eY(n);if(o.length===0){B.stdout.write(`No oracles required \u2014 set project.oracle_policy or require_oracles, or no done ACs match the policy. -`),B.exit(0);return}let s=o.filter(a=>!a.hasOracle);for(let a of o){let c=a.hasOracle?"\u2713":"\xB7",l=a.hasOracle?"":" \u2190 needs an impl-blind oracle";B.stdout.write(` ${c} ${a.featureId}.${a.acId} [${a.reason}${a.ears?`:${a.ears}`:""}]${l} -`)}B.stdout.write(` +`),i.appended?L("note","measure","snapshot recorded to .cladding/measure.jsonl \u2014 see `clad measure --trend`"):i.reason==="deduped"?L("note","measure","commit+spec state unchanged since last snapshot \u2014 not recorded"):i.reason==="no_head"&&L("note","measure","no git HEAD \u2014 snapshot not recorded (commit first; a head-less line has no reproduce target)")}H.exit(0)}catch(e){L("fail","measure",e.message),H.exit(1)}}function vXe(t){let e;if(t.feature)try{let i=(q().features??[]).find(o=>o.id===t.feature||o.slug===t.feature);i||(L("fail","check",`no feature '${t.feature}' in spec \u2014 cannot scope gate`),H.exit(1)),e=i.modules}catch(n){L("fail","check",n.message),H.exit(1)}let r=LA({...t,focusModules:e});if(!t.json){let n=d7(".");n&&H.stdout.write(`\u2139 ${n} +`)}H.exitCode=r.worst}function SXe(t){let e;try{e={policy:q(".").project.independence_policy??"label",evidence:pr(".")}}catch{e=void 0}let r=n7(".",t,{checkStages:LA,onIndex:rc,gitOpInProgress:zT,independence:e});if(L(r.ok?"pass":"fail",`done \xB7 ${t}`,r.reason),r.independence){let n=r.independence==="independent"?"independence: independent \u2014 backed by human or independent review":"independence: self-certified \u2014 no independent or human review yet";L("note",`done \xB7 ${t}`,n)}H.exit(r.code)}function wXe(t,e={}){let r=e.cwd??".",n;try{n=q(r)}catch(o){L("fail","oracle",`spec not loaded: ${o.message}`),H.exit(1);return}if(e.required){t&&H.stdout.write(`(note: --required lists the whole-project worklist; ignoring '${t}') +`);let o=jY(n);if(o.length===0){H.stdout.write(`No oracles required \u2014 set project.oracle_policy or require_oracles, or no done ACs match the policy. +`),H.exit(0);return}let s=o.filter(a=>!a.hasOracle);for(let a of o){let c=a.hasOracle?"\u2713":"\xB7",l=a.hasOracle?"":" \u2190 needs an impl-blind oracle";H.stdout.write(` ${c} ${a.featureId}.${a.acId} [${a.reason}${a.ears?`:${a.ears}`:""}]${l} +`)}H.stdout.write(` ${o.length} AC(s) required, ${s.length} missing an oracle. -`),B.exit(s.length>0?1:0);return}if(!t){L("fail","oracle","provide a to print its blind brief, or --required to list the ACs the policy needs an oracle for"),B.exit(1);return}let i=tre(n,t,e.ac,r);if(!i||i.acs.length===0){L("fail","oracle",`no acceptance criteria for ${t}${e.ac?`.${e.ac}`:""} \u2014 nothing to author a blind oracle from`),B.exit(1);return}B.stdout.write(`${rre(i)} -`),B.exit(0)}function Z5e(t){if(t.findings&&t.findings.length>0){let e=t.findings.filter(i=>i.severity==="error"),r=t.findings.filter(i=>i.severity==="warn"),n=e.length>0?e:r;for(let i of n.slice(0,3)){let o=y4(Oa(i.detector,i.message),140),s=i.path?` \u2014 ${i.path}`:"";if(B.stdout.write(` ${o}${s} [${i.detector}] -`),Oa(i.detector,i.message)!==i.message){let c=i.message.split(` -`).map(l=>l.trim()).filter(l=>l.length>0);for(let l of c.slice(0,4))B.stdout.write(` ${y4(l,160)} -`);c.length>4&&B.stdout.write(` \u2026 and ${c.length-4} more line(s) \u2014 see \`clad check --json\` -`)}}n.length>3&&B.stdout.write(` \u2026 and ${n.length-3} more finding(s) -`),t.hint&&B.stdout.write(` fix: run \`${t.hint}\` +`),H.exit(s.length>0?1:0);return}if(!t){L("fail","oracle","provide a to print its blind brief, or --required to list the ACs the policy needs an oracle for"),H.exit(1);return}let i=Ure(n,t,e.ac,r);if(!i||i.acs.length===0){L("fail","oracle",`no acceptance criteria for ${t}${e.ac?`.${e.ac}`:""} \u2014 nothing to author a blind oracle from`),H.exit(1);return}H.stdout.write(`${qre(i)} +`),H.exit(0)}function xXe(t){if(t.findings&&t.findings.length>0){let e=t.findings.filter(i=>i.severity==="error"),r=t.findings.filter(i=>i.severity==="warn"),n=e.length>0?e:r;for(let i of n.slice(0,3)){let o=P4(Ia(i.detector,i.message),140),s=i.path?` \u2014 ${i.path}`:"";if(H.stdout.write(` ${o}${s} [${i.detector}] +`),Ia(i.detector,i.message)!==i.message){let c=i.message.split(` +`).map(l=>l.trim()).filter(l=>l.length>0);for(let l of c.slice(0,4))H.stdout.write(` ${P4(l,160)} +`);c.length>4&&H.stdout.write(` \u2026 and ${c.length-4} more line(s) \u2014 see \`clad check --json\` +`)}}n.length>3&&H.stdout.write(` \u2026 and ${n.length-3} more finding(s) +`),t.hint&&H.stdout.write(` fix: run \`${t.hint}\` `);return}if(t.stderr&&t.stderr.trim().length>0){let e=t.stderr.split(` -`).map(r=>r.trim()).filter(r=>r.length>0);for(let r of e.slice(0,5))B.stdout.write(` ${y4(r,160)} -`);e.length>5&&B.stdout.write(` \u2026 and ${e.length-5} more line(s) \u2014 see \`clad check --json\` -`)}}function y4(t,e){return t.length<=e?t:`${t.slice(0,e-1)}\u2026`}function V5e(t){let e=q();if(t.json){B.stdout.write(`${JSON.stringify(o0(e,"."),null,2)} -`),B.exitCode=0;return}B.stdout.write(`${nre(e,".",{internal:t.internal})} -`),B.exit(0)}function W5e(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(2)} MB`}function K5e(t){let e=t.cwd??".",r=(t.out??"").trim();if(r.length===0){L("fail","bundle","missing --out \u2014 the bundle needs a destination path"),B.exit(1);return}let n;try{let i=q(e),o=o0(i,e),s={gitHead:Sa(e),version:ru(),generatedAt:t.now??new Date().toISOString()},a=vl(i),c;try{let l=t.since??ns(e),u=is(e,l);c={kind:"present",sinceRef:l,changelogMarkdown:_l(u),auditMarkdown:bl(u,i,e)}}catch(l){c={kind:"omitted",reason:l.message}}n=NG({spec:i,panel:o,provenance:s,catalogMarkdown:a,changes:c})}catch(i){L("fail","bundle",i.message),B.exit(1);return}try{O5e(r,n,"utf8")}catch(i){L("fail","bundle",`could not write ${r}: ${i.message}`),B.exit(1);return}L("pass","bundle",`${r} \xB7 ${W5e(Buffer.byteLength(n,"utf8"))}`),B.exit(0)}function J5e(t){let e=JA(t);L("note",`route \u2192 ${e}`,t),B.exit(e==="unknown"?1:0)}function Y5e(){let t=new I4;t.name("clad").description("Reference Ironclad CLI").version("0.9.3"),t.command("init [intent...]").description("Scaffold a cladding workspace. Pass a free-text project description as positional argument (e.g. `clad init payment SaaS for B2B` \u2014 free text in any language) to drive intent-aware onboarding \u2014 the LLM dispatcher then produces domain-aware capabilities/architecture/project-context plus product-level follow-up questions. Bare `clad init` keeps the v0.3.42 behaviour (greenfield seeds, or observed scan when \u22653 source files exist).").option("-n, --name ","Project name (default: cwd basename)").option("-f, --force","Overwrite existing spec.yaml").option("--scan","Force-walk the existing codebase. Default auto-detects (\u22653 source files trigger scan). Use --no-scan to skip even when source is present.").option("--no-llm","Force the deterministic interpreter (skip the LLM dispatcher chain). Intent text falls back to a deterministic quote in project-context.md.").option("--roots ","Override scanner source roots, comma-separated (e.g. packages/a/src,packages/b/src). Otherwise inferred from manifests + directory heuristics.").option("--with-hook","Install git pre-commit (cheap tier) AND pre-push (strict tier) hooks. Opt-in; cladding never touches .git without it.").option("--with-ci","Scaffold .github/workflows/cladding.yml running the strict pre-push gate \u2014 the authoritative enforcement layer.").option("--json","emit the raw InitResult for tooling; default is the human-readable surface").action(I5e),t.command("run [goal]").description("(experimental) Headless autonomous loop \u2014 iterate ready features, dispatch developer + reviewer personas, run L1 gates, record evidence. The supported, exercised path is host-delegated (clad serve + your AI host loops the cadence); this loop needs a real LLM transport and is not auto-invoked").option("--cwd ","target project directory (default cwd)").option("--max-iterations ","cap iterations (default 50)","50").option("--max-wall-clock-ms ","cap wall clock (default 600000)","600000").option("--max-retries ","cap retries per feature (default 3)","3").option("--json","emit the raw internal result (Iron Core view); default is a plain Soft Shell summary").action(P5e),t.command("sync").description("Validate spec.yaml against schema and report").option("--propose-archive","list STALE_SPECIFICATION findings whose suggestion.action is propose-archive (Phased Decommissioning Tier 2)").action(C5e),t.command("setup").description("Activate Cladding only for the current project (Claude Code / Codex / Gemini / Antigravity / Cursor)").option("--project ","activate a project other than the current directory").option("--host ","activate detected hosts (default), all, or one of: claude, codex, gemini, antigravity, cursor").option("--force","replace an existing conflicting cladding-owned project entry").option("--quiet","suppress stdout output").action(j5e),t.command("update").description("Run from a project dir AFTER `npm update -g cladding`: refresh project host wiring + sync inventory + refresh managed CLAUDE.md/AGENTS.md, then report stricter detector findings").action(M5e),t.command("check").description("Run every Iron Law stage and the drift detector suite").option("--internal","show stage codes (`stage_1.1`) instead of names (`Type`)").option("--strict","promote warn-severity drift findings to errors (CI / pre-publish gate)").option("--tier ","run only the stages for a trigger: pre-commit (drift/arch/secret) | pre-push (+ type/lint/unit/cov/spec-conformance/deliverable-smoke) | all (default; full 15-stage gate, used by CI)").option("--json","emit structured per-stage results (machine-readable: findings with file/line/suggestion, untruncated) \u2014 for agents/CI; cuts RED\u2192fix round-trips").option("--feature ","scope the gate to this feature's modules[] (Gradle monorepos): runs only :project: tasks instead of the root aggregate. No-op for non-Gradle repos or modules-less features").action(B5e),t.command("checkpoint ").description("Record a checkpoint event pinning git HEAD + spec digest for the feature (iron-law \xA72.5)").action(D5e),t.command("done ").description("Mark a feature done ONLY if `clad check --tier=pre-push --strict` is GREEN (flip \u2192 gate \u2192 revert-on-red). Keeps `done` honest.").action(H5e),t.command("oracle [featureId]").description("Print the impl-blind oracle authoring brief (acceptance criteria + signatures, never the implementation). Hand it to a fresh blind sub-agent; record the result with clad_author_oracle. cladding calls no LLM. Use --required to list which done ACs the project policy needs an oracle for.").option("--ac ","restrict the brief to a single acceptance criterion").option("--required","list the done ACs the oracle_policy / require_oracles requires an oracle for (worklist), instead of a brief").option("--cwd ","project root (defaults to .)").action((r,n)=>G5e(r,n)),t.command("rollback ").description("Record a rollback event and print the maintainer-runnable git command for the latest checkpoint").option("-r, --reason ","optional free-text reason recorded on the event payload").action(N5e),t.command("status").description("Render the feature \xD7 stage integrity matrix (business titles; use --internal for raw F-NNN ids)").option("--internal","show internal F-NNN ids and stage codes").option("--json","emit the row model as JSON \u2014 the same feature \xD7 stage integrity matrix rendered to the terminal (columns + per-feature glyph cells), one SSoT for terminal, JSON, and the audit bundle").action(V5e),t.command("context ").description("Print the context slice for one feature \u2014 id (F-\u2026), slug, or module path (F-d2c806)").action(L5e),t.command("impact ").description("Print the blast radius for a change \u2014 what depends on a feature/file + the tests to re-run (F-7794a6bc)").option("--depth ","bound the dependent walk to N hops (default: the full transitive radius)").action((r,n)=>z5e(r,n)),t.command("verdict").description("One-poll loop decision: DONE|ITERATE|ESCALATE|BLOCKED|BOOTSTRAP over the pre-push strict gate + feature statuses (F-2e28cc72). Single gate touch; DONE requires \u22651 non-liveness proof.").option("--json","emit the verdict object as JSON").option("--tier ","gate tier (default pre-push)").action(r=>XX(r,{checkStages:IA})),t.command("infer-deps").description("Suggest feature depends_on edges from the code import graph \u2014 the dependency edges cladding never auto-produced (F-2be3e3bb). Prints reviewable suggestions; does not write the spec.").option("--ambiguity ","emit edges for imports owned by \u2264 N features (default 1 = unambiguous single-owner only)").action(r=>U5e(r)),t.command("measure").description("Report the search + context efficiency the graph provides per feature \u2014 working-set tokens vs the naive baseline, dependency depth/edges resolved, regression-set coverage (F-16138071). Deterministic; no agent.").option("--json","emit the full report as JSON").option("--sessions","summarize recorded value-delivery telemetry instead \u2014 impact-card fire rate over eligible edits, the per-reason skip histogram, and MCP read-serve counts. Measures DELIVERY (did the surfaces fire), NOT adoption (F-6ba22c5c).").option("--trend [n]","render the last N (default 5) recorded measure snapshots with signed deltas \u2014 spot efficiency drift over time from the deduped .cladding/measure.jsonl ledger (F-39609db4)").action(r=>q5e(r));let e=t.command("graph").description("Render the spec\u2194code\u2194doc knowledge graph for a viewer, or report its shape (F-569f4b37)");return e.command("export").description("Export the graph: mermaid/dot/json to stdout, or an Obsidian vault to --out").option("--format ","mermaid | dot | json | obsidian | html (default: mermaid). html = a single self-contained offline viewer (requires --out)").option("--focus ","restrict to a feature/file node\u2019s neighborhood (id, slug, or module path)").option("--depth ","neighborhood radius around --focus (default: unbounded)").option("--out ","write to a file (or, for obsidian, a vault dir \u2014 default .cladding/graph)").action(r=>wte(r)),e.command("stats").description("Report node/edge counts by kind and the top hubs by degree").action(()=>xte()),e.command("serve").description("Serve a LIVE graph at localhost \u2014 recomputes on each load + auto-reloads on spec/doc changes (F-64a5c159)").option("--port ","port to listen on (default 3000)").action(r=>{$te(r)}),t.command("changelog").description("Render shipped changes since a git ref into human-facing documents (F-904495a5). Default: capability-grouped markdown from feature titles + acceptance sentences (no internal ids). --json emits the deterministic manifest hosts render release notes from; --audit the id-keeping verification table; --catalog the full capability \u2192 feature \u2192 acceptance catalog.").option("--since ","git ref to diff from (default: the latest tag via `git describe --tags --abbrev=0`)").option("--json","print the deterministic ChangelogManifest as JSON (byte-identical across runs on the same state)").option("--audit","print the audit table \u2014 feature | AC | EARS | verification refs, each marked resolved \u2713/\u2717").option("--catalog","print the full capability \u2192 feature \u2192 acceptance listing of the living spec (no git range)").option("--measure","embed the release's own re-derivable measurement \u2014 but ONLY a snapshot taken at the current HEAD; no match renders a not-measured notice, never an older snapshot (F-ede6fa75)").action(r=>SG(r)),t.command("report").description("Render one deterministic review packet for a git range (F-f6cc5e5a) \u2014 spec entry movement (from the changelog), how each acceptance criterion moved, changed source files resolved to their owning features via the reverse index, the tests those features declare, the deduped regression set, and gate + attestation state. For PR reviewers, team-leads, and auditors: it RENDERS, it gates nothing. Byte-identical across two runs on the same repository state.").option("--since ","git ref to diff from (default: the latest tag via `git describe --tags --abbrev=0`)").option("--format ","md (default, the six-section markdown packet) | sarif (SARIF 2.1.0 \u2014 one result per error/warn drift finding, for code-scanning UIs) | json (the raw deterministic model)").action(r=>NY(r)),t.command("bundle").description("Write ONE self-contained HTML audit bundle (F-e940fffe) a non-coder can double-click \u2014 offline, zero network, no CDN, no scripts. Contains the project header + inventory, the feature \xD7 stage matrix, the capability catalog, shipped changes for the range, the audit table with resolved refs, and the attestation summary, under a provenance banner (git HEAD, date, version). Deterministic modulo the date stamp. If no anchor ref resolves, the changelog + audit sections show an omitted notice while the rest still renders.").requiredOption("--out ","destination path for the HTML bundle").option("--since ","git ref to diff shipped changes from (default: the latest tag via `git describe --tags --abbrev=0`)").action(r=>K5e(r)),t.command("route ").description("Classify a natural-language prompt to a verb").action(J5e),t.command("hook ").description("Host hook protocol adapter \u2014 consume one host lifecycle event (SessionStart | UserPromptSubmit | PreToolUse | PostToolUse | Stop) as stdin JSON and print the protocol response on stdout. Always exits 0 so a hook failure never bricks the host session.").action(BX),t.command("serve").description("Run cladding as an MCP server over stdio \u2014 tools/resources/prompts for any MCP client").option("--cwd ","project directory exposed to the client (default cwd)").action(R5e),t.command("doctor").description("Summarise .cladding/events.log.jsonl \u2014 sentinel-miss frequency by phase/cause/fallback plus the top missed sentinels (LLM dispatcher health check)").option("--cwd ","project directory to read events from (default cwd)").option("--json","emit the raw DoctorReport for tooling; default is the human-readable surface").option("--hosts","smoke-test host CLIs (Claude Code / Gemini / Antigravity / Codex / Cursor) and project wiring \u2192 dated artifact + docs/dogfood/matrix.md. Live LLM prompts run only with consent (CLAD_HOST_SMOKE=1 or --yes); otherwise not-run").option("--yes","grant live-run consent for --hosts (equivalent to CLAD_HOST_SMOKE=1)").option("--matrix-only","regenerate docs/dogfood/matrix.md from the newest host-smoke artifact without any probing").action(r=>{if(r.hosts||r.matrixOnly){uX({cwd:r.cwd,yes:r.yes,matrixOnly:r.matrixOnly});return}FY(r)}),t.command("clarify [answer...]").description("Advance the onboarding Q&A loop. Pass the user's answer to the next pending question as a positional (no quotes needed, free text in any language, e.g. `clad clarify B2B only`); the LLM refines spec/docs based on the full Q-A history and may emit new follow-up questions. Reads/writes `.cladding/onboarding/state.yaml`. Requires `clad init ` to have started a session first.").option("--cwd ","project directory containing .cladding/onboarding/state.yaml (default cwd)").option("--no-llm","force the deterministic interpreter (preserves current artifacts, logs the answer)").option("--json","emit the raw RefineReport for tooling; default is the human-readable surface").action(ote),t}var X5e=!!globalThis.__CLADDING_BUNDLED,Q5e=X5e||import.meta.url===`file://${B.argv[1]}`;Q5e&&Y5e().parse();export{F5e as TIER_STAGES,Y5e as createProgram,K5e as runBundleCommand,B5e as runCheckCommand,IA as runCheckStages,D5e as runCheckpointCommand,L5e as runContextCommand,H5e as runDoneCommand,z5e as runImpactCommand,U5e as runInferDepsCommand,I5e as runInitCommand,q5e as runMeasureCommand,G5e as runOracleCommand,N5e as runRollbackCommand,J5e as runRouteCommand,P5e as runRunCommand,R5e as runServeCommand,j5e as runSetupCommand,V5e as runStatusCommand,C5e as runSyncCommand,M5e as runUpdateCommand}; +`).map(r=>r.trim()).filter(r=>r.length>0);for(let r of e.slice(0,5))H.stdout.write(` ${P4(r,160)} +`);e.length>5&&H.stdout.write(` \u2026 and ${e.length-5} more line(s) \u2014 see \`clad check --json\` +`)}}function P4(t,e){return t.length<=e?t:`${t.slice(0,e-1)}\u2026`}function $Xe(t){let e=q();if(t.json){H.stdout.write(`${JSON.stringify(f0(e,"."),null,2)} +`),H.exitCode=0;return}H.stdout.write(`${Hre(e,".",{internal:t.internal})} +`),H.exit(0)}function kXe(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(2)} MB`}function EXe(t){let e=t.cwd??".",r=(t.out??"").trim();if(r.length===0){L("fail","bundle","missing --out \u2014 the bundle needs a destination path"),H.exit(1);return}let n;try{let i=q(e),o=f0(i,e),s={gitHead:xa(e),version:fn(),generatedAt:t.now??new Date().toISOString()},a=xl(i),c;try{let l=t.since??is(e),u=os(e,l);c={kind:"present",sinceRef:l,changelogMarkdown:Sl(u),auditMarkdown:wl(u,i,e)}}catch(l){c={kind:"omitted",reason:l.message}}n=JG({spec:i,panel:o,provenance:s,catalogMarkdown:a,changes:c})}catch(i){L("fail","bundle",i.message),H.exit(1);return}try{oXe(r,n,"utf8")}catch(i){L("fail","bundle",`could not write ${r}: ${i.message}`),H.exit(1);return}L("pass","bundle",`${r} \xB7 ${kXe(Buffer.byteLength(n,"utf8"))}`),H.exit(0)}function AXe(t){let e=iO(t);L("note",`route \u2192 ${e}`,t),H.exit(e==="unknown"?1:0)}function OXe(){let t=new Z4;t.name("clad").description("Reference Ironclad CLI").version("0.9.4"),t.command("init [intent...]").description("Scaffold a cladding workspace. Pass a free-text project description as positional argument (e.g. `clad init payment SaaS for B2B` \u2014 free text in any language) to drive intent-aware onboarding \u2014 the LLM dispatcher then produces domain-aware capabilities/architecture/project-context plus product-level follow-up questions. Bare `clad init` keeps the v0.3.42 behaviour (greenfield seeds, or observed scan when \u22653 source files exist).").option("-n, --name ","Project name (default: cwd basename)").option("-f, --force","Overwrite existing spec.yaml").option("--scan","Force-walk the existing codebase. Default auto-detects (\u22653 source files trigger scan). Use --no-scan to skip even when source is present.").option("--no-llm","Force the deterministic interpreter (skip the LLM dispatcher chain). Intent text falls back to a deterministic quote in project-context.md.").option("--roots ","Override scanner source roots, comma-separated (e.g. packages/a/src,packages/b/src). Otherwise inferred from manifests + directory heuristics.").option("--with-hook","Install git pre-commit (cheap tier) AND pre-push (strict tier) hooks. Opt-in; cladding never touches .git without it.").option("--with-ci","Scaffold .github/workflows/cladding.yml running the strict pre-push gate \u2014 the authoritative enforcement layer.").option("--json","emit the raw InitResult for tooling; default is the human-readable surface").action(aXe),t.command("run [goal]").description("(experimental) Headless autonomous loop \u2014 iterate ready features, dispatch developer + reviewer personas, run L1 gates, record evidence. The supported, exercised path is host-delegated (clad serve + your AI host loops the cadence); this loop needs a real LLM transport and is not auto-invoked").option("--cwd ","target project directory (default cwd)").option("--max-iterations ","cap iterations (default 50)","50").option("--max-wall-clock-ms ","cap wall clock (default 600000)","600000").option("--max-retries ","cap retries per feature (default 3)","3").option("--json","emit the raw internal result (Iron Core view); default is a plain Soft Shell summary").action(cXe),t.command("sync").description("Validate spec.yaml against schema and report").option("--propose-archive","list STALE_SPECIFICATION findings whose suggestion.action is propose-archive (Phased Decommissioning Tier 2)").action(lXe),t.command("setup").description("Activate Cladding only for the current project (Claude Code / Codex / Gemini / Antigravity / Cursor)").option("--project ","activate a project other than the current directory").option("--host ","activate detected hosts (default), all, or one of: claude, codex, gemini, antigravity, cursor").option("--force","replace an existing conflicting cladding-owned project entry").option("--quiet","suppress stdout output").action(fXe),t.command("update").description("Run from a project dir AFTER `npm update -g cladding`: refresh project host wiring + sync inventory + refresh managed CLAUDE.md/AGENTS.md, then report stricter detector findings").action(pXe),t.command("check").description("Run every Iron Law stage and the drift detector suite").option("--internal","show stage codes (`stage_1.1`) instead of names (`Type`)").option("--strict","promote warn-severity drift findings to errors (CI / pre-publish gate)").option("--tier ","run only the stages for a trigger: pre-commit (drift/arch/secret) | pre-push (+ type/lint/unit/cov/spec-conformance/deliverable-smoke) | all (default; full 15-stage gate, used by CI)").option("--json","emit structured per-stage results (machine-readable: findings with file/line/suggestion, untruncated) \u2014 for agents/CI; cuts RED\u2192fix round-trips").option("--feature ","scope the gate to this feature's modules[] (Gradle monorepos): runs only :project: tasks instead of the root aggregate. No-op for non-Gradle repos or modules-less features").action(vXe),t.command("checkpoint ").description("Record a checkpoint event pinning git HEAD + spec digest for the feature (iron-law \xA72.5)").action(uXe),t.command("done ").description("Mark a feature done ONLY if `clad check --tier=pre-push --strict` is GREEN (flip \u2192 gate \u2192 revert-on-red). Keeps `done` honest.").action(SXe),t.command("oracle [featureId]").description("Print the impl-blind oracle authoring brief (acceptance criteria + signatures, never the implementation). Hand it to a fresh blind sub-agent; record the result with clad_author_oracle. cladding calls no LLM. Use --required to list which done ACs the project policy needs an oracle for.").option("--ac ","restrict the brief to a single acceptance criterion").option("--required","list the done ACs the oracle_policy / require_oracles requires an oracle for (worklist), instead of a brief").option("--cwd ","project root (defaults to .)").action((r,n)=>wXe(r,n)),t.command("rollback ").description("Record a rollback event and print the maintainer-runnable git command for the latest checkpoint").option("-r, --reason ","optional free-text reason recorded on the event payload").action(dXe),t.command("status").description("Render the feature \xD7 stage integrity matrix (business titles; use --internal for raw F-NNN ids)").option("--internal","show internal F-NNN ids and stage codes").option("--json","emit the row model as JSON \u2014 the same feature \xD7 stage integrity matrix rendered to the terminal (columns + per-feature glyph cells), one SSoT for terminal, JSON, and the audit bundle").action($Xe),t.command("context ").description("Print the context slice for one feature \u2014 id (F-\u2026), slug, or module path (F-d2c806)").action(gXe),t.command("impact ").description("Print the blast radius for a change \u2014 what depends on a feature/file + the tests to re-run (F-7794a6bc)").option("--depth ","bound the dependent walk to N hops (default: the full transitive radius)").action((r,n)=>yXe(r,n)),t.command("verdict").description("One-poll loop decision: DONE|ITERATE|ESCALATE|BLOCKED|BOOTSTRAP over the pre-push strict gate + feature statuses (F-2e28cc72). Single gate touch; DONE requires \u22651 non-liveness proof.").option("--json","emit the verdict object as JSON").option("--tier ","gate tier (default pre-push)").action(r=>F7(r,{checkStages:LA})),t.command("infer-deps").description("Suggest feature depends_on edges from the code import graph \u2014 the dependency edges cladding never auto-produced (F-2be3e3bb). Prints reviewable suggestions; does not write the spec.").option("--ambiguity ","emit edges for imports owned by \u2264 N features (default 1 = unambiguous single-owner only)").action(r=>_Xe(r)),t.command("measure").description("Report the search + context efficiency the graph provides per feature \u2014 working-set tokens vs the naive baseline, dependency depth/edges resolved, regression-set coverage (F-16138071). Deterministic; no agent.").option("--json","emit the full report as JSON").option("--sessions","summarize recorded value-delivery telemetry instead \u2014 impact-card fire rate over eligible edits, the per-reason skip histogram, and MCP read-serve counts. Measures DELIVERY (did the surfaces fire), NOT adoption (F-6ba22c5c).").option("--trend [n]","render the last N (default 5) recorded measure snapshots with signed deltas \u2014 spot efficiency drift over time from the deduped .cladding/measure.jsonl ledger (F-39609db4)").action(r=>bXe(r));let e=t.command("graph").description("Render the spec\u2194code\u2194doc knowledge graph for a viewer, or report its shape (F-569f4b37)");return e.command("export").description("Export the graph: mermaid/dot/json to stdout, or an Obsidian vault to --out").option("--format ","mermaid | dot | json | obsidian | html (default: mermaid). html = a single self-contained offline viewer (requires --out)").option("--focus ","restrict to a feature/file node\u2019s neighborhood (id, slug, or module path)").option("--depth ","neighborhood radius around --focus (default: unbounded)").option("--out ","write to a file (or, for obsidian, a vault dir \u2014 default .cladding/graph)").action(r=>cre(r)),e.command("stats").description("Report node/edge counts by kind and the top hubs by degree").action(()=>lre()),e.command("serve").description("Serve a LIVE graph at localhost \u2014 recomputes on each load + auto-reloads on spec/doc changes (F-64a5c159)").option("--port ","port to listen on (default 3000)").action(r=>{ure(r)}),t.command("changelog").description("Render shipped changes since a git ref into human-facing documents (F-904495a5). Default: capability-grouped markdown from feature titles + acceptance sentences (no internal ids). --json emits the deterministic manifest hosts render release notes from; --audit the id-keeping verification table; --catalog the full capability \u2192 feature \u2192 acceptance catalog.").option("--since ","git ref to diff from (default: the latest tag via `git describe --tags --abbrev=0`)").option("--json","print the deterministic ChangelogManifest as JSON (byte-identical across runs on the same state)").option("--audit","print the audit table \u2014 feature | AC | EARS | verification refs, each marked resolved \u2713/\u2717").option("--catalog","print the full capability \u2192 feature \u2192 acceptance listing of the living spec (no git range)").option("--measure","embed the release's own re-derivable measurement \u2014 but ONLY a snapshot taken at the current HEAD; no match renders a not-measured notice, never an older snapshot (F-ede6fa75)").action(r=>jG(r)),t.command("report").description("Render one deterministic review packet for a git range (F-f6cc5e5a) \u2014 spec entry movement (from the changelog), how each acceptance criterion moved, changed source files resolved to their owning features via the reverse index, the tests those features declare, the deduped regression set, and gate + attestation state. For PR reviewers, team-leads, and auditors: it RENDERS, it gates nothing. Byte-identical across two runs on the same repository state.").option("--since ","git ref to diff from (default: the latest tag via `git describe --tags --abbrev=0`)").option("--format ","md (default, the six-section markdown packet) | sarif (SARIF 2.1.0 \u2014 one result per error/warn drift finding, for code-scanning UIs) | json (the raw deterministic model)").action(r=>vX(r)),t.command("bundle").description("Write ONE self-contained HTML audit bundle (F-e940fffe) a non-coder can double-click \u2014 offline, zero network, no CDN, no scripts. Contains the project header + inventory, the feature \xD7 stage matrix, the capability catalog, shipped changes for the range, the audit table with resolved refs, and the attestation summary, under a provenance banner (git HEAD, date, version). Deterministic modulo the date stamp. If no anchor ref resolves, the changelog + audit sections show an omitted notice while the rest still renders.").requiredOption("--out ","destination path for the HTML bundle").option("--since ","git ref to diff shipped changes from (default: the latest tag via `git describe --tags --abbrev=0`)").action(r=>EXe(r)),t.command("route ").description("Classify a natural-language prompt to a verb").action(AXe),t.command("hook ").description("Host hook protocol adapter \u2014 consume one host lifecycle event (SessionStart | UserPromptSubmit | PreToolUse | PostToolUse | Stop) as stdin JSON and print the protocol response on stdout. Always exits 0 so a hook failure never bricks the host session.").action(I7),t.command("serve").description("Run cladding as an MCP server over stdio \u2014 tools/resources/prompts for any MCP client").option("--cwd ","project directory exposed to the client (default cwd)").action(sXe),t.command("doctor").description("Diagnose Claude Code hook liveness/version, lifecycle governance, and LLM dispatcher sentinel misses").option("--cwd ","project directory to read events from (default cwd)").option("--json","emit the raw DoctorReport for tooling; default is the human-readable surface").option("--hosts","smoke-test host CLIs (Claude Code / Gemini / Antigravity / Codex / Cursor) and project wiring \u2192 dated artifact + docs/dogfood/matrix.md. Live LLM prompts run only with consent (CLAD_HOST_SMOKE=1 or --yes); otherwise not-run").option("--yes","grant live-run consent for --hosts (equivalent to CLAD_HOST_SMOKE=1)").option("--matrix-only","regenerate docs/dogfood/matrix.md from the newest host-smoke artifact without any probing").action(r=>{if(r.hosts||r.matrixOnly){QX({cwd:r.cwd,yes:r.yes,matrixOnly:r.matrixOnly});return}HX(r)}),t.command("clarify [answer...]").description("Advance the onboarding Q&A loop. Pass the user's answer to the next pending question as a positional (no quotes needed, free text in any language, e.g. `clad clarify B2B only`); the LLM refines spec/docs based on the full Q-A history and may emit new follow-up questions. Reads/writes `.cladding/onboarding/state.yaml`. Requires `clad init ` to have started a session first.").option("--cwd ","project directory containing .cladding/onboarding/state.yaml (default cwd)").option("--no-llm","force the deterministic interpreter (preserves current artifacts, logs the answer)").option("--json","emit the raw RefineReport for tooling; default is the human-readable surface").action(Gte),t}var TXe=!!globalThis.__CLADDING_BUNDLED,RXe=TXe||import.meta.url===`file://${H.argv[1]}`;RXe&&OXe().parse();export{mXe as TIER_STAGES,OXe as createProgram,hXe as renderNoRunnerGuidance,EXe as runBundleCommand,vXe as runCheckCommand,LA as runCheckStages,uXe as runCheckpointCommand,gXe as runContextCommand,SXe as runDoneCommand,yXe as runImpactCommand,_Xe as runInferDepsCommand,aXe as runInitCommand,bXe as runMeasureCommand,wXe as runOracleCommand,dXe as runRollbackCommand,AXe as runRouteCommand,cXe as runRunCommand,sXe as runServeCommand,fXe as runSetupCommand,$Xe as runStatusCommand,lXe as runSyncCommand,pXe as runUpdateCommand}; diff --git a/plugins/codex/.codex-plugin/plugin.json b/plugins/codex/.codex-plugin/plugin.json index 0d5cc9d7..b3084a61 100644 --- a/plugins/codex/.codex-plugin/plugin.json +++ b/plugins/codex/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "cladding", - "version": "0.9.3", + "version": "0.9.4", "description": "Reference implementation of the Ironclad standard — multi-agent dev harness for OpenAI Codex CLI / IDE / cloud. Exposes spec validation, drift detection, the Iron Law stage runner, and 5 agent personas as Codex skills + an auto-launched MCP server.", "author": { "name": "qwerfunch", diff --git a/plugins/codex/skills/check/SKILL.md b/plugins/codex/skills/check/SKILL.md index fe7bb3ea..a8a755a4 100644 --- a/plugins/codex/skills/check/SKILL.md +++ b/plugins/codex/skills/check/SKILL.md @@ -29,4 +29,6 @@ the project: fast inner-loop feedback while implementing. - `clad check --tier=pre-push --strict` — the full gate (type / lint / unit / cov + drift). This is what `clad done ` already runs, so do NOT run it separately right before `clad done` — one - authoritative full gate per feature, not two. See `docs/feature-cycle.md` § Gate economy. + authoritative full gate per feature, not two. A GREEN run refreshes `spec/attestation.yaml` with the + running Cladding version, strict blocking mode, detector-catalog SHA-256, module hashes, and feature + markers. See `docs/feature-cycle.md` § Gate economy. diff --git a/plugins/codex/skills/doctor/SKILL.md b/plugins/codex/skills/doctor/SKILL.md index 10214faa..5425d651 100644 --- a/plugins/codex/skills/doctor/SKILL.md +++ b/plugins/codex/skills/doctor/SKILL.md @@ -1,5 +1,5 @@ --- -description: Summarise .cladding/events.log.jsonl — sentinel-miss frequency by phase × cause × fallback plus the top missed sentinels. Use when the user asks whether their LLM dispatcher (MCP sampling host, Anthropic SDK, …) is healthy, when scan / drive results look thinner than expected, or as a one-shot triage before tuning model / max_tokens / temperature. Activate only when the connected project contains spec.yaml or the user explicitly names Cladding; ignore ordinary requests in uninitialized projects. +description: Diagnose Cladding runtime health — Claude Code hook liveness and version, CI package pinning, lifecycle governance, and sentinel-miss frequency by phase × cause × fallback. Use when hooks may be silent, CI may float across Cladding releases, scan or run results look thinner than expected, or before tuning the host model or transport. Activate only when the connected project contains spec.yaml or the user explicitly names Cladding; ignore ordinary requests in uninitialized projects. --- # Cladding doctor @@ -7,13 +7,16 @@ description: Summarise .cladding/events.log.jsonl — sentinel-miss frequency by Run `clad doctor` from the project root. The verb is observability — it never mutates the working tree. - `--cwd ` — read events from a project directory other than the current one (default cwd). -- `--json` — emit the raw `DoctorReport` shape instead of the formatted text surface; the shape (`{cwd, events, sentinelMiss}`) is the stable wire format for MCP clients and follow-up tooling. +- `--json` — emit the raw `DoctorReport` shape instead of the formatted text surface; the additive shape (`{cwd, events, sentinelMiss, governance, hooks, ciVersion}`) is the stable wire format for MCP clients and follow-up tooling. The text surface prints: 1. One pulse line with total events and total sentinel-miss count (`pass` when zero misses, `note` otherwise). 2. An event-type breakdown line (one `=` token per non-zero `EventType`). -3. When sentinel-miss events exist: +3. Claude Code hook health: whether the runtime has actually been observed, whether the observed engine version matches the current CLI, and the last firing time (or `never observed`) for session start, prompt submit, before edit, after edit, and session stop. +4. A non-blocking CI warning naming each GitHub Actions workflow that invokes an unversioned or floating `npx cladding` package. Numeric selectors such as `cladding@0.9` and `cladding@0.9.4` stay quiet. +5. Governance counts for gate runs, done attempts and rejections, stop blocks, known-failing Stop exits, blocked fingerprints reproduced by a later gate, and attestation state. +6. When sentinel-miss events exist: - `by phase` / `by cause` / `by fallback` aggregates from the v0.3.39 telemetry payload. - Top-5 missed sentinels (`CONVENTIONS_MD` / `ARCHITECTURE_YAML` / `SCENARIO_FLOWS` / `CAPABILITIES_YAML` / `WHY` / `WHAT` / `PURPOSE`) sorted by count desc, name asc. - Last 3 unique dispatcher error strings (most recent first; errors are truncated to 200 chars at the emit site). @@ -27,6 +30,7 @@ The text surface prints: ## When to run - After `clad init --scan` to confirm the scan refinement ran with full LLM coverage (no `sentinel_miss` events). +- After installing or updating the Claude Code plugin to confirm a new session actually fired the shipped hooks and loaded the current engine. - After `clad run` to confirm the autonomous loop received refined replies from the configured host. - Periodically in CI to track miss rate across sampling-policy changes. - Before reporting "the LLM seems off" to a host (Claude Code / Cursor / Continue) — the breakdown tells you whether the issue is dispatcher transport (`cause: dispatcher_error`) or model output quality (`cause: blank_section`). diff --git a/plugins/codex/skills/init/SKILL.md b/plugins/codex/skills/init/SKILL.md index a7cb3156..1a45dcca 100644 --- a/plugins/codex/skills/init/SKILL.md +++ b/plugins/codex/skills/init/SKILL.md @@ -25,4 +25,6 @@ Do not run `clad init` in a shell from an AI-host onboarding session. Do not use `clad_prepare_init` does not modify the workspace, and `clad_stage_init` writes only ignored runtime state. Never call stage and apply in the same assistant turn. Only `clad_init` writes authored artifacts, after explicit user confirmation plus schema and freshness validation. A stale, malformed, or replayed apply request must be prepared again. +Initialization also creates or appends `spec/index.yaml merge=union` in `.gitattributes`. It preserves every existing attribute and never assigns a merge driver to `spec/attestation.yaml`; the strict gate rewrites that verification record canonically after an ordinary merge. + The raw CLI remains available for terminal, CI, offline, and explicitly configured SDK automation; it is not the primary host onboarding path. diff --git a/plugins/gemini-cli/commands/init.toml b/plugins/gemini-cli/commands/init.toml index 760cf3d9..ab836d1c 100644 --- a/plugins/gemini-cli/commands/init.toml +++ b/plugins/gemini-cli/commands/init.toml @@ -22,5 +22,7 @@ Do not run `clad init` in a shell from an AI-host onboarding session. Do not use `clad_prepare_init` does not modify the workspace, and `clad_stage_init` writes only ignored runtime state. Never call stage and apply in the same assistant turn. Only `clad_init` writes authored artifacts, after explicit user confirmation plus schema and freshness validation. A stale, malformed, or replayed apply request must be prepared again. +Initialization also creates or appends `spec/index.yaml merge=union` in `.gitattributes`. It preserves every existing attribute and never assigns a merge driver to `spec/attestation.yaml`; the strict gate rewrites that verification record canonically after an ordinary merge. + The raw CLI remains available for terminal, CI, offline, and explicitly configured SDK automation; it is not the primary host onboarding path. ''' diff --git a/plugins/gemini-cli/gemini-extension.json b/plugins/gemini-cli/gemini-extension.json index f3f74882..4f197a2e 100644 --- a/plugins/gemini-cli/gemini-extension.json +++ b/plugins/gemini-cli/gemini-extension.json @@ -1,6 +1,6 @@ { "name": "cladding", - "version": "0.9.3", + "version": "0.9.4", "description": "Reference implementation of the Ironclad standard — multi-agent dev harness for Gemini CLI. Exposes spec validation, drift detection, 15 Iron Law stages, and 5 agent personas as custom commands + an auto-launched MCP server.", "contextFileName": "GEMINI.md", "mcpServers": { diff --git a/scripts/build-plugin.mjs b/scripts/build-plugin.mjs index 37db48f3..6af41481 100644 --- a/scripts/build-plugin.mjs +++ b/scripts/build-plugin.mjs @@ -26,7 +26,9 @@ // The src side stays canonical — every loadPersona() call in the // runtime reads from src/agents. The drift detector enforces lockstep. // -// Run: `npm run build:plugin` or as part of `npm run build`. +// Run through `npm run build:plugin`, which rebuilds the ignored root dist +// from source before this script copies it. `npm run build` already invokes +// build.mjs immediately before this file. import { chmodSync, @@ -118,11 +120,11 @@ try { // serve]` (inline mcpServers — the reliable spot for ${CLAUDE_PLUGIN_ROOT} // expansion, side-stepping the .mcp.json expansion bug, claude-code#9427). // -// build.mjs runs before this script under `npm run build`, so dist/clad.js + -// dist/schema.json + dist/agents/ already exist. The bundle is committed -// (same model as the agent mirrors above) because the git source IS what users -// install. Only the Claude Code lane is bundled — Codex/Gemini do not expand -// ${CLAUDE_PLUGIN_ROOT}, so they keep the global `clad` command. +// build.mjs runs before this script under both public npm build commands, so +// dist/clad.js + dist/schema.json + dist/agents/ are source-fresh. The bundle +// is committed (same model as the agent mirrors above) because the git source +// IS what users install. Only the Claude Code lane is bundled — Codex/Gemini +// do not expand ${CLAUDE_PLUGIN_ROOT}, so they keep the global `clad` command. const CLAUDE_DIST = `${CLAUDE_PLUGIN_DIR}/dist`; if (existsSync('dist/clad.js')) { mkdirSync(`${CLAUDE_DIST}/agents`, {recursive: true}); diff --git a/skills/check/SKILL.md b/skills/check/SKILL.md index fe7bb3ea..a8a755a4 100644 --- a/skills/check/SKILL.md +++ b/skills/check/SKILL.md @@ -29,4 +29,6 @@ the project: fast inner-loop feedback while implementing. - `clad check --tier=pre-push --strict` — the full gate (type / lint / unit / cov + drift). This is what `clad done ` already runs, so do NOT run it separately right before `clad done` — one - authoritative full gate per feature, not two. See `docs/feature-cycle.md` § Gate economy. + authoritative full gate per feature, not two. A GREEN run refreshes `spec/attestation.yaml` with the + running Cladding version, strict blocking mode, detector-catalog SHA-256, module hashes, and feature + markers. See `docs/feature-cycle.md` § Gate economy. diff --git a/skills/doctor/SKILL.md b/skills/doctor/SKILL.md index 10214faa..5425d651 100644 --- a/skills/doctor/SKILL.md +++ b/skills/doctor/SKILL.md @@ -1,5 +1,5 @@ --- -description: Summarise .cladding/events.log.jsonl — sentinel-miss frequency by phase × cause × fallback plus the top missed sentinels. Use when the user asks whether their LLM dispatcher (MCP sampling host, Anthropic SDK, …) is healthy, when scan / drive results look thinner than expected, or as a one-shot triage before tuning model / max_tokens / temperature. Activate only when the connected project contains spec.yaml or the user explicitly names Cladding; ignore ordinary requests in uninitialized projects. +description: Diagnose Cladding runtime health — Claude Code hook liveness and version, CI package pinning, lifecycle governance, and sentinel-miss frequency by phase × cause × fallback. Use when hooks may be silent, CI may float across Cladding releases, scan or run results look thinner than expected, or before tuning the host model or transport. Activate only when the connected project contains spec.yaml or the user explicitly names Cladding; ignore ordinary requests in uninitialized projects. --- # Cladding doctor @@ -7,13 +7,16 @@ description: Summarise .cladding/events.log.jsonl — sentinel-miss frequency by Run `clad doctor` from the project root. The verb is observability — it never mutates the working tree. - `--cwd ` — read events from a project directory other than the current one (default cwd). -- `--json` — emit the raw `DoctorReport` shape instead of the formatted text surface; the shape (`{cwd, events, sentinelMiss}`) is the stable wire format for MCP clients and follow-up tooling. +- `--json` — emit the raw `DoctorReport` shape instead of the formatted text surface; the additive shape (`{cwd, events, sentinelMiss, governance, hooks, ciVersion}`) is the stable wire format for MCP clients and follow-up tooling. The text surface prints: 1. One pulse line with total events and total sentinel-miss count (`pass` when zero misses, `note` otherwise). 2. An event-type breakdown line (one `=` token per non-zero `EventType`). -3. When sentinel-miss events exist: +3. Claude Code hook health: whether the runtime has actually been observed, whether the observed engine version matches the current CLI, and the last firing time (or `never observed`) for session start, prompt submit, before edit, after edit, and session stop. +4. A non-blocking CI warning naming each GitHub Actions workflow that invokes an unversioned or floating `npx cladding` package. Numeric selectors such as `cladding@0.9` and `cladding@0.9.4` stay quiet. +5. Governance counts for gate runs, done attempts and rejections, stop blocks, known-failing Stop exits, blocked fingerprints reproduced by a later gate, and attestation state. +6. When sentinel-miss events exist: - `by phase` / `by cause` / `by fallback` aggregates from the v0.3.39 telemetry payload. - Top-5 missed sentinels (`CONVENTIONS_MD` / `ARCHITECTURE_YAML` / `SCENARIO_FLOWS` / `CAPABILITIES_YAML` / `WHY` / `WHAT` / `PURPOSE`) sorted by count desc, name asc. - Last 3 unique dispatcher error strings (most recent first; errors are truncated to 200 chars at the emit site). @@ -27,6 +30,7 @@ The text surface prints: ## When to run - After `clad init --scan` to confirm the scan refinement ran with full LLM coverage (no `sentinel_miss` events). +- After installing or updating the Claude Code plugin to confirm a new session actually fired the shipped hooks and loaded the current engine. - After `clad run` to confirm the autonomous loop received refined replies from the configured host. - Periodically in CI to track miss rate across sampling-policy changes. - Before reporting "the LLM seems off" to a host (Claude Code / Cursor / Continue) — the breakdown tells you whether the issue is dispatcher transport (`cause: dispatcher_error`) or model output quality (`cause: blank_section`). diff --git a/skills/init/SKILL.md b/skills/init/SKILL.md index a7cb3156..1a45dcca 100644 --- a/skills/init/SKILL.md +++ b/skills/init/SKILL.md @@ -25,4 +25,6 @@ Do not run `clad init` in a shell from an AI-host onboarding session. Do not use `clad_prepare_init` does not modify the workspace, and `clad_stage_init` writes only ignored runtime state. Never call stage and apply in the same assistant turn. Only `clad_init` writes authored artifacts, after explicit user confirmation plus schema and freshness validation. A stale, malformed, or replayed apply request must be prepared again. +Initialization also creates or appends `spec/index.yaml merge=union` in `.gitattributes`. It preserves every existing attribute and never assigns a merge driver to `spec/attestation.yaml`; the strict gate rewrites that verification record canonically after an ordinary merge. + The raw CLI remains available for terminal, CI, offline, and explicitly configured SDK automation; it is not the primary host onboarding path. diff --git a/spec.yaml b/spec.yaml index 6afa3f68..efe3dfa1 100644 --- a/spec.yaml +++ b/spec.yaml @@ -11,7 +11,7 @@ project: name: cladding language: typescript description: "Reference implementation of the Ironclad harness for AI-coupled software." - version: "0.9.3" + version: "0.9.4" repository: "https://github.com/qwerfunch/cladding" intent_summary: "Make AI-coupled development measurably safer and more honest — 41 drift detectors + 4-tier SSoT governance + A/B-measurable cladding-vs-vanilla evaluation." deliverable: @@ -54,7 +54,7 @@ project: # Auto-maintained by `clad sync` (F-5b9f9f). Do not edit by hand. inventory: - features: 273 + features: 281 scenarios: 2 capabilities: 6 - test_files: 249 + test_files: 259 diff --git a/spec/_doc-links.yaml b/spec/_doc-links.yaml index ede2f8f7..e98e261d 100644 --- a/spec/_doc-links.yaml +++ b/spec/_doc-links.yaml @@ -23,7 +23,7 @@ docs: "docs/gate-stages.md": doc_links: ["src/stages/detectors/README.md"] "docs/glossary.md": - features: [F-1d23a6, F-6ba22c5c, F-7ce18e, F-b84c38] + features: [F-1aab1bba, F-1d23a6, F-6ba22c5c, F-7ce18e, F-b84c38] "docs/knowledge-graph/design.md": features: [F-02343cd1, F-64a5c159, F-77f7ead0] "docs/multi-provider-roadmap.md": diff --git a/spec/attestation.yaml b/spec/attestation.yaml index 8c131933..8ab42183 100644 --- a/spec/attestation.yaml +++ b/spec/attestation.yaml @@ -2,6 +2,8 @@ # `clad check --tier=pre-push --strict` gate — the file's one honest author. # Do not edit by hand. # +# policy: verifier identity: Cladding version, strict blocking, +# and SHA-256 of the ordered detector catalog. # attested_modules: one line per module file across all done features, # value = sha256 of that file's bytes (16 hex). Editing a # file moves exactly its own line — not every co-owning @@ -13,27 +15,31 @@ # Merge conflict here? NEVER hand-resolve the hashes — keep either side and run # `clad check --tier=pre-push --strict`; the GREEN gate rewrites the truth. # Content-anchored: survives fresh clones and squash/rebase. +policy: + cladding: "0.9.4" + blocking: strict + detectors_sha256: 133c1ab691da7642223bcfe93ecdf4dc253f1aba08ee4e1bad865e427a2c37db attested_modules: - .claude/settings.json: d0bba3583aef0960 + .claude/settings.json: 08a64351770badf4 .github/workflows/ci.yml: 8ea99219cb80df60 - .gitignore: 1294975ba3b47043 - CHANGELOG.md: f2d8bae463e3279e + .gitignore: d311656aff3813ca + CHANGELOG.md: 5f869dbb27431e60 CLAUDE.md: 9f2fa4edd5c6df80 GOVERNANCE.md: 21cc28eaaf637a20 - README.html: 042398234df7c6db - README.ja.md: c0e21f65682fdddf - README.ko.html: c6c9c457101a7faa - README.ko.md: d5c8665fb5126908 - README.md: 988329327e2b04dd - README.zh.md: ac6e59d1dfb425da + README.html: e648da173a27d318 + README.ja.md: bda546d9642b960d + README.ko.html: 105a0068180d3892 + README.ko.md: 3e1293e9f5d5bcc7 + README.md: 9cba3b899b969660 + README.zh.md: 624317af25d6ab0e SECURITY.md: df1d0c80304b2f28 bin/clad: 77b80666665dd1b0 - conformance/fixtures.yaml: 4b1b94dae1cd20b0 - conformance/runner.ts: b9c9e71df85d382e + conformance/fixtures.yaml: 5b461bb43a79a983 + conformance/runner.ts: 5e638e070dbb10c2 docs/README.md: 5672e5726104d845 docs/ab-evaluation-extended/README.md: f690562df2e5ec06 - docs/ab-evaluation-extended/scenarios/dashboard/report.md: 9ad86472f76c2c29 - docs/ab-evaluation-extended/scenarios/task-manager/report.md: fe3c789cc9b88eb1 + docs/ab-evaluation-extended/scenarios/dashboard/report.md: a656cad8c8ac2772 + docs/ab-evaluation-extended/scenarios/task-manager/report.md: 91df11ca4e9bed26 docs/ab-evaluation-extended/summary.md: d16f16836f94bd80 docs/ab-evaluation/README.md: 2467808b9871dcf0 docs/ab-evaluation/case-doverunner-scale.md: 2a435b6855823d41 @@ -41,7 +47,7 @@ attested_modules: docs/ab-evaluation/case-existing-adoption.md: 240a7c641da50a42 docs/ab-evaluation/case-graph-efficiency.md: 83d3956d14a1517d docs/ab-evaluation/case-iterative-vs-fixed-vapt.md: 1d242b8b6071f343 - docs/ab-evaluation/case-payment-saas.md: a316271b319816f6 + docs/ab-evaluation/case-payment-saas.md: e29406c4f5d179b2 docs/ab-evaluation/case-working-set-landmine.md: b4f44dc463e99722 docs/ab-evaluation/summary.md: 59e527a531f13209 docs/b1-adoption-protocol.md: a041d8ad5ba1447f @@ -56,7 +62,7 @@ attested_modules: docs/dogfood/cursor-agent-2026-07-15.md: a2f621fd0c3b57af docs/dogfood/gemini-cli-2026-05-20.md: 2da1ba66c4f108f0 docs/feature-cycle.md: e1847cc9fe9b6eb6 - docs/glossary.md: fc7258d4d3dcb9a2 + docs/glossary.md: 62175865fa2bf721 docs/img/en/ecosystem.svg: ed14d1d17f088b00 docs/img/en/independence.svg: 1b3048b3b5206483 docs/img/en/relationship.svg: c7a24203925b4664 @@ -66,26 +72,26 @@ attested_modules: docs/img/ko/relationship.svg: 9ec8fb2254978f37 docs/img/zh/independence.svg: 073303a42e601f7c docs/multi-provider-roadmap.md: 1e5cf27ea1b18d06 - docs/refinement-backlog.md: 918426e582bf2739 + docs/refinement-backlog.md: 51469bde4d9dddfd docs/setup.md: a5c062651d267983 - docs/spec-ids-multi-dev.md: 28d58e84879f58b1 + docs/spec-ids-multi-dev.md: ee52e431278e1c1a docs/ssot-model.md: 66b9439e2f71ac4b docs/ssot-testing.md: abf3b2bd5acb29a1 - package-lock.json: 505b6ea10c37fcf6 - package.json: bc72ea4dbf16fc7d - plugins/claude-code/.claude-plugin/plugin.json: e46cfdf3bf480696 + package-lock.json: 446ffb2632fbb457 + package.json: 6e246e66421c0d84 + plugins/claude-code/.claude-plugin/plugin.json: 0b3e617b8d8ea59a plugins/claude-code/agents/developer.md: 3002b4ef69ddab43 plugins/claude-code/agents/observability.md: 637fde18c012e2a7 plugins/claude-code/agents/orchestrator.md: 1b758de0bdab8eb0 plugins/claude-code/agents/planner.md: 2ca87ed1fe99c913 plugins/claude-code/agents/reviewer.md: cdf7469a3e58b438 - plugins/claude-code/commands/init.md: 5529b13d0f1ab4bf + plugins/claude-code/commands/init.md: cc23bc61906cd39d plugins/claude-code/hooks/hooks.json: 42321ead26fb1da8 - plugins/codex/.codex-plugin/plugin.json: b662ba85804e6abb + plugins/codex/.codex-plugin/plugin.json: 0d183985e538e27c plugins/codex/.mcp.json: 43e3f4b2af24aa18 - plugins/codex/skills/check/SKILL.md: 6a665422af510e72 + plugins/codex/skills/check/SKILL.md: 8e9cf445c4263393 plugins/codex/skills/developer/SKILL.md: 3002b4ef69ddab43 - plugins/codex/skills/init/SKILL.md: 5529b13d0f1ab4bf + plugins/codex/skills/init/SKILL.md: cc23bc61906cd39d plugins/codex/skills/observability/SKILL.md: 637fde18c012e2a7 plugins/codex/skills/orchestrator/SKILL.md: 1b758de0bdab8eb0 plugins/codex/skills/planner/SKILL.md: 2ca87ed1fe99c913 @@ -96,20 +102,20 @@ attested_modules: plugins/codex/skills/sync/SKILL.md: 775c0f990a52a3d9 plugins/gemini-cli/GEMINI.md: ba08eaf2cd557a65 plugins/gemini-cli/commands/README.md: 3527d771578431bd - plugins/gemini-cli/commands/init.toml: e7f310fd7af23f95 - plugins/gemini-cli/gemini-extension.json: 082af8a03ae1601d - scripts/build-plugin.mjs: 7fabe2b6301b142a + plugins/gemini-cli/commands/init.toml: ab31dfdb28b474d2 + plugins/gemini-cli/gemini-extension.json: 8851b0ac89a34f74 + scripts/build-plugin.mjs: d171b326ed61f40b scripts/build.mjs: 3a4b204063024ef1 scripts/migrate-dogfood-v0.3.16.mjs: 1e265fb370019996 scripts/shard-spec.ts: 0c728bbc1e869421 scripts/test-count.d.mts: a392f5dea372a40e scripts/test-count.mjs: aea2620221c8d5ff scripts/version-bump.mjs: 770b066b8279db39 - skills/check/SKILL.md: 6a665422af510e72 + skills/check/SKILL.md: 8e9cf445c4263393 skills/checkpoint/SKILL.md: f723e8cfb8286a64 skills/clarify/SKILL.md: 5d08bbb821258d03 - skills/doctor/SKILL.md: 6581c6c900c72d68 - skills/init/SKILL.md: 5529b13d0f1ab4bf + skills/doctor/SKILL.md: e530159f5d3a7864 + skills/init/SKILL.md: cc23bc61906cd39d skills/oracle/SKILL.md: 11e111ac0a4963c1 skills/rollback/SKILL.md: d472dc3a562b347b skills/route/SKILL.md: 5958830fef280c67 @@ -117,7 +123,7 @@ attested_modules: skills/serve/SKILL.md: f08bbdbbfeb05041 skills/status/SKILL.md: 09faadc50b3449da skills/sync/SKILL.md: 775c0f990a52a3d9 - spec.yaml: 35b159a6c3949112 + spec.yaml: 9b979cd4e7d137d2 spec/README.md: 7c257426396d435c spec/architecture.yaml: f0888480405a13a8 spec/features/: a4d0f0eb87fed960 @@ -150,17 +156,19 @@ attested_modules: src/cli: a4d0f0eb87fed960 src/cli/benchmark.ts: 77f84d2a898d724f src/cli/changelog.ts: 2de1adb009b89ab4 - src/cli/clad.ts: a02fe02bcb5e942d + src/cli/ci-version.ts: 9fce2c2d7415b4ca + src/cli/clad.ts: 8705b384a37f38e1 src/cli/clarify.ts: f17177969d5b75ff src/cli/doctor-hosts.ts: 1f0c2cec5a310b81 - src/cli/doctor.ts: b98b955fe75e7f7e - src/cli/done.ts: b4c8ed409f001487 + src/cli/doctor.ts: 50d904fdbfe7e942 + src/cli/done.ts: 4a5dd13769252f51 src/cli/enforcement-advisory.ts: 395c5be696e88b5c src/cli/graph-serve.ts: 23e6e389225d0f98 src/cli/graph.ts: bab410061b8c746a - src/cli/hook.ts: 59d5fddd52d330ac + src/cli/hook-health.ts: e103afb67ecde8bb + src/cli/hook.ts: 59a2f8dbcfbd2c60 src/cli/host-onboarding.ts: b046571d4be7280c - src/cli/init.ts: 91cf7be2b7427fbf + src/cli/init.ts: b074f84900f3e10c src/cli/intent-from-path.ts: e69862821d979f22 src/cli/measure.ts: 3a562f16589e26c2 src/cli/report.ts: ee7d35b6c36dfa76 @@ -178,13 +186,14 @@ attested_modules: src/cli/scan/roots.ts: 7475eed8c9836531 src/cli/scan/scenarios.ts: 6c2a4ce3b469a668 src/cli/scan/stats.ts: 00c737b7b7acad97 - src/cli/scan/thresholds.ts: ec0047b894a6aa6a + src/cli/scan/thresholds.ts: 1b4ef8c865ca1ae1 src/cli/scan/types.ts: ea0170aa88c1c14a src/cli/scan/walker.ts: 33e4448e365e47c6 src/cli/update.ts: b0151396c9a0f6ca src/cli/verdict.ts: 85a4ef27292b9169 src/core/checkpoint.ts: 63300c2764533b6c src/core/git-ops.ts: c144e5cc253822b3 + src/core/language-evidence.ts: eaccacbbf14020e8 src/core/postmortem.ts: 73be29d5e8a16fd4 src/core/telemetry-summary.ts: 6782bfaa6c3ecfa6 src/drive: a4d0f0eb87fed960 @@ -192,8 +201,9 @@ attested_modules: src/drive/halt.ts: 386dd57f84f8e297 src/drive/loop.ts: c37e15ece8e2ae41 src/events: a4d0f0eb87fed960 - src/events/log.ts: ed70cf9bfeb2eaf0 + src/events/log.ts: b70905904b07c7ea src/events/session-report.ts: d0b34f848c360334 + src/events/stop-telemetry.ts: 6b8bbc1b17379aa6 src/graph/layout3d.ts: fdbf08bacad2c049 src/graph/model.ts: 9dfae1cb48bfe3d5 src/graph/render.ts: fd228d5929fd0b47 @@ -209,8 +219,9 @@ attested_modules: src/hitl/independence.ts: 202f4e5ef8bc69e3 src/init/agents-md.ts: 5369a15847ce1ae7 src/init/git-hook.ts: b77910b0df392cbf + src/init/gitignore-policy.ts: 2c3f278e8779e0c6 src/init/host-instructions.ts: c598f8598d8d1cd4 - src/init/host-setup.ts: 158cc9306a746da1 + src/init/host-setup.ts: d4d7c55f16e43dc3 src/optimizer: a4d0f0eb87fed960 src/optimizer/code-excerpt.ts: e2c4598efcd28d2a src/optimizer/context-slice.ts: b5864aaed1e7ae48 @@ -234,9 +245,9 @@ attested_modules: src/report/sarif.ts: 71e97aceeb0a4473 src/router: a4d0f0eb87fed960 src/router/intent.ts: 430590f761b891a6 - src/serve/server.ts: 0a76fefb0aca1434 + src/serve/server.ts: 6a46b2ee32229b7c src/spec: a4d0f0eb87fed960 - src/spec/attestation.ts: 294a1e99c42d4aef + src/spec/attestation.ts: bacd18efacb55615 src/spec/cli.ts: 7a9bcd0f66677810 src/spec/deliverable-detect.ts: 9206a91bf5e84723 src/spec/doc-references.ts: 40e844b5b73467aa @@ -249,17 +260,17 @@ attested_modules: src/spec/reverse-index.ts: fa54d7203a02799a src/spec/schema.json: 848951cd01d7f82f src/spec/test-ref-repair.ts: 5ce823b479aaaca3 - src/spec/types.ts: 5799bc9fc1e00553 + src/spec/types.ts: e8a195929f114491 src/spec/validate.ts: db88ca6512ab363a src/stages: a4d0f0eb87fed960 src/stages/README.md: c79d2bced8c8b8d8 src/stages/arch.ts: 268422e53c6d20bb src/stages/audit.ts: 3ba117606f8a81a1 src/stages/commit.ts: f6b6836af0a4d96c - src/stages/cov.ts: 3dbe8381e374e8c0 + src/stages/cov.ts: 4529f5e80bda08fd src/stages/deliverable-smoke.ts: 9ecfd4210e6ec5c0 src/stages/detector-result-cache.ts: 93ea6af02ef361c5 - src/stages/detectors/README.md: 12e8d24351eef05c + src/stages/detectors/README.md: 3fe2c865aa2adcba src/stages/detectors/absence-of-governance.ts: 954d8ce5c45b3b32 src/stages/detectors/ac-drift.ts: 1bceeae9ee99080b src/stages/detectors/ac-duplicate-within-feature.ts: 652ad48c8cd1ab2e @@ -277,7 +288,7 @@ attested_modules: src/stages/detectors/hardcoded-secret.ts: d9fb55e3d2e429b6 src/stages/detectors/harness-integrity.ts: c9717bc296d6c11d src/stages/detectors/hollow-governance.ts: 57d3f25c421f993b - src/stages/detectors/host-claim-drift.ts: aad755cec4ce24d0 + src/stages/detectors/host-claim-drift.ts: a03b67342b854bd5 src/stages/detectors/id-collision.ts: 9292f2dac0578276 src/stages/detectors/index.ts: bb8d9398ea726cf5 src/stages/detectors/inferable-depends-on.ts: 29dbc744efe3df00 @@ -299,8 +310,8 @@ attested_modules: src/stages/detectors/stale-specification.ts: 0fe84db592fd406d src/stages/detectors/stale-tests.ts: caf59404d1282201 src/stages/detectors/status-drift.ts: 9cc5cf3f9b62ea00 - src/stages/detectors/tech-stack-mismatch.ts: 099162aff2c2966b - src/stages/detectors/unmapped-artifact.ts: b29f7e277d8187ae + src/stages/detectors/tech-stack-mismatch.ts: 4da504acb67aaa86 + src/stages/detectors/unmapped-artifact.ts: b46ec1bd013dcce5 src/stages/detectors/untested-ac.ts: 90725ef1fc9245d8 src/stages/detectors/unverified-ac.ts: 6887c4d699afaad5 src/stages/detectors/with-spec.ts: dcf3205e8d563574 @@ -309,7 +320,7 @@ attested_modules: src/stages/finding-parser.ts: d9cd56dbe3c3b9a7 src/stages/graph-health.ts: a294f06796b0e293 src/stages/junit-report.ts: f8466dc1e00140f1 - src/stages/lint.ts: e9c4505e587e6088 + src/stages/lint.ts: e2bd76900a583983 src/stages/perf.ts: 2b27c12427f65b2e src/stages/secret.ts: b90abc0e00c86219 src/stages/skip-policy.ts: 1a6412d708561cf0 @@ -323,32 +334,32 @@ attested_modules: src/stages/toolchain/module-scope.ts: 88358ec3b84eedd3 src/stages/toolchain/scoped-command.ts: f2dd6410c063279f src/stages/toolchain/types.ts: 05f018fb3dddc321 - src/stages/type.ts: 0ac37e45b407446d - src/stages/types.ts: 95e8c9e13187d85b + src/stages/type.ts: 56c43d7954c25db3 + src/stages/types.ts: ccc885299871e57f src/stages/uat.ts: 62ec3e37a124f8c5 - src/stages/unit.ts: b503350b0e5c7e5a - src/stages/util.ts: 7c49de3250816de8 + src/stages/unit.ts: 7471a2cca0c969d6 + src/stages/util.ts: c9e18d2c9cd90dba src/stages/vacuous-tests.ts: 8e71b81e151325af src/stages/visual.ts: 2b60dd991fa8124e src/ui: a4d0f0eb87fed960 src/ui/panel.ts: 8b78cb14dafb28fb src/ui/pulse.ts: ee4255f5c6e49f51 - src/ui/softShell.ts: f21a30930c164afd - src/verdict/gate-progress.ts: ac75e3082cc97a40 + src/ui/softShell.ts: a733d024692689a2 + src/verdict/gate-progress.ts: 41b677e10596ea42 src/verdict/verdict.ts: 2dcfb0e7408bd28d tests/adapters/anthropic.test.ts: fa2fc7faf032a782 tests/adapters/index.test.ts: 4454e6b4ea05a74f tests/adapters/transport.test.ts: 68f22e9e8df7b813 tests/agents/loader.test.ts: a7df7b1c9a95d37d tests/cli/benchmark.test.ts: b4a87289605ee75f - tests/cli/clad.test.ts: 95a6303c6d9437e2 - tests/cli/gate-golden-matrix.test.ts: 39cf615407a55abe - tests/cli/init.test.ts: 3428a89708fc9330 + tests/cli/clad.test.ts: 4413920b79b15ee0 + tests/cli/gate-golden-matrix.test.ts: 81d88e1cd40723fa + tests/cli/init.test.ts: e88394472a0b95b3 tests/cli/intent-onboarding.test.ts: 0681b98ce2e74c22 tests/conformance/registry.test.ts: 018b1e5c0d8d4baf tests/drive/loop.test.ts: ae49bcfa745a8cdb - tests/events/log.test.ts: 15e6d04c72431bfb - tests/init/git-hook.test.ts: cef479cfb759bbe8 + tests/events/log.test.ts: 221f74acfdb7f7c0 + tests/init/git-hook.test.ts: 6e43b2a970e5c39b tests/integration/loop-real-transport.test.ts: 7bd5bfa97eca28c6 tests/integration/multi-dev-merge.test.ts: 1ba5aef6c649b6c7 tests/optimizer/preamble.test.ts: 806d479c41473d22 @@ -424,13 +435,13 @@ attested_modules: tests/stages/stale-specification.test.ts: 09bd06db377d890c tests/stages/stale-tests.test.ts: 1467ceedb8019e86 tests/stages/status-drift.test.ts: cff1092eeb23c268 - tests/stages/tech-stack-mismatch.test.ts: 878436ffd2f94c97 + tests/stages/tech-stack-mismatch.test.ts: 57c435b76972c055 tests/stages/toolchain.test.ts: 200184f572abcf88 tests/stages/toolchain/gate-config.test.ts: aef5813a6591b153 tests/stages/type.test.ts: b57cf7455cae3b32 tests/stages/uat.test.ts: 29c5bf3e7f3abc35 tests/stages/unit.test.ts: 97781210eb81bb25 - tests/stages/unmapped-artifact.test.ts: 6bfdae66990fd63a + tests/stages/unmapped-artifact.test.ts: d29ba5a32abadcc9 tests/stages/util.test.ts: a162cbe069c85f41 tests/stages/visual.test.ts: dd819e7d25586b92 tests/ui/panel.test.ts: ad9ea207f34b1c51 @@ -537,6 +548,7 @@ attested_features: F-17df0a: ok F-18e951: ok F-195cb59e: ok + F-1aab1bba: ok F-1c9166: ok F-1d23a6: ok F-1e7a10c3: ok @@ -613,6 +625,7 @@ attested_features: F-836a90: ok F-8476ccb1: ok F-876b6f48: ok + F-87bb7ed3: ok F-898783ee: ok F-8f419e: ok F-904495a5: ok @@ -622,6 +635,7 @@ attested_features: F-96250595: ok F-96700032: ok F-96d1f69d: ok + F-96fa5622: ok F-987be195: ok F-99c6e5: ok F-9a3b61: ok @@ -629,17 +643,20 @@ attested_features: F-9b643e: ok F-9d168287: ok F-9d8ece66: ok + F-9e1279d4: ok F-a04cd9: ok F-a4085adf: ok F-a4b512: ok F-a5228c: ok F-aa7197: ok + F-abd10f3c: ok F-ae61c1: ok F-aee1da: ok F-aee61f: ok F-af45042a: ok F-af96b1: ok F-b010427b: ok + F-b0c2e724: ok F-b0c8ba2c: ok F-b0f898a6: ok F-b2094740: ok @@ -659,6 +676,7 @@ attested_features: F-bdcd90: ok F-be5306eb: ok F-c037ae: ok + F-c17e1edc: ok F-c2c996: ok F-c3747d7d: ok F-c48eb2: ok @@ -668,6 +686,7 @@ attested_features: F-c6a32fff: ok F-c6c3daaf: ok F-c8aef8: ok + F-caff8598: ok F-cd0415: ok F-cfba0c: ok F-d12edf: ok diff --git a/spec/features/F-013.yaml b/spec/features/F-013.yaml index 29b51abc..0d915546 100644 --- a/spec/features/F-013.yaml +++ b/spec/features/F-013.yaml @@ -10,9 +10,13 @@ depends_on: acceptance_criteria: - id: AC-021 ears: event - condition: when spec.project.language differs from the toolchain-detected language - action: emit a warn finding - response: stage_1.3 surfaces but does not fail on this finding alone - text: When spec.project.language differs from the language resolved by the - toolchain manifest chain, the detector shall emit a warn-severity finding. + condition: when the declared spec.project.language is absent from the observed + sources with at least five classified files + action: emit a warn finding naming the observed distribution + response: stage_1.3 surfaces but does not fail on this finding alone; the + evidence model (vocabulary, floor, minority band) is owned by F-9e1279d4 + text: When the declared language is absent from the observed source set with + at least five classified files, the detector shall emit a warn-severity + finding naming the observed distribution (amended 2026-08-26 — the manifest + chain is no longer consulted for identity). evidence_refs: [fixture:F-013_AC-021] diff --git a/spec/features/ac-hash-ids-a04cd9.yaml b/spec/features/ac-hash-ids-a04cd9.yaml index 2856347b..03ab4097 100644 --- a/spec/features/ac-hash-ids-a04cd9.yaml +++ b/spec/features/ac-hash-ids-a04cd9.yaml @@ -25,7 +25,12 @@ acceptance_criteria: test_refs: [tests/spec/new.test.ts] - id: AC-003 ears: ubiquitous - action: 'mark architecture layer.modules as advisory and stop the LLM onboarding prompts from emitting it, since ARCHITECTURE_FROM_SPEC does not consume it' - response: 'the dead glob field is removed from the two onboarding prompts and the type documents it as advisory-not-enforced; full consumption is a tracked follow-up rather than a hidden dead link' - text: The system shall not generate the unconsumed architecture layer.modules field and shall document it as advisory, so the schema does not invite a link the detector cannot follow. + action: 'stop the LLM onboarding prompts from emitting architecture layer.modules, and document exactly who consumes it' + response: 'the glob field is removed from the two onboarding prompts; the tracked follow-up landed in F-87bb7ed3, which made UNMAPPED_ARTIFACT consume the declared globs as that layer''s scan universe, while ARCHITECTURE_FROM_SPEC still does not read it — the type comment names both facts' + text: The system shall not generate the architecture layer.modules field from onboarding prompts and shall document its consumers precisely, so the schema neither invites a dead link nor hides a live one. + notes: | + ## Why (amended 2026-08-26) + Originally the field was advisory because no detector consumed it. + F-87bb7ed3 (AC-96ff696f) made UNMAPPED_ARTIFACT consume declared layer + globs; this criterion's prose is updated so the two entries agree. test_refs: [tests/spec/new.test.ts] diff --git a/spec/features/attestation-policy-stamp-caff8598.yaml b/spec/features/attestation-policy-stamp-caff8598.yaml new file mode 100644 index 00000000..3d5372db --- /dev/null +++ b/spec/features/attestation-policy-stamp-caff8598.yaml @@ -0,0 +1,50 @@ +id: F-caff8598 +slug: attestation-policy-stamp +title: "Verification policy identity and generated merge attributes" +status: done +modules: + - src/spec/attestation.ts + - src/cli/clad.ts + - src/cli/init.ts + - docs/spec-ids-multi-dev.md +acceptance_criteria: + - id: AC-a4d41de9 + ears: event + condition: "when a GREEN strict pre-push or all gate writes spec/attestation.yaml" + action: "prepend a deterministic policy section carrying the running Cladding version, blocking=strict, and a full SHA-256 over the ordered detector catalog identity" + response: "the committed verification record says which engine and detector policy earned the stamp instead of recording module freshness without its verifier" + text: "When a strict GREEN gate attests the tree, the system shall stamp the running Cladding version, strict blocking mode, and deterministic detector-catalog SHA-256 alongside the module and feature evidence." + test_refs: ["tests/spec/attestation-policy.test.ts#writes and reads the policy stamp deterministically", "tests/cli/gate-golden-matrix.test.ts#a plain GREEN strict pre-push run stamps policy identity; non-strict does not"] + - id: AC-734d8d3b + ears: state + condition: "while reading an attestation written before the policy section existed" + action: "return a null policy while preserving all v1 and v2 feature freshness verdicts" + response: "upgrading adopters need no migration command and old verification evidence remains readable" + text: "While an attestation has no policy section, the reader shall preserve its existing v1/v2 semantics and expose policy as unknown rather than reject the file." + test_refs: ["tests/spec/attestation-policy.test.ts#legacy v2 without policy remains readable"] + - id: AC-1f6b157b + ears: event + condition: "when detector catalog identity is fingerprinted" + action: "hash each registered detector's order, stable name, and subprocess classification with SHA-256" + response: "unchanged catalogs reproduce byte-identically while a changed name, order, or execution class changes the policy identity" + text: "When the detector catalog is fingerprinted, the system shall produce a deterministic full SHA-256 that changes for detector order, name, or subprocess classification changes." + test_refs: ["tests/spec/attestation-policy.test.ts#detector catalog fingerprint is deterministic and configuration-sensitive"] + - id: AC-0ef508a1 + ears: event + condition: "when clad init runs in a project with no correct index merge attribute" + action: "create or append spec/index.yaml merge=union in .gitattributes without replacing existing user content" + response: "the generated high-churn index receives the intended merge behavior in adopter repositories" + text: "When clad init finds no exact index merge attribute, the system shall append `spec/index.yaml merge=union` to `.gitattributes` while preserving existing content." + test_refs: ["tests/cli/init.test.ts#creates the index merge attribute while leaving attestation unassigned", "tests/cli/init.test.ts#preserves existing gitattributes and appends the managed index line"] + - id: AC-ad6374ef + ears: unwanted + condition: "if the exact index merge attribute already exists" + action: "leave .gitattributes byte-identical and never add any merge attribute for spec/attestation.yaml" + response: "repeated initialization is idempotent and the attestation union-safety invariant survives" + text: "If `.gitattributes` already carries the exact index rule, the system shall not append it again and shall never assign a merge driver to the attestation." + test_refs: ["tests/cli/init.test.ts#does not duplicate an existing index merge attribute"] +design_impact: + classification: none + rationale: "The change adds provenance fields to an existing derived attestation format and scaffolds the already-documented index merge attribute; it changes no architecture, capability, or journey." + status: resolved + artifacts: [] diff --git a/spec/features/ci-version-pinning-abd10f3c.yaml b/spec/features/ci-version-pinning-abd10f3c.yaml new file mode 100644 index 00000000..2188bbb1 --- /dev/null +++ b/spec/features/ci-version-pinning-abd10f3c.yaml @@ -0,0 +1,42 @@ +id: F-abd10f3c +slug: ci-version-pinning +title: "Pinned Cladding version in generated CI" +status: done +modules: + - src/cli/ci-version.ts + - src/cli/init.ts + - src/cli/doctor.ts +acceptance_criteria: + - id: AC-84011597 + ears: event + condition: "when clad init --with-ci scaffolds a GitHub Actions workflow and the running Cladding version is available" + action: "derive the numeric major.minor selector from that runtime version and render npx --yes cladding@ check --tier=pre-push --strict --json" + response: "generated CI stays within the installed release line instead of silently adopting a future breaking version" + text: "When clad init --with-ci scaffolds CI, the system shall pin Cladding to the running binary's numeric major.minor release line while preserving the strict pre-push gate." + test_refs: ["tests/init/git-hook.test.ts#creates a major.minor-pinned authoritative-gate workflow once and never overwrites it"] + - id: AC-8604b579 + ears: unwanted + condition: "if the running Cladding version is absent or malformed" + action: "decline to create the workflow and return an informational skip reason" + response: "the generator never falls back to an unpinned package invocation" + text: "If the runtime version cannot produce a numeric major.minor selector, the system shall leave CI untouched and report that pinning was unavailable rather than generate an unpinned workflow." + test_refs: ["tests/init/git-hook.test.ts#does not scaffold an unpinned workflow when the runtime version is unavailable"] + - id: AC-b0ade1e9 + ears: state + condition: "while clad doctor inspects a project whose GitHub Actions YAML contains an unversioned or floating-tag npx cladding invocation" + action: "collect the affected workflow paths deterministically and expose them in both text and JSON output" + response: "operators can identify CI that may drift to an unintended Cladding release without turning doctor into a gate" + text: "While project CI invokes an unpinned or floating Cladding package, the system shall report the exact workflow paths through doctor text and JSON while continuing to exit successfully." + test_refs: ["tests/cli/ci-version.test.ts#finds unpinned and floating Cladding npx calls in yml and yaml workflows", "tests/cli/doctor.test.ts#reports unpinned CI in text and JSON without failing"] + - id: AC-9501f50d + ears: unwanted + condition: "if a workflow uses a numeric major.minor or major.minor.patch Cladding selector, or does not invoke Cladding through npx" + action: "exclude it from the unpinned workflow list" + response: "doctor avoids warning on the generated safe form and unrelated workflow prose" + text: "If CI uses a numeric Cladding version selector or no npx Cladding invocation, the system shall not report a version-pinning warning." + test_refs: ["tests/cli/ci-version.test.ts#accepts numeric selectors and ignores comments or unrelated commands", "tests/cli/doctor.test.ts#keeps pinned CI quiet"] +design_impact: + classification: none + rationale: "This tightens the existing generated GitHub Actions command and adds read-only doctor diagnostics without changing architecture, capabilities, or user journeys." + status: resolved + artifacts: [] diff --git a/spec/features/gate-config-committable-b0c2e724.yaml b/spec/features/gate-config-committable-b0c2e724.yaml new file mode 100644 index 00000000..12f0a676 --- /dev/null +++ b/spec/features/gate-config-committable-b0c2e724.yaml @@ -0,0 +1,49 @@ +id: F-b0c2e724 +slug: gate-config-committable +title: "Gate config survives a fresh clone: committable .cladding/config.yaml" +status: done +modules: + - src/init/gitignore-policy.ts + - src/cli/init.ts + - src/cli/doctor.ts +acceptance_criteria: + - id: AC-2e9c61f8 + ears: event + condition: "when clad init manages the .gitignore entry for cladding runtime state and no cladding entry exists yet" + action: "write the contents-exclusion pair `.cladding/*` plus `!.cladding/config.yaml` instead of the directory exclusion" + response: "the gate configuration (scope, commands, coverage, test_report) can be committed, so a fresh clone and CI see the same gate the author tuned — a directory exclusion makes re-inclusion impossible by git semantics, which silently discarded every declared gate override" + text: "When clad init writes the cladding ignore entry, the system shall write `.cladding/*` and `!.cladding/config.yaml` so the gate config file is committable while runtime state stays ignored." + notes: | + ## Why + Measured live: the strict gate is CI's reason to exist, yet the one file + that tunes it was unignorable-in-reverse — `.cladding/` (directory form) + blocks `!.cladding/config.yaml` re-inclusion entirely, so every documented + gate.commands recommendation produced local-only configuration. Found by a + live host run during the gate.language E2E and verified with + git check-ignore. + test_refs: ["tests/cli/gitignore-gate-config.test.ts", "tests/cli/init.test.ts"] + - id: AC-6a58f0d1 + ears: unwanted + condition: "if the project's .gitignore already carries a cladding entry — the legacy `.cladding/` directory form or the new pair" + action: "leave the file byte-identical" + response: "repeated init stays idempotent and no adopter's hand-tuned ignore file is rewritten behind their back" + text: "If a cladding ignore entry already exists in any recognized form, the system shall not modify .gitignore." + test_refs: ["tests/cli/gitignore-gate-config.test.ts", "tests/cli/init.test.ts"] + - id: AC-d47b93c5 + ears: event + condition: "when clad doctor inspects a project whose root .gitignore blocks .cladding/config.yaml from being committed" + action: "report the blocked gate config in both text and JSON while continuing to exit successfully" + response: "existing adopters with the legacy directory exclusion learn their gate config is local-only and how to fix it, through a read-only diagnosis that never rewrites their file — the same posture as the unpinned-CI report" + text: "When the root .gitignore blocks the gate config from being committed, clad doctor shall report it in text and JSON and still exit zero." + test_refs: ["tests/cli/gitignore-gate-config.test.ts", "tests/cli/doctor.test.ts"] + - id: AC-f30a7c62 + ears: ubiquitous + action: "expose the ignore-entry rendering and the blocked-status classification as pure exported functions" + response: "the contract is testable without a git repository or a built binary, and git check-ignore agreement is proven once against the rendered content" + text: "The system shall expose pure functions that render the managed ignore entry and classify a .gitignore text as commitable, blocked, or absent for the gate config." + test_refs: ["tests/cli/gitignore-gate-config.test.ts"] +design_impact: + classification: none + rationale: "Changes one scaffold line, adds a read-only doctor diagnosis; no gate policy, architecture, or capability change." + status: resolved + artifacts: [] diff --git a/spec/features/hook-health-observability-96fa5622.yaml b/spec/features/hook-health-observability-96fa5622.yaml new file mode 100644 index 00000000..555976eb --- /dev/null +++ b/spec/features/hook-health-observability-96fa5622.yaml @@ -0,0 +1,45 @@ +id: F-96fa5622 +slug: hook-health-observability +title: "Hook health visibility in doctor and host evidence freshness" +status: done +modules: + - src/cli/hook-health.ts + - src/cli/hook.ts + - src/cli/doctor.ts + - src/cli/clad.ts + - src/init/host-setup.ts + - src/stages/detectors/host-claim-drift.ts + - skills/doctor/SKILL.md +acceptance_criteria: + - id: AC-4c90cd04 + ears: ubiquitous + action: "record each recognized Claude Code lifecycle hook invocation before dispatch in one bounded project-local health sidecar" + response: "the sidecar keeps the current engine version and only the latest ISO timestamp for SessionStart, UserPromptSubmit, PreToolUse, PostToolUse, and Stop; repeated high-frequency tool hooks overwrite fixed keys instead of growing the lifecycle event log" + text: "The system shall record every recognized Claude Code lifecycle hook invocation in a bounded project-local health snapshot so operators can distinguish a live hook runtime from silent wiring without growing the append-only event log." + test_refs: ["tests/cli/hook-health.test.ts"] + - id: AC-8b37ba53 + ears: unwanted + condition: "if the project has no spec, the hook event is unknown, or the health snapshot cannot be read or written" + action: "leave the host protocol result unchanged and represent unavailable health evidence as not observed" + response: "observability never activates Cladding in unrelated projects, never bricks a host session, and never turns malformed local telemetry into an installation claim" + text: "If hook-health evidence is inapplicable or unavailable, the system shall preserve hook protocol behavior and report the runtime as not observed rather than guessing that it is installed." + test_refs: ["tests/cli/hook-health.test.ts", "tests/cli/doctor.test.ts"] + - id: AC-8b386416 + ears: event + condition: "when clad doctor reads a project" + action: "report runtime installation evidence, recorded versus current engine version, and the last observed firing time for all five hook events in both text and JSON" + response: "operators see observed or not-observed installation state plus explicit never-observed gaps without inspecting host registries or raw telemetry files" + text: "When clad doctor reads a project, the system shall report evidence-backed hook installation state and the last observed firing time for every shipped Claude Code hook event in both the human and machine-readable surfaces." + test_refs: ["tests/cli/doctor.test.ts", "tests/cli/setup.test.ts"] + - id: AC-19d3a3d0 + ears: unwanted + condition: "if a positive README host-support claim relies on matrix evidence older than 30 days or generated by an older Cladding engine" + action: "emit one informational HOST_CLAIM_DRIFT freshness finding while retaining the existing warning only for claims that exceed recorded grades" + response: "stale evidence is visible and actionable without changing Phase 0 gate outcomes" + text: "If positive host-support claims rely on stale matrix evidence, the system shall surface one non-blocking freshness finding without weakening or broadening the existing contradictory-claim warning." + test_refs: ["tests/stages/detectors/host-claim-drift.test.ts"] +design_impact: + classification: none + rationale: "Adds bounded operational telemetry and an additive doctor report field; it does not change architecture, capability taxonomy, or gate decisions." + status: resolved + artifacts: [] diff --git a/spec/features/language-evidence-core-9e1279d4.yaml b/spec/features/language-evidence-core-9e1279d4.yaml new file mode 100644 index 00000000..a60a6073 --- /dev/null +++ b/spec/features/language-evidence-core-9e1279d4.yaml @@ -0,0 +1,70 @@ +id: F-9e1279d4 +slug: language-evidence-core +title: "Language evidence core and evidence-based TECH_STACK_MISMATCH" +status: done +modules: + - src/core/language-evidence.ts + - src/stages/detectors/tech-stack-mismatch.ts + - src/cli/scan/thresholds.ts + - src/ui/softShell.ts +acceptance_criteria: + - id: AC-1c7a90b2 + ears: ubiquitous + action: "resolve the extension-to-language vocabulary, a bounded source walk, and the observed language distribution from one foundation module consumed by both the scan layer and the stage layer" + response: "the onboarding scan and the drift detectors read the same vocabulary, ending the class of bugs where one layer writes a label another layer cannot recognize; the walk skips vendored and generated directories and is capped, so a detector invoking it on every gate run stays bounded" + text: "The system shall expose the extension-to-language vocabulary and the observed source-language distribution from a single foundation module under src/core/ that both the scan layer and the stage layer import." + notes: | + ## Why + Three divergent language tables (scan EXT_TO_LANGUAGE 15, toolchain CHAIN 12, + unmapped EXT_BY_LANGUAGE 6) meant clad init could seed a label the detector + layer then rejected under --strict — measured: init seeded cpp/rust and the + gate blocked both with zero user error. Architecture forbids stages -> cli + imports, so the shared home must be the foundation tier. + test_refs: ["tests/core/language-evidence.test.ts"] + - id: AC-3f8e6d15 + ears: unwanted + condition: "if the declared spec.project.language is outside the vocabulary, or fewer than 5 classified source files exist in the tree" + action: "emit no TECH_STACK_MISMATCH finding at all" + response: "ignorance is never treated as drift: unknown languages (zig, haskell, nim) and evidence-thin trees produce silence instead of a false alarm, and a coverage-ratio rule is deliberately absent because its denominator list flipped failure directions in red-team testing" + text: "If the declared language is unknown to the vocabulary or fewer than 5 classified source files exist, the TECH_STACK_MISMATCH detector shall emit nothing." + notes: | + ## Why + The prior manifest-chain comparison blocked 12 of 19 realistic normal repo + shapes (63%) under --strict. A coverage-ratio guard (D7) was tried and + refuted out-of-sample: whether an unknown extension sat in the denominator + list flipped the failure between false-warn and missed-drift. The + evidence-count rule replaces it and removes that list entirely. + test_refs: ["tests/stages/tech-stack-mismatch.test.ts"] + - id: AC-5b2d47c9 + ears: event + condition: "when the declared language is in the vocabulary, at least 5 classified source files exist, and the declared language is absent from the observed language set" + action: "emit one warn finding naming the declared language and the observed set with counts" + response: "an active contradiction (ported to TypeScript while the spec still says python) is still surfaced and still blocks under --strict, and the message shows the evidence so the developer sees why" + text: "When the declared language is absent from the observed source set with at least 5 classified files, the detector shall emit one warn finding naming the declared language and the observed distribution." + test_refs: ["tests/stages/tech-stack-mismatch.test.ts"] + - id: AC-8d94a1e6 + ears: event + condition: "when the declared language is observed but accounts for less than 10% of classified source files" + action: "emit one info finding naming the share" + response: "a small-but-essential core (a thin C++ SDK under a Kotlin wrapper) is disclosed without ever failing a gate, since residue and thin-core are not mechanically separable" + text: "When the declared language is observed at under 10% of classified sources, the detector shall emit one info finding and never a gate-failing severity." + notes: | + ## Why + Boundary attack proved a normal thin-native SDK (4.8%) sits BELOW a real + ported-residue case (8.3%) — no threshold separates them, so the minority + band discloses instead of blocking. Corpus-supported ranges: evidence + floor K in [3,10] (5 chosen), minority t in [9,50]% (10 chosen; higher t + only adds info noise on normal polyglots). + test_refs: ["tests/stages/tech-stack-mismatch.test.ts"] + - id: AC-e07c3241 + ears: unwanted + condition: "if the project is a normal polyglot whose declared language is a majority or plural presence (an Android app with Kotlin plus NDK C++, a React Native app, a JVM service with Kotlin tests)" + action: "emit nothing" + response: "the manifest chain is no longer consulted for identity, so a build-host label (gradle says java) can no longer contradict a truthful product language, and detectToolchain keeps serving gate-command selection unchanged" + text: "If the declared language is present at or above the minority threshold among observed sources, the detector shall emit nothing, regardless of what the build-manifest chain resolves." + test_refs: ["tests/stages/tech-stack-mismatch.test.ts"] +design_impact: + classification: none + rationale: "Moves a vocabulary map to the foundation tier and re-anchors one detector's evidence source; no architecture layer, capability, or gate-severity policy changes. detectToolchain and gate-command selection are untouched." + status: resolved + artifacts: [] diff --git a/spec/features/lifecycle-events-identity-b84c38.yaml b/spec/features/lifecycle-events-identity-b84c38.yaml index b006c263..c27a55b4 100644 --- a/spec/features/lifecycle-events-identity-b84c38.yaml +++ b/spec/features/lifecycle-events-identity-b84c38.yaml @@ -25,17 +25,17 @@ acceptance_criteria: response: "every done transition — kept or reverted — is forensic data" text: "When runDone attempts a status flip, the system shall append a done_attempted event recording feature id, gate outcome, kept-or-reverted, git HEAD, and identity, so every done transition is forensic data." test_refs: - - "tests/cli/done.test.ts#records done_attempted with kept:true on a GREEN gate" - - "tests/cli/done.test.ts#records done_attempted with kept:false when the gate is RED and the flip reverts" + - "tests/cli/done.test.ts#records done_attempted blockers on GREEN and RED gates" - id: AC-49da41 ears: event condition: "when runCheckStages completes a tier run" - action: "append a gate_run event with tier, strict flag, worst code, anyFailed, git HEAD, and identity — deduplicated when an identical (HEAD, tier, strict, worst) tuple is already the ledger's latest gate_run" + action: "append a gate_run event with tier, strict flag, worst code, anyFailed, git HEAD, identity, and compact blocker evidence — deduplicated when the outcome and blocker evidence are identical to the ledger's latest gate_run" response: "verification freshness has a data source without unbounded log growth from repeated identical runs" - text: "When runCheckStages completes a tier run, the system shall append a gate_run event with tier, strict, worst, anyFailed, git HEAD, and identity, deduplicating when an identical (HEAD, tier, strict, worst) tuple is already the latest gate_run, so verification freshness gains a data source without unbounded growth." + text: "When runCheckStages completes a tier run, the system shall append a gate_run event with tier, strict, worst, anyFailed, git HEAD, identity, and compact blocker evidence, deduplicating when the outcome and blocker evidence are identical to the latest gate_run, so verification freshness gains a data source without hiding changed blockers or growing on exact repeats." test_refs: - - "tests/cli/gate-golden-matrix.test.ts#PINNED (0.6.0): every invocation records exactly one gate_run with tier/strict/worst/anyFailed" + - "tests/cli/gate-golden-matrix.test.ts#records compact blocker telemetry without changing the gate matrix" - "tests/events/log.test.ts#gate_run dedupes the identical (head, tier, strict, worst) tuple but appends on any change" + - "tests/events/log.test.ts#changed blocker evidence is not deduped behind the same red outcome tuple" - id: AC-346653 ears: unwanted condition: "if .cladding/events.log.jsonl exceeds the rotation threshold at append time" @@ -50,4 +50,4 @@ acceptance_criteria: notes: "## Decision\nerror-as-data: append failures degrade silently (the command outcome is unchanged). ## Trade-off\nA lost event is acceptable; a gate broken by its own telemetry is not." test_refs: - - "tests/events/log.test.ts#never throws even when the cwd is not writable territory" \ No newline at end of file + - "tests/events/log.test.ts#never throws even when the cwd is not writable territory" diff --git a/spec/features/self-describing-scan-universe-87bb7ed3.yaml b/spec/features/self-describing-scan-universe-87bb7ed3.yaml new file mode 100644 index 00000000..a7936b8f --- /dev/null +++ b/spec/features/self-describing-scan-universe-87bb7ed3.yaml @@ -0,0 +1,93 @@ +id: F-87bb7ed3 +slug: self-describing-scan-universe +title: "Self-describing scan universe for UNMAPPED_ARTIFACT" +status: done +modules: + - src/stages/detectors/unmapped-artifact.ts + - src/core/language-evidence.ts +acceptance_criteria: + - id: AC-4d21c8a7 + ears: event + condition: "when the project has at least 8 features and declared architecture layers" + action: "derive the scan universe from evidence — extensions are the union of (observed source extensions that the vocabulary knows) and (extensions of modules claimed under layer roots), expanded to one glob per root, layer, and extension" + response: "a C++, Java, or C# project is actually scanned instead of falling through to a *.ts glob that matches nothing, which was measured to pass vacuously on exactly the projects the module-to-feature honesty check exists for" + text: "When the full scan is active, the system shall build the UNMAPPED_ARTIFACT universe from observed known extensions united with the extensions of layer-claimed modules, replacing the fixed per-language extension table." + notes: | + ## Why + EXT_BY_LANGUAGE knew 6 languages; declaring cpp, java, or csharp fell back + to 'ts', producing zero scanned files and a silent pass — verified by + direct scanPatterns calls. Two evidence sources compose: observation + covers lazy specs (unclaimed .cpp stays visible even when only .java is + claimed), and claimed modules teach unknown languages (.zig enters the + universe the moment a feature claims a .zig file) with no table growth. + test_refs: ["tests/stages/unmapped-artifact.test.ts", "tests/stages/unmapped-universe-evidence.test.ts"] + - id: AC-9a6f02d3 + ears: event + condition: "when claimed module paths place layer directories under a nested root such as src/main/kotlin" + action: "infer each scan root from the path segments before the layer segment, falling back to src when no module teaches a root" + response: "the Kotlin source-set layout keeps working without its dedicated ROOT_BY_LANGUAGE entry, and any other nested layout works the same way for free" + text: "The system shall infer scan roots from the claimed module paths' segments preceding a declared layer name, keep only roots carrying at least 25% of layer-claimed modules, and default to src when no module teaches a root." + notes: | + ## Why the dominance filter + Layer names are common words, so segment matching alone teaches collision + roots — measured on this repository: tests/ (9.6% of layer-claimed + modules), skills/, plugins/claude-code, and the empty root via + spec/features, together producing 430 false unclaimed findings and a red + strict gate. A root must carry >=25% of layer-claimed modules; src + carries 86% here and a Gradle src/main/kotlin + src/main/java split at + 50/50 keeps both roots (pinned by test). Accepted trade, recorded + honestly: a genuine minority source root under 25% is silently not + scanned — a false negative matching the old world's blindness to every + non-src root, so coverage is still a superset of the table it replaces. + The share is ratio-noisy at small claim counts: with only two + layer-claimed modules, one test-file claim makes its root a 50% peer and + its unclaimed siblings error findings. Measured and accepted — claiming a + test file under modules declares that root governed, and the cure is + claiming or unclaiming deliberately, not a special-casing table. + test_refs: ["tests/stages/unmapped-artifact.test.ts", "tests/stages/unmapped-universe-evidence.test.ts"] + - id: AC-c5e83b19 + ears: unwanted + condition: "if the project has fewer than 8 features or no declared architecture layers" + action: "keep the existing legacy narrow fallback patterns byte-identical" + response: "day-1 adoptions keep their protective narrow scan; the evidence model only governs grown projects" + text: "If the full-scan scale gate is not met, the system shall return the unchanged legacy fallback patterns." + test_refs: ["tests/stages/unmapped-artifact.test.ts"] + - id: AC-7f14d6e0 + ears: ubiquitous + action: "build the scan universe without reading spec.project.language" + response: "the detector is language-independent: no label lookup can misdirect the universe, and an unknown declared language cannot produce a vacuous scan" + text: "The system shall derive the UNMAPPED_ARTIFACT universe without consulting spec.project.language." + notes: | + ## Why + The language scalar was the single point through which every mislabel + became a wrong or empty universe. Evidence (what is on disk, what the + spec claims) cannot be mislabeled the way a string can. Measured on the + dogfood repo (277 features): the evidence universe produces zero new + unclaimed findings — the discipline is in the spec, not the label. + test_refs: ["tests/stages/unmapped-universe-evidence.test.ts"] + - id: AC-96ff696f + ears: event + condition: "when a declared architecture layer carries its own modules globs" + action: "use those globs, expanded by the evidenced extensions, as that layer's universe patterns instead of name-segment inference" + response: "a layer whose name is not a literal directory segment still gets scanned exactly where its declaration points — the declared architecture is the SSoT the detector was ignoring" + text: "When a layer declares modules globs, the system shall derive that layer's scan patterns from the declared globs and the evidenced extensions, bypassing name-based root inference for it." + notes: | + ## Why + External E2E (D1): two specs identical except the layer name — 'core' + (matches a path segment) found 21 unclaimed files, 'native' (no matching + segment) found 0, silently, despite both declaring + modules: ["core/src/main/cpp/**"]. The schema already supports per-layer + globs; the detector ignored a declared surface. + test_refs: ["tests/stages/unmapped-artifact.test.ts", "tests/stages/unmapped-universe-evidence.test.ts"] + - id: AC-e20dbafe + ears: unwanted + condition: "if the active full scan resolves to an empty universe or matches zero files" + action: "emit one info finding naming the layers and roots it looked for" + response: "an empty module-honesty scan is visible instead of reading as a clean pass — the no-silent-caps rule applied to this detector" + text: "If the full scan matches nothing, the system shall emit one info finding instead of silence." + test_refs: ["tests/stages/unmapped-artifact.test.ts", "tests/stages/unmapped-universe-evidence.test.ts"] +design_impact: + classification: none + rationale: "Rewires one detector's universe derivation from a language table to spec-and-tree evidence; scale gate, severity, and finding shape unchanged." + status: resolved + artifacts: [] diff --git a/spec/features/skip-exit-guidance-c17e1edc.yaml b/spec/features/skip-exit-guidance-c17e1edc.yaml new file mode 100644 index 00000000..d0360b70 --- /dev/null +++ b/spec/features/skip-exit-guidance-c17e1edc.yaml @@ -0,0 +1,63 @@ +id: F-c17e1edc +slug: skip-exit-guidance +title: "Runner-less skips name their exit: gate.commands guidance" +status: done +modules: + - src/stages/types.ts + - src/stages/type.ts + - src/stages/lint.ts + - src/stages/unit.ts + - src/stages/cov.ts + - src/stages/util.ts + - src/cli/clad.ts +acceptance_criteria: + - id: AC-4b7d20e5 + ears: ubiquitous + action: "tag every skip result with a structured reason — 'no-runner' when a command stage skips because no runner is registered for the project's language, 'tool-missing' when the resolved tool is absent or npx cannot fetch it — leaving by-design skips (missing oracles, no declared deliverable) untagged" + response: "the machine surface distinguishes 'cladding does not know how to run this' from 'this stage does not apply', without changing any existing stderr string, exit code, or skip semantics" + text: "The system shall carry a structured skipReason ('no-runner' | 'tool-missing') on command-stage skip results, tagged at the production sites, with by-design skips untagged and every existing skip message byte-identical." + notes: | + ## Why + Measured on a zig adopter: six of nine stages skip, and the six split into + two classes — four say "no registered for language" (curable by + declaring gate.commands) and two are by-design (oracle absence, no + deliverable) where that cure is a false prescription. Blanket guidance + would lie on two stages; a stderr regex would be a parser where a field + belongs. + test_refs: ["tests/cli/skip-exit-guidance.test.ts", "tests/cli/gate-golden-matrix.test.ts"] + - id: AC-90c3f1a8 + ears: event + condition: "when a check run finishes with at least one no-runner skip and text output is active" + action: "print exactly one trailing info line that lists the skipped stage labels and shows the concrete remedy inline — declaring commands under gate.commands in .cladding/config.yaml — noting the file is committable so CI runs the same gate" + response: "an adopter whose language cladding cannot drive sees, at the moment of the skip, the one declaration that turns those stages on — measured true end-to-end before this feature was designed: declaring gate.commands flips all four stages from skip to run through the shipped binary" + text: "When at least one stage skipped for lack of a runner, the system shall print one info line naming those stages and the gate.commands declaration inline, and shall print nothing when no such skip occurred." + notes: | + ## Why + The exit exists but is invisible: across every adopter-reachable surface + (gate output, READMEs, managed AGENTS.md, doctor, MCP tool descriptions) + gate.commands is mentioned once — a CHANGELOG line. The gate.language + external E2E proved this exact configuration fails: removing that one + line left a fully-capable AI unable to find the exit. The guidance is + inline (key path + example) because docs/ does not ship in the npm + package. The language name is not printed — it reads 'unknown' in the + motivating case. + test_refs: ["tests/cli/skip-exit-guidance.test.ts"] + - id: AC-2f6e88d0 + ears: unwanted + condition: "if every skip is by-design or tool-missing, or gate.commands is already declared, or all stages ran" + action: "print no guidance line" + response: "the by-design skips (spec-conformance oracles, deliverable smoke) never carry a false prescription, a tool-missing skip is not advised to declare commands it already has, and a fully-driven project sees nothing new — measured 4/0/0/0 across the four guard environments before implementation" + text: "If no stage skipped for lack of a runner, the system shall print no guidance." + test_refs: ["tests/cli/skip-exit-guidance.test.ts"] + - id: AC-b59a37c4 + ears: event + condition: "when check emits its JSON report" + action: "include the skipReason field on each skipped stage entry that carries one" + response: "MCP and CI consumers receive the same discrimination the terminal renders, additively — no existing JSON field changes" + text: "When emitting JSON, the system shall include skipReason on tagged stage entries and change no existing field." + test_refs: ["tests/cli/skip-exit-guidance.test.ts"] +design_impact: + classification: none + rationale: "Additive observability: a structured reason on an existing skip lane and one rendered line. No gate decision, severity, or stage semantics change; skips stay skips." + status: resolved + artifacts: [] diff --git a/spec/features/stop-outcome-telemetry-1aab1bba.yaml b/spec/features/stop-outcome-telemetry-1aab1bba.yaml new file mode 100644 index 00000000..65efc9cd --- /dev/null +++ b/spec/features/stop-outcome-telemetry-1aab1bba.yaml @@ -0,0 +1,51 @@ +id: F-1aab1bba +slug: stop-outcome-telemetry +title: "Stop and completion outcome telemetry" +status: done +modules: + - src/events/log.ts + - src/events/stop-telemetry.ts + - src/cli/hook.ts + - src/cli/clad.ts + - src/cli/done.ts + - src/cli/doctor.ts +acceptance_criteria: + - id: AC-28df4cc4 + ears: event + condition: "when Stop finds a fresh blocking fingerprint" + action: "record additive attribution fields on stop_blocked" + response: "the event carries count, fingerprint, detectors, introduced, preexisting, dirty_hit, head, and identity while preserving the Stop decision and output" + text: "When Stop finds a fresh blocking fingerprint, the system shall record count, fingerprint, sorted detector names, counts introduced since versus present in the latest observed gate, dirty-path intersection, head, and identity without changing the block decision." + test_refs: ["tests/cli/hook.test.ts#fresh failure records complete attribution without changing block output"] + - id: AC-5c94711a + ears: event + condition: "when Stop sees the identical persisted fingerprint again" + action: "demote the repeat and record stop_exit_recorded" + response: "the hook remains protocol-silent and the observer-only event links the known-failing exit to the same fingerprint" + text: "When Stop sees the identical persisted fingerprint again, the system shall preserve the existing empty allow response and append a stop_exit_recorded event for that known-failing exit." + test_refs: ["tests/cli/hook.test.ts#identical second run stays empty and records the known-failing exit"] + - id: AC-8894d11f + ears: ubiquitous + action: "enrich gate_run and derive Stop follow-through at read time" + response: "gate events carry compact blocker names and a Stop-compatible fingerprint, consecutive identical gates remain deduplicated except that a gate after a stop block is retained, and the pure summary reports whether each blocked fingerprint appeared in a later gate" + text: "The system shall retain enough compact gate evidence to determine at read time whether a blocked Stop fingerprint was observed by any later gate, without persisting a second correlation state file." + test_refs: ["tests/events/log.test.ts#a stop block makes the next identical gate observable", "tests/events/stop-telemetry.test.ts#matches a blocked fingerprint only against later gate runs"] + - id: AC-3cb0ca39 + ears: event + condition: "when clad done completes its strict gate attempt" + action: "record the gate blocker names on done_attempted" + response: "both kept and reverted attempts carry a sorted blockers array and all prior gate and status behavior is unchanged" + text: "When a completion attempt finishes its strict gate, the system shall add a sorted blockers array to done_attempted, empty on green and populated on red, without changing flip-gate-revert behavior." + test_refs: ["tests/cli/done.test.ts#records done_attempted blockers on GREEN and RED gates", "tests/cli/gate-golden-matrix.test.ts#records compact blocker telemetry without changing the gate matrix"] + - id: AC-a2a3beb3 + ears: event + condition: "when clad doctor reads current or legacy lifecycle events" + action: "summarize recorded Stop exits and later-gate observations in text and JSON" + response: "operators can read the counters without parsing JSONL and missing or malformed additive fields degrade to zero rather than throwing" + text: "When doctor reads the lifecycle ledger, the system shall expose Stop exit and later-gate observation counters in text and JSON while tolerating legacy events that lack the new fields." + test_refs: ["tests/cli/doctor.test.ts#governance summary exposes stop outcomes and tolerates legacy events"] +design_impact: + classification: none + rationale: "This additively enriches the existing lifecycle event stream and doctor summary without adding a service, boundary, capability, or committed policy surface." + status: resolved + artifacts: [] diff --git a/spec/index.yaml b/spec/index.yaml index 376866d5..8936f075 100644 --- a/spec/index.yaml +++ b/spec/index.yaml @@ -103,6 +103,7 @@ features: F-17df0a: {slug: scan-artifacts-llm-refinement, status: done, modules: 3} F-18e951: {slug: drift-baseline-cleanup, status: done, modules: 7} F-195cb59e: {slug: onboarding-handoff-steer, status: done, modules: 2} + F-1aab1bba: {slug: stop-outcome-telemetry, status: done, modules: 6} F-1c9166: {slug: readme-capability-sync, status: done, modules: 2} F-1d23a6: {slug: host-hooks, status: done, modules: 5} F-1e7a10c3: {slug: adoption-report-surface, status: done, modules: 2} @@ -181,6 +182,7 @@ features: F-836a90: {slug: link-capability-tool, status: done, modules: 2} F-8476ccb1: {slug: readme-multiagent-inversion, status: done, modules: 6} F-876b6f48: {slug: shard-term-to-spec-entry, status: done, modules: 7} + F-87bb7ed3: {slug: self-describing-scan-universe, status: done, modules: 2} F-898783ee: {slug: self-count-guard, status: done, modules: 17} F-8f419e: {slug: smoke-legacy-liveness, status: done, modules: 1} F-904495a5: {slug: changelog-render, status: done, modules: 5} @@ -191,6 +193,7 @@ features: F-96250595: {slug: iterative-impact-slice, status: done, modules: 2} F-96700032: {slug: unverified-ac-junit, status: done, modules: 4} F-96d1f69d: {slug: readme-role-contract-alignment, status: done, modules: 6} + F-96fa5622: {slug: hook-health-observability, status: done, modules: 7} F-987be195: {slug: docs-prune, status: done, modules: 4} F-99c6e5: {slug: cladding-self-fixes, status: done, modules: 13} F-9a3b61: {slug: ab-ext-uncommit-demos, status: done, modules: 3} @@ -198,17 +201,20 @@ features: F-9b643e: {slug: scan-conventions, status: done, modules: 5} F-9d168287: {slug: ears-complex-pattern, status: done, modules: 6} F-9d8ece66: {slug: persona-map-non-exclusivity, status: done, modules: 2} + F-9e1279d4: {slug: language-evidence-core, status: done, modules: 4} F-a04cd9: {slug: ac-hash-ids, status: done, modules: 3} F-a4085adf: {slug: spec-driven-agents-md, status: done, modules: 1} F-a4b512: {slug: dependency-cycle-detector, status: done, modules: 2} F-a5228c: {slug: attestation-marker, status: done, modules: 4} F-aa7197: {slug: scan-audit-residuals, status: done, modules: 2} + F-abd10f3c: {slug: ci-version-pinning, status: done, modules: 3} F-ae61c1: {slug: ab-tm-query-domain-fix, status: done, modules: 3} F-aee1da: {slug: scan-residuals, status: done, modules: 3} F-aee61f: {slug: scan-roots-from-architecture, status: done, modules: 1} F-af45042a: {slug: graph-live-health, status: done, modules: 5} F-af96b1: {slug: no-vacuous-green-gate-contract, status: done, modules: 14} F-b010427b: {slug: detector-layer-purity, status: done, modules: 2} + F-b0c2e724: {slug: gate-config-committable, status: done, modules: 3} F-b0c8ba2c: {slug: gate-no-progress, status: done, modules: 1} F-b0f898a6: {slug: attestation-v2-per-module, status: done, modules: 3} F-b2094740: {slug: lint-config-detection, status: done, modules: 1} @@ -228,6 +234,7 @@ features: F-bdcd90: {slug: oracle-policy-risk-weighted, status: done, modules: 8} F-be5306eb: {slug: cold-start-cycle-signal, status: done, modules: 3} F-c037ae: {slug: test-refs-repair, status: done, modules: 4} + F-c17e1edc: {slug: skip-exit-guidance, status: done, modules: 7} F-c2c996: {slug: checkpoint-events, status: done, modules: 3} F-c3747d7d: {slug: spec-first-window-complete, status: done, modules: 5} F-c48eb2: {slug: scan-source-roots, status: done, modules: 5} @@ -237,6 +244,7 @@ features: F-c6a32fff: {slug: graph-honest-fallback, status: done, modules: 7} F-c6c3daaf: {slug: kotlin-module-scoped-gate, status: done, modules: 13} F-c8aef8: {slug: project-context, status: done, modules: 5} + F-caff8598: {slug: attestation-policy-stamp, status: done, modules: 4} F-cd0415: {slug: spec-load-once, status: done, modules: 2} F-cfba0c: {slug: scenarios-deprecate, status: done, modules: 3} F-d12edf: {slug: ssot-governance, status: done, modules: 19} diff --git a/src/cli/ci-version.ts b/src/cli/ci-version.ts new file mode 100644 index 00000000..89ca427a --- /dev/null +++ b/src/cli/ci-version.ts @@ -0,0 +1,81 @@ +// Cladding · generated-CI version pinning and read-only diagnostics. + +import {existsSync, readFileSync, readdirSync} from 'node:fs'; +import {join, relative, sep} from 'node:path'; + +const NUMERIC_SELECTOR = /^\d+\.\d+(?:\.\d+)?(?:-[0-9A-Za-z.-]+)?$/; +const CLADDING_PACKAGE = /(?:^|\s)cladding(?:@([^\s"'`]+))?(?=\s|$)/g; + +/** Read-only diagnosis of Cladding package selectors in GitHub Actions. */ +export interface CiVersionHealth { + /** Workflow paths containing at least one unversioned or floating invocation. */ + readonly unpinnedWorkflows: readonly string[]; +} + +/** + * Reduces a runtime SemVer string to the npm major.minor selector used in generated CI. + * + * @param version - The running Cladding version, or null when its manifest is unavailable. + * @returns A numeric major.minor selector, or null for an absent or malformed version. + * @throws Never; invalid input is represented by null. + * @example + * ```ts + * claddingMajorMinor('0.9.3'); // '0.9' + * ``` + * @see spec/features/ci-version-pinning-abd10f3c.yaml AC-84011597 + * @since 0.9.4 + */ +export function claddingMajorMinor(version: string | null): string | null { + const match = /^(\d+)\.(\d+)\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.exec(version ?? ''); + return match ? `${match[1]}.${match[2]}` : null; +} + +function workflowFiles(root: string): string[] { + if (!existsSync(root)) return []; + const paths: string[] = []; + for (const entry of readdirSync(root, {withFileTypes: true}).sort((a, b) => a.name.localeCompare(b.name))) { + const path = join(root, entry.name); + if (entry.isDirectory()) { + paths.push(...workflowFiles(path)); + } else if (entry.isFile() && /\.ya?ml$/i.test(entry.name)) { + paths.push(path); + } + } + return paths; +} + +function hasUnpinnedInvocation(body: string): boolean { + for (const line of body.split(/\r?\n/)) { + const trimmed = line.trim(); + if (trimmed.startsWith('#') || !/\bnpx(?:\s|$)/.test(line)) continue; + const command = line.slice(line.search(/\bnpx(?:\s|$)/)); + CLADDING_PACKAGE.lastIndex = 0; + for (const match of command.matchAll(CLADDING_PACKAGE)) { + const selector = match[1]; + if (selector === undefined || !NUMERIC_SELECTOR.test(selector)) return true; + } + } + return false; +} + +/** + * Finds GitHub Actions workflows whose npx Cladding package selector can float. + * + * @param cwd - Project root containing `.github/workflows`. + * @returns Deterministically sorted project-relative workflow paths. + * @throws Only when an existing workflow cannot be read; unreadable CI is not a healthy result. + * @example + * ```ts + * const health = readCiVersionHealth('/workspace'); + * ``` + * @see spec/features/ci-version-pinning-abd10f3c.yaml AC-b0ade1e9 + * @since 0.9.4 + */ +export function readCiVersionHealth(cwd: string): CiVersionHealth { + const root = join(cwd, '.github', 'workflows'); + const unpinnedWorkflows = workflowFiles(root) + .filter((path) => hasUnpinnedInvocation(readFileSync(path, 'utf8'))) + .map((path) => relative(cwd, path).split(sep).join('/')) + .sort((a, b) => a.localeCompare(b)); + return {unpinnedWorkflows}; +} diff --git a/src/cli/clad.ts b/src/cli/clad.ts index 613bf3c7..dc8e3caa 100644 --- a/src/cli/clad.ts +++ b/src/cli/clad.ts @@ -29,6 +29,7 @@ import {refineOnboarding, resolveOnboardingReview, runClarifyCommand} from './cl import {prepareHostClarify, prepareHostInit, renderHostDraft} from './host-onboarding.js'; import {getCurrentCladdingVersion, runHostSetup} from '../init/host-setup.js'; import {recordEvent} from '../events/log.js'; +import {blockingDetectorNames, gateStopFingerprint} from '../events/stop-telemetry.js'; import {buildContextSlice} from '../optimizer/context-slice.js'; import {buildImpactSlice} from '../optimizer/reverse-slice.js'; import {inferDependsOn} from '../optimizer/infer-depends-on.js'; @@ -45,6 +46,7 @@ import {clearTestRunCache, primeTestRunCache} from '../stages/test-run-cache.js' import {runCommit} from '../stages/commit.js'; import {runCov} from '../stages/cov.js'; import {runDrift} from '../stages/drift.js'; +import {allDetectors} from '../stages/detectors/index.js'; import {runLint} from '../stages/lint.js'; import {runPerf} from '../stages/perf.js'; import {runSecret} from '../stages/secret.js'; @@ -65,7 +67,7 @@ import {computeInventory, writeInventoryToSpecYaml, writeFeatureIndex} from '../ import {writeDocLinksYaml} from '../spec/doc-references.js'; import {writeSpecDrivenAgentsMd} from '../init/agents-md.js'; import {repairTestRefs} from '../spec/test-ref-repair.js'; -import {writeAttestation} from '../spec/attestation.js'; +import {detectorCatalogSha256, writeAttestation} from '../spec/attestation.js'; import {buildBlindPayload, renderBlindBrief} from '../oracle/payload.js'; import {requiredOracleWorklist} from '../oracle/policy.js'; import {loadSpec} from '../spec/load.js'; @@ -489,6 +491,13 @@ export interface StageOutcome { readonly stderr?: string; /** Structured drift findings (only the drift stage carries these). */ readonly findings?: readonly DriftFinding[]; + /** + * WHY a skipped stage skipped (F-c17e1edc), carried through from the stage + * result: `no-runner` = cladding knows no command for this project (curable + * by declaring `gate.commands`), `tool-missing` = the command is known but + * absent here. By-design skips (no oracle, no deliverable) carry nothing. + */ + readonly skipReason?: 'no-runner' | 'tool-missing'; } /** Outcome of running a tier's stages — exported so `clad done` can gate on @@ -506,6 +515,28 @@ export interface CheckOutcome { readonly stages?: readonly StageOutcome[]; } +/** + * Renders the one trailing line a runner-less project needs (F-c17e1edc). + * + * WHY: on a project whose language cladding cannot drive, the command stages + * skip silently and the exit is invisible — `gate.commands` appears nowhere an + * adopter reaches (gate output, doctor, READMEs), so a fully-capable agent + * still could not find it. The remedy is inline (key path + example) because + * `docs/` does not ship in the npm package. The language name is deliberately + * absent: it reads `'unknown'` in exactly the case this fires. + * + * @param labels - Labels of the stages that skipped for lack of a runner, in run order. + * @returns The guidance line, or `''` when nothing skipped that way (print nothing). + */ +export function renderNoRunnerGuidance(labels: readonly string[]): string { + if (labels.length === 0) return ''; + return ( + `${labels.join(', ')} skipped — no runner is known for this project. ` + + 'Declare commands in .cladding/config.yaml (gate: → commands: → e.g. test: ["zig","test"]) ' + + 'to run them; the file is committable, so CI runs the same gate you do.' + ); +} + /** * Runs a tier's Iron Law stages in-process and reports the worst exit code. * Shared by `clad check` (which wraps it with `process.exit`) and `clad done` @@ -560,7 +591,7 @@ export function runCheckStages(opts: {internal?: boolean; strict?: boolean; tier // Mutable during the run (the EXEMPT half below rewrites the drift row); the // element shape matches StageOutcome exactly, so `collected` returns cleanly // as `readonly StageOutcome[]`. - const collected: {stage: string; label: string; status: GateStatus; exitCode: number; stderr?: string; findings?: readonly DriftFinding[]}[] = []; + const collected: {stage: string; label: string; status: GateStatus; exitCode: number; stderr?: string; findings?: readonly DriftFinding[]; skipReason?: 'no-runner' | 'tool-missing'}[] = []; // F-e53596dd — prime the run-scoped detector cache so the drift stage's // ARCHITECTURE_VIOLATION + HARDCODED_SECRET runs are reused by stage_1.5/1.6 // instead of re-spawning madge + secretlint (~5s of duplicate work per run). @@ -580,6 +611,7 @@ export function runCheckStages(opts: {internal?: boolean; strict?: boolean; tier stderr?: string; findings?: readonly DriftFinding[]; disposition?: Disposition; + skipReason?: 'no-runner' | 'tool-missing'; }; const label = opts.internal ? name : gateLabel(name); // INVARIANT: exitCode 2 means "skipped" (cladding chose not to run — tool @@ -593,7 +625,9 @@ export function runCheckStages(opts: {internal?: boolean; strict?: boolean; tier anyFailed = true; worst = Math.max(worst, worstContribution(r, status)); } - collected.push({stage: name, label, status, exitCode: r.exitCode, stderr: r.stderr, findings: r.findings}); + // `skipReason` rides along additively (F-c17e1edc) — the --json writer + // serializes `collected` wholesale, so no field whitelist to update. + collected.push({stage: name, label, status, exitCode: r.exitCode, stderr: r.stderr, findings: r.findings, skipReason: r.skipReason}); if (!opts.json && !silent) { pulse(pulseKindOf(status), label); if (isBlocking(status)) printStageDetails(r); @@ -662,7 +696,11 @@ export function runCheckStages(opts: {internal?: boolean; strict?: boolean; tier if (!opts.json) pulse('note', 'attestation', 'deferred — git operation in progress; run the gate again after the merge/rebase completes.'); } else { try { - if (writeAttestation('.', loadSpec())) { + if (writeAttestation('.', loadSpec(), { + cladding: getCurrentCladdingVersion() ?? 'unknown', + blocking: 'strict', + detectorsSha256: detectorCatalogSha256(allDetectors), + })) { if (!opts.json) pulse('note', 'attestation', 'spec/attestation.yaml refreshed (verified tree stamped)'); } } catch { @@ -678,10 +716,28 @@ export function runCheckStages(opts: {internal?: boolean; strict?: boolean; tier } else if (anyFailed && !silent) { process.stdout.write('\nℹ Run `clad doctor` for the event log, or `clad sync` to check the spec. The findings above say what drifted and why.\n'); } - // F-b84c38 — verification freshness needs a data source: every tier run - // lands in the ledger (best-effort, deduped per identical HEAD/tier/strict/ - // worst tuple so repeated identical runs add no growth). The poll counts too. - recordEvent('.', 'gate_run', {tier, strict: opts.strict === true, worst, anyFailed}); + // F-c17e1edc — name the exit for the curable skips only. A no-runner skip is + // one declaration away from running; a tool-missing skip already HAS its + // command, and a by-design skip (no oracle / no deliverable) would be given a + // false prescription — so both stay out of the line, and out of its list. + if (!opts.json && !silent) { + const guidance = renderNoRunnerGuidance( + collected.filter((c) => c.skipReason === 'no-runner').map((c) => c.label), + ); + if (guidance) process.stdout.write(`\nℹ ${guidance}\n`); + } + // F-b84c38 + F-1aab1bba — verification freshness and Stop follow-through + // need one gate record. Compact blocker names explain rejected done attempts; + // the Stop-compatible trio fingerprint lets read-time analysis determine + // whether a prior Stop block was later reproduced by a normal gate. + recordEvent('.', 'gate_run', { + tier, + strict: opts.strict === true, + worst, + anyFailed, + blockers: blockingDetectorNames(collected), + stopFingerprint: gateStopFingerprint(collected), + }); return {worst, anyFailed, stages: collected}; } @@ -1096,7 +1152,7 @@ export function runRouteCommand(prompt: string): void { */ export function createProgram(): Command { const program = new Command(); - program.name('clad').description('Reference Ironclad CLI').version('0.9.3'); + program.name('clad').description('Reference Ironclad CLI').version('0.9.4'); program .command('init [intent...]') @@ -1321,7 +1377,7 @@ export function createProgram(): Command { program .command('doctor') - .description('Summarise .cladding/events.log.jsonl — sentinel-miss frequency by phase/cause/fallback plus the top missed sentinels (LLM dispatcher health check)') + .description('Diagnose Claude Code hook liveness/version, lifecycle governance, and LLM dispatcher sentinel misses') .option('--cwd ', 'project directory to read events from (default cwd)') .option('--json', 'emit the raw DoctorReport for tooling; default is the human-readable surface') .option('--hosts', 'smoke-test host CLIs (Claude Code / Gemini / Antigravity / Codex / Cursor) and project wiring → dated artifact + docs/dogfood/matrix.md. Live LLM prompts run only with consent (CLAD_HOST_SMOKE=1 or --yes); otherwise not-run') diff --git a/src/cli/doctor.ts b/src/cli/doctor.ts index 3aada916..6db1258d 100644 --- a/src/cli/doctor.ts +++ b/src/cli/doctor.ts @@ -15,11 +15,12 @@ // so it stays a peer surface that adopters reach for diagnostics, not // a gate. -import {existsSync} from 'node:fs'; +import {existsSync, readFileSync} from 'node:fs'; import {join} from 'node:path'; import process from 'node:process'; import {readEvents, type Event} from '../events/log.js'; +import {summarizeStopOutcomes, type StopOutcomeSummary} from '../events/stop-telemetry.js'; import {attestedFeatureCount, readAttestation} from '../spec/attestation.js'; import {pulse} from '../ui/pulse.js'; import { @@ -28,6 +29,9 @@ import { type SentinelMissSummary, type EventCounts, } from '../core/telemetry-summary.js'; +import {HOOK_EVENTS, readHookHealth, type HookEventName, type HookHealthReport} from './hook-health.js'; +import {readCiVersionHealth, type CiVersionHealth} from './ci-version.js'; +import {gateConfigIgnoreStatus, type GateConfigIgnoreStatus} from '../init/gitignore-policy.js'; export interface DoctorCommandOptions { readonly cwd?: string; @@ -42,6 +46,12 @@ export interface DoctorReport { readonly sentinelMiss: SentinelMissSummary; /** F-95a096 — the governance ledger 0.6.0 writes, summarized for operators. */ readonly governance: GovernanceSummary; + /** Runtime evidence from the bounded Claude Code hook-health snapshot. */ + readonly hooks: HookHealthReport; + /** Read-only diagnosis of floating Cladding package selectors in CI. */ + readonly ciVersion: CiVersionHealth; + /** Whether the root .gitignore lets `.cladding/config.yaml` reach CI and fresh clones. */ + readonly gateConfigIgnore: GateConfigIgnoreStatus; } export interface GovernanceSummary { @@ -50,6 +60,8 @@ export interface GovernanceSummary { readonly doneAttempts: number; readonly doneRejected: number; readonly stopBlocked: number; + /** Stop demotions and read-time correlation with later gate fingerprints. */ + readonly stopOutcomes: StopOutcomeSummary; readonly unresolvedStopBlock: boolean; readonly attestation: {readonly present: boolean; readonly entries: number}; } @@ -65,6 +77,7 @@ function summarizeGovernance(cwd: string, events: readonly Event[]): GovernanceS doneAttempts: dones.length, doneRejected: dones.filter((e) => e.payload.kept !== true).length, stopBlocked: events.filter((e) => e.type === 'stop_blocked').length, + stopOutcomes: summarizeStopOutcomes(events), unresolvedStopBlock: existsSync(join(cwd, '.cladding', 'stop-block.json')), attestation: {present: attested !== null, entries: attested === null ? 0 : attestedFeatureCount(attested)}, }; @@ -92,7 +105,10 @@ export function runDoctorCommand(opts: DoctorCommandOptions = {}): void { const eventCounts = summarizeEvents(events); const sentinelMiss = summarizeSentinelMisses(events); const governance = summarizeGovernance(cwd, events); - const report: DoctorReport = {cwd, events: eventCounts, sentinelMiss, governance}; + const hooks = readHookHealth(cwd); + const ciVersion = readCiVersionHealth(cwd); + const gateConfigIgnore = readGateConfigIgnoreStatus(cwd); + const report: DoctorReport = {cwd, events: eventCounts, sentinelMiss, governance, hooks, ciVersion, gateConfigIgnore}; if (opts.json) { process.stdout.write(`${JSON.stringify(report, null, 2)}\n`); @@ -106,6 +122,9 @@ export function runDoctorCommand(opts: DoctorCommandOptions = {}): void { 'doctor', 'no events recorded yet — run `clad init --scan` or a stage to populate .cladding/events.log.jsonl', ); + renderHookHealth(report.hooks); + renderCiVersionHealth(report.ciVersion); + renderGateConfigIgnore(report.gateConfigIgnore); process.exit(0); return; } @@ -132,6 +151,10 @@ function renderTextReport(report: DoctorReport): void { process.stdout.write(`Events: ${typeLine}\n`); } + renderHookHealth(report.hooks); + renderCiVersionHealth(report.ciVersion); + renderGateConfigIgnore(report.gateConfigIgnore); + // F-95a096 — the governance ledger, readable without parsing JSONL by hand. // Rendered before the sentinel-miss early return: gate/done/stop state is // worth a glance even when the dispatcher is perfectly healthy. @@ -143,6 +166,10 @@ function renderTextReport(report: DoctorReport): void { process.stdout.write(` gate runs: ${g.gateRuns} (last: ${lastGate})\n`); process.stdout.write(` done attempts: ${g.doneAttempts} rejected by the gate: ${g.doneRejected}\n`); process.stdout.write(` stop blocks: ${g.stopBlocked}${g.unresolvedStopBlock ? ' ⚠ UNRESOLVED stop-block pending' : ''}\n`); + process.stdout.write( + ` stop exits recorded: ${g.stopOutcomes.exitsRecorded} blocked fingerprints later seen by a gate: ` + + `${g.stopOutcomes.observedByLaterGate}/${g.stopOutcomes.blocked}\n`, + ); process.stdout.write( g.attestation.present ? ` attestation: ${g.attestation.entries} feature(s) stamped (spec/attestation.yaml)\n` @@ -177,6 +204,63 @@ function renderTextReport(report: DoctorReport): void { process.stdout.write('Tune your host: raise max_tokens, switch model, or check MCP transport health.\n'); } +/** + * Reads the root `.gitignore` (absent file included) and classifies whether the + * gate config can be committed. Read-only, like every doctor diagnosis: the + * adopter's ignore file is never rewritten from here. + */ +function readGateConfigIgnoreStatus(cwd: string): GateConfigIgnoreStatus { + const path = join(cwd, '.gitignore'); + return gateConfigIgnoreStatus(existsSync(path) ? readFileSync(path, 'utf8') : null); +} + +// Quiet unless the gate config is unreachable — a working ignore file needs no +// commentary, and a blocked one costs the adopter their whole gate tuning in CI. +function renderGateConfigIgnore(status: GateConfigIgnoreStatus): void { + if (status !== 'blocked') return; + process.stdout.write( + '\ngate config: .gitignore blocks .cladding/config.yaml — CI and fresh clones cannot see your gate ' + + "overrides. Change '.cladding/' to '.cladding/*' + '!.cladding/config.yaml'.\n", + ); +} + +function renderCiVersionHealth(health: CiVersionHealth): void { + if (health.unpinnedWorkflows.length === 0) return; + process.stdout.write('\nCI version pinning\n'); + for (const path of health.unpinnedWorkflows) { + process.stdout.write(` ⚠ ${path}: npx Cladding package is unpinned or floating\n`); + } + process.stdout.write(' Pin it to the running major.minor release, for example `cladding@0.9`.\n'); +} + +const HOOK_LABELS: Readonly> = { + SessionStart: 'session start', + UserPromptSubmit: 'prompt submit', + PreToolUse: 'before edit', + PostToolUse: 'after edit', + Stop: 'session stop', +}; + +function renderHookHealth(hooks: HookHealthReport): void { + process.stdout.write('\nClaude Code hooks\n'); + if (hooks.installation === 'not-observed') { + process.stdout.write( + ' runtime: not observed — install or enable the Cladding plugin, then start a new Claude Code session\n', + ); + } else { + const recorded = hooks.recordedVersion === null ? 'unknown version' : `engine v${hooks.recordedVersion}`; + const versionState = hooks.versionCurrent === true + ? 'current' + : hooks.versionCurrent === false + ? `current engine is v${hooks.currentVersion}; refresh the plugin` + : 'current version unavailable'; + process.stdout.write(` runtime: observed (${recorded}; ${versionState})\n`); + } + for (const event of HOOK_EVENTS) { + process.stdout.write(` ${HOOK_LABELS[event]}: ${hooks.lastFiredAt[event] ?? 'never observed'}\n`); + } +} + function formatCounts(counts: Readonly>): string { const entries = Object.entries(counts).filter(([, n]) => n > 0); if (entries.length === 0) return '(none)'; diff --git a/src/cli/done.ts b/src/cli/done.ts index 38146ccb..07305b66 100644 --- a/src/cli/done.ts +++ b/src/cli/done.ts @@ -19,6 +19,7 @@ import {existsSync, readFileSync, readdirSync, writeFileSync} from 'node:fs'; import {recordEvent} from '../events/log.js'; +import {blockingDetectorNames, type TelemetryStage} from '../events/stop-telemetry.js'; import {join} from 'node:path'; import {parseSpec} from '../spec/parse.js'; @@ -34,7 +35,7 @@ export interface DoneDeps { strict?: boolean; tier?: string; focusModules?: readonly string[]; - }) => {worst: number; anyFailed?: boolean}; + }) => {worst: number; anyFailed?: boolean; stages?: readonly TelemetryStage[]}; /** * Regenerate the committed feature index after a status flip (on BOTH the * kept and the reverted branch) so spec/index.yaml's per-row status never lags @@ -195,11 +196,12 @@ export function runDone(cwd: string, featureId: string, deps: DoneDeps): DoneRes deps.onIndex?.(cwd); // Scope the gate to THIS feature's modules (Gradle monorepos). Empty → the // gate runs whole-repo, exactly as before. @see toolchain/scoped-command.ts - const {worst, anyFailed} = deps.checkStages({ + const {worst, anyFailed, stages} = deps.checkStages({ tier: 'pre-push', strict: true, focusModules: hit.modules, }); + const blockers = blockingDetectorNames(stages ?? []); // F-c566f590 — the evidence-based independence label. Computed once from the // injected evidence slice (an omitted dep ⇒ undefined ⇒ pre-independence // behavior). It does NOT depend on the gate: a feature can be GREEN yet still @@ -221,6 +223,7 @@ export function runDone(cwd: string, featureId: string, deps: DoneDeps): DoneRes worst, anyFailed: anyFailed ?? worst > 0, kept, + blockers, ...(independence ? {independence} : {}), }); if (kept) { diff --git a/src/cli/hook-health.ts b/src/cli/hook-health.ts new file mode 100644 index 00000000..9f98677b --- /dev/null +++ b/src/cli/hook-health.ts @@ -0,0 +1,173 @@ +// Cladding · bounded host-hook liveness snapshot. +// +// Hook invocations are much more frequent than lifecycle transitions. Recording +// every call in events.log.jsonl would undo the log-growth protection added for +// impact-card skips, so this observer keeps one replace-in-place timestamp per +// shipped Claude Code event instead. + +import {existsSync, mkdirSync, readFileSync, renameSync, writeFileSync} from 'node:fs'; +import {dirname, join} from 'node:path'; +import process from 'node:process'; + +import {getCurrentCladdingVersion} from '../init/host-setup.js'; + +/** The lifecycle events shipped in the Claude Code plugin hook manifest. */ +export const HOOK_EVENTS = [ + 'SessionStart', + 'UserPromptSubmit', + 'PreToolUse', + 'PostToolUse', + 'Stop', +] as const; + +/** One event name accepted by the host hook protocol. */ +export type HookEventName = (typeof HOOK_EVENTS)[number]; + +/** Evidence-backed hook state exposed by `clad doctor --json`. */ +export interface HookHealthReport { + /** `observed` means this engine actually handled at least one hook call. */ + readonly installation: 'observed' | 'not-observed'; + /** Engine version written by the most recent hook invocation. */ + readonly recordedVersion: string | null; + /** Version of the engine running `clad doctor`. */ + readonly currentVersion: string | null; + /** Null until both recorded and current versions are known. */ + readonly versionCurrent: boolean | null; + /** Fixed-key map; null means that event has never been observed. */ + readonly lastFiredAt: Readonly>; +} + +interface HookHealthSnapshot { + readonly schemaVersion: 1; + readonly engineVersion: string | null; + readonly lastFiredAt: Partial>; +} + +interface RecordHookFiringOptions { + readonly now?: Date; + readonly engineVersion?: string | null; +} + +const HEALTH_FILE = join('.cladding', 'hook-health.json'); + +function healthPath(cwd: string): string { + return join(cwd, HEALTH_FILE); +} + +function isHookEventName(event: string): event is HookEventName { + return (HOOK_EVENTS as readonly string[]).includes(event); +} + +function validTimestamp(value: unknown): value is string { + return typeof value === 'string' && Number.isFinite(Date.parse(value)); +} + +function readSnapshot(cwd: string): HookHealthSnapshot | null { + try { + const parsed = JSON.parse(readFileSync(healthPath(cwd), 'utf8')) as { + schemaVersion?: unknown; + engineVersion?: unknown; + lastFiredAt?: unknown; + }; + if (parsed.schemaVersion !== 1 || typeof parsed.lastFiredAt !== 'object' || parsed.lastFiredAt === null) { + return null; + } + const candidate = parsed.lastFiredAt as Record; + const lastFiredAt: Partial> = {}; + for (const event of HOOK_EVENTS) { + if (validTimestamp(candidate[event])) lastFiredAt[event] = candidate[event]; + } + return { + schemaVersion: 1, + engineVersion: typeof parsed.engineVersion === 'string' ? parsed.engineVersion : null, + lastFiredAt, + }; + } catch { + return null; + } +} + +/** + * Records a recognized hook invocation without changing its protocol outcome. + * + * The project must already contain `spec.yaml`; this observer never activates + * Cladding in an unrelated working directory. Writes are atomic and + * best-effort, and the fixed five-key snapshot cannot grow with call volume. + * + * @param cwd - Project directory in which the host invoked the hook. + * @param event - Host event name; unknown future events are ignored. + * @param options - Injectable clock/version used by deterministic tests. + * @returns True only when a new snapshot was successfully installed. + * @throws Never; filesystem and parsing failures degrade to false. + * @example + * ```ts + * recordHookFiring('.', 'SessionStart'); + * ``` + * @see spec/features/hook-health-observability-96fa5622.yaml AC-4c90cd04 + * @since 0.9.4 + */ +export function recordHookFiring( + cwd: string, + event: string, + options: RecordHookFiringOptions = {}, +): boolean { + if (!isHookEventName(event) || !existsSync(join(cwd, 'spec.yaml'))) return false; + try { + const path = healthPath(cwd); + const previous = readSnapshot(cwd); + const snapshot: HookHealthSnapshot = { + schemaVersion: 1, + engineVersion: options.engineVersion === undefined + ? getCurrentCladdingVersion() + : options.engineVersion, + lastFiredAt: { + ...(previous?.lastFiredAt ?? {}), + [event]: (options.now ?? new Date()).toISOString(), + }, + }; + mkdirSync(dirname(path), {recursive: true}); + const temporary = `${path}.${process.pid}.tmp`; + writeFileSync(temporary, `${JSON.stringify(snapshot, null, 2)}\n`, 'utf8'); + renameSync(temporary, path); + return true; + } catch { + return false; + } +} + +/** + * Reads the bounded hook snapshot into the stable doctor report shape. + * + * Missing or malformed data is not evidence of installation. The returned map + * still contains all five events so machine consumers never infer absence from + * an omitted key. + * + * @param cwd - Project directory containing the optional health snapshot. + * @param currentVersion - Engine version running doctor; injectable for tests. + * @returns Evidence-backed installation, version, and per-event timestamps. + * @throws Never; unreadable evidence returns the not-observed zero state. + * @example + * ```ts + * const health = readHookHealth('.'); + * ``` + * @see spec/features/hook-health-observability-96fa5622.yaml AC-8b37ba53 + * @see spec/features/hook-health-observability-96fa5622.yaml AC-8b386416 + * @since 0.9.4 + */ +export function readHookHealth( + cwd: string, + currentVersion: string | null = getCurrentCladdingVersion(), +): HookHealthReport { + const snapshot = readSnapshot(cwd); + const lastFiredAt = Object.fromEntries( + HOOK_EVENTS.map((event) => [event, snapshot?.lastFiredAt[event] ?? null]), + ) as Record; + const installation = Object.values(lastFiredAt).some((timestamp) => timestamp !== null) + ? 'observed' + : 'not-observed'; + const recordedVersion = installation === 'observed' ? snapshot?.engineVersion ?? null : null; + const versionCurrent = recordedVersion !== null && currentVersion !== null + ? recordedVersion === currentVersion + : null; + return {installation, recordedVersion, currentVersion, versionCurrent, lastFiredAt}; +} diff --git a/src/cli/hook.ts b/src/cli/hook.ts index 0fa688fe..997b2b70 100644 --- a/src/cli/hook.ts +++ b/src/cli/hook.ts @@ -35,6 +35,7 @@ import process from 'node:process'; import {parse as parseYaml} from 'yaml'; import {latestEventOfType, recordEvent, type ImpactSkipReason} from '../events/log.js'; +import {attributeStopFailures} from '../events/stop-telemetry.js'; import type {Intent} from '../router/intent.js'; import {suggestIntent} from '../router/intent.js'; import {runArch} from '../stages/arch.js'; @@ -48,6 +49,7 @@ import {estTokens} from '../optimizer/code-excerpt.js'; import {loadSpec} from '../spec/load.js'; import {WATCHED_EXTENSIONS} from '../stages/toolchain/language-config.js'; import {coldStartAdvisory} from './enforcement-advisory.js'; +import {recordHookFiring} from './hook-health.js'; import {driftNudge, plainFinding, plainLead, stopBlockMessage} from '../ui/softShell.js'; // --- shared helpers ---------------------------------------------------- @@ -412,9 +414,20 @@ function runStopGate(input: unknown, cwd: string): string { const fingerprint = createHash('sha256') .update(failures.map((f) => `${f.detector}|${f.path}`).sort().join('\n')) .digest('hex'); + const priorGate = latestEventOfType(cwd, 'gate_run'); + const priorBlockers = Array.isArray(priorGate?.payload.blockers) + ? priorGate.payload.blockers.filter((value): value is string => typeof value === 'string') + : []; + const attribution = attributeStopFailures(failures, priorBlockers, gitChangedPaths(cwd) ?? []); + const eventPayload = {count: failures.length, fingerprint, ...attribution}; try { const prev = JSON.parse(readFileSync(blockFile, 'utf8')) as {fingerprint?: unknown}; - if (prev.fingerprint === fingerprint) return ''; // identical → demote; the SessionStart card resurfaces it + if (prev.fingerprint === fingerprint) { + // F-1aab1bba — the existing demotion remains protocol-silent, but the + // known-failing exit now contributes the denominator Stop lacked. + recordEvent(cwd, 'stop_exit_recorded', eventPayload); + return ''; + } } catch { /* no prior block recorded */ } @@ -428,7 +441,7 @@ function runStopGate(input: unknown, cwd: string): string { } catch { /* unwritable state dir → still block; demotion just won't persist */ } - recordEvent(cwd, 'stop_blocked', {count: failures.length, fingerprint}); + recordEvent(cwd, 'stop_blocked', eventPayload); // Plain-first render (F-dd8dc994): a plain English lead per top finding, the // machine detail (detector · path) demoted to a parenthetical tail. The host // agent renders the user's own language (F-9af291fa). The fingerprint above @@ -1137,6 +1150,10 @@ function runPostToolUseDrift(input: unknown, cwd: string): string { */ export function runHookEvent(event: string, input: unknown, cwd: string): string { try { + // Record before dispatch so even an internal hook failure remains observable. + // Keeping it inside the protocol boundary preserves error-as-silence if the + // observer itself ever regresses beyond its best-effort contract. + recordHookFiring(cwd, event); switch (event) { case 'SessionStart': { const out = renderSessionStartCard(cwd); diff --git a/src/cli/init.ts b/src/cli/init.ts index eb277a45..91b4ec1f 100644 --- a/src/cli/init.ts +++ b/src/cli/init.ts @@ -3,7 +3,9 @@ // One command, three side-effects on a fresh directory: // 1. spec.yaml seed with one placeholder feature (F-001) // 2. .cladding/ runtime dir (audit + events log live here) -// 3. .gitignore append (.cladding/ entry; appended only if missing) +// 3. .gitignore + .gitattributes managed-entry append (only when missing) — +// the ignore entry keeps runtime state untracked while leaving +// .cladding/config.yaml committable, so CI sees the tuned gate // // Idempotent by default — re-running on an initialised workspace is a // no-op except for reporting. `--force` overwrites the seed spec.yaml @@ -34,8 +36,10 @@ import { } from './scan/intent-onboarding.js'; import type {ScanLlmDispatcher} from './scan/llm.js'; import {captureArtifactDigests, loadState, saveState, type OnboardingState} from './scan/onboarding-state.js'; +import {claddingMajorMinor} from './ci-version.js'; import {detectToolchain} from '../stages/toolchain/detect.js'; import {writeSpecDrivenAgentsMd} from '../init/agents-md.js'; +import {CLADDING_IGNORE_BLOCK, hasCladdingIgnoreEntry} from '../init/gitignore-policy.js'; import {getCurrentCladdingVersion, getLastSetupVersion} from '../init/host-setup.js'; import {installGitHook} from '../init/git-hook.js'; import {loadIntentFromPathIfApplicable} from './intent-from-path.js'; @@ -258,22 +262,48 @@ function specSeed( ].join('\n'); } -function appendIfMissing(gitignorePath: string, marker: string, line: string): boolean { - const existing = existsSync(gitignorePath) ? readFileSync(gitignorePath, 'utf8') : ''; - if (existing.includes(marker)) return false; +/** Appends a managed block to a user-owned file, never disturbing what is already there. */ +function appendManagedBlock(path: string, block: string): void { + const existing = existsSync(path) ? readFileSync(path, 'utf8') : ''; const ensureNewline = existing.length > 0 && !existing.endsWith('\n') ? '\n' : ''; - writeFileSync(gitignorePath, `${existing}${ensureNewline}\n# Cladding runtime state\n${line}\n`); + const sectionGap = existing.length > 0 ? '\n' : ''; + writeFileSync(path, `${existing}${ensureNewline}${sectionGap}${block}`); +} + +function appendIfMissing(path: string, marker: string, line: string, heading: string): boolean { + const existing = existsSync(path) ? readFileSync(path, 'utf8') : ''; + if (existing.split(/\r?\n/).some((existingLine) => existingLine.trim() === marker)) return false; + appendManagedBlock(path, `${heading}\n${line}\n`); return true; } -/** F-16746b — the authoritative gate: client hooks are per-dev bypassable - * (--no-verify is printed in the hook body itself); CI + branch protection is - * where enforcement is real. Scaffolds a starting-point workflow the user - * owns afterwards; never overwrites an existing file. */ -export function scaffoldCiWorkflow(cwd: string): 'created' | 'exists' { +/** + * Scaffolds the authoritative, release-line-pinned GitHub Actions gate. + * + * Client hooks are per-developer and bypassable; CI plus branch protection is + * where enforcement is real. The generated workflow becomes user-owned and is + * never overwritten. + * + * @param cwd - Project root in which `.github/workflows` will be inspected. + * @param version - Running Cladding SemVer; defaults to the discovered runtime. + * @returns Whether the workflow was created, already existed, or lacked a safe pin. + * @throws Only for filesystem write failures. + * @example + * ```ts + * scaffoldCiWorkflow('/workspace', '0.9.3'); + * ``` + * @see spec/features/ci-version-pinning-abd10f3c.yaml AC-84011597 + * @since 0.9.4 + */ +export function scaffoldCiWorkflow( + cwd: string, + version: string | null = getCurrentCladdingVersion(), +): 'created' | 'exists' | 'version-unavailable' { const path = join(cwd, '.github', 'workflows', 'cladding.yml'); if (existsSync(path)) return 'exists'; + const selector = claddingMajorMinor(version); + if (selector === null) return 'version-unavailable'; mkdirSync(join(cwd, '.github', 'workflows'), {recursive: true}); writeFileSync( path, @@ -295,7 +325,7 @@ export function scaffoldCiWorkflow(cwd: string): 'created' | 'exists' { ' - uses: actions/setup-node@v4', ' with: {node-version: 22}', ' - run: npm ci || npm install', - ' - run: npx --yes cladding check --tier=pre-push --strict --json', + ` - run: npx --yes cladding@${selector} check --tier=pre-push --strict --json`, '', ].join('\n'), 'utf8', @@ -470,13 +500,40 @@ export async function runInit(opts: InitOptions = {}): Promise { created.push('.cladding/'); } - // 3. .gitignore append + // 3. .gitignore append — runtime state ignored, gate config committable. + // + // The entry is the contents-exclusion pair `.cladding/*` + `!.cladding/config.yaml`, + // never the directory exclusion `.cladding/`: git cannot re-include a file whose + // parent directory is excluded, which silently made every declared gate override + // (scope, commands, coverage, test_report) local-only. Any recognized entry that + // already exists — including the legacy directory form — leaves the file + // byte-identical; adopters are told about it by `clad doctor`, not migrated behind + // their back. const gitignorePath = join(cwd, '.gitignore'); - const appended = appendIfMissing(gitignorePath, '.cladding/', '.cladding/'); - if (appended) { - created.push('.gitignore (.cladding/ entry appended)'); + const existingGitignore = existsSync(gitignorePath) ? readFileSync(gitignorePath, 'utf8') : ''; + if (hasCladdingIgnoreEntry(existingGitignore)) { + skipped.push('.gitignore (cladding entry already present)'); + } else { + appendManagedBlock(gitignorePath, CLADDING_IGNORE_BLOCK); + created.push('.gitignore (.cladding/* ignored, .cladding/config.yaml committable)'); + } + + // F-caff8598 — the append-mostly feature index is safe under union merge; + // attestation deliberately remains on plain merge because union can silently + // resurrect stale hashes. Preserve every user-authored attribute and append + // only the exact managed index rule when absent. + const attributesPath = join(cwd, '.gitattributes'); + const indexMergeAttribute = 'spec/index.yaml merge=union'; + const attributesAppended = appendIfMissing( + attributesPath, + indexMergeAttribute, + indexMergeAttribute, + '# Cladding derived feature index', + ); + if (attributesAppended) { + created.push('.gitattributes (spec/index.yaml merge=union appended)'); } else { - skipped.push('.gitignore (.cladding/ entry already present)'); + skipped.push('.gitattributes (spec/index.yaml merge=union already present)'); } const proposals: string[] = []; @@ -660,11 +717,13 @@ export async function runInit(opts: InitOptions = {}): Promise { } if (opts.withCi) { - const ci = scaffoldCiWorkflow(cwd); + const ci = scaffoldCiWorkflow(cwd, pkgVersion); if (ci === 'created') { created.push('.github/workflows/cladding.yml (clad check --tier=pre-push --strict — the authoritative gate)'); } else if (ci === 'exists') { skipped.push('.github/workflows/cladding.yml already exists — cladding never overwrites a CI workflow'); + } else { + skipped.push('--with-ci: current Cladding version unavailable — no unpinned CI workflow was written'); } } diff --git a/src/cli/scan/thresholds.ts b/src/cli/scan/thresholds.ts index 4da598fc..fe042dbf 100644 --- a/src/cli/scan/thresholds.ts +++ b/src/cli/scan/thresholds.ts @@ -105,21 +105,14 @@ export const ENTRYPOINT_NAMES: ReadonlySet = new Set([ 'Program', 'Main', 'App', ]); -/** Maps a file extension to a normalised language label. */ -export const EXT_TO_LANGUAGE: Readonly> = { - '.ts': 'typescript', '.tsx': 'typescript', - '.js': 'javascript', '.jsx': 'javascript', '.mjs': 'javascript', '.cjs': 'javascript', - '.py': 'python', '.pyi': 'python', - '.go': 'go', - '.rs': 'rust', - '.java': 'java', - '.kt': 'kotlin', '.kts': 'kotlin', - '.cs': 'csharp', - '.rb': 'ruby', - '.php': 'php', - '.swift': 'swift', - '.ex': 'elixir', '.exs': 'elixir', - '.scala': 'scala', - '.dart': 'dart', - '.cpp': 'cpp', '.cc': 'cpp', '.cxx': 'cpp', '.hpp': 'cpp', '.h': 'cpp', -}; +/** + * Maps a file extension to a normalised language label. + * + * Owned by `core/language-evidence.ts` since F-9e1279d4 and re-exported + * here so the scan layer's import surface is unchanged. The map moved to + * the foundation tier because the drift detectors need the same + * vocabulary and the architecture forbids `stages → cli`; when scan and + * the detectors read different tables, `clad init` seeds labels the gate + * then rejects. + */ +export {EXT_TO_LANGUAGE} from '../../core/language-evidence.js'; diff --git a/src/core/language-evidence.ts b/src/core/language-evidence.ts new file mode 100644 index 00000000..72f7b6f9 --- /dev/null +++ b/src/core/language-evidence.ts @@ -0,0 +1,221 @@ +// Cladding · core · source-language vocabulary + observed distribution +// +// Three divergent language tables used to live in three layers (the scan +// layer's extension map, the toolchain chain, the unmapped-artifact +// extension-by-language map). `clad init` could therefore seed a label — +// `cpp`, `rust` — that the detector layer then refused under `--strict`, +// with zero user error. The fix is a single vocabulary, owned by the +// foundation tier so BOTH the scan layer (cli) and the drift detectors +// (stages) can import it: the architecture forbids `stages → cli`, so +// there is no other legal shared home. +// +// The second export answers the question a detector actually has — +// "what language IS this tree?" — from the files on disk rather than +// from a build manifest. A build manifest names the build host (gradle +// says java), which is the right answer for "what command do we run" +// and the wrong answer for project identity. +// +// The third export answers the neighbouring question — "which source +// extensions does this tree actually contain?" — because a caller that +// builds file globs needs the extensions themselves, not the labels: +// inverting a label back through the map would glob for `.hpp`, `.cc` +// and `.cxx` on a project that only ever writes `.cpp`. +// +// Deterministic + synchronous by contract (Iron Law): filesystem reads +// only, no LLM, never throws. An unreadable directory is skipped, not +// raised, so a permission-denied subtree can never break a gate run. +// +// @see F-9e1279d4 — language evidence core. + +import {readdirSync, type Dirent} from 'node:fs'; +import {extname, join} from 'node:path'; + +/** + * Maps a file extension to a normalised language label. The single + * vocabulary for the whole toolchain — the scan layer re-exports this + * from `cli/scan/thresholds.ts` so existing scan imports are unchanged. + */ +export const EXT_TO_LANGUAGE: Readonly> = { + '.ts': 'typescript', '.tsx': 'typescript', + '.js': 'javascript', '.jsx': 'javascript', '.mjs': 'javascript', '.cjs': 'javascript', + '.py': 'python', '.pyi': 'python', + '.go': 'go', + '.rs': 'rust', + '.java': 'java', + '.kt': 'kotlin', '.kts': 'kotlin', + '.cs': 'csharp', + '.rb': 'ruby', + '.php': 'php', + '.swift': 'swift', + '.ex': 'elixir', '.exs': 'elixir', + '.scala': 'scala', + '.dart': 'dart', + '.cpp': 'cpp', '.cc': 'cpp', '.cxx': 'cpp', '.hpp': 'cpp', '.h': 'cpp', +}; + +/** + * Every language label {@link EXT_TO_LANGUAGE} can produce. A declared + * `spec.project.language` outside this set is unknown to cladding, not + * wrong — callers must treat absence here as "cannot judge", never as drift. + */ +export const LANGUAGE_VOCABULARY: ReadonlySet = new Set(Object.values(EXT_TO_LANGUAGE)); + +/** + * Directories the walk never enters: vendored dependencies, build + * output, coverage reports, and cladding's own runtime state. Any + * dot-directory is skipped too (see {@link classifySources}), so `.git` + * and `.cladding` are listed only for readability. + */ +const SKIP_DIRS: ReadonlySet = new Set([ + 'node_modules', '.git', 'dist', 'build', 'out', + 'coverage', 'target', 'vendor', '.cladding', +]); + +/** + * Hard cap on files visited by one {@link classifySources} walk. A drift + * detector calls this on EVERY gate run, so the walk must be bounded + * rather than proportional to repository size: at the cap the walk stops + * and the counts collected so far are returned. 20 000 files is roughly + * an order of magnitude above cladding's own source tree and still costs + * only a few hundred milliseconds of `readdirSync`, so a monorepo slows + * the gate by a bounded amount instead of an unbounded one. The + * distribution is a ratio, and a 20 000-file sample settles a ratio. + * + * Below the cap the result is fully determined by the tree contents; a + * tree that exceeds the cap is sampled in directory-read order, so its + * ratio is an estimate rather than a census. Consumers therefore compare + * the distribution against wide bands, never against exact counts. + */ +export const MAX_FILES = 20_000; + +/** The observed source-language distribution of one project tree. */ +export interface SourceEvidence { + /** Files counted per language label; languages with zero files are absent. */ + readonly counts: Readonly>; + /** Total files whose extension was in the vocabulary. */ + readonly classified: number; + /** The language labels observed, sorted alphabetically. */ + readonly set: readonly string[]; + /** Most-seen language (alphabetical tie-break), or null when nothing was classified. */ + readonly dominant: string | null; + /** + * Fraction of classified files written in `language`, in [0, 1]. + * Zero for an unobserved language and for an empty tree. + */ + share(language: string): number; +} + +/** Tuning knobs for {@link classifySources}. Present for testability. */ +export interface ClassifyOptions { + /** Override for {@link MAX_FILES}. Values below 1 are ignored. */ + readonly maxFiles?: number; +} + +/** Resolves the walk cap from {@link ClassifyOptions}; values below 1 are ignored. */ +function resolveCap(opts: ClassifyOptions): number { + return opts.maxFiles !== undefined && opts.maxFiles >= 1 ? opts.maxFiles : MAX_FILES; +} + +/** + * The one bounded tree walk both public readers share, so a caller that + * asks for labels and a caller that asks for extensions can never see + * different files. + * + * Synchronous, iterative (no recursion depth limit), and stopped at + * `cap` files. Symlinked directories are not followed — + * `Dirent.isDirectory()` is false for a symlink — so a cyclic link + * cannot hang the walk. Unreadable directories are skipped silently. + * + * @param cwd - Project root to walk. + * @param cap - Hard file budget for this walk. + * @param onFile - Receives each visited file's lower-cased extension + * (`''` when the name carries none). + */ +function walkExtensions(cwd: string, cap: number, onFile: (ext: string) => void): void { + let visited = 0; + const stack: string[] = [cwd]; + while (stack.length > 0 && visited < cap) { + const dir = stack.pop()!; + let entries: Dirent[]; + try { + entries = readdirSync(dir, {withFileTypes: true}); + } catch { + continue; // unreadable subtree — skipped, never raised + } + for (const entry of entries) { + if (entry.isDirectory()) { + if (entry.name.startsWith('.') || SKIP_DIRS.has(entry.name)) continue; + stack.push(join(dir, entry.name)); + continue; + } + if (!entry.isFile()) continue; + if (visited >= cap) break; + visited += 1; + onFile(extname(entry.name).toLowerCase()); + } + } +} + +/** + * Walks `cwd` and counts source files per language. + * + * The walk is synchronous, iterative (no recursion depth limit), and + * bounded by {@link MAX_FILES}. Symlinked directories are not followed — + * `Dirent.isDirectory()` is false for a symlink — so a cyclic link + * cannot hang the walk. Unreadable directories are skipped silently. + * + * @param cwd - Project root to classify. + * @param opts - Optional {@link ClassifyOptions}. + * @returns The observed {@link SourceEvidence}; an empty tree yields + * `classified: 0`, `dominant: null`, and `share() === 0`. + */ +export function classifySources(cwd: string, opts: ClassifyOptions = {}): SourceEvidence { + const counts: Record = {}; + let classified = 0; + + walkExtensions(cwd, resolveCap(opts), (ext) => { + const language = EXT_TO_LANGUAGE[ext]; + if (language === undefined) return; + counts[language] = (counts[language] ?? 0) + 1; + classified += 1; + }); + + const set = Object.keys(counts).sort(); + let dominant: string | null = null; + for (const language of set) { + if (dominant === null || counts[language] > counts[dominant]) dominant = language; + } + + return { + counts, + classified, + set, + dominant, + share(language: string): number { + if (classified === 0) return 0; + return (counts[language] ?? 0) / classified; + }, + }; +} + +/** + * Walks `cwd` and reports which vocabulary-known extensions occur in it. + * + * Same bounded walk as {@link classifySources} — same cap, same skipped + * directories — but it answers with extensions rather than labels, for + * callers that build file globs. Extensions the vocabulary does not know + * are omitted: an unknown extension names no language, and a caller that + * wants one anyway has to learn it from somewhere other than a guess. + * + * @param cwd - Project root to inspect. + * @param opts - Optional {@link ClassifyOptions}. + * @returns The observed extensions, lower-cased with their leading dot + * (`.ts`), sorted; an empty or unreadable tree yields `[]`. + */ +export function observedKnownExtensions(cwd: string, opts: ClassifyOptions = {}): readonly string[] { + const found = new Set(); + walkExtensions(cwd, resolveCap(opts), (ext) => { + if (EXT_TO_LANGUAGE[ext] !== undefined) found.add(ext); + }); + return [...found].sort(); +} diff --git a/src/events/log.ts b/src/events/log.ts index 07ebce94..7c35297e 100644 --- a/src/events/log.ts +++ b/src/events/log.ts @@ -50,14 +50,19 @@ export type EventType = | 'feature_created' // payload: feature, slug | 'design_impact_resolved' // payload: feature | 'scenario_created' // payload: scenario, slug - | 'done_attempted' // payload: feature, worst, anyFailed, kept - | 'gate_run' // payload: tier, strict, worst, anyFailed (deduped per HEAD) + | 'done_attempted' // payload: feature, worst, anyFailed, kept, blockers[] + | 'gate_run' // payload: tier, strict, worst, anyFailed, blockers[], stopFingerprint // v0.6.0 (F-1d23a6) — the Stop host hook blocked a session end on a FRESH // deterministic-trio failure (drift strict / arch / secret). Fingerprint- // keyed: an identical failure set demotes to allow without an event, so // this fires only on new breakage — the demotion itself persists as // .cladding/stop-block.json and resurfaces on the SessionStart card. - | 'stop_blocked' // payload: count, fingerprint + | 'stop_blocked' // payload: count, fingerprint, detectors[], introduced, preexisting, dirty_hit + // v0.9.4 (F-1aab1bba) — an identical Stop fingerprint took the existing + // demotion path, allowing the known-failing session to exit. The payload + // mirrors stop_blocked attribution so later analysis has both denominator + // arms; observer-only, never consulted by the hook decision. + | 'stop_exit_recorded' // v0.8.0 (F-6ba22c5c) — value-delivery telemetry. cladding's value surfaces // (PostToolUse impact card, SessionStart card, UserPromptSubmit suggestion, MCP // read serves) left ZERO trace, so the 0.7.1 "impact card fired 0%" bug was @@ -222,8 +227,10 @@ export function latestEventOfType(cwd: string, type: EventType): Event | null { * failure path degrades to a silent no-op. * * `gate_run` dedupe: when the latest gate_run already carries the identical - * (head, tier, strict, worst) tuple, the append is skipped — repeated - * identical runs on the same tree add no information, only log growth. + * head/tier/strict/worst plus blocker evidence, the append is skipped — except + * when a stop_blocked event occurred after that gate. The first later gate must + * remain observable so Stop's fingerprint can be correlated without a second + * state file; subsequent identical gates dedupe normally. */ export function recordEvent(cwd: string, type: EventType, payload: Record): void { try { @@ -231,13 +238,25 @@ export function recordEvent(cwd: string, type: EventType, payload: Record= 0; index--) { + if (events[index].type === 'gate_run') { + prevIndex = index; + break; + } + } + const prev = prevIndex >= 0 ? events[prevIndex] : undefined; + const stopBlockedSince = prevIndex >= 0 && events.slice(prevIndex + 1).some((event) => event.type === 'stop_blocked'); if ( prev && + !stopBlockedSince && prev.payload.head === head && prev.payload.tier === payload.tier && prev.payload.strict === payload.strict && - prev.payload.worst === payload.worst + prev.payload.worst === payload.worst && + prev.payload.stopFingerprint === payload.stopFingerprint && + JSON.stringify(prev.payload.blockers ?? []) === JSON.stringify(payload.blockers ?? []) ) { return; } diff --git a/src/events/stop-telemetry.ts b/src/events/stop-telemetry.ts new file mode 100644 index 00000000..26a9cb63 --- /dev/null +++ b/src/events/stop-telemetry.ts @@ -0,0 +1,193 @@ +// Cladding · Stop outcome telemetry (F-1aab1bba, pure) +// +// Stop's refusal is useful only if the lifecycle ledger can later answer what +// it caught and whether a normal gate would have caught the same failure set. +// This module derives that evidence from existing event order. It owns no IO +// and no policy: hook/done/gate decisions remain in their existing callers. + +import {createHash} from 'node:crypto'; + +import {isBlocking, type GateStatus} from '../stages/disposition.js'; +import type {Event} from './log.js'; + +/** Minimal structured finding needed by the telemetry reducers. */ +export interface TelemetryFinding { + readonly detector: string; + readonly path?: string; + readonly severity?: 'error' | 'warn' | 'info'; +} + +/** Structural gate-stage input accepted from the CLI without importing it. */ +export interface TelemetryStage { + readonly stage: string; + readonly status: GateStatus; + readonly findings?: readonly TelemetryFinding[]; +} + +/** Stop failure input after the hook has normalized a missing path to `''`. */ +export interface StopFailureTelemetry { + readonly detector: string; + readonly path: string; +} + +/** Attribution attached to each Stop outcome event. */ +export interface StopAttribution { + /** Sorted, unique detector names in the current Stop failure set. */ + readonly detectors: readonly string[]; + /** Finding count whose detector was absent from the latest observed gate. */ + readonly introduced: number; + /** Finding count whose detector was present in the latest observed gate. */ + readonly preexisting: number; + /** Whether at least one path-bearing finding intersects the current dirty tree. */ + readonly dirty_hit: boolean; +} + +/** Read-time Stop outcome counters exposed by `clad doctor`. */ +export interface StopOutcomeSummary { + /** Fresh fingerprints that caused Stop to block. */ + readonly blocked: number; + /** Identical repeat fingerprints that demoted to an allowed exit. */ + readonly exitsRecorded: number; + /** Blocked fingerprints reproduced by at least one later gate run. */ + readonly observedByLaterGate: number; + /** Blocked fingerprints without a matching later gate in this event slice. */ + readonly notObservedByLaterGate: number; +} + +/** + * Returns sorted, unique blocker names for a gate outcome. + * + * Structured non-info findings retain their detector identity. A blocking + * stage without structured findings falls back to its stable stage id so red + * type/lint/smoke outcomes are never reported as blocker-free. + * + * @param stages - Gate stages after all strict/exemption reductions. + * @returns Compact blocker names; empty for a green gate. + * @see spec/features/stop-outcome-telemetry-1aab1bba.yaml AC-004 + */ +export function blockingDetectorNames(stages: readonly TelemetryStage[]): readonly string[] { + const names = new Set(); + for (const stage of stages) { + if (!isBlocking(stage.status)) continue; + const findings = (stage.findings ?? []).filter((finding) => finding.severity !== 'info'); + if (findings.length === 0) { + names.add(stage.stage); + continue; + } + for (const finding of findings) names.add(finding.detector); + } + return [...names].sort(); +} + +/** + * Computes the gate-side equivalent of Stop's persisted fingerprint. + * + * This intentionally does not replace the hook's deployed calculation. The + * hook has a compatibility-sensitive sidecar contract; the gate mirrors its + * normalized `detector|path` keys so old sidecars keep demoting byte-for-byte. + * Only the deterministic Stop trio participates: strict Drift plus synthetic + * ARCH/SECRET stage failures. + * + * @param stages - Gate stages after strict/exemption reductions. + * @returns SHA-256 fingerprint, or `''` when the Stop trio is green/absent. + * @see spec/features/stop-outcome-telemetry-1aab1bba.yaml AC-003 + */ +export function gateStopFingerprint(stages: readonly TelemetryStage[]): string { + const keys: string[] = []; + const drift = stages.find((stage) => stage.stage === 'stage_1.3'); + if (drift && isBlocking(drift.status)) { + for (const finding of drift.findings ?? []) { + if (finding.severity === 'error' || finding.severity === 'warn') { + keys.push(`${finding.detector}|${finding.path ?? ''}`); + } + } + } + if (stages.some((stage) => stage.stage === 'stage_1.5' && isBlocking(stage.status))) { + keys.push('ARCH|stage'); + } + if (stages.some((stage) => stage.stage === 'stage_1.6' && isBlocking(stage.status))) { + keys.push('SECRET|stage'); + } + if (keys.length === 0) return ''; + return createHash('sha256').update(keys.sort().join('\n')).digest('hex'); +} + +/** + * Attributes a Stop failure set against the latest observed gate and dirty tree. + * + * `introduced` means "not named by the latest observed gate", not causal proof + * that the current session created the problem. With no prior blocker names, + * all current failures are conservatively counted as newly observed. The + * independent `dirty_hit` bit records working-tree intersection without + * conflating dirty state with causality. + * + * @param failures - Current Stop failures. + * @param priorBlockers - Compact blocker names from the latest gate event. + * @param dirtyPaths - Repo-relative paths reported dirty by Git. + * @returns Additive attribution fields for the lifecycle event. + * @see spec/features/stop-outcome-telemetry-1aab1bba.yaml AC-001 + */ +export function attributeStopFailures( + failures: readonly StopFailureTelemetry[], + priorBlockers: readonly string[], + dirtyPaths: readonly string[], +): StopAttribution { + const prior = new Set(priorBlockers); + const dirty = new Set(dirtyPaths); + let introduced = 0; + let preexisting = 0; + let dirtyHit = false; + for (const failure of failures) { + if (prior.has(failure.detector)) preexisting++; + else introduced++; + if (failure.path.length > 0 && dirty.has(failure.path)) dirtyHit = true; + } + return { + detectors: [...new Set(failures.map((failure) => failure.detector))].sort(), + introduced, + preexisting, + dirty_hit: dirtyHit, + }; +} + +/** + * Correlates each Stop block only with gate events that occur later in order. + * + * Legacy or malformed payloads remain countable but cannot fabricate a match. + * No state file is needed: event order plus the additive gate fingerprint is + * the complete correlation source. + * + * @param events - Lifecycle events in append order. + * @returns Stop block, recorded-exit, and later-gate counters. + * @see spec/features/stop-outcome-telemetry-1aab1bba.yaml AC-003 + */ +export function summarizeStopOutcomes(events: readonly Event[]): StopOutcomeSummary { + let blocked = 0; + let exitsRecorded = 0; + let observedByLaterGate = 0; + const laterGateFingerprints = new Set(); + for (let index = events.length - 1; index >= 0; index--) { + const event = events[index]; + if (event.type === 'gate_run') { + const fingerprint = event.payload.stopFingerprint; + if (typeof fingerprint === 'string' && fingerprint.length > 0) { + laterGateFingerprints.add(fingerprint); + } + continue; + } + if (event.type === 'stop_exit_recorded') { + exitsRecorded++; + continue; + } + if (event.type !== 'stop_blocked') continue; + blocked++; + const fingerprint = typeof event.payload.fingerprint === 'string' ? event.payload.fingerprint : ''; + if (fingerprint.length > 0 && laterGateFingerprints.has(fingerprint)) observedByLaterGate++; + } + return { + blocked, + exitsRecorded, + observedByLaterGate, + notObservedByLaterGate: blocked - observedByLaterGate, + }; +} diff --git a/src/init/gitignore-policy.ts b/src/init/gitignore-policy.ts new file mode 100644 index 00000000..62026399 --- /dev/null +++ b/src/init/gitignore-policy.ts @@ -0,0 +1,125 @@ +// Cladding · .gitignore policy for the `.cladding/` runtime directory +// +// Why this module exists: `.cladding/` holds two kinds of file with opposite +// fates. Runtime state (events.log.jsonl, stop-block.json, scan proposals) is +// per-developer noise that must stay untracked. The gate configuration +// (`.cladding/config.yaml` — scope, commands, coverage, test_report) is a +// project decision that CI and every fresh clone must see; the strict gate is +// CI's reason to exist, so losing its tuning silently is the worst outcome. +// +// Git cannot separate the two from a *directory* exclusion. Once a pattern +// excludes a directory, git never descends into it, so a later +// `!.cladding/config.yaml` re-include is unreachable and the file stays +// ignored no matter what follows it. Only the contents form `.cladding/*` +// leaves the directory itself un-excluded, which is what makes the negation +// effective. Verified with `git check-ignore` before this module existed: +// every documented gate override was silently local-only. +// +// Pure by design (F-b0c2e724 AC-f30a7c62): rendering the managed entry and +// classifying an existing file are string operations, so the contract is +// testable without a git repository or a built binary, and the one place that +// needs git agreement is proven once against the rendered content. + +/** + * The managed ignore block `clad init` writes for a project that has no + * cladding entry yet: runtime state ignored, gate config committable. + */ +export const CLADDING_IGNORE_BLOCK = '# Cladding runtime state\n.cladding/*\n!.cladding/config.yaml\n'; + +/** + * Whether `.cladding/config.yaml` can be committed under a given `.gitignore`. + * + * - `commitable` — nothing ignores the gate config (no cladding entry at all, + * or the contents form followed by the re-include). + * - `blocked` — the gate config is ignored, so CI and fresh clones cannot see it. + * - `absent` — there is no `.gitignore` file to classify. + */ +export type GateConfigIgnoreStatus = 'commitable' | 'blocked' | 'absent'; + +/** Ignore lines this project recognizes as "the cladding entry", in any generation. */ +const RECOGNIZED_ENTRIES: ReadonlySet = new Set(['.cladding/', '.cladding', '.cladding/*']); + +/** + * Directory-matching forms. Both exclude the directory itself, and git never + * descends into an excluded directory — so no later negation can re-include a + * child. Conservative by design: a hand-crafted file that first excludes the + * directory and then un-excludes it is reported blocked, which only ever + * advises a clearer rewrite. + */ +const DIRECTORY_FORMS: ReadonlySet = new Set(['.cladding/', '.cladding']); + +/** The contents form — excludes children while leaving the directory itself walkable. */ +const CONTENTS_FORM = '.cladding/*'; + +/** The negation that re-includes the gate config; only effective after {@link CONTENTS_FORM}. */ +const GATE_CONFIG_REINCLUDE = '!.cladding/config.yaml'; + +/** + * Trimmed, non-empty, non-comment lines — the only ones git treats as patterns. + */ +function patternLines(text: string): string[] { + return text + .split(/\r?\n/) + .map((line) => line.trim()) + .filter((line) => line.length > 0 && !line.startsWith('#')); +} + +/** + * Whether a `.gitignore` text already carries a cladding ignore entry in any + * recognized generation (`.cladding/`, `.cladding`, or `.cladding/*`). + * + * Used by `clad init` to stay idempotent: when this is true the file is left + * byte-identical, so no adopter's hand-tuned ignore file is rewritten behind + * their back and no migration happens without being asked. + * + * @param gitignoreText - Full text of a `.gitignore`; `''` for an absent file. + * @returns True when a recognized entry is present on its own pattern line. + * @throws Never. + * @example + * ```ts + * hasCladdingIgnoreEntry('node_modules/\n.cladding/\n'); // true (legacy form) + * hasCladdingIgnoreEntry('# .cladding/\n'); // false (comment) + * ``` + * @see spec/features/gate-config-committable-b0c2e724.yaml AC-6a58f0d1 + * @since 0.9.4 + */ +export function hasCladdingIgnoreEntry(gitignoreText: string): boolean { + return patternLines(gitignoreText).some((line) => RECOGNIZED_ENTRIES.has(line)); +} + +/** + * Classifies whether a `.gitignore` lets `.cladding/config.yaml` be committed. + * + * Follows git's own resolution order: the directory forms are terminal (git + * cannot re-include a file whose parent directory is excluded), while the + * contents form is only safe when the re-include comes *after* it — a later + * pattern wins in git, so `!.cladding/config.yaml` above `.cladding/*` is dead. + * + * @param gitignoreText - Full text of the root `.gitignore`, or null/undefined when the file does not exist. + * @returns `absent` for no file, `blocked` when the gate config is ignored, `commitable` otherwise. + * @throws Never; every input maps to a status. + * @example + * ```ts + * gateConfigIgnoreStatus(CLADDING_IGNORE_BLOCK); // 'commitable' + * gateConfigIgnoreStatus('.cladding/\n'); // 'blocked' + * gateConfigIgnoreStatus(null); // 'absent' + * ``` + * @see spec/features/gate-config-committable-b0c2e724.yaml AC-d47b93c5, AC-f30a7c62 + * @since 0.9.4 + */ +export function gateConfigIgnoreStatus(gitignoreText: string | null | undefined): GateConfigIgnoreStatus { + if (gitignoreText === null || gitignoreText === undefined) return 'absent'; + + const lines = patternLines(gitignoreText); + let contentsAt = -1; + let reincludeAt = -1; + for (const [index, line] of lines.entries()) { + if (DIRECTORY_FORMS.has(line)) return 'blocked'; + if (line === CONTENTS_FORM) contentsAt = index; + else if (line === GATE_CONFIG_REINCLUDE) reincludeAt = index; + } + + // No contents exclusion at all → nothing ignores the gate config. + if (contentsAt === -1) return 'commitable'; + return reincludeAt > contentsAt ? 'commitable' : 'blocked'; +} diff --git a/src/init/host-setup.ts b/src/init/host-setup.ts index dfe87fe7..6658dce0 100644 --- a/src/init/host-setup.ts +++ b/src/init/host-setup.ts @@ -718,15 +718,36 @@ function resolveDefaultPkgRoot(): string { } function readCladdingVersion(pkgRoot: string): string { - try { - return (JSON.parse(readFileSync(join(pkgRoot, 'package.json'), 'utf8')) as {version?: string}).version ?? 'unknown'; - } catch { - return 'unknown'; + for (const relativePath of ['package.json', join('.claude-plugin', 'plugin.json')]) { + try { + const version = (JSON.parse(readFileSync(join(pkgRoot, relativePath), 'utf8')) as {version?: unknown}).version; + if (typeof version === 'string' && version.length > 0) return version; + } catch { + // npm installs carry package.json; the self-contained Claude cache carries + // only its plugin manifest. Absence of either source is expected. + } } + return 'unknown'; } -export function getCurrentCladdingVersion(): string | null { - const version = readCladdingVersion(resolveDefaultPkgRoot()); +/** + * Resolves the running engine version across npm and Claude plugin installs. + * + * Claude copies only the plugin subtree into its cache, so `package.json` is + * absent there and `.claude-plugin/plugin.json` is the authoritative fallback. + * + * @param pkgRoot - Optional engine/plugin root; defaults to the discovered runtime root. + * @returns The recorded Cladding version, or null when neither manifest is readable. + * @throws Never; malformed or absent manifests return null. + * @example + * ```ts + * const version = getCurrentCladdingVersion(); + * ``` + * @see spec/features/hook-health-observability-96fa5622.yaml AC-8b386416 + * @since 0.9.4 + */ +export function getCurrentCladdingVersion(pkgRoot: string = resolveDefaultPkgRoot()): string | null { + const version = readCladdingVersion(pkgRoot); return version === 'unknown' ? null : version; } diff --git a/src/serve/server.ts b/src/serve/server.ts index c8930933..3541d536 100644 --- a/src/serve/server.ts +++ b/src/serve/server.ts @@ -174,7 +174,7 @@ export function buildServer(opts: ServerOptions = {}): McpServer { const server = new McpServer( { name: opts.name ?? 'cladding', - version: opts.version ?? '0.9.3', + version: opts.version ?? '0.9.4', }, { instructions: @@ -703,7 +703,7 @@ function registerTools(server: McpServer, cwd: string, onboarding?: OnboardingOp 'Create spec.yaml, spec/architecture.yaml, and spec/capabilities.yaml.', 'Create 1-3 spec/scenarios/*.yaml journey files.', 'Create docs/project-context.md and docs/conventions.md.', - 'Create .cladding/onboarding/state.yaml and append .cladding/ to .gitignore.', + 'Create .cladding/onboarding/state.yaml and append the .cladding/* ignore pair (config.yaml stays committable).', 'Create a managed AGENTS.md block; preserve an existing unmanaged AGENTS.md.', 'Preserve any existing CLAUDE.md unchanged; AGENTS.md is the shared host instruction surface.', ], diff --git a/src/spec/attestation.ts b/src/spec/attestation.ts index ec69b3c5..3d1b5746 100644 --- a/src/spec/attestation.ts +++ b/src/spec/attestation.ts @@ -22,6 +22,47 @@ import type {Feature, Spec} from './types.js'; const ATTESTATION_PATH = ['spec', 'attestation.yaml'] as const; +/** + * Identity of the verification policy that earned an attestation. + * + * @see spec/features/attestation-policy-stamp-caff8598.yaml AC-a4d41de9 + * @since 0.9.4 + */ +export interface AttestationPolicy { + /** Running Cladding engine version, or `unknown` if its manifest was unavailable. */ + readonly cladding: string; + /** Gate policy that promoted warnings and required the full verification ladder. */ + readonly blocking: 'strict'; + /** Full SHA-256 over the ordered detector catalog identity. */ + readonly detectorsSha256: string; +} + +/** + * Fingerprints the ordered detector catalog without serializing functions. + * + * The Cladding version identifies implementation bytes; this digest identifies + * which stable names, order, and subprocess classes were registered. + * + * @param detectors - Ordered detector identities from the live registry. + * @returns A deterministic lowercase, 64-character SHA-256 digest. + * @throws Never for string names and boolean subprocess flags. + * @example + * ```ts + * detectorCatalogSha256([{name: 'STATUS_DRIFT'}]); + * ``` + * @see spec/features/attestation-policy-stamp-caff8598.yaml AC-1f6b157b + * @since 0.9.4 + */ +export function detectorCatalogSha256( + detectors: readonly {readonly name: string; readonly subprocess?: true}[], +): string { + const hash = createHash('sha256'); + detectors.forEach((detector, index) => { + hash.update(`${index}\u0000${detector.name}\u0000${detector.subprocess === true ? 'subprocess' : 'pure'}\n`); + }); + return hash.digest('hex'); +} + /** sha256 over a done feature's modules: sorted path + file bytes per entry. * A missing module file hashes as absent (the MISSING_IMPLEMENTATION * detector owns that error; the hash just has to be deterministic). The v1 @@ -61,6 +102,8 @@ export function moduleFileHash(cwd: string, path: string): string { * absent FILE is signalled by {@link readAttestation} returning `null`. */ export interface AttestationFile { + /** v2.1+ verification-policy identity; null for legacy attestations. */ + readonly policy: AttestationPolicy | null; /** v1 `attested:` section — feature id → module tree-hash. */ readonly v1: Map | null; /** v2 `attested_modules:` section — module path → file hash. */ @@ -85,8 +128,13 @@ export function readAttestation(cwd: string): AttestationFile | null { let v1: Map | null = null; let modules: Map | null = null; let features: Set | null = null; - let section: 'v1' | 'modules' | 'features' | 'other' = 'other'; + const policyFields: {cladding?: string; blocking?: 'strict'; detectorsSha256?: string} = {}; + let section: 'policy' | 'v1' | 'modules' | 'features' | 'other' = 'other'; for (const line of text.split('\n')) { + if (line === 'policy:') { + section = 'policy'; + continue; + } if (line === 'attested:') { section = 'v1'; v1 ??= new Map(); @@ -103,7 +151,14 @@ export function readAttestation(cwd: string): AttestationFile | null { continue; } if (line.startsWith('#') || line.trim() === '') continue; - if (section === 'v1') { + if (section === 'policy') { + const cladding = line.match(/^ {2}cladding: "([^"]+)"$/); + const blocking = line.match(/^ {2}blocking: (strict)$/); + const detectors = line.match(/^ {2}detectors_sha256: ([0-9a-f]{64})$/); + if (cladding) policyFields.cladding = cladding[1]; + if (blocking) policyFields.blocking = blocking[1] as 'strict'; + if (detectors) policyFields.detectorsSha256 = detectors[1]; + } else if (section === 'v1') { const m = line.match(/^ {2}(F-[\w-]+): ([0-9a-f]{16})$/); if (m) v1!.set(m[1], m[2]); } else if (section === 'modules') { @@ -114,7 +169,17 @@ export function readAttestation(cwd: string): AttestationFile | null { if (m) features!.add(m[1]); } } - return {v1, modules, features}; + const policy = + policyFields.cladding !== undefined && + policyFields.blocking === 'strict' && + policyFields.detectorsSha256 !== undefined + ? { + cladding: policyFields.cladding, + blocking: policyFields.blocking, + detectorsSha256: policyFields.detectorsSha256, + } + : null; + return {policy, v1, modules, features}; } /** How many features an attestation vouches for — v2 markers when present, @@ -162,6 +227,8 @@ const HEADER = '# `clad check --tier=pre-push --strict` gate — the file\'s one honest author.\n' + '# Do not edit by hand.\n' + '#\n' + + '# policy: verifier identity: Cladding version, strict blocking,\n' + + '# and SHA-256 of the ordered detector catalog.\n' + '# attested_modules: one line per module file across all done features,\n' + '# value = sha256 of that file\'s bytes (16 hex). Editing a\n' + '# file moves exactly its own line — not every co-owning\n' + @@ -174,12 +241,25 @@ const HEADER = '# `clad check --tier=pre-push --strict`; the GREEN gate rewrites the truth.\n' + '# Content-anchored: survives fresh clones and squash/rebase.\n'; -/** Writes the v2 attestation for every done feature with modules. Only a GREEN - * strict verification run calls this — the file's one honest author. Output is - * whole-file, sorted, LF, deterministic: an unchanged tree rewrites - * byte-identically. Returns false (writing nothing) when there is nothing to - * attest. */ -export function writeAttestation(cwd: string, spec: Spec): boolean { +/** + * Writes the v2 attestation for every done feature with modules. + * + * Only a GREEN strict verification run supplies a policy and calls this in + * production. Output is whole-file, sorted, LF, and deterministic. + * + * @param cwd - Project root containing the attested modules and `spec/`. + * @param spec - Loaded project spec whose done features will be stamped. + * @param policy - Optional verifier identity; omitted only for legacy-compatible callers. + * @returns False without writing when no done feature has modules; otherwise true. + * @throws When the canonical attestation file cannot be written. + * @example + * ```ts + * writeAttestation('/workspace', spec, policy); + * ``` + * @see spec/features/attestation-policy-stamp-caff8598.yaml AC-a4d41de9 + * @since 0.9.4 + */ +export function writeAttestation(cwd: string, spec: Spec, policy?: AttestationPolicy): boolean { const done = (spec.features ?? []).filter((f) => f.status === 'done' && (f.modules ?? []).length > 0); if (done.length === 0) return false; @@ -192,6 +272,12 @@ export function writeAttestation(cwd: string, spec: Spec): boolean { const body = HEADER + + (policy + ? 'policy:\n' + + ` cladding: ${JSON.stringify(policy.cladding)}\n` + + ` blocking: ${policy.blocking}\n` + + ` detectors_sha256: ${policy.detectorsSha256}\n` + : '') + 'attested_modules:\n' + moduleRows.join('\n') + '\n' + diff --git a/src/spec/types.ts b/src/spec/types.ts index 1da5770c..ef88df4c 100644 --- a/src/spec/types.ts +++ b/src/spec/types.ts @@ -127,16 +127,19 @@ export interface Scenario { export interface ArchitectureLayerObject { readonly name?: string; /** - * ADVISORY (not yet enforced). Glob(s) naming the files in this layer. - * `ARCHITECTURE_FROM_SPEC` currently derives a layer's directory from - * `name` (`src//`) and does NOT consume these globs — so a declared - * `modules` is documentation for humans/reviewers, not a live binding. The - * deterministic scan renderer (`renderArchitectureYaml`, src/cli/scan/llm.ts) - * still emits it on `clad init --scan`, so it is live-but-advisory in real - * specs. Marking it advisory (rather than wiring the detector to consume the - * globs) is the deliberate J5b decision recorded in - * spec/features/ac-hash-ids-a04cd9.yaml (AC-003); full consumption stays a - * tracked follow-up there, not a hidden dead link. + * Glob(s) naming the files in this layer, as the deterministic scan + * renderer emits them (`renderArchitectureYaml`, src/cli/scan/llm.ts) on + * `clad init --scan`. + * + * PARTIALLY CONSUMED, by exactly one detector: + * · `UNMAPPED_ARTIFACT` (F-87bb7ed3, AC-96ff696f) takes these globs as + * the layer's scan universe, so a layer whose `name` is not a literal + * path segment is still scanned where its declaration points. + * · `ARCHITECTURE_FROM_SPEC` still derives a layer's directory from + * `name` (`//`) and does NOT read these globs — the + * deliberate J5b decision recorded in + * spec/features/ac-hash-ids-a04cd9.yaml (AC-003). Its forbidden-import + * and empty-layer checks therefore remain name-based. */ readonly modules?: readonly string[]; readonly forbidden_imports?: readonly string[]; diff --git a/src/stages/cov.ts b/src/stages/cov.ts index 7b7afff5..0a41715e 100644 --- a/src/stages/cov.ts +++ b/src/stages/cov.ts @@ -36,6 +36,8 @@ export function runCov(opts: CommandStageOptions = {}): StageResult { pass: false, exitCode: 2, stderr: `no coverage runner registered for language '${language}'`, + // F-c17e1edc — curable skip: declaring gate.commands.coverage turns this on. + skipReason: 'no-runner', }; } // F-49f6f2d2 (#215): on a primed vitest gate the unit stage (stage_2.1) already diff --git a/src/stages/detectors/README.md b/src/stages/detectors/README.md index aff64994..59849ba4 100644 --- a/src/stages/detectors/README.md +++ b/src/stages/detectors/README.md @@ -93,7 +93,7 @@ Each of the remaining 38 is real, but carries a condition — or stays dormant u | **config-dependent** (needs external config / binary) | `HARDCODED_SECRET` (needs `.secretlintrc` + secretlint), `COVERAGE_DROP` (needs coverage report), `PERFORMANCE_DRIFT` (needs perf baseline) | | **code-anchor-dependent** (needs a `// AC-NNN: ` comment in source — no anchor → no catch) | `AC_DRIFT` | | **warn-severity** (does not fail the gate alone) | `MISSING_TESTS`, `STALE_TESTS`, `COVERAGE_DROP`, `STALE_EVIDENCE`, `STALE_SPECIFICATION`, `TECH_STACK_MISMATCH`, `CONVENTION_DRIFT`, `PERFORMANCE_DRIFT`, `UNMAPPED_ARTIFACT` *(default; promoted to error by `--strict`)* | -| **scoped-scan** (narrow glob — drift outside the scan paths is invisible) | `UNMAPPED_ARTIFACT` scans `stages/**` and `spec/**` only | +| **scoped-scan** (bounded universe — drift outside it is invisible) | `UNMAPPED_ARTIFACT` scans declared-layer roots for evidenced extensions (observed known + layer-claimed); legacy narrow globs below the 8-feature scale gate | | **environment** (needs project structure cladding expects) | `HARNESS_INTEGRITY`, `REFERENCE_INTEGRITY`, `META_INTEGRITY` | ### Opt-in strict mode diff --git a/src/stages/detectors/host-claim-drift.ts b/src/stages/detectors/host-claim-drift.ts index 7b288acb..d7461649 100644 --- a/src/stages/detectors/host-claim-drift.ts +++ b/src/stages/detectors/host-claim-drift.ts @@ -10,6 +10,9 @@ // 2. matrix.md — `` // (EVIDENCE: the newest committed smoke result per host, // written by `clad doctor --hosts`). +// 3. matrix.md metadata — generated timestamp + Cladding version. Evidence +// older than 30 days or recorded by an older engine is +// informational: visible debt, never a Phase-0 gate change. // // GENERIC / NO-OP BY DESIGN: the detector fires findings ONLY when BOTH fences // exist. A project without the README claims fence, or without a generated @@ -32,12 +35,16 @@ import {existsSync, readFileSync} from 'node:fs'; import {join} from 'node:path'; +import {getCurrentCladdingVersion} from '../../init/host-setup.js'; import type {CommandStageOptions, DriftDetector, DriftFinding} from '../types.js'; const NAME = 'HOST_CLAIM_DRIFT'; const README_FENCE = //; const MATRIX_FENCE = //; +const MATRIX_VERSION = /^- Cladding version:\s*`([^`]+)`\s*$/m; +const MATRIX_GENERATED = /^- Generated:\s*(\S+)\s*$/m; +const MAX_EVIDENCE_AGE_MS = 30 * 24 * 60 * 60 * 1000; /** Parse a JSON object fence into a host→grade map, or null on absence/parse error. */ function parseFence(text: string, re: RegExp): Record | null { @@ -83,14 +90,46 @@ function claimRank(claim: string): number | null { } } +function numericVersion(version: string): readonly [number, number, number] | null { + const match = version.match(/^(\d+)\.(\d+)\.(\d+)(?:[-+]|$)/); + return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null; +} + +function olderVersion(recorded: string, current: string): boolean { + const left = numericVersion(recorded); + const right = numericVersion(current); + if (!left || !right) return false; + for (let index = 0; index < left.length; index++) { + if (left[index] !== right[index]) return left[index] < right[index]; + } + return false; +} + +function freshnessReasons(matrix: string, now: number): string[] { + const reasons: string[] = []; + const generatedAt = matrix.match(MATRIX_GENERATED)?.[1]; + const generatedTime = generatedAt === undefined ? Number.NaN : Date.parse(generatedAt); + if (Number.isFinite(generatedTime) && now - generatedTime > MAX_EVIDENCE_AGE_MS) { + reasons.push(`generated ${generatedAt}, more than 30 days ago`); + } + const recordedVersion = matrix.match(MATRIX_VERSION)?.[1]; + const currentVersion = getCurrentCladdingVersion(); + if (recordedVersion !== undefined && currentVersion !== null && olderVersion(recordedVersion, currentVersion)) { + reasons.push(`generated by cladding v${recordedVersion}, before the current v${currentVersion}`); + } + return reasons; +} + function detect(cwd: string): readonly DriftFinding[] { const readmePath = join(cwd, 'README.md'); const matrixPath = join(cwd, 'docs', 'dogfood', 'matrix.md'); // No-op unless BOTH surfaces are present (see docstring). if (!existsSync(readmePath) || !existsSync(matrixPath)) return []; - const claims = parseFence(readFileSync(readmePath, 'utf8'), README_FENCE); - const grades = parseFence(readFileSync(matrixPath, 'utf8'), MATRIX_FENCE); + const readme = readFileSync(readmePath, 'utf8'); + const matrix = readFileSync(matrixPath, 'utf8'); + const claims = parseFence(readme, README_FENCE); + const grades = parseFence(matrix, MATRIX_FENCE); if (!claims || !grades) return []; const findings: DriftFinding[] = []; @@ -112,6 +151,18 @@ function detect(cwd: string): readonly DriftFinding[] { }); } } + const hasPositiveClaim = Object.values(claims).some((claim) => claimRank(claim) !== null); + const stale = hasPositiveClaim ? freshnessReasons(matrix, Date.now()) : []; + if (stale.length > 0) { + findings.push({ + detector: NAME, + severity: 'info', + path: 'docs/dogfood/matrix.md', + message: + `Host support evidence needs a fresh receipt: ${stale.join('; ')}. ` + + 'Re-run `clad doctor --hosts` with consent; existing contradictory-claim warnings are unchanged.', + }); + } return findings; } @@ -120,6 +171,14 @@ function run(opts: CommandStageOptions): readonly DriftFinding[] { return detect(cwd); } +/** + * Checks host-support claims against recorded grades and evidence freshness. + * + * @returns The stable detector registration consumed by the Drift stage. + * @see spec/features/host-smoke-matrix-5283985e.yaml AC-922cd29d + * @see spec/features/hook-health-observability-96fa5622.yaml AC-19d3a3d0 + * @since 0.9.4 + */ export const hostClaimDrift: DriftDetector = { name: NAME, run, diff --git a/src/stages/detectors/tech-stack-mismatch.ts b/src/stages/detectors/tech-stack-mismatch.ts index 8cb7b7cb..699914c7 100644 --- a/src/stages/detectors/tech-stack-mismatch.ts +++ b/src/stages/detectors/tech-stack-mismatch.ts @@ -1,44 +1,125 @@ // Cladding · drift detector · TECH_STACK_MISMATCH // -// Detector #4 from the catalog (axis: spec_vs_code, severity: warn). -// Compares `spec.project.language` against the language `detectToolchain` -// resolves from the actual project manifest. A mismatch means the spec -// claims one language while the codebase is shaped like another — the -// classic "we ported to TS but spec.yaml still says python" drift. +// Detector #4 from the catalog (axis: spec_vs_code). Answers ONE question: +// does `spec.project.language` contradict the source files on disk? +// +// EVIDENCE MODEL — the files, not the manifest. +// The declared language is compared against the observed distribution of +// source files (`core/language-evidence.ts`), under two guards: +// +// 1. declared language outside the vocabulary → silence. Cladding does +// not know zig or haskell; ignorance is not drift. +// 2. fewer than EVIDENCE_FLOOR classified files → silence. A tree with +// three files cannot support an assertion about what it is. +// +// Then: declared absent from the observed set → one `warn` (an active +// contradiction — ported to TypeScript, spec still says python — which +// still blocks under `--strict`, with the counts shown so the developer +// can see why). Declared present but under MINORITY_SHARE → one `info`, +// never a blocking severity. Anything else → silence. +// +// WHY THERE IS DELIBERATELY NO COVERAGE-RATIO RULE. +// An earlier design guarded on "what fraction of source files did we +// classify at all". Red-team testing refuted it out-of-sample: the rule's +// behaviour hinged entirely on whether an unrecognised extension sat in +// the denominator list. In-list, an unclassifiable tree looked +// well-covered and REAL drift went unreported; out-of-list, an ordinary +// project using one unlisted extension tripped a FALSE warn. The failure +// direction flipped on a list edit, which makes the rule unownable. The +// evidence-count floor replaces it and deletes the list entirely. +// +// WHY THE MANIFEST CHAIN IS NOT CONSULTED HERE. +// `detectToolchain` resolves the BUILD HOST (a gradle wrapper resolves +// java, whatever the product is written in). That is exactly the right +// question for "which commands do we run" — where it keeps serving, and +// which this change does not touch — and exactly the wrong question for +// "what IS this project". Using it for identity let a build-host label +// contradict a truthful product language: the manifest comparison +// blocked 12 of 19 realistic normal repo shapes (63%) under `--strict`. +// +// WHY THE MINORITY BAND DISCLOSES INSTEAD OF BLOCKING. +// A boundary attack found a legitimate thin native SDK at 4.8% sitting +// BELOW a genuine ported-residue case at 8.3%: residue and thin-core are +// not mechanically separable, so the band says so out loud and moves on. +// +// @see F-9e1279d4 — language evidence core. -import {detectToolchain} from '../toolchain/detect.js'; +import {classifySources, LANGUAGE_VOCABULARY} from '../../core/language-evidence.js'; import type {Spec} from '../../spec/types.js'; import type {CommandStageOptions, DriftDetector, DriftFinding} from '../types.js'; import {withSpec} from './with-spec.js'; const NAME = 'TECH_STACK_MISMATCH'; +/** + * Minimum classified source files before the detector will assert + * anything. Corpus-supported range [3, 10]; 5 is the chosen point — + * low enough to catch a small ported repo, high enough that a scaffold + * or a docs-only checkout stays silent. + */ +const EVIDENCE_FLOOR = 5; + +/** + * Share below which a declared-but-present language is merely disclosed. + * Corpus-supported range [9%, 50%]; 10% is the chosen point — a higher + * threshold only adds `info` noise on ordinary polyglot repositories. + */ +const MINORITY_SHARE = 0.10; + function runTechStackMismatch(opts: CommandStageOptions): readonly DriftFinding[] { const {cwd = '.'} = opts; return withSpec(cwd, NAME, (spec) => detect(spec, cwd)); } +/** + * Renders the observed distribution most-seen first, e.g. + * `{typescript ×20, python ×3}`. Alphabetical tie-break keeps the + * message deterministic across filesystems. + */ +function renderDistribution(counts: Readonly>): string { + const parts = Object.keys(counts) + .sort((a, b) => counts[b] - counts[a] || a.localeCompare(b)) + .map((language) => `${language} ×${counts[language]}`); + return `{${parts.join(', ')}}`; +} + function detect(spec: Spec, cwd: string): readonly DriftFinding[] { - const detected = detectToolchain(cwd).language; - if (detected === 'unknown') { + const declared = spec.project?.language ?? ''; + // Rule 1 — a language cladding has no vocabulary for cannot be judged. + if (!LANGUAGE_VOCABULARY.has(declared)) return []; + + const evidence = classifySources(cwd); + // Rule 2 — too few classified files to assert anything about the tree. + if (evidence.classified < EVIDENCE_FLOOR) return []; + + // Rule 3 — declared language is nowhere in the tree: an active contradiction. + if (!evidence.set.includes(declared)) { + return [ + { + detector: NAME, + severity: 'warn', + message: + `spec.project.language='${declared}' but the observed sources are ` + + `${renderDistribution(evidence.counts)} — the spec no longer matches the tree`, + }, + ]; + } + + // Rule 4 — present but a sliver: disclose the share, never block on it. + if (evidence.share(declared) < MINORITY_SHARE) { return [ { detector: NAME, severity: 'info', - message: 'no manifest matched — language cannot be cross-checked', + message: + `spec.project.language='${declared}' is a minority of observed sources ` + + `(${evidence.counts[declared]}/${evidence.classified}) — disclosed, not blocking`, }, ]; } - if (spec.project.language === detected) return []; - return [ - { - detector: NAME, - severity: 'warn', - message: - `spec.project.language='${spec.project.language}' but the manifest` + - ` chain detects '${detected}'`, - }, - ]; + + // Rule 5 — declared language is a majority or plural presence: nothing to say. + return []; } export const techStackMismatch: DriftDetector = { diff --git a/src/stages/detectors/unmapped-artifact.ts b/src/stages/detectors/unmapped-artifact.ts index bcc59a30..225c9679 100644 --- a/src/stages/detectors/unmapped-artifact.ts +++ b/src/stages/detectors/unmapped-artifact.ts @@ -5,13 +5,58 @@ // MISSING_IMPLEMENTATION: it scans real source files and flags any // that no feature in spec.yaml claims via `features[].modules`. // +// The scan universe is EVIDENCE, never a language label (F-87bb7ed3). +// Three sources compose, each covering the others' blind spots: +// +// 1. Declared layer globs — a layer written in object form with its +// own `modules: ["core/src/main/cpp/**"]` has already said where it +// lives, so that layer's patterns are its globs crossed with the +// evidenced extensions and name-segment inference is not used for +// it at all. The defect this repairs (external E2E, D1): two specs +// identical except the layer name — `core` (a real path segment) +// reported 21 unclaimed files, `native` (no matching segment) +// reported 0, silently, though both declared the same glob. The +// declared architecture is the SSoT; the detector was ignoring a +// surface the schema already carried. +// 2. Observation — every vocabulary-known extension that actually +// occurs in the tree (core/language-evidence). This covers the +// lazy spec: an unclaimed `.cpp` file stays visible even when the +// spec claims only `.java` ones, which is the exact case this +// detector exists for. +// 3. Claimed modules — the extension and the root of every module a +// feature claims under a declared layer. This teaches languages +// the vocabulary has never heard of: a claimed `.zig` file enters +// the universe with no table to grow, and a claimed +// `src/main/kotlin/core/A.kt` teaches the root `src/main/kotlin` +// that used to need a per-language table entry. +// +// `EXT_BY_LANGUAGE` and `ROOT_BY_LANGUAGE` are gone, and with them every +// read of `spec.project.language`. Those tables knew six languages, so a +// project declaring `cpp`, `java`, or `csharp` fell through to a `*.ts` +// glob that matched nothing — a silent pass on precisely the projects +// the module→feature honesty check is for. A label can be wrong; what +// is on disk and what the spec claims cannot be mislabelled the same way. +// +// A universe can still come out empty: a layer name matching no directory, +// a declared glob pointing at a moved tree, a tree of extensions nothing +// knows or claims. Zero scanned files reads exactly like a clean bill of +// health, so it is never silent — an ACTIVE full scan that matches nothing +// emits ONE `info` finding naming the layers and the roots it looked under +// (AC-e20dbafe). Below the scale gate, and whenever files were scanned, +// the diagnostic stays quiet. +// // Pure spec ↔ filesystem comparison, no OSS for the *logic* — though // glob scanning is delegated to `tinyglobby` because Node's stdlib // doesn't ship a globber. +// +// @see spec/features/self-describing-scan-universe-87bb7ed3.yaml + +import {extname} from 'node:path'; import {globSync} from 'tinyglobby'; -import type {Spec} from '../../spec/types.js'; +import {observedKnownExtensions} from '../../core/language-evidence.js'; +import type {Architecture, ArchitectureLayerObject, Spec} from '../../spec/types.js'; import type {CommandStageOptions, DriftDetector, DriftFinding} from '../types.js'; import {normalizeArchitecture} from './architecture-from-spec.js'; import {withSpec} from './with-spec.js'; @@ -25,48 +70,275 @@ const NAME = 'UNMAPPED_ARTIFACT'; */ const LEGACY_SCAN_PATTERNS: readonly string[] = ['src/stages/**/*.ts', 'src/spec/**/*.ts']; -const EXT_BY_LANGUAGE: Record = { - typescript: 'ts', - javascript: 'js', - python: 'py', - rust: 'rs', - go: 'go', - kotlin: 'kt', -}; +const MIN_FEATURES_FOR_FULL_SCAN = 8; // same scale-gate idiom as HOLLOW_GOVERNANCE et al. + +/** Where layer directories live when no claimed module teaches a root. */ +const DEFAULT_ROOT = 'src'; /** - * Layer-scan root per language. Defaults to `src` (where the other - * languages keep their layer dirs); Kotlin nests its layers under the - * Gradle/Maven `src/main/kotlin` source set. + * Share of layer-claimed modules a root must carry to become a scan root. + * + * Root inference reads a path segment, so any directory that happens to + * reuse a layer name teaches a root: `tests/spec/parse.test.ts` teaches + * `tests`, `skills/init/SKILL.md` teaches `skills`. Those are name + * collisions, not source roots, and admitting them turns every mirrored + * test tree into hundreds of "unclaimed" findings — the false-RED class + * the scale gate below exists to prevent. A real second source root + * carries a substantial share of the claims (a Gradle project split + * across `src/main/kotlin` and `src/main/java` is near 50/50); an + * incidental collision carries a thin tail. Measured on the dogfood repo + * (279 features, 811 layer-claimed modules): unfiltered inference yields + * 430 findings, all from collisions; at this threshold `src` alone + * survives with 86% of the claims and the finding count is 0. */ -const ROOT_BY_LANGUAGE: Record = { - kotlin: 'src/main/kotlin', -}; +const MIN_ROOT_SHARE = 0.25; /** - * F-aee61f — the scan universe derives from the DECLARED architecture: one - * `src//**` pattern per layer (both string-tier and {name} object - * forms), extension from project.language. Before this, two hardcoded - * directories left the module→feature honesty check blind to 13 of - * cladding's own 15 src/ directories — a confidently wrong map is worse - * than none. No architecture declared → legacy narrow fallback. - * Exported for tests. + * Reads the `modules` globs each declared layer carries, keyed by layer name. + * + * `normalizeArchitecture` stays the SSoT for WHICH layers exist — it is + * shared with ARCHITECTURE_FROM_SPEC and answers with names only. The globs + * are read here, locally, because this detector is the one that consumes + * them; layers declared in the canonical tier form (`[[cli, serve]]`) carry + * no globs and are absent from the map. + * + * @param arch - `spec.architecture`, in either declared shape. + * @returns Layer name → its non-empty declared globs; layers without globs + * are omitted, so `has(layer)` answers "declares its own location". */ -const MIN_FEATURES_FOR_FULL_SCAN = 8; // same scale-gate idiom as HOLLOW_GOVERNANCE et al. +function declaredGlobs(arch: Architecture): ReadonlyMap { + const byLayer = new Map(); + for (const tier of arch.layers ?? []) { + if (Array.isArray(tier)) continue; // canonical tier form: names, no globs + const layer = tier as ArchitectureLayerObject; + if (typeof layer.name !== 'string' || layer.name.length === 0) continue; + const globs = (layer.modules ?? []).filter( + (glob): glob is string => typeof glob === 'string' && glob.length > 0, + ); + if (globs.length === 0) continue; + byLayer.set(layer.name, [...(byLayer.get(layer.name) ?? []), ...globs]); + } + return byLayer; +} + +/** + * The literal directory prefix of a declared glob — everything before its + * first wildcard, slash-terminated: `core/src/main/cpp/**` and a + * wildcard-free `core/src/main/cpp` both yield `core/src/main/cpp/`. + * + * Deliberately not a glob matcher. The only question asked of it is "does + * this claimed module live where the layer says the layer lives", and a + * prefix answers that for the directory globs `clad init --scan` writes + * without pulling in a matching engine. + */ +function globPrefix(glob: string): string { + const star = glob.indexOf('*'); + const literal = star < 0 ? glob : glob.slice(0, star); + return literal.length === 0 || literal.endsWith('/') ? literal : `${literal}/`; +} + +/** + * Expands one declared glob into the scan pattern for `ext`. + * + * A glob that already ends in a recursive wildcard keeps that recursion and + * only gains the file part; any other form gains the recursion too — so a + * bare directory glob (`core/src/main/cpp`) and its wildcard spelling scan + * the same tree. + * + * Both branches treat the declared glob as a DIRECTORY, which is the shape + * the scan renderer writes. A hand-written glob that already names files + * (`src/core/*.ts`) therefore expands to a pattern matching nothing; when + * that leaves the whole scan empty, the finding below reports it rather + * than passing silently. + */ +function expandGlob(glob: string, ext: string): string { + return glob.endsWith('**') ? `${glob}/*${ext}` : `${glob}/**/*${ext}`; +} + +/** What the spec's own module claims teach about the scan universe. */ +interface ClaimedEvidence { + /** Path prefixes that precede a declared layer name, dominance-filtered. */ + readonly roots: readonly string[]; + /** Extensions claimed under one of those roots or under a declared glob. */ + readonly extensions: readonly string[]; +} + +/** + * Reads roots and extensions out of `features[].modules`. + * + * A module teaches only when it is layer-claimed, and there are two ways to + * be: it sits under an inferred root + a declared layer name (the root it + * teaches must then survive the dominance filter), or its path starts with + * the literal prefix of a glob some layer declares. Anything else teaches + * nothing — a root-level `CHANGELOG.md` claim cannot widen the source + * universe. + * + * @param spec - The loaded spec; `features[].modules` is the only field read. + * @param layers - Declared layer names, for the name-segment match. + * @param globPrefixes - Literal prefixes of every declared layer glob. + */ +function claimedEvidence( + spec: Spec, + layers: ReadonlySet, + globPrefixes: readonly string[], +): ClaimedEvidence { + const claimsByRoot = new Map(); + const extensionsByRoot = new Map>(); + const underDeclaredGlob = new Set(); + let total = 0; + + for (const feature of spec.features ?? []) { + for (const modulePath of feature.modules ?? []) { + const segments = modulePath.split('/'); + const ext = extname(segments[segments.length - 1]); + + // A layer's own glob needs no root inference — the declaration already + // located the layer, so a claim under it only teaches its extension. + if (ext !== '' && globPrefixes.some((prefix) => modulePath.startsWith(prefix))) { + underDeclaredGlob.add(ext); + } + + // The last segment is the file itself — a file named like a layer + // is not a directory the layer lives in. + const layerAt = segments.findIndex( + (segment, i) => i < segments.length - 1 && layers.has(segment), + ); + if (layerAt < 0) continue; + + const root = segments.slice(0, layerAt).join('/'); + claimsByRoot.set(root, (claimsByRoot.get(root) ?? 0) + 1); + total += 1; -export function scanPatterns(spec: Spec): readonly string[] { + if (ext === '') continue; // a claimed directory teaches its root, not an extension + const known = extensionsByRoot.get(root) ?? new Set(); + known.add(ext); + extensionsByRoot.set(root, known); + } + } + + const roots: string[] = []; + const extensions = new Set(underDeclaredGlob); + for (const [root, claims] of claimsByRoot) { + if (claims / total < MIN_ROOT_SHARE) continue; + roots.push(root); + for (const ext of extensionsByRoot.get(root) ?? []) extensions.add(ext); + } + return {roots, extensions: [...extensions]}; +} + +/** The resolved scan universe plus what it took to build it. */ +interface ScanUniverse { + /** Globs to scan; the legacy narrow pair when the scale gate is not met. */ + readonly patterns: readonly string[]; + /** True only when the evidence universe is active (≥8 features + layers). */ + readonly fullScan: boolean; + /** Declared layer names, in declaration order. */ + readonly layers: readonly string[]; + /** Where the scan looked: inferred roots, and each declared layer glob. */ + readonly roots: readonly string[]; + /** True when every declared layer brought its own globs. */ + readonly everyLayerDeclaresGlobs: boolean; +} + +const LEGACY_UNIVERSE: ScanUniverse = { + patterns: LEGACY_SCAN_PATTERNS, + fullScan: false, + layers: [], + roots: [], + everyLayerDeclaresGlobs: false, +}; + +/** + * Resolves the glob set the detector scans, plus the layers and roots that + * produced it (the empty-universe diagnostic reports them). + * + * Per layer, one of two derivations runs — never both: + * · the layer declared `modules` globs → its patterns are those globs + * crossed with the evidenced extensions (AC-96ff696f); + * · it did not → one pattern per inferred scan root, the layer NAME as a + * path segment, and each evidenced extension (AC-9a6f02d3). + * + * The extension set is shared by both: observed known extensions united + * with the layer-claimed ones. + */ +function scanUniverse(spec: Spec, cwd: string): ScanUniverse { // Scale-gated (F-aee61f): a fresh adoption legitimately has scan-derived // architecture layers but features accumulating on demand — instantly // flagging every not-yet-claimed file would wall off day-1 adoption (the // false-RED class the 0.6 design review warned about). Once the project // is grown (≥8 features), an unclaimed file in a declared layer is drift. - if ((spec.features ?? []).length < MIN_FEATURES_FOR_FULL_SCAN) return LEGACY_SCAN_PATTERNS; - const {layers} = normalizeArchitecture(spec.architecture ?? {}); - if (layers.size === 0) return LEGACY_SCAN_PATTERNS; - const language = spec.project?.language ?? ''; - const ext = EXT_BY_LANGUAGE[language] ?? 'ts'; - const root = ROOT_BY_LANGUAGE[language] ?? 'src'; - return [...layers].sort().map((l) => `${root}/${l}/**/*.${ext}`); + if ((spec.features ?? []).length < MIN_FEATURES_FOR_FULL_SCAN) return LEGACY_UNIVERSE; + const architecture = spec.architecture ?? {}; + const {layers} = normalizeArchitecture(architecture); + if (layers.size === 0) return LEGACY_UNIVERSE; + + const globsByLayer = declaredGlobs(architecture); + const globPrefixes = [...globsByLayer.values()].flat().map(globPrefix); + const claimed = claimedEvidence(spec, layers, globPrefixes); + const roots = claimed.roots.length > 0 ? claimed.roots : [DEFAULT_ROOT]; + const extensions = new Set([...observedKnownExtensions(cwd), ...claimed.extensions]); + + const patterns = new Set(); + const searched = new Set(); + for (const layer of layers) { + const globs = globsByLayer.get(layer); + if (globs !== undefined) { + for (const glob of globs) { + searched.add(glob); + for (const ext of extensions) patterns.add(expandGlob(glob, ext)); + } + continue; + } + for (const root of roots) { + // An empty root means the layers sit at the repository root itself. + const prefix = root === '' ? '' : `${root}/`; + searched.add(root === '' ? '.' : root); + for (const ext of extensions) patterns.add(`${prefix}${layer}/**/*${ext}`); + } + } + + return { + patterns: [...patterns].sort(), + fullScan: true, + layers: [...layers], + roots: [...searched], + everyLayerDeclaresGlobs: globsByLayer.size === layers.size, + }; +} + +/** + * Builds the glob set the detector scans: one pattern per declared layer + * glob, or per scan root and layer name when the layer declares none. + * + * @param spec - The loaded spec; read for features, architecture, and + * module claims — never for `project.language`. + * @param cwd - Project root, walked once for the observed extensions. + * @returns Sorted, deduplicated glob patterns; the legacy narrow pair + * when the full-scan scale gate is not met. + */ +export function scanPatterns(spec: Spec, cwd: string): readonly string[] { + return scanUniverse(spec, cwd).patterns; +} + +/** + * The single `info` finding for an active full scan that matched nothing. + * + * An empty universe and a fully-claimed tree produce the same silence, and + * only one of them is good news — so the scan says where it looked and what + * would move it. Info severity: it never blocks a gate, it just refuses to + * let a scan of nothing read as a pass (AC-e20dbafe). + */ +function emptyUniverseFinding(universe: ScanUniverse): DriftFinding { + const advice = universe.everyLayerDeclaresGlobs + ? 'check the declared layer modules globs against the tree' + : 'declare layer modules globs or align layer names with directories'; + return { + detector: NAME, + severity: 'info', + message: + `full scan matched no files — layers {${universe.layers.join(', ')}} ` + + `under roots {${universe.roots.join(', ')}}; ${advice}`, + }; } /** @@ -75,8 +347,8 @@ export function scanPatterns(spec: Spec): readonly string[] { * Returns one `error` finding per unclaimed file. When spec.yaml is * absent or unparseable, returns a single `info` finding (opt-in: * spec-less projects keep green CI). The detector intentionally does - * not walk the entire repo — only the directories cladding's own - * tsconfig declares as source. + * not walk the entire repo — only the roots, globs, and layers the spec + * and the tree together evidence as source. * * @see iron-law.md stage_1.3 — detector contract. * @see ironclad-design/08-drift-detectors.md — UNMAPPED_ARTIFACT (#1). @@ -92,7 +364,16 @@ function detect(spec: Spec, cwd: string): readonly DriftFinding[] { for (const modulePath of feature.modules ?? []) claimed.add(modulePath); } - const files = globSync([...scanPatterns(spec)], {cwd, dot: false}); + const universe = scanUniverse(spec, cwd); + // No evidenced extension means no source universe. Guarded rather than + // handed to the globber, so "nothing to scan" can never be read as + // "scan everything". + const files = + universe.patterns.length === 0 ? [] : globSync([...universe.patterns], {cwd, dot: false}); + // Empty patterns and matching patterns that find nothing are the same + // outcome — a scan that inspected no file — and both are reported. + if (universe.fullScan && files.length === 0) return [emptyUniverseFinding(universe)]; + const findings: DriftFinding[] = []; for (const file of files) { if (claimed.has(file)) continue; diff --git a/src/stages/lint.ts b/src/stages/lint.ts index 5fa08b86..8f5faee8 100644 --- a/src/stages/lint.ts +++ b/src/stages/lint.ts @@ -60,6 +60,8 @@ export function runLint(opts: CommandStageOptions = {}): StageResult { pass: false, exitCode: 2, stderr: `no linter registered for language '${language}'`, + // F-c17e1edc — curable skip: declaring gate.commands.lint turns this on. + skipReason: 'no-runner', }; } const proc = execaSync(cmd, [...args], {cwd, reject: false}); diff --git a/src/stages/type.ts b/src/stages/type.ts index b8cf5f61..e4055d7f 100644 --- a/src/stages/type.ts +++ b/src/stages/type.ts @@ -53,6 +53,8 @@ export function runType(opts: CommandStageOptions = {}): StageResult { pass: false, exitCode: 2, stderr: `no type checker registered for language '${language}'`, + // F-c17e1edc — curable skip: declaring gate.commands.type turns this on. + skipReason: 'no-runner', }; } const proc = execaSync(cmd, [...args], {cwd, reject: false}); diff --git a/src/stages/types.ts b/src/stages/types.ts index 2a6ad7d0..835971b4 100644 --- a/src/stages/types.ts +++ b/src/stages/types.ts @@ -61,6 +61,19 @@ export interface StageResult { * absent on green stages and on stages with no known fix command. */ readonly hint?: string; + /** + * NEW (F-c17e1edc) — WHY this skip (exitCode 2) happened, structured so the + * renderer and machine consumers stop parsing stderr prose: + * no-runner — cladding knows no command for this stage in this project + * (`no registered for language '…'`). Curable by ONE + * declaration: `gate.commands` in `.cladding/config.yaml`. + * tool-missing — the resolved tool is absent (ENOENT) or `npx` cannot fetch + * it offline. The command IS known; the environment lacks it. + * By-design skips stay UNTAGGED — a missing spec-conformance oracle or an + * undeclared deliverable is "this stage does not apply", and prescribing + * `gate.commands` there would be a false cure. Absent on pass/fail results. + */ + readonly skipReason?: 'no-runner' | 'tool-missing'; } /** Shared options for any stage that wraps an external command. */ diff --git a/src/stages/unit.ts b/src/stages/unit.ts index 192b1886..f9d80243 100644 --- a/src/stages/unit.ts +++ b/src/stages/unit.ts @@ -200,6 +200,8 @@ export function runUnit(opts: UnitStageOptions = {}): StageResult { pass: false, exitCode: 2, stderr: `no unit test runner registered for language '${language}'`, + // F-c17e1edc — curable skip: declaring gate.commands.test turns this on. + skipReason: 'no-runner', }; } // Guard applies only under --strict on a vitest runner (the only path we can diff --git a/src/stages/util.ts b/src/stages/util.ts index 2a45968c..3be6564c 100644 --- a/src/stages/util.ts +++ b/src/stages/util.ts @@ -104,7 +104,9 @@ export function missingToolSkip( args: readonly string[] = [], ): StageResult | null { if (isMissingBinary(proc)) { - return {stage, pass: false, exitCode: 2, stderr: `'${cmd}' not installed`}; + // F-c17e1edc — the command IS known; the environment lacks it. Tagged + // `tool-missing` so the renderer never prescribes `gate.commands` here. + return {stage, pass: false, exitCode: 2, stderr: `'${cmd}' not installed`, skipReason: 'tool-missing'}; } const output = `${String(proc.stderr ?? '')}\n${String(proc.stdout ?? '')}`; const npxResolutionFailure = @@ -121,6 +123,9 @@ export function missingToolSkip( stderr: "setup gap: 'npx' could not resolve the configured tool without installing it; " + 'the inferred tool is not installed or unavailable offline', + // F-c17e1edc — same lane as ENOENT: a resolution/installation gap, not an + // absent runner declaration. + skipReason: 'tool-missing', }; } return null; diff --git a/src/ui/softShell.ts b/src/ui/softShell.ts index 29a4a0cc..d57dc8d8 100644 --- a/src/ui/softShell.ts +++ b/src/ui/softShell.ts @@ -145,7 +145,7 @@ export const DETECTOR_PLAIN: Readonly> = { ARCHITECTURE_VIOLATION: {lead: 'The code has an import loop or crosses a layer boundary the design forbids', action: 'break the import cycle or remove the disallowed import'}, MISSING_IMPLEMENTATION: {lead: 'The spec lists a file that is not on disk yet', action: 'create the file, or remove it from the feature module list'}, UNMAPPED_ARTIFACT: {lead: 'A source file exists that no feature in the spec claims', action: 'add it to a feature module list, or delete the file'}, - TECH_STACK_MISMATCH: {lead: 'The spec names one programming language but the code looks like another', action: 'update project.language in the spec to match the code'}, + TECH_STACK_MISMATCH: {lead: 'The spec names one programming language but the source files on disk are another', action: 'update project.language to a language the source tree actually contains'}, STATUS_DRIFT: {lead: 'A feature is marked done but its files or checks do not back that up', action: 'add the missing modules, or set the status back'}, STALE_SPECIFICATION: {lead: "A feature's lifecycle labels don't match its actual state", action: 'reconcile the feature status and archive fields'}, REFERENCE_INTEGRITY: {lead: 'The spec points to a feature id that does not exist', action: 'fix the reference or add the missing feature'}, diff --git a/src/verdict/gate-progress.ts b/src/verdict/gate-progress.ts index a0e5d711..85c9bcf8 100644 --- a/src/verdict/gate-progress.ts +++ b/src/verdict/gate-progress.ts @@ -15,8 +15,9 @@ // state in; the reducer (src/verdict/verdict.ts) takes `stuck` as an input. So // the whole thing stays unit-testable in isolation and, critically, the GATE is // never touched — verdict computes the fingerprint from the result it already -// receives (the `gate_run` event is deduped by (head,tier,strict,worst), so two -// identical stuck runs collapse to ONE event; "stuck" cannot be read from there). +// receives (the `gate_run` event dedupes identical outcomes plus blocker +// evidence, so two identical stuck runs collapse to ONE event; "stuck" cannot +// be read from there). // // SOUNDNESS (AC-a2320103): the fingerprint hashes ONLY `detector|path`, sorted + // deduped — message-free, line-free, temp-path-free. A fingerprint too NARROW diff --git a/tests/cli/ci-version.test.ts b/tests/cli/ci-version.test.ts new file mode 100644 index 00000000..ae1cd9f2 --- /dev/null +++ b/tests/cli/ci-version.test.ts @@ -0,0 +1,60 @@ +import {mkdirSync, mkdtempSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {dirname, join} from 'node:path'; + +import {afterEach, beforeEach, describe, expect, test} from 'vitest'; + +import {claddingMajorMinor, readCiVersionHealth} from '../../src/cli/ci-version.js'; + +describe('CI version health', () => { + let dir: string; + + beforeEach(() => { + dir = mkdtempSync(join(tmpdir(), 'clad-ci-version-')); + }); + + afterEach(() => { + rmSync(dir, {recursive: true, force: true}); + }); + + function write(relativePath: string, body: string): void { + const path = join(dir, relativePath); + mkdirSync(dirname(path), {recursive: true}); + writeFileSync(path, body, 'utf8'); + } + + test('finds unpinned and floating Cladding npx calls in yml and yaml workflows', () => { + write('.github/workflows/z-unpinned.yml', 'steps:\n - run: npx --yes cladding check --strict\n'); + write('.github/workflows/nested/a-floating.yaml', 'steps:\n - run: npx cladding@latest doctor\n'); + write('.github/workflows/pinned.yml', 'steps:\n - run: npx --yes cladding@0.9 check --strict\n'); + + expect(readCiVersionHealth(dir)).toEqual({ + unpinnedWorkflows: [ + '.github/workflows/nested/a-floating.yaml', + '.github/workflows/z-unpinned.yml', + ], + }); + }); + + test('accepts numeric selectors and ignores comments or unrelated commands', () => { + write( + '.github/workflows/safe.yml', + [ + '# run: npx --yes cladding check --strict', + 'steps:', + ' - run: npx --yes cladding@0.9 check --strict', + ' - run: npx cladding@0.9.3 doctor', + ' - run: npx cladding@0.9.4-beta.1 check', + ' - run: npx eslint .', + ' - run: npm ci', + '', + ].join('\n'), + ); + + expect(readCiVersionHealth(dir).unpinnedWorkflows).toEqual([]); + expect(claddingMajorMinor('0.9.3')).toBe('0.9'); + expect(claddingMajorMinor('10.12.0-beta.1+build.7')).toBe('10.12'); + expect(claddingMajorMinor(null)).toBeNull(); + expect(claddingMajorMinor('latest')).toBeNull(); + }); +}); diff --git a/tests/cli/clad.test.ts b/tests/cli/clad.test.ts index 1891590e..7e173291 100644 --- a/tests/cli/clad.test.ts +++ b/tests/cli/clad.test.ts @@ -561,7 +561,7 @@ describe('cli/clad — createProgram', () => { test('program version matches current package version', () => { const program = clad.createProgram(); - expect(program.version()).toBe('0.9.3'); + expect(program.version()).toBe('0.9.4'); }); }); diff --git a/tests/cli/doctor.test.ts b/tests/cli/doctor.test.ts index 50695413..b09dba8e 100644 --- a/tests/cli/doctor.test.ts +++ b/tests/cli/doctor.test.ts @@ -7,7 +7,7 @@ // readEvents would test less than the file-based path. import {afterEach, beforeEach, describe, expect, test, vi} from 'vitest'; -import {appendFileSync, mkdirSync, mkdtempSync, rmSync, writeFileSync} from 'node:fs'; +import {appendFileSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync} from 'node:fs'; import {tmpdir} from 'node:os'; import {join} from 'node:path'; @@ -27,6 +27,31 @@ function seedEvents(cwd: string, events: readonly EventLine[]): void { } } +function seedHookHealth(cwd: string): void { + mkdirSync(join(cwd, '.cladding'), {recursive: true}); + writeFileSync( + join(cwd, '.cladding', 'hook-health.json'), + `${JSON.stringify({ + schemaVersion: 1, + engineVersion: '0.0.1', + lastFiredAt: { + SessionStart: '2026-08-10T00:00:00.000Z', + PostToolUse: '2026-08-10T00:05:00.000Z', + }, + })}\n`, + 'utf8', + ); +} + +function seedGitignore(cwd: string, body: string): void { + writeFileSync(join(cwd, '.gitignore'), body, 'utf8'); +} + +function seedWorkflow(cwd: string, name: string, body: string): void { + mkdirSync(join(cwd, '.github', 'workflows'), {recursive: true}); + writeFileSync(join(cwd, '.github', 'workflows', name), body, 'utf8'); +} + describe('clad doctor handler', () => { let dir: string; let exitCalls: number[]; @@ -60,6 +85,9 @@ describe('clad doctor handler', () => { const out = stdoutChunks.join(''); expect(out).toContain('doctor'); expect(out).toContain('no events recorded'); + expect(out).toContain('Claude Code hooks'); + expect(out).toContain('runtime: not observed'); + expect(out.match(/never observed/g)).toHaveLength(5); }); test('healthy: events but zero sentinel_miss → pass pulse + event-type line + exit 0', () => { @@ -109,6 +137,7 @@ describe('clad doctor handler', () => { }); test('--json: emits the raw DoctorReport and skips the formatted surface', () => { + seedHookHealth(dir); seedEvents(dir, [ {id: '1', timestamp: 't', type: 'sentinel_miss', payload: { phase: 'scan_artifacts', cause: 'blank_section', fallback: 'per_artifact', missed_sections: ['CAPABILITIES_YAML'], @@ -124,6 +153,17 @@ describe('clad doctor handler', () => { expect(parsed.sentinelMiss.topMissedSections[0]).toEqual({name: 'CAPABILITIES_YAML', count: 1}); expect(parsed.events.total).toBe(1); expect(parsed.events.byType.sentinel_miss).toBe(1); + expect(parsed.hooks.installation).toBe('observed'); + expect(parsed.hooks.recordedVersion).toBe('0.0.1'); + expect(parsed.hooks.versionCurrent).toBe(false); + expect(parsed.hooks.lastFiredAt).toEqual({ + SessionStart: '2026-08-10T00:00:00.000Z', + UserPromptSubmit: null, + PreToolUse: null, + PostToolUse: '2026-08-10T00:05:00.000Z', + Stop: null, + }); + expect(parsed.ciVersion).toEqual({unpinnedWorkflows: []}); // The formatted-text surface (pulse line, "Sentinel-miss breakdown") // is suppressed under --json so callers parse the JSON cleanly. expect(out).not.toContain('Sentinel-miss breakdown'); @@ -136,6 +176,94 @@ describe('clad doctor handler', () => { expect(parsed.events.total).toBe(0); expect(parsed.sentinelMiss.total).toBe(0); expect(parsed.sentinelMiss.byPhase).toEqual({}); + expect(parsed.hooks.installation).toBe('not-observed'); + expect(Object.values(parsed.hooks.lastFiredAt)).toEqual([null, null, null, null, null]); + expect(parsed.ciVersion).toEqual({unpinnedWorkflows: []}); + }); + + test('reports unpinned CI in text and JSON without failing', () => { + seedWorkflow(dir, 'release.yml', 'steps:\n - run: npx --yes cladding check --strict\n'); + runDoctorCommand({cwd: dir}); + expect(exitCalls).toEqual([0]); + expect(stdoutChunks.join('')).toContain('CI version pinning'); + expect(stdoutChunks.join('')).toContain('.github/workflows/release.yml'); + expect(stdoutChunks.join('')).toContain('unpinned or floating'); + + exitCalls = []; + stdoutChunks = []; + runDoctorCommand({cwd: dir, json: true}); + expect(exitCalls).toEqual([0]); + expect(JSON.parse(stdoutChunks.join('')).ciVersion).toEqual({ + unpinnedWorkflows: ['.github/workflows/release.yml'], + }); + }); + + // F-b0c2e724 — the legacy directory exclusion makes .cladding/config.yaml + // uncommittable, so the gate an author tuned never reaches CI or a fresh + // clone. Doctor diagnoses it read-only; it never rewrites the ignore file. + test('reports a blocked gate config in text and JSON without failing', () => { + seedGitignore(dir, 'node_modules/\n.cladding/\n'); + seedEvents(dir, [ + {id: '1', timestamp: 't', type: 'feature_checkpoint', payload: {featureId: 'F-a0000001'}}, + ]); + runDoctorCommand({cwd: dir}); + expect(exitCalls).toEqual([0]); + const out = stdoutChunks.join(''); + expect(out).toContain('gate config'); + expect(out).toContain('blocks .cladding/config.yaml'); + expect(out).toContain('.cladding/*'); + expect(out).toContain('!.cladding/config.yaml'); + // Read-only diagnosis: the adopter's file is untouched. + expect(readFileSync(join(dir, '.gitignore'), 'utf8')).toBe('node_modules/\n.cladding/\n'); + + exitCalls = []; + stdoutChunks = []; + runDoctorCommand({cwd: dir, json: true}); + expect(exitCalls).toEqual([0]); + expect(JSON.parse(stdoutChunks.join('')).gateConfigIgnore).toBe('blocked'); + }); + + test('keeps a committable gate config quiet while still reporting it in JSON', () => { + seedGitignore(dir, '# Cladding runtime state\n.cladding/*\n!.cladding/config.yaml\n'); + seedEvents(dir, [ + {id: '1', timestamp: 't', type: 'feature_checkpoint', payload: {featureId: 'F-a0000001'}}, + ]); + runDoctorCommand({cwd: dir}); + expect(exitCalls).toEqual([0]); + expect(stdoutChunks.join('')).not.toContain('gate config'); + + exitCalls = []; + stdoutChunks = []; + runDoctorCommand({cwd: dir, json: true}); + expect(JSON.parse(stdoutChunks.join('')).gateConfigIgnore).toBe('commitable'); + }); + + test('a project with no .gitignore reports an absent status and stays quiet', () => { + runDoctorCommand({cwd: dir, json: true}); + expect(exitCalls).toEqual([0]); + expect(JSON.parse(stdoutChunks.join('')).gateConfigIgnore).toBe('absent'); + }); + + test('keeps pinned CI quiet', () => { + seedWorkflow(dir, 'cladding.yaml', 'steps:\n - run: npx --yes cladding@0.9 check --strict\n'); + runDoctorCommand({cwd: dir}); + expect(exitCalls).toEqual([0]); + expect(stdoutChunks.join('')).not.toContain('CI version pinning'); + }); + + test('text mode names observed hook times and stale runtime version without guessing missing events', () => { + seedHookHealth(dir); + seedEvents(dir, [ + {id: '1', timestamp: 't', type: 'feature_checkpoint', payload: {featureId: 'F-001'}}, + ]); + runDoctorCommand({cwd: dir}); + const out = stdoutChunks.join(''); + expect(out).toContain('runtime: observed (engine v0.0.1; current engine is v'); + expect(out).toContain('refresh the plugin'); + expect(out).toContain('session start: 2026-08-10T00:00:00.000Z'); + expect(out).toContain('after edit: 2026-08-10T00:05:00.000Z'); + expect(out).toContain('before edit: never observed'); + expect(exitCalls).toEqual([0]); }); test('corrupt events.log: fail pulse + exit 1 (json flag does NOT swallow the parse error)', () => { @@ -153,9 +281,12 @@ describe('clad doctor handler', () => { seedEvents(dir, [ {id: '1', timestamp: 't1', type: 'gate_run', payload: {tier: 'pre-commit', strict: false, worst: 1, anyFailed: true}}, {id: '2', timestamp: 't2', type: 'done_attempted', payload: {feature: 'F-aaa111', worst: 1, anyFailed: true, kept: false}}, - {id: '3', timestamp: 't3', type: 'gate_run', payload: {tier: 'pre-push', strict: true, worst: 0, anyFailed: false}}, - {id: '4', timestamp: 't4', type: 'done_attempted', payload: {feature: 'F-aaa111', worst: 0, anyFailed: false, kept: true}}, - {id: '5', timestamp: 't5', type: 'stop_blocked', payload: {count: 2, fingerprint: 'abc'}}, + // Legacy stop_blocked shape deliberately lacks every additive P3 field. + {id: '3', timestamp: 't3', type: 'stop_blocked', payload: {count: 2, fingerprint: 'abc'}}, + {id: '4', timestamp: 't4', type: 'stop_exit_recorded', payload: {fingerprint: 'abc'}}, + {id: '5', timestamp: 't5', type: 'gate_run', payload: {tier: 'pre-push', strict: true, worst: 1, anyFailed: true, stopFingerprint: 'abc'}}, + {id: '6', timestamp: 't6', type: 'gate_run', payload: {tier: 'pre-push', strict: true, worst: 0, anyFailed: false, stopFingerprint: ''}}, + {id: '7', timestamp: 't7', type: 'done_attempted', payload: {feature: 'F-aaa111', worst: 0, anyFailed: false, kept: true}}, ]); } @@ -171,9 +302,10 @@ describe('clad doctor handler', () => { expect(exitCalls).toEqual([0]); const out = stdoutChunks.join(''); expect(out).toContain('Governance (lifecycle ledger)'); - expect(out).toContain('gate runs: 2 (last: pre-push strict=true → GREEN)'); + expect(out).toContain('gate runs: 3 (last: pre-push strict=true → GREEN)'); expect(out).toContain('done attempts: 2 rejected by the gate: 1'); expect(out).toContain('stop blocks: 1'); + expect(out).toContain('stop exits recorded: 1 blocked fingerprints later seen by a gate: 1/1'); expect(out).not.toContain('UNRESOLVED'); // no stop-block.json on disk expect(out).toContain('attestation: 2 feature(s) stamped'); }); @@ -193,16 +325,17 @@ describe('clad doctor handler', () => { expect(exitCalls).toEqual([0]); }); - test('--json carries the same summary machine-readably', () => { + test('governance summary exposes stop outcomes and tolerates legacy events', () => { seedGovernance(); runDoctorCommand({cwd: dir, json: true}); const parsed = JSON.parse(stdoutChunks.join('')); expect(parsed.governance).toEqual({ - gateRuns: 2, + gateRuns: 3, lastGate: {tier: 'pre-push', strict: true, worst: 0}, doneAttempts: 2, doneRejected: 1, stopBlocked: 1, + stopOutcomes: {blocked: 1, exitsRecorded: 1, observedByLaterGate: 1, notObservedByLaterGate: 0}, unresolvedStopBlock: false, attestation: {present: false, entries: 0}, }); @@ -216,6 +349,12 @@ describe('clad doctor handler', () => { expect(parsed.governance.lastGate).toBeNull(); expect(parsed.governance.doneAttempts).toBe(0); expect(parsed.governance.stopBlocked).toBe(0); + expect(parsed.governance.stopOutcomes).toEqual({ + blocked: 0, + exitsRecorded: 0, + observedByLaterGate: 0, + notObservedByLaterGate: 0, + }); }); }); }); diff --git a/tests/cli/done.test.ts b/tests/cli/done.test.ts index aee75d04..cd6266d7 100644 --- a/tests/cli/done.test.ts +++ b/tests/cli/done.test.ts @@ -355,20 +355,47 @@ describe('runDone ledger emission (F-b84c38)', () => { }); afterEach(() => rmSync(dir, {recursive: true, force: true})); - test('records done_attempted with kept:true on a GREEN gate', () => { - runDone(dir, FEATURE_ID, {checkStages: () => ({worst: 0, anyFailed: false})}); - const kept = readEvents(dir).filter((e) => e.type === 'done_attempted'); - expect(kept.length).toBe(1); - expect(kept[0].payload).toMatchObject({feature: FEATURE_ID, worst: 0, kept: true}); - expect((kept[0].payload as {identity?: {author?: string}}).identity?.author).toBe('human'); - }); + test('records done_attempted blockers on GREEN and RED gates', () => { + runDone(dir, FEATURE_ID, { + checkStages: () => ({ + worst: 0, + anyFailed: false, + stages: [{stage: 'stage_1.3', status: 'pass'}], + }), + }); + writeFileSync( + join(dir, 'spec', 'features', 'x-aaaaaa.yaml'), + `id: ${FEATURE_ID}\nslug: x\ntitle: t\nstatus: in_progress\n`, + ); + runDone(dir, FEATURE_ID, { + checkStages: () => ({ + worst: 1, + anyFailed: true, + stages: [ + { + stage: 'stage_1.3', + status: 'fail', + findings: [ + {detector: 'MISSING_TESTS', severity: 'error'}, + {detector: 'FYI', severity: 'info'}, + ], + }, + {stage: 'stage_2.1', status: 'fail'}, + ], + }), + }); - test('records done_attempted with kept:false when the gate is RED and the flip reverts', () => { - runDone(dir, FEATURE_ID, {checkStages: () => ({worst: 1, anyFailed: true})}); - const ev = readEvents(dir).filter((e) => e.type === 'done_attempted'); - expect(ev.length).toBe(1); - expect(ev[0].payload).toMatchObject({feature: FEATURE_ID, worst: 1, kept: false}); - // and the shard really reverted + const events = readEvents(dir).filter((event) => event.type === 'done_attempted'); + expect(events).toHaveLength(2); + expect(events[0].payload).toMatchObject({feature: FEATURE_ID, worst: 0, kept: true, blockers: []}); + expect(events[1].payload).toMatchObject({ + feature: FEATURE_ID, + worst: 1, + kept: false, + blockers: ['MISSING_TESTS', 'stage_2.1'], + }); + expect((events[0].payload as {identity?: {author?: string}}).identity?.author).toBe('human'); + // The red attempt still reverts the shard; telemetry cannot alter policy. expect(readFileSync(join(dir, 'spec', 'features', 'x-aaaaaa.yaml'), 'utf8')).toContain('status: in_progress'); }); }); diff --git a/tests/cli/gate-golden-matrix.test.ts b/tests/cli/gate-golden-matrix.test.ts index f7ef6621..a2c4e3ea 100644 --- a/tests/cli/gate-golden-matrix.test.ts +++ b/tests/cli/gate-golden-matrix.test.ts @@ -24,7 +24,12 @@ import {afterEach, beforeEach, describe, expect, test, vi} from 'vitest'; -type StageResult = {pass: boolean; exitCode: number; stderr?: string}; +type StageResult = { + pass: boolean; + exitCode: number; + stderr?: string; + findings?: readonly {detector: string; severity: 'error' | 'warn' | 'info'; path?: string; message: string}[]; +}; const PASS: StageResult = {pass: true, exitCode: 0}; const FAIL: StageResult = {pass: false, exitCode: 1}; const SKIP: StageResult = {pass: false, exitCode: 2}; @@ -70,8 +75,12 @@ vi.mock('../../src/stages/uat.js', () => ({runUat: (...a: unknown[]) => stubs['s // the guard variant swaps in one done feature declaring test_refs. // gate_run emission (F-b84c38) is part of the pinned contract — mocked so the // matrix never writes to the real repo ledger, asserted explicitly below. -const writeAttestationMock = vi.fn(() => true); -vi.mock('../../src/spec/attestation.js', () => ({writeAttestation: (...a: unknown[]) => writeAttestationMock(...(a as []))})); +const writeAttestationMock = vi.fn((..._args: unknown[]) => true); +const detectorCatalogSha256Mock = vi.fn((..._args: unknown[]) => 'a'.repeat(64)); +vi.mock('../../src/spec/attestation.js', () => ({ + writeAttestation: (...a: unknown[]) => writeAttestationMock(...a), + detectorCatalogSha256: (...a: unknown[]) => detectorCatalogSha256Mock(...a), +})); const recordEventMock = vi.fn(); vi.mock('../../src/events/log.js', () => ({recordEvent: (...a: unknown[]) => recordEventMock(...(a as []))})); @@ -241,13 +250,38 @@ describe('gate golden matrix — runCheckStages exit contract (F-d49585)', () => for (const fn of Object.values(stubs)) expect(fn).not.toHaveBeenCalled(); }); - test('PINNED (0.6.0): every invocation records exactly one gate_run with tier/strict/worst/anyFailed', () => { + test('records compact blocker telemetry without changing the gate matrix', () => { setAll(PASS); recordEventMock.mockClear(); runMatrixCase('pre-push', true); - const gateRuns = recordEventMock.mock.calls.filter((c) => c[1] === 'gate_run'); - expect(gateRuns.length).toBe(1); - expect(gateRuns[0][2]).toEqual({tier: 'pre-push', strict: true, worst: 0, anyFailed: false}); + let gateRuns = recordEventMock.mock.calls.filter((call) => call[1] === 'gate_run'); + expect(gateRuns).toHaveLength(1); + expect(gateRuns[0][2]).toEqual({ + tier: 'pre-push', + strict: true, + worst: 0, + anyFailed: false, + blockers: [], + stopFingerprint: '', + }); + + recordEventMock.mockClear(); + stubs['stage_1.3'].mockImplementation(() => ({ + pass: false, + exitCode: 1, + findings: [{detector: 'AC_DRIFT', severity: 'error', path: 'spec/x.yaml', message: 'mismatch'}], + })); + runMatrixCase('pre-push', true); + gateRuns = recordEventMock.mock.calls.filter((call) => call[1] === 'gate_run'); + expect(gateRuns).toHaveLength(1); + expect(gateRuns[0][2]).toMatchObject({ + tier: 'pre-push', + strict: true, + worst: 1, + anyFailed: true, + blockers: ['AC_DRIFT'], + }); + expect((gateRuns[0][2] as {stopFingerprint: string}).stopFingerprint).toMatch(/^[0-9a-f]{64}$/); }); test('PINNED (F-a5228c): solely-stale drift under strict pre-push is exempted, run counts GREEN, attestation stamps', () => { @@ -288,11 +322,16 @@ describe('gate golden matrix — runCheckStages exit contract (F-d49585)', () => expect(runMatrixCase('pre-commit', true).worst).toBe(1); }); - test('a plain GREEN strict pre-push run stamps the attestation; non-strict does not', () => { + test('a plain GREEN strict pre-push run stamps policy identity; non-strict does not', () => { setAll(PASS); writeAttestationMock.mockClear(); runMatrixCase('pre-push', true); expect(writeAttestationMock).toHaveBeenCalledTimes(1); + expect(writeAttestationMock.mock.calls[0]?.[2]).toEqual({ + cladding: expect.stringMatching(/^\d+\.\d+\.\d+$/), + blocking: 'strict', + detectorsSha256: 'a'.repeat(64), + }); writeAttestationMock.mockClear(); runMatrixCase('pre-push', false); expect(writeAttestationMock).not.toHaveBeenCalled(); diff --git a/tests/cli/gitignore-gate-config.test.ts b/tests/cli/gitignore-gate-config.test.ts new file mode 100644 index 00000000..af16d7e4 --- /dev/null +++ b/tests/cli/gitignore-gate-config.test.ts @@ -0,0 +1,186 @@ +// Cladding · impl-blind oracle for F-b0c2e724 — authored from the spec contract only. +// +// The author of this file had no access to src/init/gitignore-policy.ts (no Read, +// Grep, Glob). Every assertion below is derived from the written acceptance +// contract for F-b0c2e724 (committable gate config) and from git's own behaviour, +// which is exercised live via execSync in a throwaway repository. + +import {execSync} from 'node:child_process'; +import {mkdtempSync, mkdirSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {join} from 'node:path'; +import {afterAll, beforeAll, describe, expect, it} from 'vitest'; + +import { + CLADDING_IGNORE_BLOCK, + gateConfigIgnoreStatus, + hasCladdingIgnoreEntry, +} from '../../src/init/gitignore-policy.js'; + +/** + * The contract states these accept text that may be null/undefined. Bind through + * locally-widened aliases so the oracle exercises the documented inputs without + * depending on the implementation's exact parameter annotations. + */ +const statusOf = gateConfigIgnoreStatus as (text?: string | null) => string; +const hasEntry = hasCladdingIgnoreEntry as (text?: string | null) => boolean; + +const blockLines = (): string[] => + String(CLADDING_IGNORE_BLOCK) + .split('\n') + .map((line) => line.trim()); + +describe('F-b0c2e724 · CLADDING_IGNORE_BLOCK shape', () => { + it('contains a `.cladding/*` line', () => { + expect(blockLines()).toContain('.cladding/*'); + }); + + it('contains `!.cladding/config.yaml` AFTER the `.cladding/*` line', () => { + const lines = blockLines(); + const star = lines.indexOf('.cladding/*'); + const reinclude = lines.indexOf('!.cladding/config.yaml'); + expect(star).toBeGreaterThanOrEqual(0); + expect(reinclude).toBeGreaterThanOrEqual(0); + expect(reinclude).toBeGreaterThan(star); + }); + + it('does NOT contain a bare `.cladding/` directory-exclusion line', () => { + expect(blockLines()).not.toContain('.cladding/'); + expect(blockLines()).not.toContain('.cladding'); + }); +}); + +describe('F-b0c2e724 · gateConfigIgnoreStatus', () => { + it('reports "absent" for null', () => { + expect(statusOf(null)).toBe('absent'); + }); + + it('reports "absent" for undefined', () => { + expect(statusOf(undefined)).toBe('absent'); + }); + + it('reports "commitable" when no cladding-related line is present', () => { + const text = ['node_modules/', 'dist/', '*.log', '.DS_Store', ''].join('\n'); + expect(statusOf(text)).toBe('commitable'); + }); + + it('reports "commitable" for `.cladding/*` followed later by `!.cladding/config.yaml`', () => { + const text = ['node_modules/', '.cladding/*', '', '!.cladding/config.yaml', ''].join('\n'); + expect(statusOf(text)).toBe('commitable'); + }); + + it('reports "blocked" for `.cladding/` alone', () => { + const text = ['node_modules/', '.cladding/', ''].join('\n'); + expect(statusOf(text)).toBe('blocked'); + }); + + it('reports "blocked" for `.cladding/` PLUS `!.cladding/config.yaml` (git cannot re-include under an excluded directory)', () => { + const text = ['.cladding/', '!.cladding/config.yaml', ''].join('\n'); + expect(statusOf(text)).toBe('blocked'); + }); + + it('reports "blocked" for bare `.cladding` alone', () => { + const text = ['dist/', '.cladding', ''].join('\n'); + expect(statusOf(text)).toBe('blocked'); + }); + + it('reports "blocked" for `.cladding/*` alone with no re-include', () => { + const text = ['dist/', '.cladding/*', ''].join('\n'); + expect(statusOf(text)).toBe('blocked'); + }); + + it('reports "commitable" when the only mention is a `#` comment', () => { + const text = ['node_modules/', '# .cladding/', ''].join('\n'); + expect(statusOf(text)).toBe('commitable'); + }); + + it('trims lines before classifying (indented `.cladding/` still blocks)', () => { + const text = ['node_modules/', ' .cladding/ ', ''].join('\n'); + expect(statusOf(text)).toBe('blocked'); + }); +}); + +describe('F-b0c2e724 · hasCladdingIgnoreEntry', () => { + it('is true for a real `.cladding/` line', () => { + expect(hasEntry(['dist/', '.cladding/', ''].join('\n'))).toBe(true); + }); + + it('is true for a real bare `.cladding` line', () => { + expect(hasEntry(['dist/', '.cladding', ''].join('\n'))).toBe(true); + }); + + it('is true for a real `.cladding/*` line', () => { + expect(hasEntry(['dist/', '.cladding/*', ''].join('\n'))).toBe(true); + }); + + it('tolerates surrounding whitespace', () => { + expect(hasEntry('\t.cladding/ \n')).toBe(true); + expect(hasEntry(' .cladding \n')).toBe(true); + expect(hasEntry(' .cladding/*\t\n')).toBe(true); + }); + + it('is false for empty text', () => { + expect(hasEntry('')).toBe(false); + }); + + it('is false for unrelated lines', () => { + expect(hasEntry(['node_modules/', 'dist/', '*.log', ''].join('\n'))).toBe(false); + }); + + it('is false when the mention is only inside a comment', () => { + expect(hasEntry(['# .cladding/', '# ignore .cladding later?', ''].join('\n'))).toBe(false); + }); +}); + +describe('F-b0c2e724 · ground truth against git itself', () => { + let repo: string; + + const gitEnv = { + ...process.env, + GIT_CONFIG_GLOBAL: '/dev/null', + GIT_CONFIG_SYSTEM: '/dev/null', + }; + + /** Returns git check-ignore's exit status: 0 = ignored, 1 = not ignored. */ + const checkIgnoreStatus = (relPath: string): number => { + try { + execSync(`git check-ignore -- ${JSON.stringify(relPath)}`, { + cwd: repo, + env: gitEnv, + stdio: 'pipe', + }); + return 0; + } catch (error) { + const status = (error as {status?: number}).status; + return typeof status === 'number' ? status : -1; + } + }; + + beforeAll(() => { + repo = mkdtempSync(join(tmpdir(), 'clad-gitignore-oracle-')); + execSync('git init -q', {cwd: repo, env: gitEnv, stdio: 'pipe'}); + mkdirSync(join(repo, '.cladding'), {recursive: true}); + writeFileSync(join(repo, '.cladding', 'config.yaml'), 'gate: {}\n', 'utf8'); + writeFileSync(join(repo, '.cladding', 'events.log.jsonl'), '{"e":1}\n', 'utf8'); + }); + + afterAll(() => { + if (repo) rmSync(repo, {recursive: true, force: true}); + }); + + it('with CLADDING_IGNORE_BLOCK, git does NOT ignore .cladding/config.yaml', () => { + writeFileSync(join(repo, '.gitignore'), String(CLADDING_IGNORE_BLOCK), 'utf8'); + expect(checkIgnoreStatus('.cladding/config.yaml')).not.toBe(0); + }); + + it('with CLADDING_IGNORE_BLOCK, git DOES ignore .cladding/events.log.jsonl', () => { + writeFileSync(join(repo, '.gitignore'), String(CLADDING_IGNORE_BLOCK), 'utf8'); + expect(checkIgnoreStatus('.cladding/events.log.jsonl')).toBe(0); + }); + + it('with `.cladding/` + `!.cladding/config.yaml`, git STILL ignores config.yaml — the "blocked" verdict is truthful', () => { + writeFileSync(join(repo, '.gitignore'), '.cladding/\n!.cladding/config.yaml\n', 'utf8'); + expect(checkIgnoreStatus('.cladding/config.yaml')).toBe(0); + expect(statusOf('.cladding/\n!.cladding/config.yaml\n')).toBe('blocked'); + }); +}); diff --git a/tests/cli/hook-health.test.ts b/tests/cli/hook-health.test.ts new file mode 100644 index 00000000..01d40ba2 --- /dev/null +++ b/tests/cli/hook-health.test.ts @@ -0,0 +1,90 @@ +// Cladding · bounded hook-health snapshot (F-96fa5622). + +import {existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {join} from 'node:path'; +import {afterEach, beforeEach, describe, expect, test} from 'vitest'; + +import {HOOK_EVENTS, readHookHealth, recordHookFiring} from '../../src/cli/hook-health.js'; +import {runHookEvent} from '../../src/cli/hook.js'; + +describe('bounded hook-health snapshot', () => { + let dir: string; + const path = (): string => join(dir, '.cladding', 'hook-health.json'); + + beforeEach(() => { + dir = mkdtempSync(join(tmpdir(), 'clad-hook-health-')); + }); + + afterEach(() => { + rmSync(dir, {recursive: true, force: true}); + }); + + test('five event pulses overwrite fixed keys instead of growing the event log', () => { + writeFileSync(join(dir, 'spec.yaml'), 'schema: "0.1"\n', 'utf8'); + HOOK_EVENTS.forEach((event, index) => { + expect(recordHookFiring(dir, event, { + now: new Date(`2026-08-10T00:00:0${index}.000Z`), + engineVersion: '0.9.4', + })).toBe(true); + }); + const first = JSON.parse(readFileSync(path(), 'utf8')) as { + lastFiredAt: Record; + }; + expect(Object.keys(first.lastFiredAt).sort()).toEqual([...HOOK_EVENTS].sort()); + expect(existsSync(join(dir, '.cladding', 'events.log.jsonl'))).toBe(false); + + expect(recordHookFiring(dir, 'PostToolUse', { + now: new Date('2026-08-10T01:00:00.000Z'), + engineVersion: '0.9.4', + })).toBe(true); + const report = readHookHealth(dir, '0.9.4'); + expect(report.installation).toBe('observed'); + expect(report.versionCurrent).toBe(true); + expect(report.lastFiredAt.PostToolUse).toBe('2026-08-10T01:00:00.000Z'); + expect(Object.keys(report.lastFiredAt)).toEqual(HOOK_EVENTS); + }); + + test('spec-less and unknown events do not create runtime state', () => { + expect(recordHookFiring(dir, 'SessionStart', {engineVersion: '0.9.4'})).toBe(false); + writeFileSync(join(dir, 'spec.yaml'), 'schema: "0.1"\n', 'utf8'); + expect(recordHookFiring(dir, 'FutureHook', {engineVersion: '0.9.4'})).toBe(false); + expect(existsSync(path())).toBe(false); + expect(runHookEvent('FutureHook', {}, dir)).toBe(''); + expect(existsSync(path())).toBe(false); + }); + + test('missing or corrupt evidence reports not-observed with all five null keys', () => { + expect(readHookHealth(dir, '0.9.4')).toEqual({ + installation: 'not-observed', + recordedVersion: null, + currentVersion: '0.9.4', + versionCurrent: null, + lastFiredAt: { + SessionStart: null, + UserPromptSubmit: null, + PreToolUse: null, + PostToolUse: null, + Stop: null, + }, + }); + mkdirSync(join(dir, '.cladding'), {recursive: true}); + writeFileSync(path(), '{not-json\n', 'utf8'); + expect(readHookHealth(dir, '0.9.4').installation).toBe('not-observed'); + }); + + test('an unwritable health path cannot change the host protocol result', () => { + writeFileSync(join(dir, 'spec.yaml'), 'schema: "0.1"\n', 'utf8'); + writeFileSync(join(dir, '.cladding'), 'blocks directory creation', 'utf8'); + expect(runHookEvent('PreToolUse', {}, dir)).toBe(''); + expect(readHookHealth(dir, '0.9.4').installation).toBe('not-observed'); + }); + + test('recording precedes hook dispatch and preserves the protocol result', () => { + writeFileSync(join(dir, 'spec.yaml'), 'schema: "0.1"\n', 'utf8'); + expect(runHookEvent('PreToolUse', {}, dir)).toBe(''); + const report = readHookHealth(dir); + expect(report.installation).toBe('observed'); + expect(report.lastFiredAt.PreToolUse).not.toBeNull(); + }); +}); diff --git a/tests/cli/hook.test.ts b/tests/cli/hook.test.ts index 7c29f8d8..2ea101b6 100644 --- a/tests/cli/hook.test.ts +++ b/tests/cli/hook.test.ts @@ -5,6 +5,7 @@ // gate-golden-matrix pattern so Stop/PostToolUse cases never spawn a // toolchain; everything else runs against a throwaway fixture dir. +import {execFileSync} from 'node:child_process'; import {existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync} from 'node:fs'; import {tmpdir} from 'node:os'; import {join} from 'node:path'; @@ -277,7 +278,7 @@ describe('Stop — deterministic trio with fingerprint-keyed demotion', () => { expect(driftStub).not.toHaveBeenCalled(); }); - test('fresh failure → block JSON + stop-block.json written + stop_blocked event', () => { + test('fresh failure records complete attribution without changing block output', () => { driftStub.mockImplementation(() => TWO_FINDINGS); const out = runHookEvent('Stop', {stop_hook_active: false}, cwd); const doc = JSON.parse(out) as {decision: string; reason: string}; @@ -294,18 +295,50 @@ describe('Stop — deterministic trio with fingerprint-keyed demotion', () => { }; expect(sb.count).toBe(2); expect(sb.first).toBe('AC_DRIFT'); - expect(sb.fingerprint).toMatch(/^[0-9a-f]{64}$/); + expect(sb.fingerprint).toBe('d4f74023335b4472084e992a445620d4815574af9ea09a384dcba816910011f1'); const blocked = readEvents(cwd).filter((e) => e.type === 'stop_blocked'); expect(blocked).toHaveLength(1); - expect(blocked[0].payload.count).toBe(2); - expect(blocked[0].payload.fingerprint).toBe(sb.fingerprint); - }); - - test('identical second run → empty (demoted; no second stop_blocked event)', () => { + expect(blocked[0].payload).toMatchObject({ + count: 2, + fingerprint: sb.fingerprint, + detectors: ['AC_DRIFT', 'MISSING_TESTS'], + introduced: 2, + preexisting: 0, + dirty_hit: false, + identity: {author: 'human'}, + }); + }); + + test('identical second run stays empty and records the known-failing exit', () => { driftStub.mockImplementation(() => TWO_FINDINGS); expect(runHookEvent('Stop', {stop_hook_active: false}, cwd)).not.toBe(''); expect(runHookEvent('Stop', {stop_hook_active: false}, cwd)).toBe(''); expect(readEvents(cwd).filter((e) => e.type === 'stop_blocked')).toHaveLength(1); + const exits = readEvents(cwd).filter((e) => e.type === 'stop_exit_recorded'); + expect(exits).toHaveLength(1); + expect(exits[0].payload).toMatchObject({ + count: 2, + detectors: ['AC_DRIFT', 'MISSING_TESTS'], + introduced: 2, + preexisting: 0, + dirty_hit: false, + }); + }); + + test('fresh attribution separates latest-gate blockers and marks a dirty finding path', () => { + mkdirSync(join(cwd, 'spec', 'features'), {recursive: true}); + writeFileSync(join(cwd, 'spec', 'features', 'x.yaml'), 'baseline\n', 'utf8'); + writeFileSync(join(cwd, 'spec', 'features', 'y.yaml'), 'baseline\n', 'utf8'); + execFileSync('git', ['init', '-q'], {cwd}); + execFileSync('git', ['add', 'spec.yaml', 'spec/features/x.yaml', 'spec/features/y.yaml'], {cwd}); + execFileSync('git', ['-c', 'user.name=Test', '-c', 'user.email=test@example.com', 'commit', '-qm', 'baseline'], {cwd}); + appendEvent(cwd, newEvent('gate_run', {blockers: ['MISSING_TESTS']})); + writeFileSync(join(cwd, 'spec', 'features', 'x.yaml'), 'changed\n', 'utf8'); + driftStub.mockImplementation(() => TWO_FINDINGS); + + expect(runHookEvent('Stop', {stop_hook_active: false}, cwd)).not.toBe(''); + const blocked = readEvents(cwd).find((event) => event.type === 'stop_blocked'); + expect(blocked?.payload).toMatchObject({introduced: 1, preexisting: 1, dirty_hit: true}); }); test('a DIFFERENT failure set re-blocks (fingerprint changed)', () => { diff --git a/tests/cli/init.test.ts b/tests/cli/init.test.ts index d32c3a1e..208b7eef 100644 --- a/tests/cli/init.test.ts +++ b/tests/cli/init.test.ts @@ -22,6 +22,7 @@ describe('runInit', () => { expect(r.created.some((c) => c.startsWith('.cladding/'))).toBe(true); expect(existsSync(join(dir, 'spec.yaml'))).toBe(true); expect(existsSync(join(dir, '.cladding'))).toBe(true); + expect(readFileSync(join(dir, '.gitattributes'), 'utf8')).toContain('spec/index.yaml merge=union'); }); test('seed spec.yaml has empty features[] — no legacy F-001 placeholder shard written (v0.4.0)', async () => { @@ -61,21 +62,61 @@ describe('runInit', () => { expect(r.language).toBe('typescript'); }); - test('appends .cladding/ to existing .gitignore without losing prior lines', async () => { + test('appends the ignore entry to an existing .gitignore without losing prior lines', async () => { writeFileSync(join(dir, '.gitignore'), 'node_modules/\nbuild/\n'); await runInit({cwd: dir}); const gi = readFileSync(join(dir, '.gitignore'), 'utf8'); expect(gi).toContain('node_modules/'); expect(gi).toContain('build/'); - expect(gi).toContain('.cladding/'); + // The contents form, never the directory form: git cannot re-include a + // file under an excluded directory, so `.cladding/` would make the gate + // config uncommittable and CI would never see the tuned gate. + expect(gi).toContain('.cladding/*'); + expect(gi).toContain('!.cladding/config.yaml'); + expect(gi.split(/\r?\n/)).not.toContain('.cladding/'); + // The re-include must come after the exclusion — a later pattern wins in git. + expect(gi.indexOf('!.cladding/config.yaml')).toBeGreaterThan(gi.indexOf('.cladding/*')); }); - test('does not re-append .cladding/ when already present', async () => { + test('leaves a .gitignore carrying the legacy .cladding/ entry byte-identical', async () => { writeFileSync(join(dir, '.gitignore'), 'node_modules/\n.cladding/\n'); const before = readFileSync(join(dir, '.gitignore'), 'utf8'); + const r = await runInit({cwd: dir}); + expect(readFileSync(join(dir, '.gitignore'), 'utf8')).toBe(before); + expect(r.skipped).toContain('.gitignore (cladding entry already present)'); + expect(r.created.some((c) => c.includes('.gitignore'))).toBe(false); + }); + + test('leaves a .gitignore already carrying the new entry byte-identical', async () => { + const before = '# Cladding runtime state\n.cladding/*\n!.cladding/config.yaml\n'; + writeFileSync(join(dir, '.gitignore'), before); + const r = await runInit({cwd: dir}); + expect(readFileSync(join(dir, '.gitignore'), 'utf8')).toBe(before); + expect(r.skipped).toContain('.gitignore (cladding entry already present)'); + }); + + test('creates the index merge attribute while leaving attestation unassigned', async () => { + const r = await runInit({cwd: dir}); + const attributes = readFileSync(join(dir, '.gitattributes'), 'utf8'); + expect(r.created).toContain('.gitattributes (spec/index.yaml merge=union appended)'); + expect(attributes.split('\n').filter((line) => line === 'spec/index.yaml merge=union')).toHaveLength(1); + expect(attributes).not.toMatch(/spec\/attestation\.yaml\b[^\n]*\bmerge/); + }); + + test('preserves existing gitattributes and appends the managed index line', async () => { + writeFileSync(join(dir, '.gitattributes'), '*.md linguist-detectable\n'); await runInit({cwd: dir}); - const after = readFileSync(join(dir, '.gitignore'), 'utf8'); - expect(after).toBe(before); + const attributes = readFileSync(join(dir, '.gitattributes'), 'utf8'); + expect(attributes).toContain('*.md linguist-detectable'); + expect(attributes).toContain('spec/index.yaml merge=union'); + }); + + test('does not duplicate an existing index merge attribute', async () => { + const original = '# user attributes\nspec/index.yaml merge=union\n'; + writeFileSync(join(dir, '.gitattributes'), original); + const r = await runInit({cwd: dir}); + expect(readFileSync(join(dir, '.gitattributes'), 'utf8')).toBe(original); + expect(r.skipped).toContain('.gitattributes (spec/index.yaml merge=union already present)'); }); test('force=true overwrites an existing spec.yaml', async () => { @@ -100,24 +141,24 @@ describe('runInit', () => { expect(yaml).toContain('my-custom-name — Cladding spec'); }); - test('appends .cladding/ to a gitignore that lacks a trailing newline', async () => { + test('appends the ignore entry to a gitignore that lacks a trailing newline', async () => { // Branch: existing.length > 0 && !existing.endsWith('\n') → prepend \n writeFileSync(join(dir, '.gitignore'), 'node_modules/'); await runInit({cwd: dir}); const gi = readFileSync(join(dir, '.gitignore'), 'utf8'); // The original line stays intact and the new entry lands on its own line expect(gi.startsWith('node_modules/')).toBe(true); - expect(gi).toContain('.cladding/'); - // No "node_modules/.cladding/" concatenation - expect(gi).not.toContain('node_modules/.cladding/'); + expect(gi.split(/\r?\n/)).toContain('.cladding/*'); + // No "node_modules/.cladding/*" concatenation + expect(gi).not.toContain('node_modules/.cladding'); }); - test('creates .gitignore from scratch when none exists', async () => { + test('creates .gitignore from scratch with runtime state ignored and gate config committable', async () => { // Branch: existing.length === 0 → ensureNewline stays '' const r = await runInit({cwd: dir}); expect(r.created.some((c) => c.includes('.gitignore'))).toBe(true); const gi = readFileSync(join(dir, '.gitignore'), 'utf8'); - expect(gi).toContain('.cladding/'); + expect(gi).toBe('# Cladding runtime state\n.cladding/*\n!.cladding/config.yaml\n'); }); // v0.3.42 (F-bd07d7) — greenfield seeds. When the auto-scan threshold diff --git a/tests/cli/setup.test.ts b/tests/cli/setup.test.ts index f04c57e3..97c9851c 100644 --- a/tests/cli/setup.test.ts +++ b/tests/cli/setup.test.ts @@ -6,7 +6,12 @@ import {tmpdir} from 'node:os'; import {join, resolve} from 'node:path'; import {afterEach, beforeEach, describe, expect, test} from 'vitest'; -import {getLastSetupVersion, renderSetupReport, runHostSetup} from '../../src/init/host-setup.js'; +import { + getCurrentCladdingVersion, + getLastSetupVersion, + renderSetupReport, + runHostSetup, +} from '../../src/init/host-setup.js'; import {hostWireNotice} from '../../src/cli/init.js'; describe('project-scoped runHostSetup', () => { @@ -67,6 +72,17 @@ describe('project-scoped runHostSetup', () => { expect(agyMcp.mcpServers.cladding.args).toEqual([join(pkgRoot, 'dist', 'clad.js'), 'serve']); }); + test('resolves the engine version from a Claude cache that has no package.json', () => { + rmSync(join(pkgRoot, 'package.json')); + mkdirSync(join(pkgRoot, '.claude-plugin'), {recursive: true}); + writeFileSync( + join(pkgRoot, '.claude-plugin', 'plugin.json'), + `${JSON.stringify({name: 'claude-code', version: '0.9.4'})}\n`, + 'utf8', + ); + expect(getCurrentCladdingVersion(pkgRoot)).toBe('0.9.4'); + }); + test('default detection wires nothing on a machine with no supported host', async () => { const bareHome = mkdtempSync(join(tmpdir(), 'clad-barehome-')); try { diff --git a/tests/cli/skip-exit-guidance.test.ts b/tests/cli/skip-exit-guidance.test.ts new file mode 100644 index 00000000..15f4b94b --- /dev/null +++ b/tests/cli/skip-exit-guidance.test.ts @@ -0,0 +1,284 @@ +// Cladding · F-c17e1edc — runner-less skips name their exit. +// +// Two halves, tested apart: +// ① the TAG — a command stage that skips because cladding knows no runner for +// this project carries `skipReason: 'no-runner'`; an absent/unfetchable tool +// carries `'tool-missing'`; a by-design skip (no oracle, no deliverable) +// carries nothing. Driven against REAL stage runners on a temp fixture whose +// language cladding cannot drive (.zig), because the split this feature turns +// on is a property of the real toolchain resolver, not of a stub. +// ② the LINE — `runCheckStages` lists the tagged stages once, with the +// `gate.commands` remedy inline, and stays silent for every other skip +// class. Driven against stubbed stages so the matrix is exact and fast. +// +// The existing stderr strings are asserted byte-for-byte here: this feature is +// additive, so a reworded skip message is a regression, not a refactor. + +import {mkdirSync, mkdtempSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {join} from 'node:path'; + +import {afterEach, beforeEach, describe, expect, test, vi} from 'vitest'; + +type StageResult = { + pass: boolean; + exitCode: number; + stderr?: string; + skipReason?: 'no-runner' | 'tool-missing'; +}; + +const PASS: StageResult = {pass: true, exitCode: 0}; +const noRunner = (stderr: string): StageResult => ({pass: false, exitCode: 2, stderr, skipReason: 'no-runner'}); +const TOOL_MISSING: StageResult = {pass: false, exitCode: 2, stderr: "'zig' not installed", skipReason: 'tool-missing'}; +const BY_DESIGN: StageResult = {pass: false, exitCode: 2, stderr: 'no project.deliverable declared — skipped'}; + +// One swappable vi.fn per stage (same shape as the gate golden matrix) so each +// case re-targets outcomes without re-mocking modules. +const stubs = { + 'stage_1.1': vi.fn((): StageResult => PASS), + 'stage_1.2': vi.fn((): StageResult => PASS), + 'stage_1.3': vi.fn((): StageResult => PASS), + 'stage_1.4': vi.fn((): StageResult => PASS), + 'stage_1.5': vi.fn((): StageResult => PASS), + 'stage_1.6': vi.fn((): StageResult => PASS), + 'stage_2.1': vi.fn((): StageResult => PASS), + 'stage_2.2': vi.fn((): StageResult => PASS), + 'stage_2.3': vi.fn((): StageResult => PASS), + 'stage_2.4': vi.fn((): StageResult => PASS), +} as const; + +vi.mock('../../src/stages/type.js', () => ({runType: () => stubs['stage_1.1']()})); +vi.mock('../../src/stages/lint.js', () => ({runLint: () => stubs['stage_1.2']()})); +vi.mock('../../src/stages/drift.js', () => ({runDrift: () => stubs['stage_1.3']()})); +vi.mock('../../src/stages/commit.js', () => ({runCommit: () => stubs['stage_1.4']()})); +vi.mock('../../src/stages/arch.js', () => ({runArch: () => stubs['stage_1.5']()})); +vi.mock('../../src/stages/secret.js', () => ({runSecret: () => stubs['stage_1.6']()})); +vi.mock('../../src/stages/unit.js', () => ({runUnit: () => stubs['stage_2.1']()})); +vi.mock('../../src/stages/cov.js', () => ({runCov: () => stubs['stage_2.2']()})); +vi.mock('../../src/stages/spec-conformance.js', () => ({runSpecConformance: () => stubs['stage_2.3']()})); +vi.mock('../../src/stages/deliverable-smoke.js', () => ({runDeliverableSmoke: () => stubs['stage_2.4']()})); + +// The gate ledger is the real repo's; a unit test must never append to it. +const recordEventMock = vi.fn(); +vi.mock('../../src/events/log.js', () => ({recordEvent: (...a: unknown[]) => recordEventMock(...(a as []))})); + +const clad = await import('../../src/cli/clad.js'); + +// The REAL runners, reached past the stubs above — half ① drives these. +const {runType} = await vi.importActual('../../src/stages/type.js'); +const {runLint} = await vi.importActual('../../src/stages/lint.js'); +const {runUnit} = await vi.importActual('../../src/stages/unit.js'); +const {runCov} = await vi.importActual('../../src/stages/cov.js'); +const {runSpecConformance} = + await vi.importActual('../../src/stages/spec-conformance.js'); +const {runDeliverableSmoke} = + await vi.importActual('../../src/stages/deliverable-smoke.js'); +const {missingToolSkip} = await vi.importActual('../../src/stages/util.js'); + +const SPEC = `schema: "0.1" +project: + name: zigdemo + language: zig +features: + - id: F-a1b2c3d4 + title: "Add two numbers" + status: planned + modules: ["src/main.zig"] + acceptance_criteria: + - id: AC-11112222 + text: "The system shall add two numbers." +`; + +/** A project whose language cladding has no registered runner for. */ +function makeRunnerlessProject(): string { + const dir = mkdtempSync(join(tmpdir(), 'clad-skipexit-')); + mkdirSync(join(dir, 'src'), {recursive: true}); + writeFileSync(join(dir, 'spec.yaml'), SPEC); + writeFileSync(join(dir, 'src', 'main.zig'), 'pub fn add(a: i32, b: i32) i32 {\n return a + b;\n}\n'); + writeFileSync(join(dir, 'src', 'util.zig'), 'pub fn double(a: i32) i32 {\n return a * 2;\n}\n'); + return dir; +} + +/** The same project after the one declaration that turns the four stages on. */ +function declareGateCommands(dir: string): void { + mkdirSync(join(dir, '.cladding'), {recursive: true}); + writeFileSync( + join(dir, '.cladding', 'config.yaml'), + `gate: + commands: + type: ["node", "--version"] + lint: ["node", "--version"] + test: ["node", "--version"] + coverage: ["node", "--version"] +`, + ); +} + +let dir: string; +beforeEach(() => { + dir = makeRunnerlessProject(); + for (const fn of Object.values(stubs)) fn.mockImplementation(() => PASS); +}); +afterEach(() => { + rmSync(dir, {recursive: true, force: true}); + vi.clearAllMocks(); + vi.restoreAllMocks(); +}); + +describe('AC-4b7d20e5 — every skip carries a structured reason, or none by design', () => { + test('the four command stages of a runner-less project tag no-runner, message byte-identical', () => { + const results = [ + {r: runType({cwd: dir}), stderr: "no type checker registered for language 'unknown'"}, + {r: runLint({cwd: dir}), stderr: "no linter registered for language 'unknown'"}, + {r: runUnit({cwd: dir}), stderr: "no unit test runner registered for language 'unknown'"}, + {r: runCov({cwd: dir}), stderr: "no coverage runner registered for language 'unknown'"}, + ]; + for (const {r, stderr} of results) { + expect(r.exitCode, r.stage).toBe(2); + expect(r.pass, r.stage).toBe(false); + expect(r.stderr, r.stage).toBe(stderr); + expect(r.skipReason, r.stage).toBe('no-runner'); + } + }); + + test('by-design skips stay untagged — the gate.commands cure would be a false prescription', () => { + const conformance = runSpecConformance({cwd: dir}); + const smoke = runDeliverableSmoke({cwd: dir}); + expect(conformance.exitCode).toBe(2); + expect(conformance.stderr).toBe('no spec-conformance oracles under tests/oracle/ — skipped'); + expect(conformance.skipReason).toBeUndefined(); + expect(smoke.exitCode).toBe(2); + expect(smoke.stderr).toBe('no project.deliverable declared — skipped'); + expect(smoke.skipReason).toBeUndefined(); + }); + + test('an absent binary is tool-missing, never no-runner — the command IS known here', () => { + const enoent = missingToolSkip('stage_1.1', 'zig', {code: 'ENOENT'}); + expect(enoent).toEqual({stage: 'stage_1.1', pass: false, exitCode: 2, stderr: "'zig' not installed", skipReason: 'tool-missing'}); + + const npxUnresolvable = missingToolSkip( + 'stage_2.1', + 'npx', + {exitCode: 1, stderr: 'npm error canceled due to missing packages'}, + ['vitest', 'run'], + ); + expect(npxUnresolvable?.exitCode).toBe(2); + expect(npxUnresolvable?.skipReason).toBe('tool-missing'); + expect(npxUnresolvable?.stderr).toBe( + "setup gap: 'npx' could not resolve the configured tool without installing it; " + + 'the inferred tool is not installed or unavailable offline', + ); + + // …and through a real stage whose resolved command does not exist. + const staged = runType({cwd: dir, cmd: 'clad-no-such-binary-xyz', args: []}); + expect(staged.exitCode).toBe(2); + expect(staged.skipReason).toBe('tool-missing'); + expect(staged.skipReason).not.toBe('no-runner'); + }); + + test('a tool that RAN is not tagged at all — skipReason lives only on the skip lane', () => { + declareGateCommands(dir); + for (const r of [runType({cwd: dir}), runLint({cwd: dir}), runUnit({cwd: dir}), runCov({cwd: dir})]) { + expect(r.pass, r.stage).toBe(true); + expect(r.exitCode, r.stage).toBe(0); + expect(r.skipReason, r.stage).toBeUndefined(); + } + }); +}); + +describe('AC-90c3f1a8 / AC-2f6e88d0 — the guidance text', () => { + test('names every skipped stage and carries the remedy inline, on one line', () => { + const line = clad.renderNoRunnerGuidance(['Type', 'Lint', 'Unit tests', 'Coverage']); + for (const label of ['Type', 'Lint', 'Unit tests', 'Coverage']) expect(line).toContain(label); + expect(line).toContain('.cladding/config.yaml'); + expect(line).toContain('gate:'); + expect(line).toContain('commands:'); + expect(line).toContain('committable'); + expect(line).not.toContain('\n'); + // The language name is deliberately absent — it reads 'unknown' exactly when + // this fires, which names nothing an adopter can act on. + expect(line).not.toContain('unknown'); + }); + + test('nothing to say when nothing skipped for lack of a runner', () => { + expect(clad.renderNoRunnerGuidance([])).toBe(''); + }); +}); + +describe('AC-90c3f1a8 / AC-2f6e88d0 / AC-b59a37c4 — what a check run renders and reports', () => { + let stdout: string; + beforeEach(() => { + stdout = ''; + vi.spyOn(process.stdout, 'write').mockImplementation(((s: unknown) => { + stdout += String(s); + return true; + }) as never); + }); + + const runnerlessGate = (): void => { + stubs['stage_1.1'].mockImplementation(() => noRunner("no type checker registered for language 'unknown'")); + stubs['stage_1.2'].mockImplementation(() => noRunner("no linter registered for language 'unknown'")); + stubs['stage_2.1'].mockImplementation(() => noRunner("no unit test runner registered for language 'unknown'")); + stubs['stage_2.2'].mockImplementation(() => noRunner("no coverage runner registered for language 'unknown'")); + stubs['stage_2.3'].mockImplementation(() => BY_DESIGN); + stubs['stage_2.4'].mockImplementation(() => BY_DESIGN); + }; + + test('one line, listing the four stages in run order, and the skips stay non-blocking', () => { + runnerlessGate(); + const out = clad.runCheckStages({tier: 'pre-push'}); + const hits = stdout.split('no runner is known for this project').length - 1; + expect(hits).toBe(1); + expect(stdout).toContain('Type, Lint, Unit tests, Coverage skipped — no runner is known for this project.'); + expect(stdout).toContain('.cladding/config.yaml'); + expect(out.worst).toBe(0); + expect(out.anyFailed).toBe(false); + }); + + test('an all-green run says nothing new', () => { + const out = clad.runCheckStages({tier: 'pre-push'}); + expect(stdout).not.toContain('no runner is known'); + expect(out.worst).toBe(0); + }); + + test('by-design and tool-missing skips alone print nothing', () => { + stubs['stage_1.1'].mockImplementation(() => TOOL_MISSING); + stubs['stage_2.3'].mockImplementation(() => BY_DESIGN); + stubs['stage_2.4'].mockImplementation(() => BY_DESIGN); + clad.runCheckStages({tier: 'pre-push'}); + expect(stdout).not.toContain('no runner is known'); + }); + + test('a tool-missing stage is not listed even when the line does fire', () => { + runnerlessGate(); + stubs['stage_1.2'].mockImplementation(() => TOOL_MISSING); // Lint has its command; it is just absent + clad.runCheckStages({tier: 'pre-push'}); + expect(stdout).toContain('Type, Unit tests, Coverage skipped — no runner is known for this project.'); + expect(stdout).not.toContain('Lint,'); + }); + + test('JSON carries the same discrimination and no prose', () => { + runnerlessGate(); + clad.runCheckStages({tier: 'pre-push', json: true}); + const doc = JSON.parse(stdout) as {stages: {stage: string; status: string; exitCode: number; skipReason?: string}[]}; + const bs = new Map(doc.stages.map((s) => [s.stage, s])); + for (const id of ['stage_1.1', 'stage_1.2', 'stage_2.1', 'stage_2.2']) { + expect(bs.get(id)?.skipReason, id).toBe('no-runner'); + expect(bs.get(id)?.status, id).toBe('skip'); + expect(bs.get(id)?.exitCode, id).toBe(2); + } + for (const id of ['stage_2.3', 'stage_2.4']) { + expect(bs.get(id), id).toBeDefined(); + expect(bs.get(id)).not.toHaveProperty('skipReason'); + } + expect(bs.get('stage_1.3')).not.toHaveProperty('skipReason'); + expect(stdout).not.toContain('no runner is known'); + }); + + test('the verdict poll observes without speaking', () => { + runnerlessGate(); + const out = clad.runCheckStages({tier: 'pre-push', silent: true}); + expect(stdout).toBe(''); + expect(out.stages?.find((s) => s.stage === 'stage_1.1')?.skipReason).toBe('no-runner'); + }); +}); diff --git a/tests/cli/skip-guidance-evidence.test.ts b/tests/cli/skip-guidance-evidence.test.ts new file mode 100644 index 00000000..5cfa9f65 --- /dev/null +++ b/tests/cli/skip-guidance-evidence.test.ts @@ -0,0 +1,173 @@ +// Cladding · impl-blind oracle for F-c17e1edc — authored from the spec contract only. +// +// AC under test: runner-less skips name their exit. +// 1. No registered runner for the project language -> the four command stages +// ('Type', 'Lint', 'Unit tests', 'Coverage') end status 'skip' AND carry +// skipReason: 'no-runner'. +// 2. By-design skips ('Spec conformance', 'Deliverable smoke') stay skip/na and +// carry NO skipReason. +// 3. With gate.commands declared in .cladding/config.yaml those four stages no +// longer skip and carry no skipReason. +// 4. skipReason is only ever 'no-runner' | 'tool-missing' | absent — on any stage. +// 5. The runner-less stderr message is unchanged: /no .* registered for language/. +// +// Written without reading src/cli/clad.ts — behaviour is asserted against the +// declared public surface `runCheckStages({tier, silent}) -> {stages: [...]}` only. + +import {afterAll, beforeAll, describe, expect, it} from 'vitest'; +import {mkdirSync, mkdtempSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {join} from 'node:path'; + +import {runCheckStages} from '../../src/cli/clad.js'; + +type StageRow = { + stage?: unknown; + label?: string; + status?: string; + exitCode?: number; + stderr?: string; + skipReason?: string; +}; +type CheckResult = {stages: StageRow[]}; + +const COMMAND_LABELS = ['Type', 'Lint', 'Unit tests', 'Coverage'] as const; +const BY_DESIGN_SKIP_LABELS = ['Spec conformance', 'Deliverable smoke'] as const; +const ALLOWED_SKIP_REASONS = ['no-runner', 'tool-missing']; +const RUNNERLESS_STDERR = /no .* registered for language/; + +const GATE_COMMANDS_YAML = [ + 'gate:', + ' commands:', + ' type: ["node", "--version"]', + ' lint: ["node", "--version"]', + ' test: ["node", "--version"]', + ' coverage: ["node", "--version"]', + '', +].join('\n'); + +/** A project in a language with no registered runner: a tree of .zig files. */ +function makeFixture(withGateCommands: boolean): string { + const dir = mkdtempSync(join(tmpdir(), 'clad-oracle-c17e1edc-')); + writeFileSync( + join(dir, 'spec.yaml'), + 'schema: "0.1"\nproject: {name: x, language: zig}\nfeatures: []\n', + 'utf8', + ); + mkdirSync(join(dir, 'spec', 'features'), {recursive: true}); + mkdirSync(join(dir, 'src', 'core'), {recursive: true}); + for (let i = 0; i < 6; i++) { + writeFileSync(join(dir, 'src', 'core', `f${i}.zig`), '// x\n', 'utf8'); + } + if (withGateCommands) { + mkdirSync(join(dir, '.cladding'), {recursive: true}); + writeFileSync(join(dir, '.cladding', 'config.yaml'), GATE_COMMANDS_YAML, 'utf8'); + } + return dir; +} + +/** runCheckStages has no cwd parameter — stages run in '.', so chdir around it. */ +function runInDir(dir: string): CheckResult { + if (typeof process.chdir !== 'function') { + throw new Error( + 'process.chdir is unavailable in this vitest pool; this oracle needs a pool where cwd can be changed (forks)', + ); + } + const origin = process.cwd(); + process.chdir(dir); + try { + return runCheckStages({tier: 'pre-push', silent: true} as never) as unknown as CheckResult; + } finally { + process.chdir(origin); + } +} + +function stageByLabel(result: CheckResult, label: string): StageRow { + const row = result.stages.find(s => s.label === label); + expect(row, `expected a stage labelled '${label}' in: ${labelsOf(result).join(', ')}`).toBeDefined(); + return row as StageRow; +} + +function labelsOf(result: CheckResult): string[] { + return result.stages.map(s => String(s.label)); +} + +let dirNoRunner = ''; +let dirConfigured = ''; +let noRunner: CheckResult; +let configured: CheckResult; + +beforeAll(() => { + dirNoRunner = makeFixture(false); + dirConfigured = makeFixture(true); + // One real gate run per fixture; every assertion below reuses these two results. + noRunner = runInDir(dirNoRunner); + configured = runInDir(dirConfigured); +}, 300_000); + +afterAll(() => { + for (const dir of [dirNoRunner, dirConfigured]) { + if (dir) rmSync(dir, {recursive: true, force: true}); + } +}); + +describe('F-c17e1edc — runner-less skips name their exit', () => { + it('produces a stage list for both fixtures', () => { + expect(Array.isArray(noRunner?.stages)).toBe(true); + expect(noRunner.stages.length).toBeGreaterThan(0); + expect(Array.isArray(configured?.stages)).toBe(true); + expect(configured.stages.length).toBeGreaterThan(0); + }); + + it.each(COMMAND_LABELS)( + "with no registered runner, the '%s' stage skips with skipReason 'no-runner'", + label => { + const row = stageByLabel(noRunner, label); + expect(row.status, `status of '${label}'`).toBe('skip'); + expect(row.skipReason, `skipReason of '${label}'`).toBe('no-runner'); + }, + ); + + it.each(BY_DESIGN_SKIP_LABELS)( + "the by-design skip '%s' carries no skipReason", + label => { + const row = stageByLabel(noRunner, label); + expect(['skip', 'na'], `status of '${label}'`).toContain(String(row.status)); + expect(row.skipReason, `skipReason of '${label}'`).toBeUndefined(); + }, + ); + + it.each(COMMAND_LABELS)( + "with gate.commands declared, the '%s' stage no longer skips and names no exit", + label => { + const row = stageByLabel(configured, label); + expect(row.status, `status of '${label}' with gate.commands`).not.toBe('skip'); + expect(row.skipReason, `skipReason of '${label}' with gate.commands`).toBeUndefined(); + }, + ); + + it('never emits a skipReason outside the declared vocabulary, in either fixture', () => { + const offenders: string[] = []; + for (const [fixture, result] of [ + ['no-runner fixture', noRunner], + ['gate.commands fixture', configured], + ] as const) { + for (const row of result.stages) { + if (row.skipReason === undefined) continue; + if (!ALLOWED_SKIP_REASONS.includes(row.skipReason)) { + offenders.push(`${fixture}: '${row.label}' -> ${JSON.stringify(row.skipReason)}`); + } + } + } + expect(offenders, `skipReason must be one of ${ALLOWED_SKIP_REASONS.join(' | ')} or absent`).toEqual([]); + }); + + it.each(COMMAND_LABELS)( + "the '%s' runner-less skip still explains itself in stderr", + label => { + const row = stageByLabel(noRunner, label); + expect(row.status).toBe('skip'); + expect(String(row.stderr ?? ''), `stderr of '${label}'`).toMatch(RUNNERLESS_STDERR); + }, + ); +}); diff --git a/tests/core/language-evidence.test.ts b/tests/core/language-evidence.test.ts new file mode 100644 index 00000000..5b710fad --- /dev/null +++ b/tests/core/language-evidence.test.ts @@ -0,0 +1,188 @@ +// Cladding · unit tests for core/language-evidence.ts +// +// Contract under test is AC-1c7a90b2 of F-9e1279d4: ONE foundation module +// owns the extension→language vocabulary and the observed source +// distribution, so the scan layer (cli) and the drift detectors (stages) +// can never read different tables. +// +// What the tests pin: +// - the vocabulary object the scan layer imports IS the core one +// (identity, not a copy that can drift); +// - classification counts per language, the sorted observed set, the +// dominant language, and share() as counts/classified; +// - the walk skips vendored/generated directories (node_modules et al.) +// and every dot-directory, so build output cannot outvote source; +// - extensions outside the vocabulary are ignored, and an empty tree +// yields classified 0 / dominant null / share 0 rather than a throw; +// - the walk is capped, so a detector invoking it on every gate run +// stays bounded (asserted through the exported cap + the injectable +// `maxFiles` override — 20 000 real files are never created); +// - `observedKnownExtensions` reports the extensions actually present +// rather than every extension the matching label could have — the +// glob-building contract UNMAPPED_ARTIFACT depends on (AC-4d21c8a7 +// of F-87bb7ed3). + +import {mkdirSync, mkdtempSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {join} from 'node:path'; +import {afterEach, beforeEach, describe, expect, test} from 'vitest'; + +import { + classifySources, + EXT_TO_LANGUAGE, + LANGUAGE_VOCABULARY, + MAX_FILES, + observedKnownExtensions, +} from '../../src/core/language-evidence.js'; +import {EXT_TO_LANGUAGE as SCAN_EXT_TO_LANGUAGE} from '../../src/cli/scan/thresholds.js'; + +/** Writes `count` files named `f0..f` with `ext` under `dir/`. */ +function seed(dir: string, sub: string, ext: string, count: number): void { + const target = join(dir, sub); + mkdirSync(target, {recursive: true}); + for (let i = 0; i < count; i += 1) { + writeFileSync(join(target, `f${i}${ext}`), '// x\n'); + } +} + +describe('core/language-evidence — shared vocabulary', () => { + test('AC-1c7a90b2 — the scan layer re-exports the core map itself, not a copy', () => { + expect(SCAN_EXT_TO_LANGUAGE).toBe(EXT_TO_LANGUAGE); + }); + + test('AC-1c7a90b2 — the vocabulary is exactly the label set of the map', () => { + expect([...LANGUAGE_VOCABULARY].sort()).toEqual([...new Set(Object.values(EXT_TO_LANGUAGE))].sort()); + for (const label of ['typescript', 'python', 'kotlin', 'cpp', 'rust', 'go']) { + expect(LANGUAGE_VOCABULARY.has(label), label).toBe(true); + } + expect(LANGUAGE_VOCABULARY.has('zig')).toBe(false); + }); +}); + +describe('core/language-evidence — classifySources', () => { + let dir: string; + beforeEach(() => { + dir = mkdtempSync(join(tmpdir(), 'clad-langev-')); + }); + afterEach(() => { + rmSync(dir, {recursive: true, force: true}); + }); + + test('AC-1c7a90b2 — counts per language, sorted set, dominant, and share', () => { + seed(dir, join('src', 'app'), '.ts', 6); + seed(dir, join('src', 'native'), '.cpp', 2); + seed(dir, 'scripts', '.py', 2); + + const evidence = classifySources(dir); + + expect(evidence.counts).toEqual({typescript: 6, cpp: 2, python: 2}); + expect(evidence.classified).toBe(10); + expect(evidence.set).toEqual(['cpp', 'python', 'typescript']); + expect(evidence.dominant).toBe('typescript'); + expect(evidence.share('typescript')).toBeCloseTo(0.6, 10); + expect(evidence.share('cpp')).toBeCloseTo(0.2, 10); + expect(evidence.share('ruby')).toBe(0); + }); + + test('AC-1c7a90b2 — one language across several extensions folds into one label', () => { + seed(dir, 'a', '.ts', 2); + seed(dir, 'b', '.tsx', 3); + const evidence = classifySources(dir); + expect(evidence.counts).toEqual({typescript: 5}); + expect(evidence.set).toEqual(['typescript']); + expect(evidence.share('typescript')).toBe(1); + }); + + test('AC-1c7a90b2 — vendored, generated and dot directories are skipped', () => { + seed(dir, join('src', 'app'), '.ts', 3); + // Each of these would outvote the real source if it were walked. + for (const skipped of ['node_modules', 'dist', 'build', 'out', 'coverage', 'target', 'vendor', '.cladding', '.git', '.venv']) { + seed(dir, join(skipped, 'pkg'), '.py', 4); + } + + const evidence = classifySources(dir); + + expect(evidence.counts).toEqual({typescript: 3}); + expect(evidence.set).toEqual(['typescript']); + expect(evidence.dominant).toBe('typescript'); + expect(evidence.share('python')).toBe(0); + }); + + test('AC-1c7a90b2 — extensions outside the vocabulary are ignored', () => { + seed(dir, 'src', '.ts', 2); + seed(dir, 'docs', '.md', 9); + seed(dir, 'assets', '.png', 5); + writeFileSync(join(dir, 'Makefile'), 'all:\n'); + + const evidence = classifySources(dir); + + expect(evidence.classified).toBe(2); + expect(evidence.counts).toEqual({typescript: 2}); + }); + + test('AC-1c7a90b2 — an empty tree classifies nothing and never throws', () => { + const evidence = classifySources(dir); + expect(evidence.classified).toBe(0); + expect(evidence.counts).toEqual({}); + expect(evidence.set).toEqual([]); + expect(evidence.dominant).toBeNull(); + expect(evidence.share('typescript')).toBe(0); + }); + + test('AC-1c7a90b2 — a directory that does not exist yields empty evidence', () => { + const evidence = classifySources(join(dir, 'nope')); + expect(evidence.classified).toBe(0); + expect(evidence.dominant).toBeNull(); + }); + + test('AC-1c7a90b2 — the walk is capped so a per-gate call stays bounded', () => { + expect(MAX_FILES).toBe(20_000); + + seed(dir, 'src', '.ts', 12); + // Same tree, tiny injected cap: the walk stops instead of classifying all 12. + const capped = classifySources(dir, {maxFiles: 4}); + expect(capped.classified).toBe(4); + expect(classifySources(dir).classified).toBe(12); + }); +}); + +describe('core/language-evidence — observedKnownExtensions', () => { + let dir: string; + beforeEach(() => { + dir = mkdtempSync(join(tmpdir(), 'clad-langext-')); + }); + afterEach(() => { + rmSync(dir, {recursive: true, force: true}); + }); + + test('AC-4d21c8a7 — reports the extensions present, not every extension the label covers', () => { + seed(dir, join('src', 'engine'), '.cpp', 3); + seed(dir, join('src', 'engine'), '.h', 1); + seed(dir, 'scripts', '.py', 2); + + // `.cc`, `.cxx` and `.hpp` share the cpp label but are absent from the + // tree — globbing for them would scan directories that cannot match. + expect(observedKnownExtensions(dir)).toEqual(['.cpp', '.h', '.py']); + }); + + test('AC-4d21c8a7 — unknown extensions, vendored trees and dot directories are left out', () => { + seed(dir, 'src', '.ts', 2); + seed(dir, 'docs', '.md', 4); + seed(dir, join('node_modules', 'pkg'), '.js', 5); + seed(dir, join('.venv', 'lib'), '.py', 5); + + expect(observedKnownExtensions(dir)).toEqual(['.ts']); + }); + + test('AC-4d21c8a7 — an empty or missing tree yields no extensions, and the walk is capped', () => { + expect(observedKnownExtensions(dir)).toEqual([]); + expect(observedKnownExtensions(join(dir, 'nope'))).toEqual([]); + + seed(dir, 'a', '.ts', 6); + seed(dir, 'b', '.py', 6); + // Injected cap: the walk stops early, so it can miss a language — the + // same bounded contract classifySources runs under. + expect(observedKnownExtensions(dir, {maxFiles: 1}).length).toBe(1); + expect(observedKnownExtensions(dir)).toEqual(['.py', '.ts']); + }); +}); diff --git a/tests/events/log.test.ts b/tests/events/log.test.ts index 2abc0313..2224129e 100644 --- a/tests/events/log.test.ts +++ b/tests/events/log.test.ts @@ -112,6 +112,40 @@ describe('recordEvent (F-b84c38)', () => { expect(runs.length).toBe(3); }); + test('a stop block makes the next identical gate observable', () => { + const gate = {tier: 'pre-push', strict: true, worst: 1, anyFailed: true, stopFingerprint: 'blocked'}; + recordEvent(dir, 'gate_run', gate); + recordEvent(dir, 'gate_run', gate); + expect(readEvents(dir).filter((event) => event.type === 'gate_run')).toHaveLength(1); + + recordEvent(dir, 'stop_blocked', {count: 1, fingerprint: 'blocked'}); + recordEvent(dir, 'gate_run', gate); + recordEvent(dir, 'gate_run', gate); + + const events = readEvents(dir); + expect(events.map((event) => event.type)).toEqual(['gate_run', 'stop_blocked', 'gate_run']); + }); + + test('changed blocker evidence is not deduped behind the same red outcome tuple', () => { + recordEvent(dir, 'gate_run', { + tier: 'pre-push', + strict: true, + worst: 1, + anyFailed: true, + blockers: ['FIRST'], + stopFingerprint: 'first', + }); + recordEvent(dir, 'gate_run', { + tier: 'pre-push', + strict: true, + worst: 1, + anyFailed: true, + blockers: ['SECOND'], + stopFingerprint: 'second', + }); + expect(readEvents(dir).filter((event) => event.type === 'gate_run')).toHaveLength(2); + }); + test('non-gate_run types are never deduped', () => { recordEvent(dir, 'done_attempted', {feature: 'F-x', worst: 0, kept: true}); recordEvent(dir, 'done_attempted', {feature: 'F-x', worst: 0, kept: true}); diff --git a/tests/events/stop-telemetry.test.ts b/tests/events/stop-telemetry.test.ts new file mode 100644 index 00000000..ba52a1f6 --- /dev/null +++ b/tests/events/stop-telemetry.test.ts @@ -0,0 +1,86 @@ +// Cladding · F-1aab1bba — pure Stop outcome attribution and correlation. + +import {describe, expect, test} from 'vitest'; + +import {newEvent, type Event} from '../../src/events/log.js'; +import { + attributeStopFailures, + blockingDetectorNames, + gateStopFingerprint, + summarizeStopOutcomes, + type TelemetryStage, +} from '../../src/events/stop-telemetry.js'; + +function event(type: Event['type'], payload: Record): Event { + return newEvent(type, payload); +} + +describe('Stop outcome telemetry', () => { + test('compact blockers retain structured detector names and opaque failing stages', () => { + const stages: TelemetryStage[] = [ + {stage: 'stage_1.1', status: 'fail'}, + { + stage: 'stage_1.3', + status: 'fail', + findings: [ + {detector: 'BETA', path: 'b', severity: 'warn'}, + {detector: 'ALPHA', path: 'a', severity: 'error'}, + {detector: 'ALPHA', path: 'other', severity: 'error'}, + {detector: 'FYI', severity: 'info'}, + ], + }, + {stage: 'stage_1.5', status: 'pass'}, + ]; + expect(blockingDetectorNames(stages)).toEqual(['ALPHA', 'BETA', 'stage_1.1']); + expect(blockingDetectorNames([{stage: 'stage_1.3', status: 'pass'}])).toEqual([]); + }); + + test('gate fingerprint is byte-compatible with the deployed Stop detector|path vector', () => { + const stages: TelemetryStage[] = [ + { + stage: 'stage_1.3', + status: 'fail', + findings: [ + {detector: 'AC_DRIFT', path: 'spec/x.yaml', severity: 'error'}, + {detector: 'IGNORED', path: 'docs/x.md', severity: 'info'}, + ], + }, + {stage: 'stage_1.5', status: 'fail'}, + {stage: 'stage_1.6', status: 'pass'}, + ]; + expect(gateStopFingerprint(stages)).toBe('bae6850452d64f7bf5284989955dcfc1994669983f354920e3d660a42687bea6'); + expect(gateStopFingerprint([{stage: 'stage_1.3', status: 'pass'}])).toBe(''); + }); + + test('attributes findings against the latest gate independently of dirty-tree intersection', () => { + expect( + attributeStopFailures( + [ + {detector: 'NEW', path: 'src/new.ts'}, + {detector: 'OLD', path: 'src/old.ts'}, + {detector: 'OLD', path: ''}, + ], + ['OLD'], + ['src/new.ts'], + ), + ).toEqual({detectors: ['NEW', 'OLD'], introduced: 1, preexisting: 2, dirty_hit: true}); + }); + + test('matches a blocked fingerprint only against later gate runs', () => { + const events = [ + event('gate_run', {stopFingerprint: 'same'}), + event('stop_blocked', {fingerprint: 'same'}), + event('stop_exit_recorded', {fingerprint: 'same'}), + event('gate_run', {stopFingerprint: 'different'}), + event('stop_blocked', {fingerprint: 'later'}), + event('gate_run', {stopFingerprint: 'later'}), + event('stop_blocked', {}), + ]; + expect(summarizeStopOutcomes(events)).toEqual({ + blocked: 3, + exitsRecorded: 1, + observedByLaterGate: 1, + notObservedByLaterGate: 2, + }); + }); +}); diff --git a/tests/init/git-hook.test.ts b/tests/init/git-hook.test.ts index e6d71820..c40eaa01 100644 --- a/tests/init/git-hook.test.ts +++ b/tests/init/git-hook.test.ts @@ -100,19 +100,31 @@ describe('installGitHook pre-push (F-16746b)', () => { }); describe('scaffoldCiWorkflow (F-16746b)', () => { - test('creates the authoritative-gate workflow once and never overwrites it', () => { + test('creates a major.minor-pinned authoritative-gate workflow once and never overwrites it', () => { const dir = mkdtempSync(join(tmpdir(), 'clad-ci-')); try { - expect(scaffoldCiWorkflow(dir)).toBe('created'); + expect(scaffoldCiWorkflow(dir, '0.9.3')).toBe('created'); const p = join(dir, '.github', 'workflows', 'cladding.yml'); const body = readFileSync(p, 'utf8'); + expect(body).toContain('npx --yes cladding@0.9 check'); expect(body).toContain('check --tier=pre-push --strict --json'); expect(body).toContain('fetch-depth: 0'); writeFileSync(p, '# user-owned\n'); - expect(scaffoldCiWorkflow(dir)).toBe('exists'); + expect(scaffoldCiWorkflow(dir, null)).toBe('exists'); expect(readFileSync(p, 'utf8')).toBe('# user-owned\n'); } finally { rmSync(dir, {recursive: true, force: true}); } }); + + test('does not scaffold an unpinned workflow when the runtime version is unavailable', () => { + const dir = mkdtempSync(join(tmpdir(), 'clad-ci-no-version-')); + try { + expect(scaffoldCiWorkflow(dir, null)).toBe('version-unavailable'); + expect(existsSync(join(dir, '.github', 'workflows', 'cladding.yml'))).toBe(false); + expect(scaffoldCiWorkflow(dir, 'not-semver')).toBe('version-unavailable'); + } finally { + rmSync(dir, {recursive: true, force: true}); + } + }); }); diff --git a/tests/scripts/hooks-config.test.ts b/tests/scripts/hooks-config.test.ts index 1af2407a..a3a6610c 100644 --- a/tests/scripts/hooks-config.test.ts +++ b/tests/scripts/hooks-config.test.ts @@ -27,6 +27,16 @@ interface HookEntry { const doc = JSON.parse(readFileSync(join(ROOT, 'plugins/claude-code/hooks/hooks.json'), 'utf8')) as { hooks: Record; }; +const projectSettings = JSON.parse(readFileSync(join(ROOT, '.claude/settings.json'), 'utf8')) as { + enabledPlugins?: Record; + extraKnownMarketplaces?: Record; +}; +const packageDoc = JSON.parse(readFileSync(join(ROOT, 'package.json'), 'utf8')) as { + scripts?: Record; +}; describe('claude-code plugin hooks.json — five events wired to the bundled engine', () => { test('every key is one of the five events, and all five are present', () => { @@ -58,10 +68,24 @@ describe('claude-code plugin hooks.json — five events wired to the bundled eng expect(doc.hooks.PostToolUse[0].matcher, 'PostToolUse matcher').toBe('Edit|Write|MultiEdit|Bash'); }); - test('plugin.json declares the hooks field pointing at hooks/hooks.json', () => { + test('the standard hooks file is auto-discovered and not declared twice', () => { const plugin = JSON.parse( readFileSync(join(ROOT, 'plugins/claude-code/.claude-plugin/plugin.json'), 'utf8'), - ) as {hooks?: string}; - expect(plugin.hooks).toBe('./hooks/hooks.json'); + ) as {hooks?: unknown}; + expect(Object.hasOwn(plugin, 'hooks')).toBe(false); + }); + + test('the dogfood project declares where Claude Code can install the enabled plugin', () => { + expect(projectSettings.enabledPlugins?.['claude-code@cladding']).toBe(true); + expect(projectSettings.extraKnownMarketplaces?.cladding).toEqual({ + source: {source: 'directory', path: '.'}, + autoUpdate: true, + }); + }); + + test('the standalone plugin build regenerates the ignored engine before copying it', () => { + expect(packageDoc.scripts?.['build:plugin']).toBe( + 'node scripts/build.mjs && node scripts/build-plugin.mjs', + ); }); }); diff --git a/tests/spec/attestation-policy.test.ts b/tests/spec/attestation-policy.test.ts new file mode 100644 index 00000000..6e8346e5 --- /dev/null +++ b/tests/spec/attestation-policy.test.ts @@ -0,0 +1,74 @@ +import {mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {join} from 'node:path'; + +import {afterEach, beforeEach, describe, expect, test} from 'vitest'; + +import { + detectorCatalogSha256, + featureAttestation, + readAttestation, + writeAttestation, + type AttestationPolicy, +} from '../../src/spec/attestation.js'; +import type {Spec} from '../../src/spec/types.js'; + +describe('attestation policy stamp', () => { + let dir: string; + let spec: Spec; + const policy: AttestationPolicy = { + cladding: '0.9.4', + blocking: 'strict', + detectorsSha256: 'a'.repeat(64), + }; + + beforeEach(() => { + dir = mkdtempSync(join(tmpdir(), 'clad-att-policy-')); + mkdirSync(join(dir, 'spec'), {recursive: true}); + mkdirSync(join(dir, 'src'), {recursive: true}); + writeFileSync(join(dir, 'src', 'main.ts'), 'export const main = true;\n', 'utf8'); + spec = { + schema: '0.1', + project: {name: 'policy-fixture', language: 'typescript'}, + features: [{id: 'F-policy1', title: 'Policy', status: 'done', modules: ['src/main.ts']}], + }; + }); + + afterEach(() => { + rmSync(dir, {recursive: true, force: true}); + }); + + test('writes and reads the policy stamp deterministically', () => { + expect(writeAttestation(dir, spec, policy)).toBe(true); + const path = join(dir, 'spec', 'attestation.yaml'); + const first = readFileSync(path, 'utf8'); + expect(first.indexOf('policy:')).toBeLessThan(first.indexOf('attested_modules:')); + expect(first).toContain(' cladding: "0.9.4"'); + expect(first).toContain(' blocking: strict'); + expect(first).toContain(` detectors_sha256: ${'a'.repeat(64)}`); + expect(readAttestation(dir)?.policy).toEqual(policy); + + writeAttestation(dir, spec, policy); + expect(readFileSync(path, 'utf8')).toBe(first); + }); + + test('legacy v2 without policy remains readable', () => { + expect(writeAttestation(dir, spec)).toBe(true); + const attestation = readAttestation(dir); + expect(attestation?.policy).toBeNull(); + expect(featureAttestation(attestation!, dir, spec.features[0])).toEqual({state: 'fresh'}); + }); + + test('detector catalog fingerprint is deterministic and configuration-sensitive', () => { + const catalog = [ + {name: 'FIRST'}, + {name: 'SECOND', subprocess: true as const}, + ]; + const baseline = detectorCatalogSha256(catalog); + expect(baseline).toMatch(/^[0-9a-f]{64}$/); + expect(detectorCatalogSha256(catalog)).toBe(baseline); + expect(detectorCatalogSha256([...catalog].reverse())).not.toBe(baseline); + expect(detectorCatalogSha256([{name: 'RENAMED'}, catalog[1]])).not.toBe(baseline); + expect(detectorCatalogSha256([{name: 'FIRST', subprocess: true}, catalog[1]])).not.toBe(baseline); + }); +}); diff --git a/tests/stages/detectors/host-claim-drift.test.ts b/tests/stages/detectors/host-claim-drift.test.ts index 945b97b8..a91d7276 100644 --- a/tests/stages/detectors/host-claim-drift.test.ts +++ b/tests/stages/detectors/host-claim-drift.test.ts @@ -35,12 +35,18 @@ describe('HOST_CLAIM_DRIFT — README claims may not exceed matrix evidence (AC- }; /** Write docs/dogfood/matrix.md with a matrix-grades fence, or a raw string body. */ - const writeMatrix = (grades: Record | string | null): void => { + const writeMatrix = ( + grades: Record | string | null, + metadata?: {readonly version: string; readonly generatedAt: string}, + ): void => { if (grades === null) return; // omit the file entirely mkdirSync(join(dir, 'docs', 'dogfood'), {recursive: true}); const fence = typeof grades === 'string' ? grades : ``; - writeFileSync(join(dir, 'docs', 'dogfood', 'matrix.md'), `# Host matrix\n\n${fence}\n`); + const meta = metadata === undefined + ? '' + : `\n- Cladding version: \`${metadata.version}\`\n- Generated: ${metadata.generatedAt}\n`; + writeFileSync(join(dir, 'docs', 'dogfood', 'matrix.md'), `# Host matrix\n\n${fence}\n${meta}`); }; const run = (): DriftFinding[] => [...hostClaimDrift.run({cwd: dir})]; @@ -127,4 +133,52 @@ describe('HOST_CLAIM_DRIFT — README claims may not exceed matrix evidence (AC- expect(fs[0].message).not.toContain('gemini'); // not-run evidence → neutral expect(fs[0].message).not.toContain('cursor'); // wiring-only vs wiring-ok → matches }); + + test('positive claim with evidence older than 30 days → one non-blocking freshness finding', () => { + writeReadme({claude: 'verified'}); + writeMatrix( + {claude: 'verified'}, + {version: '999.0.0', generatedAt: '2000-01-01T00:00:00.000Z'}, + ); + const fs = run(); + expect(fs).toHaveLength(1); + expect(fs[0]).toMatchObject({ + detector: 'HOST_CLAIM_DRIFT', + severity: 'info', + path: 'docs/dogfood/matrix.md', + }); + expect(fs[0].message).toContain('more than 30 days ago'); + expect(fs[0].message).toContain('clad doctor --hosts'); + }); + + test('positive claim from an older engine → freshness info without changing the matching grade', () => { + writeReadme({codex: 'verified'}); + writeMatrix( + {codex: 'verified'}, + {version: '0.0.1', generatedAt: '2999-01-01T00:00:00.000Z'}, + ); + const fs = run(); + expect(fs).toHaveLength(1); + expect(fs[0].severity).toBe('info'); + expect(fs[0].message).toContain('generated by cladding v0.0.1'); + expect(fs[0].message).toContain('existing contradictory-claim warnings are unchanged'); + }); + + test('matching claim with fresh, non-older metadata → no freshness finding', () => { + writeReadme({claude: 'verified'}); + writeMatrix( + {claude: 'verified'}, + {version: '999.0.0', generatedAt: '2999-01-01T00:00:00.000Z'}, + ); + expect(run()).toEqual([]); + }); + + test('no positive README claim → stale matrix metadata remains a no-op', () => { + writeReadme({claude: 'not-run'}); + writeMatrix( + {claude: 'fail'}, + {version: '0.0.1', generatedAt: '2000-01-01T00:00:00.000Z'}, + ); + expect(run()).toEqual([]); + }); }); diff --git a/tests/stages/tech-stack-mismatch-evidence.test.ts b/tests/stages/tech-stack-mismatch-evidence.test.ts new file mode 100644 index 00000000..113e3529 --- /dev/null +++ b/tests/stages/tech-stack-mismatch-evidence.test.ts @@ -0,0 +1,319 @@ +// Cladding · impl-blind oracle for F-9e1279d4 — authored from the spec contract only. +import {afterEach, describe, expect, test} from 'vitest'; +import {mkdirSync, mkdtempSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {join} from 'node:path'; +import {techStackMismatch} from '../../src/stages/detectors/tech-stack-mismatch.js'; + +/** + * Contract under test (D8), encoded without sight of the implementation: + * + * 1. declared language not a known label -> no findings + * 2. fewer than 5 classifiable source files -> no findings + * 3. declared language absent from observed sources -> exactly 1 finding, 'warn', + * message names declared + dominant observed + * 4. declared observed but under 10% of sources -> exactly 1 finding, 'info' + * 5. otherwise -> no findings + * 6. build manifests have no influence on the outcome + * 7. severity 'error' is never produced + */ + +type FileSpec = readonly [count: number, ext: string]; + +type Expectation = + | {readonly kind: 'none'} + | {readonly kind: 'warn' | 'info'; readonly contains?: readonly string[]}; + +interface Fixture { + readonly language: string; + readonly files: readonly FileSpec[]; + readonly manifests?: readonly string[]; +} + +interface Row extends Fixture { + readonly id: number; + readonly why: string; + readonly expect: Expectation; +} + +const tempDirs: string[] = []; + +function makeFixture(fixture: Fixture): string { + const dir = mkdtempSync(join(tmpdir(), 'tsm-')); + tempDirs.push(dir); + + writeFileSync( + join(dir, 'spec.yaml'), + `schema: "0.1"\nproject: {name: x, language: ${fixture.language}}\nfeatures: []\n`, + 'utf8', + ); + mkdirSync(join(dir, 'spec', 'features'), {recursive: true}); + + const srcDir = join(dir, 'src', 'pkg'); + mkdirSync(srcDir, {recursive: true}); + let seq = 0; + for (const [count, ext] of fixture.files) { + for (let n = 0; n < count; n++) { + seq++; + writeFileSync(join(srcDir, `f${seq}.${ext}`), `// f${seq}\n`, 'utf8'); + } + } + + for (const manifest of fixture.manifests ?? []) { + writeFileSync(join(dir, manifest), '', 'utf8'); + } + + return dir; +} + +function runOn(fixture: Fixture): ReadonlyArray<{ + detector: string; + severity: string; + message: string; +}> { + const cwd = makeFixture(fixture); + return techStackMismatch.run({cwd}) as ReadonlyArray<{ + detector: string; + severity: string; + message: string; + }>; +} + +afterEach(() => { + while (tempDirs.length > 0) { + const dir = tempDirs.pop(); + if (dir) rmSync(dir, {recursive: true, force: true}); + } +}); + +const rows: readonly Row[] = [ + { + id: 1, + language: 'cpp', + files: [[12, 'cpp'], [6, 'h'], [3, 'java']], + manifests: ['build.gradle'], + why: 'declared cpp dominates the observed sources', + expect: {kind: 'none'}, + }, + { + id: 2, + language: 'kotlin', + files: [[24, 'kt'], [4, 'cpp'], [2, 'java']], + manifests: ['build.gradle.kts'], + why: 'declared kotlin dominates the observed sources', + expect: {kind: 'none'}, + }, + { + id: 3, + language: 'typescript', + files: [[20, 'ts'], [6, 'java'], [4, 'swift'], [3, 'kt']], + manifests: ['package.json'], + why: 'declared typescript dominates a polyglot tree', + expect: {kind: 'none'}, + }, + { + id: 4, + language: 'javascript', + files: [[14, 'js']], + manifests: ['package.json'], + why: 'declared javascript is the only observed language', + expect: {kind: 'none'}, + }, + { + id: 5, + language: 'csharp', + files: [[16, 'cs']], + manifests: [], + why: 'declared csharp is the only observed language, no manifest at all', + expect: {kind: 'none'}, + }, + { + id: 6, + language: 'scala', + files: [[12, 'scala']], + manifests: ['build.sbt'], + why: 'declared scala is the only observed language', + expect: {kind: 'none'}, + }, + { + id: 7, + language: 'rust', + files: [[15, 'rs']], + manifests: ['package.json'], + why: 'declared rust matches sources; a node manifest must not sway the verdict', + expect: {kind: 'none'}, + }, + { + id: 8, + language: 'zig', + files: [[16, 'zig']], + manifests: [], + why: 'declared label is not a known language', + expect: {kind: 'none'}, + }, + { + id: 9, + language: 'nim', + files: [[10, 'nim'], [6, 'ts']], + manifests: ['package.json'], + why: 'declared label is not a known language, even with known sources present', + expect: {kind: 'none'}, + }, + { + id: 10, + language: 'python', + files: [[38, 'zig'], [2, 'ts']], + manifests: ['package.json'], + why: 'only 2 classifiable files — evidence below the floor of 5', + expect: {kind: 'none'}, + }, + { + id: 11, + language: 'python', + files: [[40, 'ipynb'], [2, 'ts']], + manifests: [], + why: 'notebooks are invisible; only 2 classifiable files', + expect: {kind: 'none'}, + }, + { + id: 12, + language: 'cpp', + files: [[10, 'c'], [4, 'h']], + manifests: [], + why: '.c is unknown, so only 4 classifiable files — below the floor', + expect: {kind: 'none'}, + }, + { + id: 13, + language: 'python', + files: [[20, 'ts']], + manifests: ['package.json'], + why: 'declared python absent from an all-typescript tree', + expect: {kind: 'warn', contains: ['python', 'typescript']}, + }, + { + id: 14, + language: 'typescript', + files: [[18, 'go']], + manifests: ['go.mod'], + why: 'declared typescript absent from an all-go tree', + expect: {kind: 'warn', contains: ['typescript', 'go']}, + }, + { + id: 15, + language: 'java', + files: [[25, 'kt']], + manifests: ['build.gradle.kts'], + why: 'declared java absent from an all-kotlin tree', + expect: {kind: 'warn', contains: ['java', 'kotlin']}, + }, + { + id: 16, + language: 'python', + files: [[38, 'zig'], [10, 'ts']], + manifests: ['package.json'], + why: 'unknown files are invisible; the 10 typescript files clear the floor of 5', + expect: {kind: 'warn', contains: ['python', 'typescript']}, + }, + { + id: 17, + language: 'python', + files: [[22, 'ts'], [2, 'py']], + manifests: ['package.json'], + why: 'declared python present but 2/24 ~= 8.3% of sources', + expect: {kind: 'info'}, + }, + { + id: 18, + language: 'cpp', + files: [[60, 'kt'], [3, 'cpp']], + manifests: ['build.gradle'], + why: 'declared cpp present but 3/63 ~= 4.8% of sources', + expect: {kind: 'info'}, + }, + { + id: 19, + language: 'typescript', + files: [[3, 'ts'], [30, 'js']], + manifests: ['package.json'], + why: 'declared typescript present but 3/33 ~= 9.1% of sources', + expect: {kind: 'info'}, + }, + { + id: 20, + language: 'java', + files: [[20, 'java'], [8, 'kt']], + manifests: ['build.gradle'], + why: 'declared java holds a ~71% majority', + expect: {kind: 'none'}, + }, +] as const; + +describe('TECH_STACK_MISMATCH — evidence-based conformance table (F-9e1279d4)', () => { + for (const row of rows) { + const label = `row ${row.id}: declared ${row.language} -> ${row.expect.kind} (${row.why})`; + + test(label, () => { + const findings = runOn(row); + + expect(Array.isArray(findings)).toBe(true); + for (const finding of findings) { + expect(finding.detector).toBe('TECH_STACK_MISMATCH'); + expect(finding.severity).not.toBe('error'); + } + + if (row.expect.kind === 'none') { + expect(findings).toEqual([]); + return; + } + + expect(findings).toHaveLength(1); + const [finding] = findings; + expect(finding.severity).toBe(row.expect.kind); + expect(typeof finding.message).toBe('string'); + + for (const needle of row.expect.contains ?? []) { + expect(finding.message.toLowerCase()).toContain(needle); + } + }); + } + + test('build manifests never influence the outcome (row 13 with and without package.json)', () => { + const withManifest = runOn({ + language: 'python', + files: [[20, 'ts']], + manifests: ['package.json'], + }); + const withoutManifest = runOn({ + language: 'python', + files: [[20, 'ts']], + manifests: [], + }); + + const shape = ( + findings: ReadonlyArray<{detector: string; severity: string; message: string}>, + ) => findings.map((f) => ({detector: f.detector, severity: f.severity, message: f.message})); + + expect(shape(withoutManifest)).toEqual(shape(withManifest)); + expect(withManifest).toHaveLength(1); + expect(withManifest[0].severity).toBe('warn'); + }); + + test("no row of the table ever produces severity 'error'", () => { + const produced: Array<{detector: string; severity: string}> = []; + + for (const row of rows) { + for (const finding of runOn(row)) { + produced.push({detector: finding.detector, severity: finding.severity}); + } + } + + // The table has 4 warn rows + 3 info rows, so the detector must speak exactly 7 times. + expect(produced).toHaveLength(7); + for (const finding of produced) { + expect(finding.detector).toBe('TECH_STACK_MISMATCH'); + expect(finding.severity).not.toBe('error'); + expect(['warn', 'info']).toContain(finding.severity); + } + }); +}); diff --git a/tests/stages/tech-stack-mismatch.test.ts b/tests/stages/tech-stack-mismatch.test.ts index b501e2c6..0a5ed03f 100644 --- a/tests/stages/tech-stack-mismatch.test.ts +++ b/tests/stages/tech-stack-mismatch.test.ts @@ -1,19 +1,25 @@ // Cladding · unit tests for stages/detectors/tech-stack-mismatch.ts // -// Detector under test cross-checks `spec.project.language` against the -// language `detectToolchain` resolves by walking the project's manifest -// chain. The three reachable outcomes: +// Detector under test compares `spec.project.language` against the source +// files actually on disk (core/language-evidence.ts) — never against the +// build-manifest chain. Outcome table (F-9e1279d4): // -// - languages agree → no finding -// - languages differ → warn finding (typo / unported drift) -// - manifest chain returns -// 'unknown' (no manifest) → info finding (cannot cross-check) +// declared language outside the vocabulary → nothing (AC-3f8e6d15) +// fewer than 5 classified source files → nothing (AC-3f8e6d15) +// declared absent from the observed set → one warn, naming the +// declared language and +// the observed counts +// (AC-5b2d47c9) +// declared observed but under 10% of sources → one info, naming the +// share; never blocking +// (AC-8d94a1e6) +// declared at or above 10% of sources → nothing (AC-e07c3241) // -// The detector relies on the manifest priority chain in -// stages/toolchain/detect.ts: package.json (TypeScript) beats -// pyproject.toml (Python) in priority order. These tests exercise that -// priority chain at the cladding-detector level — the chain itself has -// dedicated coverage in tests/stages/toolchain.test.ts. +// The manifest chain is deliberately not consulted for identity, so a +// package.json / build.gradle in the fixture must not move any outcome — +// that invariant is asserted directly. Fixtures write ≥5 real source files +// under /src/pkg/ so the evidence floor is genuinely cleared rather +// than mocked. import {mkdirSync, mkdtempSync, rmSync, writeFileSync} from 'node:fs'; import {tmpdir} from 'node:os'; @@ -30,6 +36,15 @@ function writeSpec(dir: string, language: string): void { mkdirSync(join(dir, 'spec', 'features'), {recursive: true}); } +/** Writes `count` source files with `ext` under /src/pkg (prefix keeps names unique). */ +function writeSources(dir: string, ext: string, count: number, prefix = 'f'): void { + const target = join(dir, 'src', 'pkg'); + mkdirSync(target, {recursive: true}); + for (let i = 0; i < count; i += 1) { + writeFileSync(join(target, `${prefix}${i}${ext}`), '// source\n'); + } +} + describe('TECH_STACK_MISMATCH detector', () => { let dir: string; beforeEach(() => { @@ -39,47 +54,145 @@ describe('TECH_STACK_MISMATCH detector', () => { rmSync(dir, {recursive: true, force: true}); }); - test('silent when spec language matches the detected manifest', () => { + test('AC-e07c3241 — silent when the declared language is the majority of sources', () => { writeSpec(dir, 'typescript'); - writeFileSync(join(dir, 'package.json'), '{"name":"x"}\n'); + writeSources(dir, '.ts', 8); expect(techStackMismatch.run({cwd: dir})).toEqual([]); }); - test('emits warn when spec language differs from the detected manifest', () => { + test('AC-e07c3241 — silent on a normal polyglot where the declared language is a plural presence', () => { + // Android-shaped: Kotlin app with an NDK C++ core. Declared kotlin is + // well above the minority band, so nothing is said. + writeSpec(dir, 'kotlin'); + writeSources(dir, '.kt', 10, 'k'); + writeSources(dir, '.cpp', 4, 'n'); + expect(techStackMismatch.run({cwd: dir})).toEqual([]); + }); + + test('AC-5b2d47c9 — warns when the declared language is absent from the tree', () => { writeSpec(dir, 'python'); - writeFileSync(join(dir, 'package.json'), '{"name":"x"}\n'); + writeSources(dir, '.ts', 6); + const findings = techStackMismatch.run({cwd: dir}); + expect(findings).toHaveLength(1); + expect(findings[0].detector).toBe('TECH_STACK_MISMATCH'); expect(findings[0].severity).toBe('warn'); + // names the declared language, the observed language, and the evidence count expect(findings[0].message).toContain("'python'"); - expect(findings[0].message).toContain("'typescript'"); + expect(findings[0].message).toContain('typescript'); + expect(findings[0].message).toContain('×6'); }); - test('emits info when no manifest matches at all', () => { - writeSpec(dir, 'typescript'); - // intentionally no package.json, no pyproject.toml, etc. + test('AC-5b2d47c9 — the warn lists every observed language, most-seen first', () => { + writeSpec(dir, 'python'); + writeSources(dir, '.ts', 6); + writeSources(dir, '.go', 2, 'g'); + + const findings = techStackMismatch.run({cwd: dir}); + + expect(findings).toHaveLength(1); + expect(findings[0].message).toContain('{typescript ×6, go ×2}'); + }); + + test('AC-8d94a1e6 — a declared language under 10% of sources is info, never blocking', () => { + // Thin native SDK: 1 C++ file under 19 TypeScript files = 5%. + writeSpec(dir, 'cpp'); + writeSources(dir, '.ts', 19); + writeSources(dir, '.cpp', 1, 'n'); + const findings = techStackMismatch.run({cwd: dir}); + expect(findings).toHaveLength(1); expect(findings[0].severity).toBe('info'); - expect(findings[0].message).toContain('no manifest matched'); + expect(findings[0].message).toContain("'cpp'"); + expect(findings[0].message).toContain('(1/20)'); + }); + + test('AC-8d94a1e6 — the detector never emits an error severity', () => { + for (const [language, ext, count] of [['python', '.ts', 6], ['cpp', '.ts', 19]] as const) { + const local = mkdtempSync(join(tmpdir(), 'clad-tsm-sev-')); + try { + writeSpec(local, language); + writeSources(local, ext, count); + if (language === 'cpp') writeSources(local, '.cpp', 1, 'n'); + for (const finding of techStackMismatch.run({cwd: local})) { + expect(finding.severity).not.toBe('error'); + } + } finally { + rmSync(local, {recursive: true, force: true}); + } + } + }); + + test('AC-e07c3241 — exactly at the 10% threshold is silence, not disclosure', () => { + // 2 of 20 = 10% — the band is "under 10%", so the boundary stays quiet. + writeSpec(dir, 'cpp'); + writeSources(dir, '.ts', 18); + writeSources(dir, '.cpp', 2, 'n'); + expect(techStackMismatch.run({cwd: dir})).toEqual([]); + }); + + test('AC-3f8e6d15 — a language outside the vocabulary produces nothing', () => { + // cladding has no extension mapping for zig; ignorance is not drift, + // even though the tree is unambiguously TypeScript. + writeSpec(dir, 'zig'); + writeSources(dir, '.ts', 8); + expect(techStackMismatch.run({cwd: dir})).toEqual([]); }); - test('package.json wins over pyproject.toml (priority chain)', () => { - // Both manifests present → priority chain returns the first match, - // which is package.json (typescript). Spec says python → mismatch - // confirms the priority order. + test('AC-3f8e6d15 — fewer than 5 classified source files produces nothing', () => { writeSpec(dir, 'python'); - writeFileSync(join(dir, 'package.json'), '{"name":"x"}\n'); - writeFileSync(join(dir, 'pyproject.toml'), '[project]\nname = "x"\n'); + writeSources(dir, '.ts', 4); + expect(techStackMismatch.run({cwd: dir})).toEqual([]); + }); + + test('AC-3f8e6d15 — the fifth file is the first that can carry an assertion', () => { + writeSpec(dir, 'python'); + writeSources(dir, '.ts', 5); const findings = techStackMismatch.run({cwd: dir}); expect(findings).toHaveLength(1); expect(findings[0].severity).toBe('warn'); - expect(findings[0].message).toContain("'typescript'"); }); - test('absent spec.yaml emits one info finding (not a throw)', () => { - // No spec.yaml at all; package.json still present. + test('AC-3f8e6d15 — a docs-only tree with no source files produces nothing', () => { + writeSpec(dir, 'typescript'); + mkdirSync(join(dir, 'docs'), {recursive: true}); + writeFileSync(join(dir, 'docs', 'guide.md'), '# guide\n'); + expect(techStackMismatch.run({cwd: dir})).toEqual([]); + }); + + test('AC-e07c3241 — a build manifest cannot contradict the sources', () => { + // Old contract: package.json resolved "typescript" and warned against a + // python spec even with zero source files. New contract: the manifest is + // not consulted at all, so a truthful python tree stays silent. + writeSpec(dir, 'python'); + writeSources(dir, '.py', 6); writeFileSync(join(dir, 'package.json'), '{"name":"x"}\n'); + writeFileSync(join(dir, 'build.gradle'), 'plugins {}\n'); + expect(techStackMismatch.run({cwd: dir})).toEqual([]); + }); + + test('AC-e07c3241 — adding or removing manifests leaves the outcome identical', () => { + writeSpec(dir, 'python'); + writeSources(dir, '.ts', 6); + const withoutManifest = techStackMismatch.run({cwd: dir}); + writeFileSync(join(dir, 'package.json'), '{"name":"x"}\n'); + writeFileSync(join(dir, 'pyproject.toml'), '[project]\nname = "x"\n'); + expect(techStackMismatch.run({cwd: dir})).toEqual(withoutManifest); + }); + + test('AC-e07c3241 — vendored dependencies cannot outvote the real sources', () => { + writeSpec(dir, 'typescript'); + writeSources(dir, '.ts', 6); + const vendored = join(dir, 'node_modules', 'left-pad'); + mkdirSync(vendored, {recursive: true}); + for (let i = 0; i < 40; i += 1) writeFileSync(join(vendored, `v${i}.py`), '# vendored\n'); + expect(techStackMismatch.run({cwd: dir})).toEqual([]); + }); + + test('absent spec.yaml emits one info finding (not a throw)', () => { + writeSources(dir, '.ts', 6); const findings = techStackMismatch.run({cwd: dir}); expect(findings).toHaveLength(1); expect(findings[0].severity).toBe('info'); diff --git a/tests/stages/unmapped-artifact.test.ts b/tests/stages/unmapped-artifact.test.ts index c9cbbfd2..1b315782 100644 --- a/tests/stages/unmapped-artifact.test.ts +++ b/tests/stages/unmapped-artifact.test.ts @@ -1,13 +1,26 @@ // Cladding · unit tests for stages/detectors/unmapped-artifact.ts // -// Detector under test scans `stages/**/*.ts` and `spec/**/*.ts` from the -// cwd, comparing every file against the set of paths declared in -// `features[].modules`. An unclaimed file emits an `error` finding. +// The detector compares real source files against the set of paths +// declared in `features[].modules`; an unclaimed file emits an `error` +// finding. Which files count as "real source" is the scan universe, and +// since F-87bb7ed3 that universe is built from evidence — what the tree +// contains plus what the spec claims — never from `project.language`. // // What's notable about this detector and how we test it: -// - Scope is **narrow on purpose** (tsconfig.include mirror) so test -// fixtures, tooling configs, and generated files do not appear as -// findings. Tests need to confirm that narrow scoping holds. +// - Below the scale gate the universe is the **narrow legacy pair**, on +// purpose, so day-1 adoptions are not walled off by findings for +// files they have not claimed yet. +// - Above it, scope is **evidenced**: observed extensions keep a lazy +// spec honest, claimed modules teach roots and unknown languages. +// Only modules under a declared layer teach, so a root-level docs +// claim cannot widen the source universe. +// - A layer that declares its own `modules` globs is scanned **there**, +// not under `//` — the layer name is then free to be +// a label ('native') rather than a directory. Measured defect: two +// specs identical but for the layer name found 21 files vs 0. +// - An active full scan that matches **zero files** says so with one +// `info` finding, because an empty universe and a fully-claimed tree +// otherwise look identical from the outside. // - It is status-blind: an archived feature still claims its modules, // because deleting the archived feature's source is a separate // workflow that STATUS_DRIFT / STALE_SPECIFICATION owns. @@ -16,7 +29,7 @@ import {mkdirSync, mkdtempSync, rmSync, writeFileSync} from 'node:fs'; import {tmpdir} from 'node:os'; -import {join} from 'node:path'; +import {dirname, join} from 'node:path'; import {afterEach, beforeEach, describe, expect, test} from 'vitest'; import {scanPatterns, unmappedArtifact} from '../../src/stages/detectors/unmapped-artifact.js'; @@ -26,6 +39,13 @@ const SPEC_HEADER = 'project: {name: x, language: typescript}\n' + 'features: []\n'; +/** Writes `rel` under `dir`, creating parent directories. */ +function write(dir: string, rel: string, body = 'x\n'): void { + const full = join(dir, rel); + mkdirSync(dirname(full), {recursive: true}); + writeFileSync(full, body); +} + describe('UNMAPPED_ARTIFACT detector', () => { let dir: string; beforeEach(() => { @@ -110,80 +130,463 @@ describe('UNMAPPED_ARTIFACT detector', () => { }); }); -// ─── F-aee61f — scan roots derive from declared architecture layers ─── +// ─── scan universe: declared layers (F-aee61f) × evidence (F-87bb7ed3) ─── const EIGHT_FEATURES = Array.from({length: 8}, (_, i) => ({ id: `F-00000${i}`, title: 't', status: 'done', - modules: [], + modules: [] as string[], acceptance_criteria: [], })); -describe('scanPatterns (F-aee61f)', () => { +/** The eight features of the full-scan scale gate, the first one claiming `modules`. */ +function claiming(...modules: string[]): unknown[] { + return EIGHT_FEATURES.map((f, i) => (i === 0 ? {...f, modules} : f)); +} + +describe('scanPatterns', () => { + let dir: string; + beforeEach(() => { + dir = mkdtempSync(join(tmpdir(), 'clad-unmapped-universe-')); + }); + afterEach(() => { + rmSync(dir, {recursive: true, force: true}); + }); + test('scale gate: under 8 features the legacy narrow patterns apply even with layers declared', () => { + write(dir, 'src/cli/a.ts'); const spec = { project: {name: 'x', language: 'typescript'}, features: EIGHT_FEATURES.slice(0, 3), architecture: {layers: [['cli']]}, } as never; - expect(scanPatterns(spec)).toEqual(['src/stages/**/*.ts', 'src/spec/**/*.ts']); + expect(scanPatterns(spec, dir)).toEqual(['src/stages/**/*.ts', 'src/spec/**/*.ts']); }); - test('derives one src/ pattern per declared layer (canonical string-tier form), language-aware', () => { + test('falls back to the legacy narrow patterns when no architecture is declared', () => { + const spec = {project: {name: 'x', language: 'typescript'}, features: []} as never; + expect(scanPatterns(spec, dir)).toEqual(['src/stages/**/*.ts', 'src/spec/**/*.ts']); + }); + + test('derives one pattern per declared layer (canonical string-tier form) from the observed extension', () => { + write(dir, 'src/cli/a.ts'); const spec = { project: {name: 'x', language: 'typescript'}, features: EIGHT_FEATURES, architecture: {layers: [['cli', 'serve'], ['core']]}, } as never; - expect(scanPatterns(spec)).toEqual(['src/cli/**/*.ts', 'src/core/**/*.ts', 'src/serve/**/*.ts']); + expect(scanPatterns(spec, dir)).toEqual([ + 'src/cli/**/*.ts', + 'src/core/**/*.ts', + 'src/serve/**/*.ts', + ]); }); - test('accepts the {name} object layer form and non-TS languages', () => { + test('accepts the {name} object layer form', () => { + write(dir, 'src/api/handler.py'); const spec = { project: {name: 'x', language: 'python'}, features: EIGHT_FEATURES, architecture: {layers: [{name: 'api'}, {name: 'domain'}]}, } as never; - expect(scanPatterns(spec)).toEqual(['src/api/**/*.py', 'src/domain/**/*.py']); + expect(scanPatterns(spec, dir)).toEqual(['src/api/**/*.py', 'src/domain/**/*.py']); }); - test('falls back to the legacy narrow patterns when no architecture is declared', () => { - const spec = {project: {name: 'x', language: 'typescript'}, features: []} as never; - expect(scanPatterns(spec)).toEqual(['src/stages/**/*.ts', 'src/spec/**/*.ts']); + test('AC-4d21c8a7 — every observed extension enters the universe, not just one per language', () => { + // The measured defect: `cpp` had no table entry, so the universe was + // `*.ts` and matched nothing. Both C++ extensions must now be scanned. + write(dir, 'src/engine/vm.cpp'); + write(dir, 'src/engine/vm.h'); + const spec = { + project: {name: 'x', language: 'cpp'}, + features: EIGHT_FEATURES, + architecture: {layers: [['engine']]}, + } as never; + expect(scanPatterns(spec, dir)).toEqual(['src/engine/**/*.cpp', 'src/engine/**/*.h']); }); - test('a file in a declared layer that no feature claims is now FOUND (was blind pre-0.6)', () => { - const dir = mkdtempSync(join(tmpdir(), 'clad-unmapped-arch-')); - try { - mkdirSync(join(dir, 'src', 'router'), {recursive: true}); - writeFileSync(join(dir, 'src', 'router', 'orphan.ts'), 'export const x = 1;\n'); - writeFileSync( - join(dir, 'spec.yaml'), - [ - 'schema: "0.1"', - 'project: {name: f, language: typescript}', - 'architecture:', - ' layers:', - ' - [router]', - 'features:', - ...Array.from({length: 8}, (_, i) => - [ - ` - id: F-10000${i}`, - ' title: t', - ' status: done', - ' modules: []', - ' acceptance_criteria:', - ' - {id: AC-001, ears: ubiquitous, text: t, test_refs: [spec.yaml]}', - ].join('\n'), - ), - ].join('\n') + '\n', + test('AC-4d21c8a7 — observation keeps a lazy spec honest: an unclaimed language stays in scope', () => { + write(dir, 'src/engine/vm.cpp'); // nothing claims this one + write(dir, 'src/engine/Bridge.java'); + const spec = { + project: {name: 'x', language: 'java'}, + features: claiming('src/engine/Bridge.java'), + architecture: {layers: [['engine']]}, + } as never; + expect(scanPatterns(spec, dir)).toEqual(['src/engine/**/*.cpp', 'src/engine/**/*.java']); + }); + + test('AC-4d21c8a7 — a claimed module teaches an extension the vocabulary has never heard of', () => { + write(dir, 'src/core/vm.zig'); // unknown to the vocabulary → observation ignores it + const spec = { + project: {name: 'x', language: 'zig'}, + features: claiming('src/core/vm.zig'), + architecture: {layers: [['core']]}, + } as never; + expect(scanPatterns(spec, dir)).toEqual(['src/core/**/*.zig']); + }); + + test('AC-9a6f02d3 — the scan root is inferred from the segments before the layer', () => { + write(dir, 'src/main/kotlin/core/A.kt'); + const spec = { + project: {name: 'x', language: 'kotlin'}, + features: claiming('src/main/kotlin/core/A.kt'), + architecture: {layers: [['core']]}, + } as never; + // Used to require a ROOT_BY_LANGUAGE entry; now the claim teaches it. + expect(scanPatterns(spec, dir)).toEqual(['src/main/kotlin/core/**/*.kt']); + }); + + test('AC-9a6f02d3 — two substantial source roots both survive (Gradle kotlin + java split)', () => { + const spec = { + project: {name: 'x', language: 'kotlin'}, + features: claiming('src/main/kotlin/core/A.kt', 'src/main/java/core/B.java'), + architecture: {layers: [['core']]}, + } as never; + expect(scanPatterns(spec, dir)).toEqual([ + 'src/main/java/core/**/*.java', + 'src/main/java/core/**/*.kt', + 'src/main/kotlin/core/**/*.java', + 'src/main/kotlin/core/**/*.kt', + ]); + }); + + test('AC-9a6f02d3 — src is the fallback root when no module teaches one', () => { + write(dir, 'src/core/a.ts'); + const spec = { + project: {name: 'x', language: 'typescript'}, + features: claiming('README.md'), // claimed, but under no declared layer + architecture: {layers: [['core']]}, + } as never; + expect(scanPatterns(spec, dir)).toEqual(['src/core/**/*.ts']); + }); + + test('a directory that merely reuses a layer name does not become a scan root', () => { + // `tests/core/...` teaches the root `tests` by segment match alone. Left + // unfiltered, a mirrored test tree turns every unclaimed test file into a + // finding — so a root has to carry a real share of the claims. + write(dir, 'src/core/a.ts'); + write(dir, 'tests/core/a.test.ts'); + const spec = { + project: {name: 'x', language: 'typescript'}, + features: claiming( + 'src/core/a.ts', + 'src/core/b.ts', + 'src/core/c.ts', + 'src/core/d.ts', + 'src/core/e.ts', + 'src/core/f.ts', + 'src/core/g.ts', + 'src/core/h.ts', + 'src/core/i.ts', + 'tests/core/a.test.ts', + ), + architecture: {layers: [['core']]}, + } as never; + expect(scanPatterns(spec, dir)).toEqual(['src/core/**/*.ts']); + }); + + test('claims outside every declared layer teach neither a root nor an extension', () => { + write(dir, 'src/core/a.ts'); + const base = { + project: {name: 'x', language: 'typescript'}, + features: claiming('src/core/a.ts'), + architecture: {layers: [['core']]}, + }; + const withDocs = { + ...base, + features: claiming('src/core/a.ts', 'CHANGELOG.md', 'docs/guide.md'), + }; + expect(scanPatterns(withDocs as never, dir)).toEqual(scanPatterns(base as never, dir)); + expect(scanPatterns(withDocs as never, dir)).toEqual(['src/core/**/*.ts']); + }); + + test('AC-7f14d6e0 — the universe is identical whatever project.language says', () => { + write(dir, 'src/core/vm.cpp'); + write(dir, 'src/core/vm.h'); + const universe = (language: unknown): readonly string[] => + scanPatterns( + { + project: language === undefined ? {name: 'x'} : {name: 'x', language}, + features: EIGHT_FEATURES, + architecture: {layers: [['core']]}, + } as never, + dir, ); - const findings = unmappedArtifact.run({cwd: dir}); - const hit = findings.find((f) => f.path === 'src/router/orphan.ts'); - expect(hit?.severity).toBe('error'); - } finally { - rmSync(dir, {recursive: true, force: true}); - } + const expected = ['src/core/**/*.cpp', 'src/core/**/*.h']; + expect(universe('cpp')).toEqual(expected); + expect(universe('typescript')).toEqual(expected); // a wrong label cannot misdirect it + expect(universe('brainfuck')).toEqual(expected); // nor an unknown one + expect(universe(undefined)).toEqual(expected); // nor a missing one + }); + + test('AC-96ff696f — a declared layer glob replaces name inference for that layer', () => { + write(dir, 'core/src/main/cpp/rasp.cpp'); + const spec = { + project: {name: 'x', language: 'cpp'}, + features: EIGHT_FEATURES, + architecture: {layers: [{name: 'native', modules: ['core/src/main/cpp/**']}]}, + } as never; + // `native` names no directory anywhere: name inference would glob + // `src/native/**` and match nothing, which is defect D1 exactly. + expect(scanPatterns(spec, dir)).toEqual(['core/src/main/cpp/**/*.cpp']); + }); + + test('AC-96ff696f — a declared glob without a trailing wildcard still recurses', () => { + write(dir, 'core/src/main/cpp/rasp.cpp'); + const spec = { + project: {name: 'x', language: 'cpp'}, + features: EIGHT_FEATURES, + architecture: {layers: [{name: 'native', modules: ['core/src/main/cpp']}]}, + } as never; + expect(scanPatterns(spec, dir)).toEqual(['core/src/main/cpp/**/*.cpp']); + }); + + test('AC-96ff696f — a glob layer and a bare layer each derive their own patterns', () => { + write(dir, 'core/src/main/cpp/rasp.cpp'); + write(dir, 'src/router/route.ts'); + const spec = { + project: {name: 'x', language: 'cpp'}, + features: EIGHT_FEATURES, + architecture: {layers: [['router'], {name: 'native', modules: ['core/src/main/cpp/**']}]}, + } as never; + // One evidenced extension set, two derivations: the glob for `native`, + // the inferred root + name for `router`. + expect(scanPatterns(spec, dir)).toEqual([ + 'core/src/main/cpp/**/*.cpp', + 'core/src/main/cpp/**/*.ts', + 'src/router/**/*.cpp', + 'src/router/**/*.ts', + ]); + }); + + test('AC-96ff696f — a claim under a declared glob teaches its extension', () => { + write(dir, 'core/src/main/zig/a.zig'); // unknown to the vocabulary → observation ignores it + const spec = { + project: {name: 'x', language: 'zig'}, + features: claiming('core/src/main/zig/a.zig'), + architecture: {layers: [{name: 'native', modules: ['core/src/main/zig/**']}]}, + } as never; + // The claim sits under no layer-named segment, so only the glob prefix + // can make it count as layer-claimed. + expect(scanPatterns(spec, dir)).toEqual(['core/src/main/zig/**/*.zig']); + }); + + test('AC-96ff696f — an object layer without globs keeps name-based inference', () => { + write(dir, 'src/api/handler.py'); + const spec = { + project: {name: 'x', language: 'python'}, + features: EIGHT_FEATURES, + architecture: {layers: [{name: 'api', modules: []}, {name: 'domain'}]}, + } as never; + expect(scanPatterns(spec, dir)).toEqual(['src/api/**/*.py', 'src/domain/**/*.py']); + }); +}); + +// ─── end-to-end: the universe reaches real findings ─── + +/** + * One declared layer: a bare name (canonical tier form) or the object form + * carrying its own `modules` globs. + */ +type LayerDecl = string | {readonly name: string; readonly modules: readonly string[]}; + +/** Renders `architecture.layers`: bare names share one tier, object layers stand alone. */ +function layerLines(layers: readonly LayerDecl[]): string[] { + const bare = layers.filter((l): l is string => typeof l === 'string'); + const lines = bare.length > 0 ? [` - [${bare.join(', ')}]`] : []; + for (const layer of layers) { + if (typeof layer === 'string') continue; + lines.push(` - name: ${layer.name}`); + lines.push(` modules: [${layer.modules.map((g) => `"${g}"`).join(', ')}]`); + } + return lines; +} + +/** An inline spec with `featureCount` features, the given layers, and an optional claim. */ +function inlineSpec( + language: string, + layers: readonly LayerDecl[], + modules: string[] = [], + featureCount = 8, +): string { + return ( + [ + 'schema: "0.1"', + `project: {name: f, language: ${language}}`, + 'architecture:', + ' layers:', + ...layerLines(layers), + 'features:', + ...Array.from({length: featureCount}, (_, i) => + [ + ` - id: F-10000${i}`, + ' title: t', + ' status: done', + ` modules: [${i === 0 ? modules.join(', ') : ''}]`, + ' acceptance_criteria:', + ' - {id: AC-001, ears: ubiquitous, text: t, test_refs: [spec.yaml]}', + ].join('\n'), + ), + ].join('\n') + '\n' + ); +} + +describe('UNMAPPED_ARTIFACT — declared layers reach real files', () => { + let dir: string; + beforeEach(() => { + dir = mkdtempSync(join(tmpdir(), 'clad-unmapped-arch-')); + }); + afterEach(() => { + rmSync(dir, {recursive: true, force: true}); + }); + + test('a file in a declared layer that no feature claims is FOUND (was blind pre-0.6)', () => { + write(dir, 'src/router/orphan.ts', 'export const x = 1;\n'); + writeFileSync(join(dir, 'spec.yaml'), inlineSpec('typescript', ['router'])); + const findings = unmappedArtifact.run({cwd: dir}); + const hit = findings.find((f) => f.path === 'src/router/orphan.ts'); + expect(hit?.severity).toBe('error'); + }); + + test('AC-4d21c8a7 — a C++ project is scanned instead of passing vacuously', () => { + // Pre-F-87bb7ed3 this project globbed `src/router/**/*.ts`, matched + // nothing, and reported a clean bill of health. + write(dir, 'src/router/orphan.cpp', 'int main() { return 0; }\n'); + write(dir, 'src/router/claimed.cpp', 'int claimed() { return 1; }\n'); + writeFileSync(join(dir, 'spec.yaml'), inlineSpec('cpp', ['router'], ['src/router/claimed.cpp'])); + const findings = unmappedArtifact.run({cwd: dir}); + expect(findings.map((f) => f.path)).toEqual(['src/router/orphan.cpp']); + expect(findings[0].severity).toBe('error'); + expect(findings[0].message).toContain('not claimed by any feature'); + }); + + test('AC-9a6f02d3 — a nested source root inferred from a claim reaches its unclaimed neighbour', () => { + write(dir, 'src/main/kotlin/core/Claimed.kt', 'fun claimed() {}\n'); + write(dir, 'src/main/kotlin/core/Orphan.kt', 'fun orphan() {}\n'); + writeFileSync( + join(dir, 'spec.yaml'), + inlineSpec('kotlin', ['core'], ['src/main/kotlin/core/Claimed.kt']), + ); + const findings = unmappedArtifact.run({cwd: dir}); + expect(findings.map((f) => f.path)).toEqual(['src/main/kotlin/core/Orphan.kt']); + }); + + test('AC-96ff696f — a layer named for a concept, not a directory, is scanned where its glob points', () => { + // Defect D1, measured through the shipped binary: two specs identical + // but for the layer name — `core` (a real segment) reported 21 unclaimed + // files, `native` reported 0, though the declared glob never moved. + write(dir, 'core/src/main/cpp/claimed.cpp', 'int claimed() { return 1; }\n'); + write(dir, 'core/src/main/cpp/orphan.cpp', 'int orphan() { return 0; }\n'); + write(dir, 'core/src/main/cpp/util/helper.h', '#pragma once\n'); + writeFileSync( + join(dir, 'spec.yaml'), + inlineSpec( + 'cpp', + [{name: 'native', modules: ['core/src/main/cpp/**']}], + ['core/src/main/cpp/claimed.cpp'], + ), + ); + const findings = unmappedArtifact.run({cwd: dir}); + expect(findings.map((f) => f.path).sort()).toEqual([ + 'core/src/main/cpp/orphan.cpp', + 'core/src/main/cpp/util/helper.h', + ]); + for (const f of findings) expect(f.severity).toBe('error'); + }); + + test('AC-96ff696f — a declared glob without a trailing wildcard reaches the same files', () => { + write(dir, 'core/src/main/cpp/claimed.cpp', 'int claimed() { return 1; }\n'); + write(dir, 'core/src/main/cpp/orphan.cpp', 'int orphan() { return 0; }\n'); + writeFileSync( + join(dir, 'spec.yaml'), + inlineSpec( + 'cpp', + [{name: 'native', modules: ['core/src/main/cpp']}], + ['core/src/main/cpp/claimed.cpp'], + ), + ); + const findings = unmappedArtifact.run({cwd: dir}); + expect(findings.map((f) => f.path)).toEqual(['core/src/main/cpp/orphan.cpp']); + expect(findings[0].severity).toBe('error'); + }); + + test('AC-96ff696f — a glob layer and a bare layer both contribute findings', () => { + write(dir, 'core/src/main/cpp/orphan.cpp', 'int orphan() { return 0; }\n'); + write(dir, 'src/router/orphan.ts', 'export const x = 1;\n'); + write(dir, 'src/router/claimed.ts', 'export const y = 1;\n'); + writeFileSync( + join(dir, 'spec.yaml'), + inlineSpec( + 'cpp', + ['router', {name: 'native', modules: ['core/src/main/cpp/**']}], + ['src/router/claimed.ts'], + ), + ); + const findings = unmappedArtifact.run({cwd: dir}); + expect(findings.map((f) => f.path).sort()).toEqual([ + 'core/src/main/cpp/orphan.cpp', + 'src/router/orphan.ts', + ]); + for (const f of findings) expect(f.severity).toBe('error'); + }); + + test('AC-e20dbafe — the same tree WITHOUT the glob reports an empty universe instead of silence', () => { + // Name-only `native`: nothing on disk is called that, so the universe + // resolves to `src/native/**` and scans zero files. Pre-fix that was a + // clean bill of health; now it says where it looked. + write(dir, 'core/src/main/cpp/claimed.cpp', 'int claimed() { return 1; }\n'); + write(dir, 'core/src/main/cpp/orphan.cpp', 'int orphan() { return 0; }\n'); + writeFileSync( + join(dir, 'spec.yaml'), + inlineSpec('cpp', ['native'], ['core/src/main/cpp/claimed.cpp']), + ); + const findings = unmappedArtifact.run({cwd: dir}); + expect(findings.filter((f) => f.severity === 'error')).toEqual([]); + expect(findings).toHaveLength(1); + expect(findings[0].severity).toBe('info'); + expect(findings[0].message).toContain('matched no files'); + expect(findings[0].message).toContain('layers {native}'); + expect(findings[0].message).toContain('roots {src}'); + expect(findings[0].message).toContain('declare layer modules globs'); + }); + + test('AC-e20dbafe — a declared glob pointing at a moved tree is reported by its glob', () => { + write(dir, 'core/src/main/cpp/orphan.cpp', 'int orphan() { return 0; }\n'); + writeFileSync( + join(dir, 'spec.yaml'), + inlineSpec('cpp', [{name: 'native', modules: ['native/src/**']}]), + ); + const findings = unmappedArtifact.run({cwd: dir}); + expect(findings).toHaveLength(1); + expect(findings[0].severity).toBe('info'); + expect(findings[0].message).toContain('roots {native/src/**}'); + // Every layer declared its location, so "declare globs" is not the cure. + expect(findings[0].message).toContain('check the declared layer modules globs'); + }); + + test('AC-e20dbafe — a scan that did match files stays silent when every one is claimed', () => { + write(dir, 'core/src/main/cpp/claimed.cpp', 'int claimed() { return 1; }\n'); + writeFileSync( + join(dir, 'spec.yaml'), + inlineSpec( + 'cpp', + [{name: 'native', modules: ['core/src/main/cpp/**']}], + ['core/src/main/cpp/claimed.cpp'], + ), + ); + expect(unmappedArtifact.run({cwd: dir})).toEqual([]); + }); + + test('AC-e20dbafe — below the scale gate an empty scan stays silent', () => { + // Day-1 adoption: the legacy narrow pair matches nothing here, and that + // protective silence is the design, not a finding to report. + write(dir, 'core/src/main/cpp/orphan.cpp', 'int orphan() { return 0; }\n'); + writeFileSync( + join(dir, 'spec.yaml'), + inlineSpec('cpp', [{name: 'native', modules: ['core/src/main/cpp/**']}], [], 3), + ); + expect(unmappedArtifact.run({cwd: dir})).toEqual([]); }); }); diff --git a/tests/stages/unmapped-universe-evidence.test.ts b/tests/stages/unmapped-universe-evidence.test.ts new file mode 100644 index 00000000..4730037a --- /dev/null +++ b/tests/stages/unmapped-universe-evidence.test.ts @@ -0,0 +1,435 @@ +// Cladding · impl-blind oracle for F-87bb7ed3 — authored from the spec contract only. +// +// Contract under test (given, not read from source): +// import {unmappedArtifact} from '../../src/stages/detectors/unmapped-artifact.js'; +// const findings = unmappedArtifact.run({cwd}); +// finding: {detector: 'UNMAPPED_ARTIFACT', severity: 'error', message: string, path?: string} +// one finding per source file in the scan universe not claimed by any features[].modules +// +// Evidence-derived universe (active only when features.length >= 8 AND architecture +// layers are declared — the legacy narrow scan is out of scope here): +// · extensions = (known-language extensions OBSERVED anywhere in the tree) +// ∪ (extensions of modules CLAIMED under a root/layer path) +// · unknown-to-vocabulary extensions (.zig …) enter ONLY by being claimed +// · scan roots are inferred from claimed module paths: the segments BEFORE the +// layer segment (src/main/kotlin/core/A.kt + layer 'core' → root src/main/kotlin); +// with no teaching module the root is 'src' +// · files scanned: //**/*; a file claimed by ANY feature is never +// reported; spec.project.language has NO effect on the universe +// +// Fixture notes (scaffolding only — no expectation is derived from the implementation): +// · feature ids must satisfy the spec schema's ^F-(\d{3,}|[a-f0-9]{6,})$, so the +// padding features use hash-shaped ids rather than the brief's shorthand F-1. +// · architecture.layers is written as the brief renders it: each entry is a sequence +// of layer names (a tier), so layers [core, app] is `- - core` / ` - app`. +// · a .ts control tree was used to confirm these fixtures actually reach the scan, so +// a zero-finding result below is a behavioural gap, not a dead fixture. +// +// Severity note: the declared severity ('error') is asserted in its own dedicated case +// rather than inside the shared shape helper, so a single deviation there cannot mask +// the eight universe verdicts. It is asserted, unweakened. + +import {afterAll, describe, expect, it} from 'vitest'; +import {mkdirSync, mkdtempSync, rmSync, writeFileSync} from 'node:fs'; +import {tmpdir} from 'node:os'; +import {dirname, join} from 'node:path'; + +import {unmappedArtifact} from '../../src/stages/detectors/unmapped-artifact.js'; + +type Finding = { + detector: string; + severity: string; + message: string; + path?: string; +}; + +type Fixture = { + /** spec.project.language — declared, and per contract inert for the universe. */ + language: string; + /** architecture.layers — one layer name per entry. */ + layers: string[]; + /** modules[] per feature; padded to nine features with empty-module entries. */ + claims: string[][]; + /** source files to materialise, repo-relative. */ + files: string[]; +}; + +const scratch: string[] = []; + +afterAll(() => { + for (const dir of scratch) rmSync(dir, {recursive: true, force: true}); +}); + +/** architecture.layers block: one tier holding every layer name. */ +function layerBlock(names: string[]): string[] { + return names.map((name, index) => (index === 0 ? ` - - ${name}` : ` - ${name}`)); +} + +function makeFixture(fixture: Fixture): string { + const dir = mkdtempSync(join(tmpdir(), 'clad-unmapped-universe-')); + scratch.push(dir); + mkdirSync(join(dir, 'spec', 'features'), {recursive: true}); + + const featureCount = Math.max(9, fixture.claims.length); + const featureBlocks: string[] = []; + for (let i = 0; i < featureCount; i++) { + const modules = fixture.claims[i] ?? []; + const id = `F-a${String(i + 1).padStart(7, '0')}`; + const lines = [` - id: ${id}`, ' title: t', ' status: done']; + if (modules.length === 0) { + lines.push(' modules: []'); + } else { + lines.push(' modules:'); + for (const module of modules) lines.push(` - "${module}"`); + } + featureBlocks.push(lines.join('\n')); + } + + const yaml = [ + 'schema: "0.1"', + 'project:', + ' name: x', + ` language: ${fixture.language}`, + 'architecture:', + ' layers:', + ...layerBlock(fixture.layers), + 'features:', + ...featureBlocks, + '', + ].join('\n'); + writeFileSync(join(dir, 'spec.yaml'), yaml, 'utf8'); + + for (const rel of fixture.files) { + const abs = join(dir, rel); + mkdirSync(dirname(abs), {recursive: true}); + writeFileSync(abs, '// x\n', 'utf8'); + } + + return dir; +} + +/** Runs the detector and enforces the declared finding identity on every finding. */ +function scan(fixture: Fixture): Finding[] { + const findings = unmappedArtifact.run({cwd: makeFixture(fixture)}) as Finding[]; + expect(Array.isArray(findings)).toBe(true); + for (const finding of findings) { + expect(finding.detector).toBe('UNMAPPED_ARTIFACT'); + expect(typeof finding.message).toBe('string'); + expect(finding.message.length).toBeGreaterThan(0); + } + return findings; +} + +/** Sorted, separator-normalised path set of the findings. */ +function reported(findings: Finding[]): string[] { + return findings + .map(finding => (finding.path ?? '').replace(/\\/g, '/').replace(/^\.\//, '')) + .sort(); +} + +/** The findings' own messages, echoed as failure context. */ +function said(findings: Finding[]): string { + if (findings.length === 0) return 'detector reported no findings'; + return findings.map(finding => `[${finding.severity}] ${finding.message}`).join(' || '); +} + +function expectExactly(findings: Finding[], expected: string[]): void { + expect(reported(findings), said(findings)).toEqual([...expected].sort()); +} + +const CASE_1_TREE = { + layers: ['core'], + claims: [['src/core/rasp.cpp']], + files: ['src/core/rasp.cpp', 'src/core/extra.cpp', 'src/core/util.h'], +} as const; + +function caseOneFixture(language: string): Fixture { + return { + language, + layers: [...CASE_1_TREE.layers], + claims: CASE_1_TREE.claims.map(modules => [...modules]), + files: [...CASE_1_TREE.files], + }; +} + +describe('UNMAPPED_ARTIFACT · evidence-derived scan universe (F-87bb7ed3)', () => { + it('reports native sources the spec never claims (cpp tree, was vacuous)', () => { + const findings = scan(caseOneFixture('cpp')); + + expectExactly(findings, ['src/core/extra.cpp', 'src/core/util.h']); + expect(reported(findings)).toEqual( + expect.arrayContaining(['src/core/extra.cpp', 'src/core/util.h']), + ); + expect(reported(findings)).not.toContain('src/core/rasp.cpp'); + }); + + it('still sees native sources when every claimed module is another language', () => { + const findings = scan({ + language: 'cpp', + layers: ['core', 'app'], + claims: [['src/core/Main.java', 'src/app/App.java']], + files: [ + 'src/core/Main.java', + 'src/app/App.java', + 'src/core/a.cpp', + 'src/core/b.cpp', + ], + }); + + // .cpp is a known-language extension observed in the tree, so it is in the + // universe even though no module ever claims a .cpp file. + expectExactly(findings, ['src/core/a.cpp', 'src/core/b.cpp']); + }); + + it('lets a claimed module teach an extension unknown to the vocabulary', () => { + const findings = scan({ + language: 'zig', + layers: ['core'], + claims: [['src/core/a.zig']], + files: ['src/core/a.zig', 'src/core/b.zig'], + }); + + expectExactly(findings, ['src/core/b.zig']); + }); + + it('keeps an untaught unknown extension out of the universe', () => { + const findings = scan({ + language: 'zig', + layers: ['core'], + claims: [['src/core/a.ts']], + files: ['src/core/a.ts', 'src/core/b.zig', 'src/core/c.ts'], + }); + + // .zig is neither observed-known nor claimed → invisible; .ts enters as both. + expectExactly(findings, ['src/core/c.ts']); + expect(reported(findings)).not.toContain('src/core/b.zig'); + }); + + it('infers the scan root from the claimed module path (kotlin layout)', () => { + const findings = scan({ + language: 'kotlin', + layers: ['core'], + claims: [['src/main/kotlin/core/A.kt']], + files: ['src/main/kotlin/core/A.kt', 'src/main/kotlin/core/B.kt'], + }); + + expectExactly(findings, ['src/main/kotlin/core/B.kt']); + }); + + it('derives the universe from evidence, not from the declared language label', () => { + const asCpp = scan(caseOneFixture('cpp')); + const asJava = scan(caseOneFixture('java')); + + expectExactly(asJava, ['src/core/extra.cpp', 'src/core/util.h']); + expect(reported(asJava), said(asJava)).toEqual(reported(asCpp)); + }); + + it('reports nothing once every scanned file is claimed by some feature', () => { + const findings = scan({ + language: 'cpp', + layers: [...CASE_1_TREE.layers], + claims: [['src/core/rasp.cpp'], ['src/core/extra.cpp'], ['src/core/util.h']], + files: [...CASE_1_TREE.files], + }); + + expectExactly(findings, []); + expect(findings, said(findings)).toHaveLength(0); + }); + + it('unions every observed known extension into one scan universe', () => { + const findings = scan({ + language: 'cpp', + layers: ['core'], + claims: [['src/core/a.cpp']], + files: ['src/core/a.cpp', 'src/core/b.h', 'src/core/c.ts'], + }); + + expectExactly(findings, ['src/core/b.h', 'src/core/c.ts']); + }); + + it('raises each unmapped artifact at the declared severity', () => { + const findings = scan(caseOneFixture('cpp')); + + expect(findings.length, said(findings)).toBeGreaterThan(0); + for (const finding of findings) { + expect(finding.severity, said(findings)).toBe('error'); + } + }); +}); + +// --------------------------------------------------------------------------- +// D1 · declared layer globs, and disclosure of an empty full scan. +// Appended blind, from the contract addition only — nothing below was derived +// from the implementation, and nothing above it was modified. +// +// Contract addition under test (given, not read from source): +// A. A layer entry may be an OBJECT — {name, modules: [glob…]}. When a layer +// declares `modules` globs, the files under those globs (with extensions +// evidenced by observation-or-claims) are in the universe EVEN THOUGH the +// layer name is not a path segment anywhere. Unclaimed such files → +// one 'error' finding each. +// B. An empty full-scan universe is DISCLOSED, not silent: a layer with no +// globs whose name matches no directory yields zero 'error' findings and +// exactly one 'info' finding that names the layer. +// +// The base contract's extension rule is relied on unchanged: every extension in +// play below (.cpp/.h/.ts) is a known-language extension observed in the tree, +// so no case here rests on an extension having to be taught by a claim. +// --------------------------------------------------------------------------- + +/** A tier of the architecture.layers sequence: bare names, or one object layer. */ +type DeclaredLayer = string[] | {name: string; modules: string[]}; + +type GlobFixture = { + /** spec.project.language — declared, and per contract inert for the universe. */ + language: string; + /** architecture.layers — each entry is a bare tier or an object layer. */ + layers: DeclaredLayer[]; + /** modules[] per feature; padded to nine features with empty-module entries. */ + claims: string[][]; + /** source files to materialise, repo-relative. */ + files: string[]; +}; + +/** architecture.layers block where a tier may be a bare list OR an object layer. */ +function declaredLayerBlock(layers: DeclaredLayer[]): string[] { + const lines: string[] = []; + for (const tier of layers) { + if (Array.isArray(tier)) { + for (const [index, name] of tier.entries()) { + lines.push(index === 0 ? ` - - ${name}` : ` - ${name}`); + } + continue; + } + lines.push(` - name: ${tier.name}`); + lines.push(` modules: [${tier.modules.map(glob => `"${glob}"`).join(', ')}]`); + } + return lines; +} + +function makeGlobFixture(fixture: GlobFixture): string { + const dir = mkdtempSync(join(tmpdir(), 'clad-unmapped-globlayer-')); + scratch.push(dir); + mkdirSync(join(dir, 'spec', 'features'), {recursive: true}); + + const featureCount = Math.max(9, fixture.claims.length); + const featureBlocks: string[] = []; + for (let i = 0; i < featureCount; i++) { + const modules = fixture.claims[i] ?? []; + const id = `F-a${String(i + 1).padStart(7, '0')}`; + const lines = [` - id: ${id}`, ' title: t', ' status: done']; + if (modules.length === 0) { + lines.push(' modules: []'); + } else { + lines.push(' modules:'); + for (const module of modules) lines.push(` - "${module}"`); + } + featureBlocks.push(lines.join('\n')); + } + + const yaml = [ + 'schema: "0.1"', + 'project:', + ' name: x', + ` language: ${fixture.language}`, + 'architecture:', + ' layers:', + ...declaredLayerBlock(fixture.layers), + 'features:', + ...featureBlocks, + '', + ].join('\n'); + writeFileSync(join(dir, 'spec.yaml'), yaml, 'utf8'); + + for (const rel of fixture.files) { + const abs = join(dir, rel); + mkdirSync(dirname(abs), {recursive: true}); + writeFileSync(abs, '// x\n', 'utf8'); + } + + return dir; +} + +/** Runs the detector on a possibly-object-layer spec, enforcing finding identity. */ +function scanDeclared(fixture: GlobFixture): Finding[] { + const findings = unmappedArtifact.run({cwd: makeGlobFixture(fixture)}) as Finding[]; + expect(Array.isArray(findings)).toBe(true); + for (const finding of findings) { + expect(finding.detector).toBe('UNMAPPED_ARTIFACT'); + expect(typeof finding.message).toBe('string'); + expect(finding.message.length).toBeGreaterThan(0); + } + return findings; +} + +function withSeverity(findings: Finding[], severity: string): Finding[] { + return findings.filter(finding => finding.severity === severity); +} + +/** Severity + path of every finding, sorted — the full identity of a verdict. */ +function severityPathSignature(findings: Finding[]): string[] { + return findings + .map(finding => `${finding.severity} ${(finding.path ?? '').replace(/\\/g, '/').replace(/^\.\//, '')}`) + .sort(); +} + +/** Case A's tree: a layer named 'native' that exists only as a declared glob. */ +function globLayerFixture(language: string, glob = 'engine/src/**'): GlobFixture { + return { + language, + layers: [{name: 'native', modules: [glob]}], + claims: [['engine/src/a.cpp']], + files: ['engine/src/a.cpp', 'engine/src/b.cpp', 'engine/src/c.h'], + }; +} + +describe('UNMAPPED_ARTIFACT · declared layer globs and empty-scan disclosure (F-87bb7ed3 D1)', () => { + it('scans a layer’s declared globs though the layer name is nowhere in the tree', () => { + const findings = scanDeclared(globLayerFixture('cpp')); + + expectExactly(withSeverity(findings, 'error'), ['engine/src/b.cpp', 'engine/src/c.h']); + expect(reported(withSeverity(findings, 'error')), said(findings)).not.toContain('engine/src/a.cpp'); + }); + + it('reads a declared glob without a trailing wildcard as the same subtree', () => { + const findings = scanDeclared(globLayerFixture('cpp', 'engine/src')); + + expectExactly(withSeverity(findings, 'error'), ['engine/src/b.cpp', 'engine/src/c.h']); + }); + + it('discloses an empty full scan instead of passing a tree it never looked at', () => { + // 'native' declares no globs and matches no directory, so the scan universe + // is empty. Silence would read as "clean"; the contract demands disclosure. + const findings = scanDeclared({ + language: 'cpp', + layers: [['native']], + claims: [['engine/src/a.cpp']], + files: ['engine/src/a.cpp', 'engine/src/b.cpp'], + }); + + expect(withSeverity(findings, 'error'), said(findings)).toHaveLength(0); + + const infos = withSeverity(findings, 'info'); + expect(infos, said(findings)).toHaveLength(1); + expect(infos[0]?.message.toLowerCase(), said(findings)).toContain('native'); + }); + + it('scans a declared-glob layer and a bare tier in the same spec', () => { + const findings = scanDeclared({ + language: 'cpp', + layers: [{name: 'native', modules: ['engine/src/**']}, ['core']], + claims: [['engine/src/a.cpp', 'src/core/x.ts']], + files: ['engine/src/a.cpp', 'engine/src/b.cpp', 'src/core/x.ts', 'src/core/y.ts'], + }); + + expectExactly(withSeverity(findings, 'error'), ['engine/src/b.cpp', 'src/core/y.ts']); + }); + + it('ignores the declared language label for glob-declared layers too', () => { + const asCpp = scanDeclared(globLayerFixture('cpp')); + const asJava = scanDeclared(globLayerFixture('java')); + + expectExactly(withSeverity(asJava, 'error'), ['engine/src/b.cpp', 'engine/src/c.h']); + expect(severityPathSignature(asJava), said(asJava)).toEqual(severityPathSignature(asCpp)); + }); +});