From 283d37d8dd5e9f73e76c69857a0920a7af5dc879 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:37:02 +0800 Subject: [PATCH 01/13] docs(design): add doc comment detection feasibility analysis per language Probed each tree-sitter grammar's comment node kinds and documented feasibility for doc_comment_detector. 8 languages feasible (Kotlin, Swift, C, C++, C#, PHP, ObjC, Zig), 2 not feasible (Ruby, Bash), 3 not applicable (JSON, TOML, YAML). Added per-language detection strategy table to the scaffold design section. Original prompt: > the branch is also clean? if so, move to main, sync, and create > a new one (the feasibility analysis was re-derived from earlier probing work) Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- docs/liyi-design.md | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/docs/liyi-design.md b/docs/liyi-design.md index c7a42f1..ab905d6 100644 --- a/docs/liyi-design.md +++ b/docs/liyi-design.md @@ -1802,11 +1802,34 @@ For unsupported languages (no tree-sitter grammar), `liyi init` falls back to th The scaffold uses two deterministic AST signals to help the agent prioritize which items need intent specs: -**1. Doc comment attachment.** Items with doc comments attached are almost certainly non-trivial — someone wrote prose about them. The scaffold detects this per-language: -- Rust: `///` / `//!` doc comments as sibling `line_comment` nodes immediately preceding the item. -- Python: docstrings as `expression_statement > string` children of the function/class body. -- Go: `//` comments immediately preceding the function/type declaration. -- Other languages: similar language-specific patterns via tree-sitter node adjacency. +**1. Doc comment attachment.** Items with doc comments attached are almost certainly non-trivial — someone wrote prose about them. The scaffold detects this per-language via the `doc_comment_detector` callback in `LanguageConfig`: + +| Language | Detector | Strategy | +|---|---|---| +| Rust | `rust_has_doc_comment` | Walks `prev_sibling` chain, checks `line_comment` for `///`/`//!`, `block_comment` for `/**`; skips `attribute_item` siblings | +| Python | `python_has_doc_comment` | Checks first `expression_statement > string` child of the item's body for `"""` or `'''` | +| Go | `go_has_doc_comment` | Checks `prev_sibling` for `comment` kind (Go convention: any `//` comment before a declaration is a doc comment) | +| Java | `java_has_doc_comment` | Walks `prev_sibling` chain, checks `block_comment` for `/**` prefix; skips `modifiers` siblings | +| JavaScript | `js_has_doc_comment` | Checks `prev_sibling` for `comment` kind with `/**` prefix | +| TypeScript/TSX | Reuses `js_has_doc_comment` | Same as JavaScript | +| Dart | `dart_has_doc_comment` | Checks `prev_sibling` for `documentation_block_comment` or `comment` with `///` prefix | +| Kotlin | `kotlin_has_doc_comment` | Walks `prev_sibling` chain, checks `block_comment` for `/**`, `line_comment` for `///`; skips `modifiers`/`annotation` siblings | +| Swift | `swift_has_doc_comment` | Walks `prev_sibling` chain, checks `comment` for `///` prefix, `multiline_comment` for `/**` prefix; skips `modifiers` | +| C | `c_has_doc_comment` | Walks `prev_sibling` chain, checks `comment` for `/**` or `///` prefix; skips non-comment siblings | +| C++ | `cpp_has_doc_comment` | Same strategy as C; additionally skips `access_specifier` siblings | +| C# | `csharp_has_doc_comment` | Walks `prev_sibling` chain, checks `comment` for `///` prefix (XML doc comment convention); skips `attribute_list` and `modifier` siblings | +| PHP | `php_has_doc_comment` | Walks `prev_sibling` chain, checks `comment` for `/**` prefix (PHPDoc convention); skips `attribute_list` and `modifier` siblings | +| Objective-C | `objc_has_doc_comment` | Walks `prev_sibling` chain, checks `comment` for `/**` or `///` prefix; skips non-comment siblings | +| Zig | `zig_has_doc_comment` | Walks `prev_sibling` chain, checks `comment` for `///` prefix (Zig doc comment convention) | +| Ruby | `None` (not feasible) | All comments are uniform `comment` kind with no unambiguous doc syntax convention | +| Bash | `None` (not feasible) | All comments are uniform `comment` kind with no unambiguous doc syntax convention | +| JSON/TOML/YAML | `None` (not applicable) | Data file grammars; doc comments are not a language-level concept | + +**Feasibility analysis (2026-03-31).** Probed each tree-sitter grammar's comment node kinds: +- Grammars that distinguish comment types by node kind: Rust (`line_comment`/`block_comment`/`doc_comment`), Java (`line_comment`/`block_comment`), Kotlin (`line_comment`/`block_comment`), Swift (`comment`/`multiline_comment`) +- Grammars with uniform `comment` kind but unambiguous doc prefix conventions: Go (`//` before declaration), JavaScript/TypeScript (`/**`), C (`/**`/`///`), C++ (`/**`/`///`), C# (`///` XML doc), PHP (`/**` PHPDoc), Objective-C (`/**`/`///`), Zig (`///`) +- Grammars with uniform `comment` kind and no unambiguous doc syntax: Ruby (no community-standard doc comment form beyond RDoc/YARD which aren't distinguishable at the AST level), Bash (no doc comment convention) +- Python: docstrings are `string` nodes inside the body, not comment nodes — handled by the existing `python_has_doc_comment` Items with doc comments get `"_has_doc": true` in their `_hints`, signaling the agent that `"intent": "=doc"` may be appropriate if the docstring contains behavioral requirements. From ac20cfbcb97ea55b5cd75fc1b7a13beaff2443d0 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:42:19 +0800 Subject: [PATCH 02/13] feat(tree_path): add doc_comment_detector for Kotlin Detect Kotlin doc comments via tree-sitter: KDoc block comments (`/** ... */`) use `block_comment` kind, triple-slash line comments (`///`) use `line_comment` kind. Skips `modifiers` and `annotation` siblings that may appear between the doc comment and the declaration. Original prompt: > Can you see the feasibility analysis results from the last crashed session? Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/lang_kotlin.rs | 35 +++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/crates/liyi/src/tree_path/lang_kotlin.rs b/crates/liyi/src/tree_path/lang_kotlin.rs index 02e95d0..c6cd032 100644 --- a/crates/liyi/src/tree_path/lang_kotlin.rs +++ b/crates/liyi/src/tree_path/lang_kotlin.rs @@ -39,6 +39,39 @@ fn kotlin_node_name(node: &Node, source: &str) -> Option { } /// Kotlin language configuration. +/// Detect Kotlin doc comments (`/** ... */` and `/// ...`). +/// +/// Kotlin's tree-sitter-grammar distinguishes `block_comment` (for `/* */` +/// and `/** */`) from `line_comment` (for `//` and `///`). We check for +/// `/**` in block_comment and `///` in line_comment. `modifiers` and +/// `annotation` siblings are skipped since they may appear between the +/// doc comment and the declaration. +fn kotlin_has_doc_comment(node: &Node, source: &str) -> bool { + let mut sibling = node.prev_sibling(); + while let Some(s) = sibling { + match s.kind() { + "block_comment" => { + let text = &source[s.byte_range()]; + if text.starts_with("/**") { + return true; + } + sibling = s.prev_sibling(); + } + "line_comment" => { + let text = &source[s.byte_range()]; + if text.starts_with("///") { + return true; + } + sibling = s.prev_sibling(); + } + "modifiers" | "annotation" | "annotation_list" => { + sibling = s.prev_sibling(); + } + _ => break, + } + } + false +} pub(super) static CONFIG: LanguageConfig = LanguageConfig { ts_language: || tree_sitter_kotlin_ng::LANGUAGE.into(), extensions: &["kt", "kts"], @@ -53,7 +86,7 @@ pub(super) static CONFIG: LanguageConfig = LanguageConfig { name_overrides: &[], body_fields: &["body", "class_body"], custom_name: Some(kotlin_node_name), - doc_comment_detector: None, + doc_comment_detector: Some(kotlin_has_doc_comment), transparent_kinds: &[], }; From 6b2394fc848576887e18f7a15280adf7575361ea Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:42:39 +0800 Subject: [PATCH 03/13] feat(tree_path): add doc_comment_detector for Swift Detect Swift doc comments via tree-sitter: triple-slash (`///`) uses `comment` kind, doc block comments (`/** ... */`) use `multiline_comment` kind. Skips `modifiers` siblings. Original prompt: > Can you see the feasibility analysis results from the last crashed session? Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/lang_swift.rs | 36 ++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/crates/liyi/src/tree_path/lang_swift.rs b/crates/liyi/src/tree_path/lang_swift.rs index 078a922..dd12f19 100644 --- a/crates/liyi/src/tree_path/lang_swift.rs +++ b/crates/liyi/src/tree_path/lang_swift.rs @@ -1,6 +1,40 @@ use super::LanguageConfig; +use tree_sitter::Node; + /// Swift language configuration. +/// Detect Swift doc comments (`/// ...` and `/** ... */`). +/// +/// Swift's tree-sitter grammar uses `comment` for line comments (both `//` +/// and `///`) and `multiline_comment` for block comments (both `/* */` and +/// `/** */`). We check for `///` prefix in `comment` and `/**` prefix in +/// `multiline_comment`. `modifiers` siblings are skipped. +fn swift_has_doc_comment(node: &Node, source: &str) -> bool { + let mut sibling = node.prev_sibling(); + while let Some(s) = sibling { + match s.kind() { + "comment" => { + let text = &source[s.byte_range()]; + if text.starts_with("///") { + return true; + } + sibling = s.prev_sibling(); + } + "multiline_comment" => { + let text = &source[s.byte_range()]; + if text.starts_with("/**") { + return true; + } + sibling = s.prev_sibling(); + } + "modifiers" => { + sibling = s.prev_sibling(); + } + _ => break, + } + } + false +} pub(super) static CONFIG: LanguageConfig = LanguageConfig { ts_language: || tree_sitter_swift::LANGUAGE.into(), extensions: &["swift"], @@ -17,7 +51,7 @@ pub(super) static CONFIG: LanguageConfig = LanguageConfig { name_overrides: &[], body_fields: &["body"], custom_name: None, - doc_comment_detector: None, + doc_comment_detector: Some(swift_has_doc_comment), transparent_kinds: &[], }; From 39dddcb7f33c6c0173b1c8287c9c99ab7ae0caaf Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:43:00 +0800 Subject: [PATCH 04/13] feat(tree_path): add doc_comment_detector for C Detect C doc comments via tree-sitter: all comments use the uniform `comment` kind. Distinguishes doc comments by prefix: `/**` for block doc and `///` for line doc. Original prompt: > Can you see the feasibility analysis results from the last crashed session? Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/lang_c.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/crates/liyi/src/tree_path/lang_c.rs b/crates/liyi/src/tree_path/lang_c.rs index 1229df1..f531d91 100644 --- a/crates/liyi/src/tree_path/lang_c.rs +++ b/crates/liyi/src/tree_path/lang_c.rs @@ -46,6 +46,26 @@ fn c_node_name(node: &Node, source: &str) -> Option { } /// C language configuration. +/// Detect C doc comments (`/** ... */` and `/// ...`). +/// +/// C's tree-sitter grammar uses a uniform `comment` kind for all comments. +/// We distinguish doc comments by prefix: `/**` for block doc and `///` +/// for line doc. Previous siblings that are not comments are skipped. +fn c_has_doc_comment(node: &Node, source: &str) -> bool { + let mut sibling = node.prev_sibling(); + while let Some(s) = sibling { + if s.kind() == "comment" { + let text = &source[s.byte_range()]; + if text.starts_with("/**") || text.starts_with("///") { + return true; + } + sibling = s.prev_sibling(); + } else { + break; + } + } + false +} pub(super) static CONFIG: LanguageConfig = LanguageConfig { ts_language: || tree_sitter_c::LANGUAGE.into(), extensions: &["c"], @@ -59,7 +79,7 @@ pub(super) static CONFIG: LanguageConfig = LanguageConfig { name_overrides: &[], body_fields: &["body"], custom_name: Some(c_node_name), - doc_comment_detector: None, + doc_comment_detector: Some(c_has_doc_comment), transparent_kinds: &[], }; From 0bb24821cc20da396be1432e44ceb536d6973d4f Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:43:41 +0800 Subject: [PATCH 05/13] feat(tree_path): add doc_comment_detector for C++ Detect C++ doc comments via tree-sitter: all comments use the uniform `comment` kind. Distinguishes doc comments by prefix: `/**` for block doc and `///` for line doc. Additionally skips `access_specifier` siblings (public/private/protected) that may appear between the doc comment and a class member. Original prompt: > Can you see the feasibility analysis results from the last crashed session? Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/lang_cpp.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/liyi/src/tree_path/lang_cpp.rs b/crates/liyi/src/tree_path/lang_cpp.rs index b20afee..3968959 100644 --- a/crates/liyi/src/tree_path/lang_cpp.rs +++ b/crates/liyi/src/tree_path/lang_cpp.rs @@ -41,6 +41,30 @@ fn cpp_node_name(node: &Node, source: &str) -> Option { } /// C++ language configuration. +/// Detect C++ doc comments (`/** ... */` and `/// ...`). +/// +/// C++'s tree-sitter grammar uses a uniform `comment` kind. We distinguish +/// doc comments by prefix: `/**` for block doc and `///` for line doc. +/// Skips `access_specifier` siblings (public/private/protected). +fn cpp_has_doc_comment(node: &Node, source: &str) -> bool { + let mut sibling = node.prev_sibling(); + while let Some(s) = sibling { + match s.kind() { + "comment" => { + let text = &source[s.byte_range()]; + if text.starts_with("/**") || text.starts_with("///") { + return true; + } + sibling = s.prev_sibling(); + } + "access_specifier" => { + sibling = s.prev_sibling(); + } + _ => break, + } + } + false +} pub(super) static CONFIG: LanguageConfig = LanguageConfig { ts_language: || tree_sitter_cpp::LANGUAGE.into(), extensions: &["cpp", "cc", "cxx", "h", "hpp", "hh", "hxx", "h++", "c++"], @@ -58,7 +82,7 @@ pub(super) static CONFIG: LanguageConfig = LanguageConfig { name_overrides: &[], body_fields: &["body", "declaration_list"], custom_name: Some(cpp_node_name), - doc_comment_detector: None, + doc_comment_detector: Some(cpp_has_doc_comment), transparent_kinds: &[], }; From a9fcd212056995a2c9a2a1fd2cac035b28bb72e6 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:44:05 +0800 Subject: [PATCH 06/13] feat(tree_path): add doc_comment_detector for C# Detect C# XML doc comments via tree-sitter: all comments use the uniform `comment` kind. The C# convention is `///` for XML documentation comments (also accepts `/**` for Javadoc-style). Skips `attribute_list` and `modifier` siblings. Original prompt: > Can you see the feasibility analysis results from the last crashed session? Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/lang_csharp.rs | 30 +++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/crates/liyi/src/tree_path/lang_csharp.rs b/crates/liyi/src/tree_path/lang_csharp.rs index 2afe47f..af04835 100644 --- a/crates/liyi/src/tree_path/lang_csharp.rs +++ b/crates/liyi/src/tree_path/lang_csharp.rs @@ -1,6 +1,34 @@ use super::LanguageConfig; +use tree_sitter::Node; + /// C# language configuration. +/// Detect C# XML doc comments (`/// ...`). +/// +/// C#'s tree-sitter grammar uses a uniform `comment` kind. The C# convention +/// is `///` for XML documentation comments. We also check for `/**` as some +/// projects use Javadoc-style. `attribute_list` and `modifier` siblings are +/// skipped since attributes and access modifiers may appear between the doc +/// comment and the declaration. +fn csharp_has_doc_comment(node: &Node, source: &str) -> bool { + let mut sibling = node.prev_sibling(); + while let Some(s) = sibling { + match s.kind() { + "comment" => { + let text = &source[s.byte_range()]; + if text.starts_with("///") || text.starts_with("/**") { + return true; + } + sibling = s.prev_sibling(); + } + "attribute_list" | "modifier" => { + sibling = s.prev_sibling(); + } + _ => break, + } + } + false +} pub(super) static CONFIG: LanguageConfig = LanguageConfig { ts_language: || tree_sitter_c_sharp::LANGUAGE.into(), extensions: &["cs"], @@ -20,7 +48,7 @@ pub(super) static CONFIG: LanguageConfig = LanguageConfig { name_overrides: &[], body_fields: &["body"], custom_name: None, - doc_comment_detector: None, + doc_comment_detector: Some(csharp_has_doc_comment), transparent_kinds: &[], }; From d7b9d6150e72f76f5f50a2213596cdb55a0d68ad Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:44:10 +0800 Subject: [PATCH 07/13] feat(tree_path): add doc_comment_detector for PHP Detect PHPDoc comments via tree-sitter: all comments use the uniform `comment` kind. The PHP convention for documentation is `/**` (PHPDoc). Skips `attribute_list`, `modifier`, and `visibility_modifier` siblings. Original prompt: > Can you see the feasibility analysis results from the last crashed session? Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/lang_php.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/crates/liyi/src/tree_path/lang_php.rs b/crates/liyi/src/tree_path/lang_php.rs index 4fcc09f..29e623f 100644 --- a/crates/liyi/src/tree_path/lang_php.rs +++ b/crates/liyi/src/tree_path/lang_php.rs @@ -20,6 +20,30 @@ fn php_node_name(node: &Node, source: &str) -> Option { } /// PHP language configuration (PHP-only grammar, no HTML interleaving). +/// Detect PHPDoc comments (`/** ... */`). +/// +/// PHP's tree-sitter grammar uses a uniform `comment` kind. The PHP +/// convention for documentation is `/**` (PHPDoc). `attribute_list` +/// and `modifier` siblings are skipped. +fn php_has_doc_comment(node: &Node, source: &str) -> bool { + let mut sibling = node.prev_sibling(); + while let Some(s) = sibling { + match s.kind() { + "comment" => { + let text = &source[s.byte_range()]; + if text.starts_with("/**") { + return true; + } + sibling = s.prev_sibling(); + } + "attribute_list" | "modifier" | "visibility_modifier" => { + sibling = s.prev_sibling(); + } + _ => break, + } + } + false +} pub(super) static CONFIG: LanguageConfig = LanguageConfig { ts_language: || tree_sitter_php::LANGUAGE_PHP_ONLY.into(), extensions: &["php"], @@ -37,7 +61,7 @@ pub(super) static CONFIG: LanguageConfig = LanguageConfig { name_overrides: &[], body_fields: &["body"], custom_name: Some(php_node_name), - doc_comment_detector: None, + doc_comment_detector: Some(php_has_doc_comment), transparent_kinds: &[], }; From 4f98cc17494f73a6b567fa433573428faaae5ed2 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:44:28 +0800 Subject: [PATCH 08/13] feat(tree_path): add doc_comment_detector for Objective-C Detect Objective-C doc comments via tree-sitter: all comments use the uniform `comment` kind. Checks for `/**` (HeaderDoc/Javadoc) and `///` (Doxygen) prefixes. Original prompt: > Can you see the feasibility analysis results from the last crashed session? Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/lang_objc.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/crates/liyi/src/tree_path/lang_objc.rs b/crates/liyi/src/tree_path/lang_objc.rs index 05ce9d0..06ecb0a 100644 --- a/crates/liyi/src/tree_path/lang_objc.rs +++ b/crates/liyi/src/tree_path/lang_objc.rs @@ -68,6 +68,25 @@ fn objc_node_name(node: &Node, source: &str) -> Option { } /// Objective-C language configuration. +/// Detect Objective-C doc comments (`/** ... */` and `/// ...`). +/// +/// ObjC's tree-sitter grammar uses a uniform `comment` kind. We check for +/// `/**` (HeaderDoc/Javadoc) and `///` (Doxygen) prefixes. +fn objc_has_doc_comment(node: &Node, source: &str) -> bool { + let mut sibling = node.prev_sibling(); + while let Some(s) = sibling { + if s.kind() == "comment" { + let text = &source[s.byte_range()]; + if text.starts_with("/**") || text.starts_with("///") { + return true; + } + sibling = s.prev_sibling(); + } else { + break; + } + } + false +} pub(super) static CONFIG: LanguageConfig = LanguageConfig { ts_language: || tree_sitter_objc::LANGUAGE.into(), extensions: &["m", "mm"], @@ -86,7 +105,7 @@ pub(super) static CONFIG: LanguageConfig = LanguageConfig { name_overrides: &[], body_fields: &["body"], custom_name: Some(objc_node_name), - doc_comment_detector: None, + doc_comment_detector: Some(objc_has_doc_comment), transparent_kinds: &[], }; From 7454af793529f3cea0d50a79e041d2551ee0d812 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:44:34 +0800 Subject: [PATCH 09/13] feat(tree_path): add doc_comment_detector for Zig Detect Zig doc comments via tree-sitter: all comments use the uniform `comment` kind. The Zig doc comment convention is `///` before a declaration. Original prompt: > Can you see the feasibility analysis results from the last crashed session? Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/lang_zig.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/crates/liyi/src/tree_path/lang_zig.rs b/crates/liyi/src/tree_path/lang_zig.rs index 501bb91..a7d8e2c 100644 --- a/crates/liyi/src/tree_path/lang_zig.rs +++ b/crates/liyi/src/tree_path/lang_zig.rs @@ -59,6 +59,26 @@ fn zig_node_name(node: &Node, source: &str) -> Option { } /// Zig language configuration. +/// Detect Zig doc comments (`/// ...`). +/// +/// Zig's tree-sitter grammar uses a uniform `comment` kind for all comments +/// (`//`, `///`, `//!`). The doc comment convention is `///` before a +/// declaration. We check for `///` prefix. +fn zig_has_doc_comment(node: &Node, source: &str) -> bool { + let mut sibling = node.prev_sibling(); + while let Some(s) = sibling { + if s.kind() == "comment" { + let text = &source[s.byte_range()]; + if text.starts_with("///") { + return true; + } + sibling = s.prev_sibling(); + } else { + break; + } + } + false +} pub(super) static CONFIG: LanguageConfig = LanguageConfig { ts_language: || tree_sitter_zig::LANGUAGE.into(), extensions: &["zig"], @@ -73,7 +93,7 @@ pub(super) static CONFIG: LanguageConfig = LanguageConfig { // container for struct-as-namespace contents (methods, fields). body_fields: &["block", "struct_declaration"], custom_name: Some(zig_node_name), - doc_comment_detector: None, + doc_comment_detector: Some(zig_has_doc_comment), transparent_kinds: &[], }; From 7298af9e62c8a7c33f3f35f43b0855e6dc01af8a Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Tue, 31 Mar 2026 18:44:56 +0800 Subject: [PATCH 10/13] test(tree_path): add doc comment detection tests for all new detectors Add shared `check_doc_comment` test helper that resolves a tree_path, finds the item-level tree-sitter node, and calls `has_doc_comment`. Add 19 tests covering positive and negative cases for all 8 new doc_comment_detector implementations: Kotlin (KDoc, triple-slash, regular), Swift (triple-slash, multiline doc, regular), C (block doc, triple-slash, regular), C++ (block doc, triple-slash), C# (triple-slash in class, regular), PHP (PHPDoc, regular), ObjC (block doc, triple-slash), Zig (triple-slash, regular). Original prompt: > Can you see the feasibility analysis results from the last crashed session? Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/mod.rs | 202 +++++++++++++++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/crates/liyi/src/tree_path/mod.rs b/crates/liyi/src/tree_path/mod.rs index b50ddb7..036e5f5 100644 --- a/crates/liyi/src/tree_path/mod.rs +++ b/crates/liyi/src/tree_path/mod.rs @@ -1932,4 +1932,206 @@ jobs: ); assert_eq!(base, injected); } + + // --------------------------------------------------------------- + // Doc comment detection tests + // --------------------------------------------------------------- + + /// Helper: parse source, find the item-level node at the resolved + /// tree_path span, and call `has_doc_comment`. + fn check_doc_comment(source: &str, tree_path: &str, lang: Language) -> Option { + let span = resolve_tree_path(source, tree_path, lang)?; + let config = lang.config(); + let mut parser = make_parser(lang); + let tree = parser.parse(source, None)?; + let root = tree.root_node(); + fn find_item_node<'a>( + node: tree_sitter::Node<'a>, + span: [usize; 2], + config: &LanguageConfig, + ) -> Option> { + let node_start = node.start_position().row + 1; + let node_end = node.end_position().row + 1; + if node_start == span[0] + && node_end == span[1] + && config.kind_to_shorthand(node.kind()).is_some() + { + return Some(node); + } + let mut cursor = node.walk(); + for child in node.children(&mut cursor) { + if let Some(found) = find_item_node(child, span, config) { + return Some(found); + } + } + None + } + let node = find_item_node(root, span, config)?; + config.has_doc_comment(&node, source) + } + + #[test] + fn doc_comment_kotlin_kdoc_block() { + let src = "/** Adds two numbers */\nfun add(a: Int, b: Int): Int { return a + b }\n"; + assert_eq!( + check_doc_comment(src, "fn.add", Language::Kotlin), + Some(true) + ); + } + + #[test] + fn doc_comment_kotlin_triple_slash() { + let src = "/// Adds two numbers\nfun add(a: Int, b: Int): Int { return a + b }\n"; + assert_eq!( + check_doc_comment(src, "fn.add", Language::Kotlin), + Some(true) + ); + } + + #[test] + fn doc_comment_kotlin_regular_not_doc() { + let src = "// regular comment\nfun add(a: Int, b: Int): Int { return a + b }\n"; + assert_eq!( + check_doc_comment(src, "fn.add", Language::Kotlin), + Some(false) + ); + } + + #[test] + fn doc_comment_swift_triple_slash() { + let src = "/// Adds two numbers\nfunc add(a: Int, b: Int) -> Int { return a + b }\n"; + assert_eq!( + check_doc_comment(src, "fn.add", Language::Swift), + Some(true) + ); + } + + #[test] + fn doc_comment_swift_multiline_doc() { + let src = "/** Adds two numbers */\nfunc add(a: Int, b: Int) -> Int { return a + b }\n"; + assert_eq!( + check_doc_comment(src, "fn.add", Language::Swift), + Some(true) + ); + } + + #[test] + fn doc_comment_swift_regular_not_doc() { + let src = "// regular\nfunc add(a: Int, b: Int) -> Int { return a + b }\n"; + assert_eq!( + check_doc_comment(src, "fn.add", Language::Swift), + Some(false) + ); + } + + #[test] + fn doc_comment_c_block_doc() { + let src = "/** Process input */\nvoid process(int x) { return; }\n"; + assert_eq!( + check_doc_comment(src, "fn.process", Language::C), + Some(true) + ); + } + + #[test] + fn doc_comment_c_triple_slash() { + let src = "/// Process input\nvoid process(int x) { return; }\n"; + assert_eq!( + check_doc_comment(src, "fn.process", Language::C), + Some(true) + ); + } + + #[test] + fn doc_comment_c_regular_not_doc() { + let src = "// regular\nvoid process(int x) { return; }\n"; + assert_eq!( + check_doc_comment(src, "fn.process", Language::C), + Some(false) + ); + } + + #[test] + fn doc_comment_cpp_block_doc() { + let src = "/** Standalone function */\nvoid standalone() {}\n"; + assert_eq!( + check_doc_comment(src, "fn.standalone", Language::Cpp), + Some(true) + ); + } + + #[test] + fn doc_comment_cpp_triple_slash() { + let src = "/// Standalone function\nvoid standalone() {}\n"; + assert_eq!( + check_doc_comment(src, "fn.standalone", Language::Cpp), + Some(true) + ); + } + + #[test] + fn doc_comment_csharp_triple_slash() { + let src = "class Foo {\n /// Adds two numbers\n int Add(int a, int b) { return a + b; }\n}\n"; + assert_eq!( + check_doc_comment(src, "class.Foo::fn.Add", Language::CSharp), + Some(true) + ); + } + + #[test] + fn doc_comment_csharp_regular_not_doc() { + let src = "class Foo {\n // regular\n int Add(int a, int b) { return a + b; }\n}\n"; + assert_eq!( + check_doc_comment(src, "class.Foo::fn.Add", Language::CSharp), + Some(false) + ); + } + + #[test] + fn doc_comment_php_phpdoc() { + let src = "/** Find a user */\nfunction findUser(int $id): ?User { return null; }\n"; + assert_eq!( + check_doc_comment(src, "fn.findUser", Language::Php), + Some(true) + ); + } + + #[test] + fn doc_comment_php_regular_not_doc() { + let src = "// regular\nfunction findUser(int $id): ?User { return null; }\n"; + assert_eq!( + check_doc_comment(src, "fn.findUser", Language::Php), + Some(false) + ); + } + + #[test] + fn doc_comment_objc_block_doc() { + let src = "/** Helper function */\nvoid helper(void) { return; }\n"; + assert_eq!( + check_doc_comment(src, "fn.helper", Language::ObjectiveC), + Some(true) + ); + } + + #[test] + fn doc_comment_objc_triple_slash() { + let src = "/// Helper function\nvoid helper(void) { return; }\n"; + assert_eq!( + check_doc_comment(src, "fn.helper", Language::ObjectiveC), + Some(true) + ); + } + + #[test] + fn doc_comment_zig_triple_slash() { + let src = "/// Add two numbers\nfn add(a: i32, b: i32) i32 { return a + b; }\n"; + assert_eq!(check_doc_comment(src, "fn.add", Language::Zig), Some(true)); + } + + #[test] + fn doc_comment_zig_regular_not_doc() { + let src = "// regular comment\nfn add(a: i32, b: i32) i32 { return a + b; }\n"; + assert_eq!(check_doc_comment(src, "fn.add", Language::Zig), Some(false)); + } } From 2e45a267e26f7905bf7f478b67ef54b8248a62e0 Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Wed, 1 Apr 2026 09:42:29 +0800 Subject: [PATCH 11/13] refactor: liyi check --fix Signed-off-by: WANG Xuerui --- crates/liyi/src/markers.rs.liyi.jsonc | 8 ++++---- crates/liyi/src/prompt.rs.liyi.jsonc | 2 +- crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc | 4 ++-- crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc | 4 ++-- crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc | 4 ++-- crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc | 4 ++-- crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc | 4 ++-- crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc | 4 ++-- crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc | 4 ++-- crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc | 4 ++-- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/crates/liyi/src/markers.rs.liyi.jsonc b/crates/liyi/src/markers.rs.liyi.jsonc index f9acb3a..f0962e4 100644 --- a/crates/liyi/src/markers.rs.liyi.jsonc +++ b/crates/liyi/src/markers.rs.liyi.jsonc @@ -43,7 +43,7 @@ "source_anchor": "const ALIAS_TABLE: &[(&str, &str)] = &[", "related": { "marker-normalization": "sha256:f1786541ac9be4533a36924a80c578a749024a4980fbc323417c2d5640ed6306", - "quine-escape-in-source": null + "quine-escape-in-source": "sha256:b929750d0d3c9ce24a6f814d7a1db15f2fc03983efa2647cfcf6a7462d2c8b81" } }, { @@ -125,7 +125,7 @@ "source_anchor": "fn is_fence_delimiter(line: &str) -> bool {", "confidence": 0.95, "related": { - "markdown-fenced-block-skip": null + "markdown-fenced-block-skip": "sha256:0bdd7d1ad747e2a826adfe2eca5652c7a9f382e1089ff12dd2c9b8d88f3920b7" } }, { @@ -164,8 +164,8 @@ "source_hash": "sha256:882dc8ffe044cfd565123f41aa19ad94b6ec641f829f96a3c7b02565beb43de3", "source_anchor": "pub fn scan_markers(content: &str) -> Vec {", "related": { - "markdown-fenced-block-skip": null, - "quine-escape-in-source": null + "markdown-fenced-block-skip": "sha256:0bdd7d1ad747e2a826adfe2eca5652c7a9f382e1089ff12dd2c9b8d88f3920b7", + "quine-escape-in-source": "sha256:b929750d0d3c9ce24a6f814d7a1db15f2fc03983efa2647cfcf6a7462d2c8b81" } } ] diff --git a/crates/liyi/src/prompt.rs.liyi.jsonc b/crates/liyi/src/prompt.rs.liyi.jsonc index c703802..fb91bef 100644 --- a/crates/liyi/src/prompt.rs.liyi.jsonc +++ b/crates/liyi/src/prompt.rs.liyi.jsonc @@ -51,7 +51,7 @@ "source_hash": "sha256:4b58abb88e8267fb636eae6727230d6f4c90fdaab97f0125c916e5a55985851e", "source_anchor": "pub fn build_prompt_output(", "related": { - "quine-escape-in-source": null + "quine-escape-in-source": "sha256:b929750d0d3c9ce24a6f814d7a1db15f2fc03983efa2647cfcf6a7462d2c8b81" } }, { diff --git a/crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc index 4ec0386..275b505 100644 --- a/crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc @@ -44,8 +44,8 @@ "reviewed": true, "intent": "Define the C language configuration for tree_path resolution: register tree-sitter-c grammar, .c extension only, kind mappings for fn/struct/enum/typedef, wire the custom c_node_name callback for name extraction, and no doc comment detector.", "source_span": [ - 49, - 64 + 69, + 84 ], "tree_path": "static.CONFIG", "source_hash": "sha256:896b0b51a031e70d135ee3c4f5c5fec8e24548e376d24f3551c1bcf865815c16", diff --git a/crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc index b97fdbb..c2f7bb2 100644 --- a/crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc @@ -20,8 +20,8 @@ "reviewed": true, "intent": "Define the C++ language configuration for tree_path resolution: register tree-sitter-cpp grammar, C++ file extensions (.cpp/.cc/.cxx/.hpp etc.), kind mappings for fn/class/struct/namespace/enum/template/typedef/using, wire the custom cpp_node_name callback, and no doc comment detector.", "source_span": [ - 44, - 63 + 68, + 87 ], "tree_path": "static.CONFIG", "source_hash": "sha256:435f6f5356bbbd674a5b9c72860141710adb9e43fbdaaec09fe98584eaff1e34", diff --git a/crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc index 3c05b32..29993fc 100644 --- a/crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc @@ -8,8 +8,8 @@ "reviewed": true, "intent": "Define the C# language configuration for tree_path resolution: register tree-sitter-c-sharp grammar, .cs extension, kind mappings for fn/class/interface/enum/struct/namespace/constructor/property/record/delegate, using standard name field with no custom name extraction and no doc comment detector.", "source_span": [ - 4, - 25 + 32, + 53 ], "tree_path": "static.CONFIG", "source_hash": "sha256:6c0a47b592b0b8db93bcf44a875e7e2ba199ecbf1dbf767894797972b290398b", diff --git a/crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc index 11b48e8..81bc0ea 100644 --- a/crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc @@ -20,8 +20,8 @@ "reviewed": true, "intent": "Define the Kotlin language configuration for tree_path resolution: register tree-sitter-kotlin-ng grammar, .kt/.kts extensions, kind mappings for fn/class/object/property/typealias, wire the custom kotlin_node_name callback, and no doc comment detector.", "source_span": [ - 42, - 58 + 75, + 91 ], "tree_path": "static.CONFIG", "source_hash": "sha256:c44502301bfedb32c49eb543da976a65e3dbe9b4c4d5fc7323a8c6541fe64423", diff --git a/crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc index 8c14c45..540866f 100644 --- a/crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc @@ -20,8 +20,8 @@ "reviewed": true, "intent": "Define the Objective-C language configuration for tree_path resolution: register tree-sitter-objc grammar, .m/.mm extensions, kind mappings for fn/class/impl/protocol/method/method_decl/struct/enum/typedef, wire the custom objc_node_name callback, and no doc comment detector.", "source_span": [ - 71, - 91 + 90, + 110 ], "tree_path": "static.CONFIG", "source_hash": "sha256:34d6d1ac114bde885324b53fac1aaf04e217c62dac9f14c49c31582a51461770", diff --git a/crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc index 4ffd204..4dc86b0 100644 --- a/crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc @@ -20,8 +20,8 @@ "reviewed": true, "intent": "Define the PHP language configuration for tree_path resolution: register tree-sitter-php PHP-only grammar (no HTML interleaving), .php extension, kind mappings for fn/class/method/interface/enum/trait/namespace/const, wire the custom php_node_name callback, and no doc comment detector.", "source_span": [ - 23, - 42 + 47, + 66 ], "tree_path": "static.CONFIG", "source_hash": "sha256:834be3bf9acb078c50e1628c4053e5bb63c524b36ca61a0fadee5ddbd2e75bc4", diff --git a/crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc index 5e62bf5..af97656 100644 --- a/crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc @@ -8,8 +8,8 @@ "reviewed": true, "intent": "Define the Swift language configuration for tree_path resolution: register tree-sitter-swift grammar, .swift extension, kind mappings for fn/class/protocol/enum/property/init/typealias, using standard name field with no custom name extraction and no doc comment detector.", "source_span": [ - 4, - 22 + 38, + 56 ], "tree_path": "static.CONFIG", "source_hash": "sha256:fc43d49db843de761bd68f8ddf03ffc2b260915d7eec1cd2245fa9729f1806b5", diff --git a/crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc index 4e6a47f..f2b73ff 100644 --- a/crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc @@ -8,8 +8,8 @@ "reviewed": true, "intent": "Define the Zig language configuration for tree_path resolution: register tree-sitter-zig grammar v1.1.2, .zig extension, kind mappings for fn (function_declaration), struct (variable_declaration for const Name = struct { ... }), and test (test_declaration). Uses custom name extraction and struct_declaration as body container for struct-as-namespace pattern. No doc comment detector.", "source_span": [ - 62, - 78 + 82, + 98 ], "tree_path": "static.CONFIG", "source_hash": "sha256:47d6bb93813d9148fe3a7e9907a87366e91ff7582e4fd38553f3711729565e1d", From 995cdf1b32b9eacff752aeefe255289c6b7fb9de Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Wed, 1 Apr 2026 09:43:37 +0800 Subject: [PATCH 12/13] docs(tree_path): approve intents Signed-off-by: WANG Xuerui --- crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc | 2 +- crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc | 2 +- crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc | 2 +- crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc | 2 +- crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc | 2 +- crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc | 2 +- crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc | 2 +- crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc index 275b505..c65dc7a 100644 --- a/crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_c.rs.liyi.jsonc @@ -48,7 +48,7 @@ 84 ], "tree_path": "static.CONFIG", - "source_hash": "sha256:896b0b51a031e70d135ee3c4f5c5fec8e24548e376d24f3551c1bcf865815c16", + "source_hash": "sha256:bc2b8ed39645ec4e16137afa87b145349dde8c1ff38d950953bfc843eedfedfe", "source_anchor": "pub(super) static CONFIG: LanguageConfig = LanguageConfig {" } ] diff --git a/crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc index c2f7bb2..5401bca 100644 --- a/crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_cpp.rs.liyi.jsonc @@ -24,7 +24,7 @@ 87 ], "tree_path": "static.CONFIG", - "source_hash": "sha256:435f6f5356bbbd674a5b9c72860141710adb9e43fbdaaec09fe98584eaff1e34", + "source_hash": "sha256:9214c791323abe5ab620f8622089e719f4f0f8e7966cce114cc8a3936208c458", "source_anchor": "pub(super) static CONFIG: LanguageConfig = LanguageConfig {" } ] diff --git a/crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc index 29993fc..8b2b1cb 100644 --- a/crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_csharp.rs.liyi.jsonc @@ -12,7 +12,7 @@ 53 ], "tree_path": "static.CONFIG", - "source_hash": "sha256:6c0a47b592b0b8db93bcf44a875e7e2ba199ecbf1dbf767894797972b290398b", + "source_hash": "sha256:c95d3244ecb954bd82a2f3df065dda6f2d58c18a11c277fd9600990ef4127b48", "source_anchor": "pub(super) static CONFIG: LanguageConfig = LanguageConfig {" } ] diff --git a/crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc index 81bc0ea..7c5efba 100644 --- a/crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_kotlin.rs.liyi.jsonc @@ -24,7 +24,7 @@ 91 ], "tree_path": "static.CONFIG", - "source_hash": "sha256:c44502301bfedb32c49eb543da976a65e3dbe9b4c4d5fc7323a8c6541fe64423", + "source_hash": "sha256:868044c379a7f1e4d25d0ff81df7a26b4714d926b08b6cd708f8dbd0c292d325", "source_anchor": "pub(super) static CONFIG: LanguageConfig = LanguageConfig {" } ] diff --git a/crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc index 540866f..0172176 100644 --- a/crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_objc.rs.liyi.jsonc @@ -24,7 +24,7 @@ 110 ], "tree_path": "static.CONFIG", - "source_hash": "sha256:34d6d1ac114bde885324b53fac1aaf04e217c62dac9f14c49c31582a51461770", + "source_hash": "sha256:036f2978cd0e40f1afde4dbca4940dac761e74bc316c96151dd1ead978b691ba", "source_anchor": "pub(super) static CONFIG: LanguageConfig = LanguageConfig {" } ] diff --git a/crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc index 4dc86b0..9eca416 100644 --- a/crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_php.rs.liyi.jsonc @@ -24,7 +24,7 @@ 66 ], "tree_path": "static.CONFIG", - "source_hash": "sha256:834be3bf9acb078c50e1628c4053e5bb63c524b36ca61a0fadee5ddbd2e75bc4", + "source_hash": "sha256:4d7ce38edb66173371fb985d94ec5b41be0eda73de3680b4cbbe36c3e7b2477d", "source_anchor": "pub(super) static CONFIG: LanguageConfig = LanguageConfig {" } ] diff --git a/crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc index af97656..2993df8 100644 --- a/crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_swift.rs.liyi.jsonc @@ -12,7 +12,7 @@ 56 ], "tree_path": "static.CONFIG", - "source_hash": "sha256:fc43d49db843de761bd68f8ddf03ffc2b260915d7eec1cd2245fa9729f1806b5", + "source_hash": "sha256:0c6a4089365f5e2fc36a878a0179fd558d8478712a8af607f79201cbdd70af64", "source_anchor": "pub(super) static CONFIG: LanguageConfig = LanguageConfig {" } ] diff --git a/crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc b/crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc index f2b73ff..d9b70d9 100644 --- a/crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc +++ b/crates/liyi/src/tree_path/lang_zig.rs.liyi.jsonc @@ -12,7 +12,7 @@ 98 ], "tree_path": "static.CONFIG", - "source_hash": "sha256:47d6bb93813d9148fe3a7e9907a87366e91ff7582e4fd38553f3711729565e1d", + "source_hash": "sha256:b80ecd2d9fab2d8d911a71895fb8b71e62a589381c220684db23d0d639daa240", "source_anchor": "pub(super) static CONFIG: LanguageConfig = LanguageConfig {" }, { From fb9832de78c6a90bb8017395734cdf3eb3aff39e Mon Sep 17 00:00:00 2001 From: WANG Xuerui Date: Wed, 1 Apr 2026 09:53:54 +0800 Subject: [PATCH 13/13] docs(next-steps): mark item 1.2 doc-comment detection as complete 15/21 languages now have doc_comment_detector. Remaining 5 are not feasible (Bash, Ruby) or not applicable (JSON, TOML, YAML). Updated date and removed item 1.2 from priority diagram. Original prompt: > pull the latest remote branch (I've updated it) and update > the roadmap, then push Human note: Fixed model identity (the model looked at "default model" that said Kimi K2.5). AI-assisted-by: Xiaomi MiMo-V2-Pro (OpenClaw) Signed-off-by: WANG Xuerui --- docs/next-steps.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/next-steps.md b/docs/next-steps.md index e2ff944..2918a2a 100644 --- a/docs/next-steps.md +++ b/docs/next-steps.md @@ -3,7 +3,7 @@ # Prioritized Next Steps -**As of**: 2026-03-17 · **Baseline**: v0.1.0, 275 specs current, 9 trivial, all tests and clippy clean. +**As of**: 2026-04-01 · **Baseline**: v0.1.0, doc-comment detection complete for all feasible languages. This document synthesizes the existing roadmaps (liyi-design.md, lsp-design.md, approve-impl.md, init-discover-impl.md, prompt-mode-design.md, @@ -20,7 +20,7 @@ These can each be done in a single focused session without new design work. | # | Item | Source | Why now | |---|------|--------|---------| | 1.1 | **Extend `--prompt` to stale/shifted/unreviewed diagnostics** | prompt-mode-design.md | The prompt-mode infra is shipped for coverage gaps; extending it to remaining diagnostic types is additive code, no new architecture. Greatly improves agent UX for the most common workflow. | -| 1.2 | **Doc-comment detection for remaining languages** | init-discover-impl.md (Phase 2 gap) | `_has_doc` hint works for 10/21 languages. Adding the remaining 11 (Ruby, Kotlin, Swift, Bash, Zig, …) is mechanical tree-sitter query work. Improves `liyi init` quality across ecosystems. | +| 1.2 | ~~**Doc-comment detection for remaining languages**~~ | init-discover-impl.md (Phase 2 gap) | ✅ Done — 15/21 languages now have `doc_comment_detector`. Remaining 5 (Bash, Ruby not feasible; JSON/TOML/YAML not applicable). | > **Note on the 14 unreferenced requirements:** `liyi check` currently reports > 7 requirements from lsp-design.md and 7 from sidecar-merge-design.md with no @@ -116,7 +116,6 @@ Not designed in detail; captured for completeness. ``` Now Tier 1.1 (prompt-mode expansion) - Tier 1.2 (doc-comment languages) │ Near-term Tier 2A (approval flows) ─── can parallelize ─── Tier 2C (VCS hints) Tier 2B (lib refactor)