docs(comments): rewrite comments across all crates to the guidelines
Sweep every first-party crate source (1956 .rs files) to the project comment guidelines: delete redundant restatements, decorative banners, change narration, and end-of-line comments; keep and tighten the crucial ones (invariants, bug rationale, SAFETY blocks, ported-source attribution). No functional code changed. Every edit is proven comment-only against the prior tree by a comment-stripping lexer (string/char/raw-string aware) plus a separate doctest-fence check. Where removing a comment made rustfmt or clippy want to re-lay-out adjacent code, the minimal triggering comment is restored so code tokens stay byte-identical. Gates green: cargo fmt --all --check (0 diffs), cargo check and cargo clippy --workspace --all-targets (0 warnings). Adds scripts/check_codegen_comment_guidelines.py — the enforcement gate for these guidelines (flags banners, end-of-line comments, change narration, and commented-out code).
This commit is contained in:
1 parent
ff0fb56c67
commit
a02b555e66
1458 files changed
+10729
-21750
No files matched your search
@@ -146,7 +146,7 @@ pub async fn run_command_hook(
|
||||
// cannot open /dev/tty and corrupt the TUI display. Delegates to
|
||||
// `kigi_tools::util::detach_command`: Unix uses the same setsid /
|
||||
// EPERM→setpgid pre_exec path as before; Windows sets CREATE_NO_WINDOW only
|
||||
// (DETACHED_PROCESS is intentionally omitted — it breaks stdio inheritance).
|
||||
// (DETACHED_PROCESS is deliberately omitted — it breaks stdio inheritance).
|
||||
kigi_tools::util::detach_command(&mut cmd);
|
||||
|
||||
// Spawn the child process.
|
||||
@@ -649,7 +649,8 @@ mod tests {
|
||||
let large = vec![b'x'; MAX_OUTPUT_BYTES + 1000];
|
||||
let result = truncate_output(&large);
|
||||
assert!(result.ends_with(" [truncated]"));
|
||||
assert!(result.len() > MAX_OUTPUT_BYTES); // marker appended
|
||||
// marker appended
|
||||
assert!(result.len() > MAX_OUTPUT_BYTES);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -833,11 +834,12 @@ mod tests {
|
||||
#[test]
|
||||
fn shell_command_detection() {
|
||||
// Commands with shell metacharacters should be detected.
|
||||
assert!("echo hello".contains(' ')); // space
|
||||
assert!("a || b".contains('|')); // pipe/or
|
||||
assert!("a && b".contains('&')); // and
|
||||
assert!("a; b".contains(';')); // semicolon
|
||||
assert!("a > out".contains('>')); // redirect
|
||||
assert!("echo hello".contains(' '));
|
||||
// pipe/or
|
||||
assert!("a || b".contains('|'));
|
||||
assert!("a && b".contains('&'));
|
||||
assert!("a; b".contains(';'));
|
||||
assert!("a > out".contains('>'));
|
||||
// Env-var interpolation must also force the sh -c branch so that
|
||||
// commands like `${CLAUDE_PLUGIN_ROOT}/hooks/foo.sh` get expanded
|
||||
// by the shell rather than treated as a literal executable path.
|
||||
@@ -860,7 +862,7 @@ mod tests {
|
||||
/// Regression: a hook command that uses `${VAR}` interpolation
|
||||
/// without any other shell metacharacters must still be invoked via
|
||||
/// `sh -c` so that the env var supplied via `extra_env` is expanded.
|
||||
/// Previously the runner treated `${...}` as part of a literal path
|
||||
/// earlier the runner treated `${...}` as part of a literal path
|
||||
/// and `command_path.exists()` failed; the hook silently never ran.
|
||||
/// Now the env-var pre-spawn check refuses with a clear reason when
|
||||
/// the var is unset (and the dispatcher fail-opens, so the tool call
|
||||
@@ -1104,7 +1106,7 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_undefined_env_var_refuses_to_spawn() {
|
||||
let mut extra_env = std::collections::HashMap::new();
|
||||
// Intentionally do NOT set NEVER_SET_GB1183 anywhere.
|
||||
// Deliberately do NOT set NEVER_SET_GB1183 anywhere.
|
||||
extra_env.insert("UNRELATED_GB1183".to_string(), "/tmp".to_string());
|
||||
|
||||
let spec = HookSpec {
|
||||
@@ -1150,7 +1152,7 @@ mod tests {
|
||||
|
||||
/// Regression: a hook command starting with `~` must be
|
||||
/// routed through `sh -c` so the shell expands `~` to `$HOME`.
|
||||
/// Previously `~/.claude/hook.sh` was treated as a relative path and
|
||||
/// earlier `~/.claude/hook.sh` was treated as a relative path and
|
||||
/// joined to `source_dir`, producing a broken path.
|
||||
///
|
||||
/// The test injects `HOME` via `extra_env` so it works in sandboxed
|
||||
@@ -1245,7 +1247,7 @@ mod tests {
|
||||
configured_matcher: None,
|
||||
matcher: None,
|
||||
enabled: true,
|
||||
// `MISSING_GB1183_DEFAULT` is intentionally unset; the `:-`
|
||||
// `MISSING_GB1183_DEFAULT` is deliberately unset; the `:-`
|
||||
// modifier supplies a fallback that points at the real script.
|
||||
command: Some(std::path::PathBuf::from(format!(
|
||||
"${{MISSING_GB1183_DEFAULT:-{}}}",
|
||||
|
||||
@@ -35,44 +35,55 @@ fn is_blocked_ip(ip: &IpAddr) -> bool {
|
||||
IpAddr::V4(v4) => {
|
||||
let octets = v4.octets();
|
||||
if octets[0] == 127 {
|
||||
return false; // loopback — allowed for local dev
|
||||
// loopback — allowed for local dev
|
||||
return false;
|
||||
}
|
||||
if octets[0] == 10 {
|
||||
return true; // RFC 1918: 10.0.0.0/8
|
||||
// RFC 1918: 10.0.0.0/8
|
||||
return true;
|
||||
}
|
||||
if octets[0] == 172 && (16..=31).contains(&octets[1]) {
|
||||
return true; // RFC 1918: 172.16.0.0/12
|
||||
// RFC 1918: 172.16.0.0/12
|
||||
return true;
|
||||
}
|
||||
if octets[0] == 192 && octets[1] == 168 {
|
||||
return true; // RFC 1918: 192.168.0.0/16
|
||||
// RFC 1918: 192.168.0.0/16
|
||||
return true;
|
||||
}
|
||||
if octets[0] == 169 && octets[1] == 254 {
|
||||
return true; // RFC 3927: 169.254.0.0/16 (link-local, cloud metadata)
|
||||
// RFC 3927: 169.254.0.0/16 (link-local, cloud metadata)
|
||||
return true;
|
||||
}
|
||||
if octets[0] == 100 && (64..=127).contains(&octets[1]) {
|
||||
return true; // RFC 6598: 100.64.0.0/10 (CGNAT)
|
||||
// RFC 6598: 100.64.0.0/10 (CGNAT)
|
||||
return true;
|
||||
}
|
||||
if v4.is_unspecified() {
|
||||
return true; // 0.0.0.0
|
||||
// 0.0.0.0
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
IpAddr::V6(v6) => {
|
||||
if v6.is_loopback() {
|
||||
return false; // ::1 — allowed for local dev
|
||||
// ::1 — allowed for local dev
|
||||
return false;
|
||||
}
|
||||
if v6.is_unspecified() {
|
||||
return true; // ::
|
||||
// ::
|
||||
return true;
|
||||
}
|
||||
if let Some(v4) = v6.to_ipv4_mapped() {
|
||||
return is_blocked_ip(&IpAddr::V4(v4));
|
||||
}
|
||||
let segments = v6.segments();
|
||||
if segments[0] & 0xffc0 == 0xfe80 {
|
||||
return true; // fe80::/10 — link-local
|
||||
// fe80::/10 — link-local
|
||||
return true;
|
||||
}
|
||||
if segments[0] & 0xfe00 == 0xfc00 {
|
||||
return true; // fc00::/7 — unique local (ULA)
|
||||
// fc00::/7 — unique local (ULA)
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
@@ -398,7 +409,7 @@ mod tests {
|
||||
use super::*;
|
||||
use reqwest::StatusCode;
|
||||
|
||||
// ── parse_http_blocking_result tests ──────────────────────────
|
||||
// parse_http_blocking_result tests
|
||||
|
||||
#[test]
|
||||
fn http_allow_json() {
|
||||
@@ -560,7 +571,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
// ── SSRF protection: is_blocked_ip tests ──────────────
|
||||
// SSRF protection: is_blocked_ip tests
|
||||
|
||||
#[test]
|
||||
fn ssrf_blocks_rfc1918_10x() {
|
||||
@@ -632,7 +643,7 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
// ── SSRF protection: validate_hook_url tests ──────────
|
||||
// SSRF protection: validate_hook_url tests
|
||||
|
||||
#[tokio::test]
|
||||
async fn ssrf_rejects_http_scheme() {
|
||||
@@ -675,7 +686,7 @@ mod tests {
|
||||
assert!(result.unwrap_err().contains("invalid URL"));
|
||||
}
|
||||
|
||||
// ── URL env-var expansion (extra_env precedence) ───────────
|
||||
// URL env-var expansion (extra_env precedence)
|
||||
|
||||
use crate::config::HookSpec;
|
||||
use crate::event::{HookEventEnvelope, HookEventName, HookPayload};
|
||||
@@ -883,7 +894,7 @@ mod tests {
|
||||
let (result, _, info) = run_http_hook(&spec, &envelope, &ctx, true).await;
|
||||
|
||||
// Either `Failed` (timeout / connection error) is fine; both
|
||||
// exercise paths that previously embedded the raw URL via
|
||||
// exercise paths that earlier embedded the raw URL via
|
||||
// `format!("...{e}")`. Pure timeouts use a different
|
||||
// formatting branch (no URL involved), so prefer the
|
||||
// connection-error case but tolerate either.
|
||||
|
||||
@@ -7,32 +7,23 @@ use crate::config::HookSpec;
|
||||
use crate::event::HookEventEnvelope;
|
||||
use crate::result::{HookDecision, HttpInfo};
|
||||
|
||||
/// Context passed to any hook runner for environment setup.
|
||||
pub struct RunContext<'a> {
|
||||
pub session_id: &'a str,
|
||||
pub workspace_root: &'a str,
|
||||
}
|
||||
|
||||
/// Result of running a single hook (any handler type).
|
||||
#[derive(Debug)]
|
||||
pub enum HookRunnerResult {
|
||||
/// Hook ran and produced a decision (for blocking hooks).
|
||||
Decision(HookDecision),
|
||||
/// Hook ran successfully (for non-blocking hooks).
|
||||
Success,
|
||||
/// Hook failed — caller should fail-open.
|
||||
/// Callers must fail open on this variant: a broken hook never blocks the
|
||||
/// session.
|
||||
Failed(String),
|
||||
}
|
||||
|
||||
/// Bundle returned by each runner: the result, wall-clock duration, and
|
||||
/// optional HTTP metadata for enriched scrollback logging.
|
||||
/// Result, wall-clock duration, and HTTP metadata for scrollback enrichment.
|
||||
pub type HookRunOutput = (HookRunnerResult, Duration, Option<HttpInfo>);
|
||||
|
||||
/// Run a hook using the appropriate handler for its type.
|
||||
///
|
||||
/// Dispatches to `command::run_command_hook()` or `http::run_http_hook()`
|
||||
/// based on `spec.handler_type`. Returns the result, elapsed duration, and
|
||||
/// optional HTTP metadata for scrollback enrichment.
|
||||
pub async fn run_hook(
|
||||
spec: &HookSpec,
|
||||
envelope: &HookEventEnvelope,
|
||||
|
||||
Reference in new issue
Block a user