Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ jobs:
}

- name: Verify formatting
run: dotnet format CodeIndex.sln --verify-no-changes --no-restore --verbosity minimal
run: dotnet format whitespace CodeIndex.sln --verify-no-changes --no-restore --verbosity minimal

- name: Verify developer task wrapper
if: matrix.os == 'ubuntu-latest' && matrix.test-framework == 'net8.0'
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
-->
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsNotAsErrors>$(WarningsNotAsErrors);IL2026;IL2067;IL2072;IL2075</WarningsNotAsErrors>
<WarningsNotAsErrors>$(WarningsNotAsErrors);IL2026;IL2067;IL2072;IL2075;IL3050</WarningsNotAsErrors>
<ILLinkTreatWarningsAsErrors>false</ILLinkTreatWarningsAsErrors>
</PropertyGroup>

Expand Down
4 changes: 4 additions & 0 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -1872,6 +1872,8 @@ The MCP `tools/list` response includes an `examples` array for every registered
| `backfill_fold` | Upgrade folded-name keys in an existing DB without reparsing source files |
| `suggest_improvement` | Submit structured improvement suggestions or error reports |

`suggest_improvement` always stores accepted suggestions locally. Its response includes `submitted_to_github` and `github_submission_reason` so clients can distinguish `submitted`, `token_not_configured`, `repo_not_configured`, `network_error`, and `api_error`; failed GitHub attempts also include `github_submission_error`.

