对应 hooks.rs:179-196
(
returncode: int | None,
stdout: str,
stderr: str,
command: str,
tool_name: str,
)
| 406 | print(" ─────────────────────────────────────") |
| 407 | |
| 408 | def interpret_hook_exit_code( |
| 409 | returncode: int | None, |
| 410 | stdout: str, |
| 411 | stderr: str, |
| 412 | command: str, |
| 413 | tool_name: str, |
| 414 | ) -> dict: |
| 415 | """ |
| 416 | 对应 hooks.rs:179-196 |
| 417 | """ |
| 418 | message = stdout.strip() if stdout.strip() else None |
| 419 | |
| 420 | if returncode == 0: |
| 421 | return {"outcome": "Allow", "message": message} |
| 422 | elif returncode == 2: |
| 423 | return { |
| 424 | "outcome": "Deny", |
| 425 | "message": message or f"Hook denied tool `{tool_name}`", |
| 426 | } |
| 427 | elif returncode is not None: |
| 428 | # 非 0 非 2 → 警告 |
| 429 | parts = [f"Hook `{command}` exited with code {returncode}"] |
| 430 | if message: |
| 431 | parts.append(f"stdout: {message}") |
| 432 | if stderr.strip(): |
| 433 | parts.append(f"stderr: {stderr.strip()}") |
| 434 | return {"outcome": "Warn", "message": " | ".join(parts)} |
| 435 | else: |
| 436 | # None = 被信号杀死 (没有退出码) |
| 437 | return { |
| 438 | "outcome": "Warn", |
| 439 | "message": f"Hook `{command}` terminated by signal", |
| 440 | } |
| 441 | |
| 442 | # 测试 |
| 443 | scenarios = [ |
no test coverage detected