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:
@@ -239,7 +239,7 @@ mod tests {
|
||||
git2::Repository::init(path).unwrap();
|
||||
}
|
||||
|
||||
// ── find_agent_files unit tests ─────────────────────────────────
|
||||
// find_agent_files unit tests
|
||||
|
||||
#[test]
|
||||
fn find_agent_files_finds_agents_md() {
|
||||
@@ -320,7 +320,7 @@ mod tests {
|
||||
assert!(files[1].to_string_lossy().contains("style.md"));
|
||||
}
|
||||
|
||||
// ── format_agents_md_section tests ──────────────────────────────
|
||||
// format_agents_md_section tests
|
||||
|
||||
#[test]
|
||||
fn format_agents_md_section_empty_returns_none() {
|
||||
@@ -370,7 +370,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Feature 2: Workspace user AGENTS.md via read_agents_config ───
|
||||
// Feature 2: Workspace user AGENTS.md via read_agents_config
|
||||
|
||||
#[tokio::test]
|
||||
async fn read_agents_config_includes_workspace_user_agents_md() {
|
||||
@@ -537,7 +537,7 @@ mod tests {
|
||||
assert!(!section.contains("globs:"));
|
||||
}
|
||||
|
||||
// ── .claude/CLAUDE.md integration tests ─────────────────────────
|
||||
// .claude/CLAUDE.md integration tests
|
||||
|
||||
#[tokio::test]
|
||||
async fn read_agents_config_discovers_claude_subdir_claude_md() {
|
||||
|
||||
@@ -224,9 +224,9 @@ impl PromptContext {
|
||||
}
|
||||
/// Format the personas section content.
|
||||
///
|
||||
/// Always returns `None` — the `persona` parameter has been removed
|
||||
/// from the task tool input, so persona summaries are no longer
|
||||
/// injected into the conversation.
|
||||
/// Always returns `None` — the task tool input carries no `persona`
|
||||
/// parameter, so persona summaries are never injected into the
|
||||
/// conversation.
|
||||
pub fn format_personas_section(&self) -> Option<String> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ use ignore::gitignore::{Gitignore, GitignoreBuilder};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub fn build_gitignore(repo_root: Option<&Path>) -> Option<Gitignore> {
|
||||
// No repo root → no gitignore rules to apply.
|
||||
let root = repo_root?;
|
||||
let mut builder = GitignoreBuilder::new(root);
|
||||
|
||||
|
||||
@@ -726,7 +726,7 @@ mod tests {
|
||||
fs::write(dir.join("SKILL.md"), content).unwrap();
|
||||
}
|
||||
|
||||
// ── Server-synced skills (injected server_skill_dirs) ────────────────
|
||||
// Server-synced skills (injected server_skill_dirs)
|
||||
|
||||
#[tokio::test]
|
||||
async fn server_skills_discovered_and_shadowed_by_local() {
|
||||
@@ -826,7 +826,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Feature 3: Recursive skill reading ──────────────────────────────
|
||||
// Feature 3: Recursive skill reading
|
||||
|
||||
#[test]
|
||||
fn find_skill_paths_flat_layout() {
|
||||
@@ -960,7 +960,7 @@ mod tests {
|
||||
assert!(path_strs.iter().any(|p| p.contains("child/SKILL.md")));
|
||||
}
|
||||
|
||||
// ── extract_first_paragraph ──────────────────────────────────────
|
||||
// extract_first_paragraph
|
||||
|
||||
#[test]
|
||||
fn first_paragraph_simple() {
|
||||
@@ -1001,7 +1001,7 @@ mod tests {
|
||||
assert!(extract_first_paragraph(body).is_none());
|
||||
}
|
||||
|
||||
// ── UTF-8 safe body truncation ──────────────────────────────────
|
||||
// UTF-8 safe body truncation
|
||||
|
||||
#[test]
|
||||
fn description_fallback_does_not_panic_on_multibyte_boundary() {
|
||||
@@ -1012,10 +1012,12 @@ mod tests {
|
||||
// Strategy: fill with ASCII up to near the limit, then pack 4-byte
|
||||
// emoji right at the boundary.
|
||||
let prefix = "# Heading\n\n";
|
||||
let filler_len = MAX_BODY_PEEK_BYTES - prefix.len() - 4; // leave room for emoji at boundary
|
||||
// leave room for emoji at boundary
|
||||
let filler_len = MAX_BODY_PEEK_BYTES - prefix.len() - 4;
|
||||
let filler = "a".repeat(filler_len);
|
||||
// Each emoji is 4 bytes. Place several so one straddles the 2048 mark.
|
||||
let emoji_run = "\u{1F600}".repeat(10); // 40 bytes of emoji
|
||||
// 40 bytes of emoji
|
||||
let emoji_run = "\u{1F600}".repeat(10);
|
||||
let body = format!("{prefix}{filler}{emoji_run}");
|
||||
assert!(body.len() > MAX_BODY_PEEK_BYTES, "body must exceed limit");
|
||||
|
||||
@@ -1041,7 +1043,8 @@ mod tests {
|
||||
|
||||
// Body (after frontmatter): heading + paragraph with multibyte chars
|
||||
// exceeding 2048 bytes.
|
||||
let long_paragraph = "\u{00E9}".repeat(MAX_BODY_PEEK_BYTES); // 2-byte chars
|
||||
// 2-byte chars
|
||||
let long_paragraph = "\u{00E9}".repeat(MAX_BODY_PEEK_BYTES);
|
||||
let content = format!("---\nname: emoji-skill\n---\n# Test\n\n{long_paragraph}\n");
|
||||
fs::write(skill_dir.join("SKILL.md"), &content).unwrap();
|
||||
|
||||
@@ -1055,7 +1058,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Frontmatter parsing (existing coverage + regression) ─────────
|
||||
// Frontmatter parsing (existing coverage + regression)
|
||||
|
||||
#[test]
|
||||
fn parse_valid_frontmatter() {
|
||||
@@ -1122,7 +1125,7 @@ mod tests {
|
||||
assert!(parsed.effort.is_none());
|
||||
}
|
||||
|
||||
// ── agentskills.io spec parity ────────────────────────────────
|
||||
// agentskills.io spec parity
|
||||
|
||||
#[test]
|
||||
fn parse_license_and_compatibility() {
|
||||
@@ -1296,7 +1299,7 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
// ── Feature 1: Workspace user skills via list_skills ─────────────
|
||||
// Feature 1: Workspace user skills via list_skills
|
||||
|
||||
/// Helper: initialize a bare git repo at `path` so git2::Repository::discover works.
|
||||
fn init_git_repo(path: &Path) {
|
||||
@@ -1423,7 +1426,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── collect_config_skills ────────────────────────────────────────
|
||||
// collect_config_skills
|
||||
|
||||
#[test]
|
||||
fn collect_config_skills_from_directory() {
|
||||
@@ -1530,7 +1533,7 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
// ── filter_skills ────────────────────────────────────────────────
|
||||
// filter_skills
|
||||
|
||||
fn make_skill(name: &str, path: &str) -> SkillInfo {
|
||||
SkillInfo {
|
||||
@@ -1622,7 +1625,7 @@ mod tests {
|
||||
assert_eq!(skills[0].plugin_name.as_deref(), Some("plugin-dev"));
|
||||
}
|
||||
|
||||
// ── Manifest `skills` entries pointing directly at skill dirs ──
|
||||
// Manifest `skills` entries pointing directly at skill dirs
|
||||
|
||||
fn make_registry_with_skill_dirs(
|
||||
name: &str,
|
||||
@@ -2006,11 +2009,11 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// discover_skills_for_paths and dedup_by_canonical_path tests removed --
|
||||
// these functions now live in kigi-tools::implementations::skills::discovery
|
||||
// and kigi-tools::types::skill_discovery_tracker, tested there.
|
||||
// discover_skills_for_paths and dedup_by_canonical_path live in
|
||||
// kigi-tools::implementations::skills::discovery and
|
||||
// kigi-tools::types::skill_discovery_tracker, and are tested there.
|
||||
|
||||
// ── Disabled skills marking ─────────────────────────────────────
|
||||
// Disabled skills marking
|
||||
|
||||
#[tokio::test]
|
||||
async fn disabled_config_marks_skill_enabled_false() {
|
||||
@@ -2091,7 +2094,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Bundled skills discovery ─────────────────────────────────────
|
||||
// Bundled skills discovery
|
||||
|
||||
#[tokio::test]
|
||||
async fn bundled_skills_are_discovered() {
|
||||
@@ -2180,7 +2183,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Command file discovery ────────────────────────────────────────
|
||||
// Command file discovery
|
||||
|
||||
/// Regression: project `.claude/commands` often sits under a full `.claude/**`
|
||||
/// gitignore with only `!.claude/skills/**` re-included (local-only vendor
|
||||
@@ -2312,7 +2315,7 @@ mod tests {
|
||||
assert!(deploy[0].path.contains("SKILL.md"));
|
||||
}
|
||||
|
||||
// ── Plugin skill identity ─────────────────────────────
|
||||
// Plugin skill identity
|
||||
|
||||
fn min_plugin(name: &str) -> crate::plugins::LoadedPlugin {
|
||||
use crate::plugins::discovery::PluginId;
|
||||
@@ -2430,7 +2433,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── collect_skill_config_dirs vendor gating ────────────
|
||||
// collect_skill_config_dirs vendor gating
|
||||
|
||||
#[test]
|
||||
fn collect_skill_config_dirs_gates_vendor_dirs() {
|
||||
@@ -2461,7 +2464,7 @@ mod tests {
|
||||
assert!(ends_with(&dirs, ".kigi"), "kigi must remain: {dirs:?}");
|
||||
}
|
||||
|
||||
// ── Same-scope frontmatter-name collisions (copied skill dirs) ──────
|
||||
// Same-scope frontmatter-name collisions (copied skill dirs)
|
||||
|
||||
fn named_skill(name: &str, path: &str, scope: SkillScope) -> SkillInfo {
|
||||
SkillInfo {
|
||||
|
||||
@@ -1,26 +1,10 @@
|
||||
//! System prompts for built-in subagent profiles.
|
||||
//!
|
||||
//!
|
||||
//! ## Tool name resolution
|
||||
//!
|
||||
//! All tool names in these prompts use the `${{ tools.by_kind.* }}` template
|
||||
//! syntax from the `TemplateRenderer`. When the prompt is rendered via
|
||||
//! `PromptContext::render()` → `ToolBridge::render_prompt()`, MiniJinja
|
||||
//! resolves each variable to the current session's tool names.
|
||||
//!
|
||||
//! This means:
|
||||
//! - Tool names are NEVER hardcoded — they adapt to name overrides and
|
||||
//! alternate tool namespaces
|
||||
//! - If a tool kind is absent from the renderer's context, MiniJinja
|
||||
//! resolves it to an empty string (templates can also use
|
||||
//! `${%- if tools.by_kind.X %}` conditionals to hide entire sections)
|
||||
//!
|
||||
//! Tool-kind mapping (common names → ToolKind):
|
||||
//! Read → `${{ tools.by_kind.read }}`
|
||||
//! Write/Edit → `${{ tools.by_kind.edit }}`
|
||||
//! Glob → `${{ tools.by_kind.list }}`
|
||||
//! Grep → `${{ tools.by_kind.search }}`
|
||||
//! Bash → `${{ tools.by_kind.execute }}`
|
||||
//! WebSearch → `${{ tools.by_kind.web_search }}`
|
||||
//! Tool names inside these prompts are never hardcoded: they are
|
||||
//! `${{ tools.by_kind.* }}` template variables that MiniJinja resolves to the
|
||||
//! session's actual tool names during `ToolBridge::render_prompt()`, so they
|
||||
//! follow name overrides and alternate namespaces. A kind that is absent from
|
||||
//! the renderer context resolves to an empty string, which is why prompts guard
|
||||
//! whole sections with `${%- if tools.by_kind.X %}`.
|
||||
|
||||
pub use kigi_tool_types::{EXPLORE_PROMPT, GENERAL_PURPOSE_PROMPT, PLAN_PROMPT};
|
||||
|
||||
@@ -149,7 +149,7 @@ mod tests {
|
||||
.expect("codex template render failed")
|
||||
}
|
||||
|
||||
// ── Variable substitution ───────────────────────────────────────
|
||||
// Variable substitution
|
||||
|
||||
#[test]
|
||||
fn test_variable_substitution_tool_kind() {
|
||||
@@ -171,7 +171,7 @@ mod tests {
|
||||
assert_eq!(result, "OS: macos, Shell: /bin/zsh");
|
||||
}
|
||||
|
||||
// ── Conditionals ────────────────────────────────────────────────
|
||||
// Conditionals
|
||||
|
||||
#[test]
|
||||
fn test_conditional_tool_present() {
|
||||
@@ -205,7 +205,7 @@ mod tests {
|
||||
assert_eq!(result, "Use {{ literal_braces }} in prose.");
|
||||
}
|
||||
|
||||
// ── Tool name overrides ─────────────────────────────────────────
|
||||
// Tool name overrides
|
||||
|
||||
#[test]
|
||||
fn test_tool_name_override() {
|
||||
@@ -225,7 +225,7 @@ mod tests {
|
||||
assert_eq!(result, "Use view_file and Edit.");
|
||||
}
|
||||
|
||||
// ── Base template rendering ─────────────────────────────────────
|
||||
// Base template rendering
|
||||
|
||||
#[test]
|
||||
fn test_base_template_renders() {
|
||||
@@ -355,7 +355,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Required sections regression ────────────────────────────────
|
||||
// Required sections regression
|
||||
|
||||
#[test]
|
||||
fn test_base_template_contains_required_sections() {
|
||||
@@ -380,7 +380,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Mid-session mode switching ──────────────────────────────────
|
||||
// Mid-session mode switching
|
||||
|
||||
#[test]
|
||||
fn test_mid_session_switch_concise_to_full() {
|
||||
@@ -430,7 +430,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Determinism ─────────────────────────────────────────────────
|
||||
// Determinism
|
||||
|
||||
#[test]
|
||||
fn test_prompt_deterministic_across_renders() {
|
||||
@@ -451,7 +451,7 @@ mod tests {
|
||||
assert_eq!(a, b, "Full mode rendering must be deterministic");
|
||||
}
|
||||
|
||||
// ── Disabled tools ──────────────────────────────────────────────
|
||||
// Disabled tools
|
||||
|
||||
#[test]
|
||||
fn test_disabled_tools_omit_sections() {
|
||||
@@ -469,11 +469,11 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Memory section ──────────────────────────────────────────────
|
||||
// Memory section
|
||||
|
||||
#[test]
|
||||
fn test_memory_enabled_does_not_render_memory_section() {
|
||||
// The <memory> section was removed from the minimal base prompt.
|
||||
// The <memory> section is absent from the minimal base prompt.
|
||||
// Even when the memory tools are registered AND memory_enabled=true,
|
||||
// the trimmed template must not render a memory section. (Complements
|
||||
// test_memory_disabled_omits_memory_section, which covers the default.)
|
||||
@@ -514,7 +514,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Web search disabled ─────────────────────────────────────────
|
||||
// Web search disabled
|
||||
|
||||
#[test]
|
||||
fn test_web_search_disabled_renders_without_crash() {
|
||||
@@ -534,7 +534,7 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
// ── Apply-patch template rendering ───────────────────────────────────
|
||||
// Apply-patch template rendering
|
||||
|
||||
#[test]
|
||||
fn test_apply_patch_template_renders() {
|
||||
@@ -634,9 +634,9 @@ mod tests {
|
||||
assert_eq!(a, b, "Subagent template rendering must be deterministic");
|
||||
}
|
||||
|
||||
// ── Task completion discipline ─────────────────────────────────
|
||||
// Task completion discipline
|
||||
//
|
||||
// The `<task_completion_discipline>` block was removed from both
|
||||
// The `<task_completion_discipline>` block is absent from both
|
||||
// base and subagent templates. These tests pin the deletion so the
|
||||
// block doesn't accidentally come back, and so the runtime TodoGate
|
||||
// doesn't start firing reminders that reference a non-existent
|
||||
@@ -681,7 +681,7 @@ mod tests {
|
||||
assert_template_size_under(&prompt, "subagent");
|
||||
}
|
||||
|
||||
// ── Guard invariant ─────────────────────────────────────────────
|
||||
// Guard invariant
|
||||
// Every `${{ tools.by_kind.X }}` must sit inside a `${%- if ... %}`
|
||||
// whose condition requires X (contains `tools.by_kind.X` at a word
|
||||
// boundary, with no top-level ` or `). If violated, X could render
|
||||
@@ -770,12 +770,12 @@ mod tests {
|
||||
assert_guards(&apply_patch_template(), "apply_patch_prompt.md");
|
||||
}
|
||||
|
||||
// ── Combination sweep ───────────────────────────────────────────
|
||||
// Combination sweep
|
||||
// Belt-and-braces: renders the base template across tool-kind subsets
|
||||
// and asserts no raw template tokens leak. The static guard test above
|
||||
// is the authoritative check; this one just catches syntax drift.
|
||||
|
||||
// ── is_non_interactive gating ──────────────────────────────────
|
||||
// is_non_interactive gating
|
||||
// Headless / SDK / stdio / generic-ACP sessions have no human typing
|
||||
// into a TUI prompt, so the `! <command>` shell-prefix tip and the
|
||||
// `<user_guide>` TUI pointer are noise. Those sections must drop out
|
||||
@@ -783,7 +783,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn interactive_renders_shell_prefix_tip_and_user_guide() {
|
||||
// The `! <command>` shell-prefix tip was removed from the minimal
|
||||
// The `! <command>` shell-prefix tip is absent from the minimal
|
||||
// prompt. The <user_guide> block still renders for interactive
|
||||
// sessions only, so that's what we assert here.
|
||||
let mut p = default_placeholders();
|
||||
|
||||
@@ -334,7 +334,7 @@ mod tests {
|
||||
assert_eq!(original, loaded);
|
||||
}
|
||||
}
|
||||
/// A status under the cap passes through unchanged (trim is a no-op for
|
||||
/// A status under the cap passes through `unchanged` (trim is a no-op for
|
||||
/// real `git status --short --branch` output, which starts with `##`).
|
||||
#[test]
|
||||
fn normalize_git_status_passthrough_under_limit() {
|
||||
|
||||
@@ -48,7 +48,7 @@ mod tests {
|
||||
use super::*;
|
||||
use std::fs;
|
||||
|
||||
// ── resolve_workspace_user_dir (pure, no env vars) ───────────────
|
||||
// resolve_workspace_user_dir (pure, no env vars)
|
||||
|
||||
#[test]
|
||||
fn resolve_returns_none_for_empty_root() {
|
||||
@@ -126,7 +126,7 @@ mod tests {
|
||||
assert_eq!(result, Some(user_dir));
|
||||
}
|
||||
|
||||
// ── workspace_user_relpath ───────────────────────────────────────
|
||||
// workspace_user_relpath
|
||||
|
||||
#[test]
|
||||
fn bare_username_is_nested_under_x() {
|
||||
|
||||
Reference in New Issue
Block a user