For `callers`, `impact_analysis`, and `deps`, the [`reference_kind` filtering matrix](DEVELOPER_GUIDE.md#reference-kind-filtering-matrix) explains which edge kinds each command walks and how to reconcile count differences with `references <Name> --kind attribute` or `--kind annotation`.

No CLAUDE.md hacks or SQL templates needed — the AI interacts with cdidx natively.
Expand Down Expand Up @@ -3928,6 +3930,8 @@ OpenAI Codex CLI (`codex.json` または `~/.codex/config.json`):
| `backfill_fold` | 既存 DB の folded-name key をソース再解析なしで更新 |
| `suggest_improvement` | 構造化された改善提案またはエラー報告を送信 |

`suggest_improvement` は受理した提案を常にローカル保存します。応答には `submitted_to_github` と `github_submission_reason` が含まれ、クライアントは `submitted`、`token_not_configured`、`repo_not_configured`、`network_error`、`api_error` を区別できます。GitHub 送信に失敗した場合は `github_submission_error` も含まれます。

`callers`、`impact_analysis`、`deps` については、[`reference_kind` フィルタの対応表](DEVELOPER_GUIDE.md#reference-kind-filtering-matrix)で各コマンドが辿る edge kind と、`references <Name> --kind attribute` または `--kind annotation` による件数差の照合方法を確認できます。

CLAUDE.mdの設定やSQLテンプレートは不要 — AIがcdidxとネイティブに連携します。
Expand Down
13 changes: 13 additions & 0 deletions changelog.d/unreleased/1460.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
category: fixed
issues:
- 1460
---

## English

- Added `github_submission_reason` to MCP `suggest_improvement` responses so clients can tell why a local suggestion was not forwarded to GitHub.

## 日本語

- MCP `suggest_improvement` の応答に `github_submission_reason` を追加し、ローカル保存された提案が GitHub に転送されなかった理由をクライアントが判別できるようにしました。
13 changes: 13 additions & 0 deletions changelog.d/unreleased/1640.changed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
category: changed
issues:
- 1640
---

## English

- Shortened the MCP `search` tool description advertised during `tools/list`, moving detailed tokenizer and ranking guidance to `USER_GUIDE.md`.

## 日本語

- `tools/list` で公開される MCP `search` ツール説明を短縮し、tokenizer や ranking の詳細案内は `USER_GUIDE.md` に寄せました。
13 changes: 13 additions & 0 deletions changelog.d/unreleased/2752.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
category: fixed
issues:
- 2752
---

## English

- Fixed the MCP `index` tool so the advertised `maxFileBytes` argument is accepted instead of rejected as unknown.

## 日本語

- MCP `index` ツールで、公開済みの `maxFileBytes` 引数が unknown argument として拒否されないよう修正しました。
17 changes: 17 additions & 0 deletions changelog.d/unreleased/2786.internal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
category: internal
issues:
- 2786
affected:
- Directory.Build.props
- .github/workflows/dotnet.yml
- dev.sh
---

## English

- **Native AOT analyzer diagnostics no longer fail regular CI builds (#2786)** — current IL3050 diagnostics remain visible as warnings while format verification focuses on whitespace and follow-up AOT compatibility work is tracked separately.

## 日本語

- **Native AOT analyzer diagnostics で通常 CI build が失敗しなくなりました (#2786)** — 現在の IL3050 diagnostics は warning として表示しつつ、format verification は whitespace に絞り、AOT compatibility 対応は別途追跡します。
4 changes: 2 additions & 2 deletions dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ case "$task" in
--blame-hang-timeout 5m
;;
lint)
dotnet format CodeIndex.sln --verify-no-changes --verbosity minimal
dotnet format whitespace CodeIndex.sln --verify-no-changes --verbosity minimal
;;
format)
dotnet format CodeIndex.sln --verbosity minimal
dotnet format whitespace CodeIndex.sln --verbosity minimal
;;
coverage)
dotnet test tests/CodeIndex.Tests/CodeIndex.Tests.csproj \
Expand Down
4 changes: 4 additions & 0 deletions src/CodeIndex/Cli/SuggestionStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ public record AddAndSubmitResult(
bool AlreadySubmitted,
SuggestionStatus Status,
string? UpstreamUrl,
string? SubmissionError = null,
string? DuplicateOfHash = null,
double? DuplicateScore = null);

Expand Down Expand Up @@ -275,6 +276,7 @@ record = RedactRecordForPersistence(record);
reservation.AlreadySubmitted,
reservation.Status,
reservation.UpstreamUrl,
null,
reservation.DuplicateOfHash,
reservation.DuplicateScore);
}
Expand Down Expand Up @@ -302,6 +304,7 @@ record = RedactRecordForPersistence(record);
reservation.AlreadySubmitted,
reservation.Status,
reservation.UpstreamUrl,
null,
reservation.DuplicateOfHash,
reservation.DuplicateScore);
}
Expand All @@ -317,6 +320,7 @@ record = RedactRecordForPersistence(record);
reservation.AlreadySubmitted,
found.Status,
issueUrl ?? found.UpstreamUrl,
submitResult.Error,
reservation.DuplicateOfHash,
reservation.DuplicateScore);
});
Expand Down
4 changes: 3 additions & 1 deletion src/CodeIndex/Mcp/McpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = false,
TypeInfoResolver = new DefaultJsonTypeInfoResolver(),

Check warning on line 259 in src/CodeIndex/Mcp/McpServer.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Using member 'System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.DefaultJsonTypeInfoResolver()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.

Check warning on line 259 in src/CodeIndex/Mcp/McpServer.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Using member 'System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.DefaultJsonTypeInfoResolver()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.

Check warning on line 259 in src/CodeIndex/Mcp/McpServer.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest, net8.0)

Using member 'System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.DefaultJsonTypeInfoResolver()' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. JSON serialization and deserialization might require types that cannot be statically analyzed. Use the overload that takes a JsonTypeInfo or JsonSerializerContext, or make sure all of the required types are preserved.

Check warning on line 259 in src/CodeIndex/Mcp/McpServer.cs

View workflow job for this annotation

GitHub Actions / build (macos-latest, net8.0)

Using member 'System.Text.Json.Serialization.Metadata.DefaultJsonTypeInfoResolver.DefaultJsonTypeInfoResolver()' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. JSON serialization and deserialization might require types that cannot be statically analyzed and might need runtime code generation. Use System.Text.Json source generation for native AOT applications.
};
_serializeResponse = serializeResponse ?? (node => node.ToJsonString(_jsonOptions));
_authenticator = authenticator ?? LocalStdioAuthenticator.Instance;
Expand Down Expand Up @@ -3187,7 +3187,9 @@
=> $"Language support: Supports graph/reference extraction for: {GraphLanguageList()}. Unsupported `lang` values are reported with graph-support metadata when the tool returns graph-support fields; use `search`, `definition`, `excerpt`, or `files` for non-graph languages.",
"definition" or "symbols" or "outline" or "analyze_symbol"
=> $"Language support: Supports symbol extraction for: {SymbolLanguageList()}. Search-only languages can still be indexed and filtered by file tools but may have no symbol rows.",
"search" or "find_in_file" or "files" or "map"
"search"
=> "Language support: Supports indexed file/content filters for every detected language; call `languages` for the full catalog.",
"find_in_file" or "files" or "map"
=> $"Language support: Supports indexed file/content filters for every detected language listed by `languages`: {DetectedLanguageList()}. Symbol and graph fields are available only for the languages whose capabilities are advertised by `languages`.",
"excerpt" or "status" or "validate"
=> $"Language support: Language-agnostic over indexed files and diagnostics for every detected language listed by `languages`: {DetectedLanguageList()}. This tool does not interpret a `lang` filter.",
Expand Down
5 changes: 3 additions & 2 deletions src/CodeIndex/Mcp/McpToolDefinitions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ private JsonNode HandleToolsList(JsonNode? id)
{
CreateToolDefinition(
"search",
"Full-text search across indexed code chunks using FTS5. Returns compact match-centered snippets with line metadata. Non-empty responses include `next_step_suggestion` for the obvious follow-up read, and empty responses include `recovery_hint`. The literal-safe path quotes each whitespace-separated token as an FTS5 phrase and combines multiple tokens with implicit AND semantics (`foo bar` requires both terms). For CJK that means `search 計算` no longer also matches `計算する`/`計算機`, because unicode61 keeps adjacent CJK codepoints in one token. Two opt-ins enable FTS5 prefix expansion: (1) trailing `*` on a single token in the `query` string (`search 計算*` to match `計算する`); (2) the `prefix` flag, which promotes every token in the query to a prefix phrase. Use `exactSubstring` for case-sensitive exact-substring matching that bypasses FTS5 entirely; `exact` is the backward-compatible alias documented in USER_GUIDE.md's flag compatibility table. Non-CJK tokens follow the same rule — ASCII identifiers also no longer auto-prefix, so use `--prefix` or trailing `*` to widen. Emoji-mixed tokens cannot be distinguished from their plain ASCII counterpart at the FTS layer (unicode61 drops the emoji on both index and query side — `foo🎉` is FTS-equivalent to `foo`), and pure emoji substring search is 0-result for the same reason; use `exactSubstring` when emoji identity matters. Examples: `search {\"query\":\"handleRequest\",\"lang\":\"csharp\"}`; `search {\"query\":\"Authenticate\",\"lang\":\"csharp\",\"path\":\"src/Auth\",\"prefix\":true}`. / FTS5を使ったコードチャンクの全文検索。一致中心の軽量スニペットと行メタデータを返す。非空レスポンスには自然な次の読み取りを示す `next_step_suggestion`、空レスポンスには `recovery_hint` を含める。literal-safe 経路は空白区切りの各トークンを FTS5 phrase として引用し、複数 token は implicit AND として結合する(`foo bar` は両方の term を要求する)。CJK の場合、unicode61 は隣接 CJK コードポイントを一語として扱うため、`search 計算` は `計算する`/`計算機` にはマッチしない。FTS5 prefix への昇格は 2 通りでオプトイン: (1) `query` 文字列内のトークン末尾に `*` を付ける(`search 計算*` で `計算する` にマッチ)。(2) `prefix` フラグで、クエリの全トークンを prefix phrase に昇格させる。`exactSubstring` を使うと FTS5 を経由せず大小文字区別の厳密部分文字列マッチになり、`exact` は USER_GUIDE.md の flag compatibility table に記載された後方互換 alias。CJK 以外(ASCII 識別子等)も同じルールで、自動 prefix は行わないため、広げたい場合は `--prefix` か末尾 `*` を使う。絵文字混在トークンは、unicode61 が indexing とクエリの両側で絵文字を削ぐため FTS 層で素の ASCII トークンと区別できず(`foo🎉` は FTS 上 `foo` と等価)、絵文字単独の部分一致も同じ理由で 0 件になる。絵文字の同一性が必要な場合は `exactSubstring` を使う。例: `search {\"query\":\"handleRequest\",\"lang\":\"csharp\"}`; `search {\"query\":\"Authenticate\",\"lang\":\"csharp\",\"path\":\"src/Auth\",\"prefix\":true}`。",
"Full-text search across indexed code chunks. Returns match-centered snippets with line metadata plus `next_step_suggestion` or `recovery_hint`. Use `prefix` or trailing `*` to widen token matching, `rawQuery` for FTS5 syntax, and `exactSubstring` for case-sensitive text identity. Details and examples: USER_GUIDE.md#search. / インデックス済みコードチャンクの全文検索。`prefix` / 末尾 `*` / `rawQuery` / `exactSubstring` の詳細と例は USER_GUIDE.md#search を参照。",
new JsonObject
{
["type"] = "object",
Expand Down Expand Up @@ -486,10 +486,11 @@ private JsonNode HandleToolsList(JsonNode? id)
+ "Call this when you notice a gap (e.g. missing language support, poor ranking) or encounter an unexpected error. "
+ "Never include source code — describe the gap in natural language only. "
+ "The tool writes to the resolved .cdidx directory, which must be writable; responses include cdidx_dir for diagnostics. "
+ "Responses also include github_submission_reason: submitted, token_not_configured, repo_not_configured, network_error, or api_error. "
+ "/ cdidxへの構造化された改善提案またはエラー報告を送信する。"
+ "ギャップ(言語サポート不足、ランキング不良等)に気づいたとき、または予期せぬエラーに遭遇したときに呼び出す。"
+ "ソースコードを含めないこと — 自然言語でのみギャップを記述する。"
+ "解決された .cdidx ディレクトリへ書き込むため、そのディレクトリは書き込み可能である必要がある。応答には診断用の cdidx_dir が含まれる。",
+ "解決された .cdidx ディレクトリへ書き込むため、そのディレクトリは書き込み可能である必要がある。応答には診断用の cdidx_dir と github_submission_reason が含まれる。",
new JsonObject
{
["type"] = "object",
Expand Down
31 changes: 29 additions & 2 deletions src/CodeIndex/Mcp/McpToolHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ private static string DescribeJsonType(JsonNode? node)
"validate" => new HashSet<string>(StringComparer.Ordinal) { "path", "lang", "limit", "excludePaths", "excludeTests", "project", "solution" },
"unused_symbols" => new HashSet<string>(StringComparer.Ordinal) { "kind", "lang", "limit", "path", "excludePaths", "excludeTests", "project", "solution" },
"symbol_hotspots" => new HashSet<string>(StringComparer.Ordinal) { "kind", "lang", "limit", "groupBy", "path", "excludePaths", "excludeTests", "project", "solution" },
"index" => new HashSet<string>(StringComparer.Ordinal) { "path", "db", "rebuild", "parallelism", "files", "commits", "changedBetween", "dryRun", "optimize" },
"index" => new HashSet<string>(StringComparer.Ordinal) { "path", "db", "rebuild", "parallelism", "maxFileBytes", "files", "commits", "changedBetween", "dryRun", "optimize" },
"backfill_fold" => new HashSet<string>(StringComparer.Ordinal) { "dry_run", "dryRun", "force" },
"suggest_improvement" => new HashSet<string>(StringComparer.Ordinal) { "category", "language", "description", "context", "toolInvocationContext" },
_ => new HashSet<string>(StringComparer.Ordinal),
Expand Down Expand Up @@ -3993,7 +3993,8 @@ private async Task<JsonNode> ExecuteSuggestImprovementAsync(JsonNode? id, JsonNo
// Build GitHub submission callback (null if no token configured).
// GitHub 送信コールバックを構築(トークン未設定なら null)。
Func<SuggestionRecord, Task<SuggestionStore.SubmitAttemptResult>>? githubCallback = null;
if (GitHubIssueReporter.ResolveToken() != null)
var githubTokenConfigured = GitHubIssueReporter.ResolveToken() != null;
if (githubTokenConfigured)
{
var version = _version;
var cancellationToken = _currentRequestToken.Value;
Expand All @@ -4014,9 +4015,12 @@ private async Task<JsonNode> ExecuteSuggestImprovementAsync(JsonNode? id, JsonNo
? "This suggestion was already recorded. GitHub submission retried successfully."
: "This suggestion has already been recorded.",
["submitted_to_github"] = result.AlreadySubmitted || result.UpstreamUrl != null,
["github_submission_reason"] = ResolveGitHubSubmissionReason(result, githubTokenConfigured),
["lifecycle_status"] = JsonNamingPolicy.SnakeCaseLower.ConvertName(result.Status.ToString()),
["cdidx_dir"] = cdidxDir,
};
if (result.SubmissionError != null)
dupPayload["github_submission_error"] = result.SubmissionError;
if (result.DuplicateOfHash != null)
dupPayload["duplicate_of"] = result.DuplicateOfHash;
if (result.DuplicateScore != null)
Expand All @@ -4038,9 +4042,12 @@ private async Task<JsonNode> ExecuteSuggestImprovementAsync(JsonNode? id, JsonNo
["language"] = language,
["stored_locally"] = true,
["submitted_to_github"] = result.UpstreamUrl != null,
["github_submission_reason"] = ResolveGitHubSubmissionReason(result, githubTokenConfigured),
["lifecycle_status"] = JsonNamingPolicy.SnakeCaseLower.ConvertName(result.Status.ToString()),
["cdidx_dir"] = cdidxDir,
};
if (result.SubmissionError != null)
payload["github_submission_error"] = result.SubmissionError;
if (result.UpstreamUrl != null)
{
payload["upstream_url"] = result.UpstreamUrl;
Expand All @@ -4053,6 +4060,26 @@ private async Task<JsonNode> ExecuteSuggestImprovementAsync(JsonNode? id, JsonNo
return CreateToolResult(id, "Suggestion recorded. Thank you for the feedback.", payload);
}

private static string ResolveGitHubSubmissionReason(SuggestionStore.AddAndSubmitResult result, bool githubTokenConfigured)
{
if (result.AlreadySubmitted || result.UpstreamUrl != null)
return "submitted";
if (!githubTokenConfigured)
return "token_not_configured";
if (result.SubmissionError != null)
return StartsWithHttpStatusCode(result.SubmissionError) ? "api_error" : "network_error";
return "repo_not_configured";
}

private static bool StartsWithHttpStatusCode(string value)
{
return value.Length >= 4
&& char.IsDigit(value[0])
&& char.IsDigit(value[1])
&& char.IsDigit(value[2])
&& value[3] == ':';
}

private sealed record SuggestionSamplingResult(string? Title, string[]? Tags);

private async Task<SuggestionSamplingResult?> TrySampleSuggestionMetadataAsync(
Expand Down
Loading
Loading