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
10 changes: 10 additions & 0 deletions DEVELOPER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -2173,6 +2173,7 @@ The `suggest_improvement` MCP tool allows AI agents to report gaps or errors.
| [`src/CodeIndex/Mcp/McpToolHandlers.cs`](src/CodeIndex/Mcp/McpToolHandlers.cs) | `ExecuteSuggestImprovement` handler |
| [`src/CodeIndex/Mcp/McpToolDefinitions.cs`](src/CodeIndex/Mcp/McpToolDefinitions.cs) | Tool schema definition |
| [`src/CodeIndex/Cli/SuggestionsCommandRunner.cs`](src/CodeIndex/Cli/SuggestionsCommandRunner.cs) | Local suggestion listing, audited lifecycle transitions, bounded atomic export, issue-draft generation, and open-issue duplicate preflight |
| [`src/CodeIndex/Cli/SuggestionsCommandRunner.Query.cs`](src/CodeIndex/Cli/SuggestionsCommandRunner.Query.cs) | Redacted full-text history matching plus count, summary, compact, and byte-bounded JSON projections |

### What is sent (when GitHub token is configured)

Expand Down Expand Up @@ -2205,6 +2206,10 @@ Local suggestion records use the `status` lifecycle field instead of a binary su

`SuggestionStore.TryTransitionStatus` is the atomic manual-transition boundary used by `suggestions update <id> --status <state>`. `submitted_pending_triage` is automatic-only. `open_in_upstream` and `resolved_in_upstream` require existing upstream evidence; `draft` requires the absence of upstream evidence; and `wont_fix`, `duplicate`, or `superseded` are local maintainer dispositions. Local dispositions suppress automatic duplicate resubmission without setting `AlreadySubmitted` or an upstream-submission response flag. Same-state transitions and transitions during an active submission reservation fail closed. The store rechecks the expected revision under its file lock, stamps the latest `previous_status`, UTC `status_changed_at`, bounded/redacted `status_changed_by`, and optional bounded/redacted `status_change_reason`, updates `resolved_at` for `resolved_in_upstream`, and recomputes `revision_hash`. Full audit values are redacted before a surrogate-safe final cap so a credential crossing the cap boundary cannot evade redaction. Content edits and lifecycle transitions are separate CLI operations so one audit event has one unambiguous meaning.

`suggestions list|export --query <text>` matches the NFKC-normalized query as an ordinal, case-insensitive substring against the redacted stable ID, sampled title, description, context, evidence paths, category, and language. Applying `SuggestionStore.RedactSensitiveText` before matching is a confidentiality contract: a caller cannot use zero-result/count differences to probe a value removed by redaction. Status, time, category, language, and agent filters run first; the text query follows; records are then ordered by descending `CreatedAt` and ordinal stable ID before offset/limit pagination.

The structured history projections share one JSON envelope. `--count` and `--summary-only` summarize the complete filtered set rather than the requested page; they report zero pagination omissions and classify non-emitted records as projection omissions. Summary dimensions have fixed distinct-value caps (status 16, category 32, language 20) and expose their own omitted/truncated metadata. `--compact` emits only redacted bounded list fields. `--max-json-bytes` measures the serialized UTF-8 document plus its final platform newline, uses a logarithmic fitting-prefix search, and removes complete trailing result rows until the envelope fits. `total_count` remains authoritative, while `byte_limit_omitted_count`, `next_offset`, and recovery guidance describe byte truncation. Row-producing compact and byte-bounded modes reject `--limit 0` so every advertised continuation can progress. If the metadata-only envelope cannot fit, the runner writes no stdout JSON. These projections are local read-only operations and do not change the streaming store's retention or mutation contracts.

`suggestions export --format markdown|issue-drafts --output <path>` renders the bounded payload in memory, rejects payloads over 16 MiB before writing, and refuses the selected database or suggestion-store path. For existing files it compares filesystem identities as well as normalized path spelling, so symlinked parents, mount aliases, and hard links cannot bypass source protection. Existing destinations are rejected unless `--overwrite` is explicit. Publication uses a sibling temporary file, flushes its contents, and performs a same-filesystem no-overwrite move or atomic replacement; failed publication cleans the temporary file. The writer emits UTF-8 without a BOM, creates missing parent directories, and keeps JSON-format suggestion exports on stdout. Tests cover the store transition/revision contract, CLI validation and filtering, source-target alias rejection, no-overwrite race safety, replacement, and temporary-file cleanup.

### GitHub retry idempotency
Expand Down Expand Up @@ -5872,6 +5877,7 @@ Unlist しても exact version restore は不可能になりません。これ
| [`src/CodeIndex/Mcp/McpToolHandlers.cs`](src/CodeIndex/Mcp/McpToolHandlers.cs) | `ExecuteSuggestImprovement` ハンドラ |
| [`src/CodeIndex/Mcp/McpToolDefinitions.cs`](src/CodeIndex/Mcp/McpToolDefinitions.cs) | ツールスキーマ定義 |
| [`src/CodeIndex/Cli/SuggestionsCommandRunner.cs`](src/CodeIndex/Cli/SuggestionsCommandRunner.cs) | ローカル提案の一覧、監査付き lifecycle 遷移、上限付き原子的 export、issue draft 生成、open issue duplicate preflight |
| [`src/CodeIndex/Cli/SuggestionsCommandRunner.Query.cs`](src/CodeIndex/Cli/SuggestionsCommandRunner.Query.cs) | redaction 済みの履歴全文検索、および count、summary、compact、byte 上限付き JSON projection |

### 送信されるデータ(GitHubトークン設定時)

Expand Down Expand Up @@ -5904,6 +5910,10 @@ suggestion sidecar は `DataDirectorySecurity.ResolveSensitiveSidecarDirectoryFo

`SuggestionStore.TryTransitionStatus` は `suggestions update <id> --status <state>` が使う原子的な手動遷移境界です。`submitted_pending_triage` は自動設定専用です。`open_in_upstream` と `resolved_in_upstream` には既存の upstream 根拠が必要で、`draft` には upstream 根拠がないことが必要です。`wont_fix`、`duplicate`、`superseded` はメンテナーによるローカルの判断です。ローカルの判断は重複提案の自動再送を抑止しますが、`AlreadySubmitted` や upstream 送信済み response flag は設定しません。同じ状態への遷移、および送信 reservation が active な間の遷移は fail closed になります。store は file lock 内で expected revision を再確認し、最新の `previous_status`、UTC の `status_changed_at`、上限・redaction 付きの `status_changed_by`、任意の上限・redaction 付き `status_change_reason` を stamp し、`resolved_in_upstream` では `resolved_at` を更新して、`revision_hash` を再計算します。監査値全体を redaction してから surrogate-safe な最終上限を適用するため、上限境界をまたぐ credential も redaction を回避できません。1件の監査 event の意味を曖昧にしないため、content 編集と lifecycle 遷移は別々の CLI 操作です。

`suggestions list|export --query <text>` は、NFKC 正規化した query を、redaction 済みの stable ID、sampled title、description、context、evidence path、category、language に対して ordinal・大文字小文字を区別しない部分一致で照合します。照合前に `SuggestionStore.RedactSensitiveText` を適用することは confidentiality contract です。caller は 0 件結果や count の差を使って redaction により除去された値を探索できません。status、時刻、category、language、agent の filter を最初に適用し、次に text query、続いて `CreatedAt` 降順と ordinal stable ID の順で並べてから offset/limit pagination を行います。

履歴の structured projection は共通 JSON envelope を使います。`--count` と `--summary-only` は要求された page ではなく filter 後の全集合を要約し、pagination omission を 0、出力しない record を projection omission として報告します。summary dimension は distinct 値に固定上限(status 16、category 32、language 20)を持ち、それぞれ omitted/truncated metadata を公開します。`--compact` は redaction・上限付きの list field だけを出力します。`--max-json-bytes` は serialized UTF-8 document と末尾の platform newline を計測し、対数回の fitting-prefix search を使って envelope が収まるまで末尾の完全な result row だけを取り除きます。`total_count` は authoritative なまま、`byte_limit_omitted_count`、`next_offset`、recovery guidance が byte truncation を表します。row を返す compact / byte 上限付き mode は `--limit 0` を拒否し、公開する continuation が必ず進捗できるようにします。metadata-only envelope が収まらない場合、runner は stdout JSON を一切書きません。これらの projection は local read-only 操作で、streaming store の retention や mutation contract は変更しません。

`suggestions export --format markdown|issue-drafts --output <path>` は上限付き payload をメモリ上で描画し、書き込み前に 16 MiB 超過を拒否し、選択中の database または suggestion-store path も拒否します。既存ファイルでは正規化した path 表記に加えて filesystem identity も比較するため、symlink 付き親 directory、mount alias、hard link で source 保護を迂回できません。既存の出力先は `--overwrite` を明示しない限り拒否します。公開処理は兄弟一時ファイルを使い、内容を flush してから同一 filesystem 上で no-overwrite move または原子的置換を行い、失敗時は一時ファイルを片付けます。writer は BOM なし UTF-8 を出力し、不足している親 directory を作成し、JSON 形式の suggestion export は stdout のままです。test は store の遷移・revision 契約、CLI validation と filtering、source target alias 拒否、no-overwrite の race safety、置換、一時ファイル cleanup を網羅します。

### GitHub 再試行の冪等性
Expand Down
2 changes: 2 additions & 0 deletions TESTING_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ Use `docs/test-doc-maintenance-plan.md` before moving oversized suites or adding
Local suggestion JSON storage: opaque/stable-ID allocation and legacy migration, all-editable-field revision conflicts, dedup hashing, submission-finalization races, persistence, corruption recovery, atomic writes. Keep suggestion-redaction cases table-driven with negative fixtures for structured PascalCase, snake_case, leading-underscore, and recipe identifiers plus positive fixtures for opaque mixed-character and known token formats; the persistence case should retain an identifier and redact a secret from the same context.
- `DataDirectorySecurityTests.cs`, `ProgramCliTests.cs` suggestion-sidecar coverage
Shared-temp database routing, owner-only directory/file modes, colocated private-directory behavior, and structured CLI filesystem failures.
Suggestion-history query coverage keeps NFKC/case-insensitive matching across every documented field, structured filters before deterministic pagination, aggregate omission reasons, compact redaction, progressing continuations, and whole-document UTF-8 byte budgets in the same production-runtime fixture.
- `SourceCodeDetectorTests.cs`
Source code leak prevention: allowed natural-language inputs vs rejected code blocks (fenced, indented, import runs, etc.).
- `ConsoleUiTests.cs`
Expand Down Expand Up @@ -1653,6 +1654,7 @@ dotnet test --filter "FullyQualifiedName~GitHelperTests"
ローカル提案JSON蓄積: 不透明で安定した ID の割り当てと legacy migration、全編集対象 field の revision conflict、ハッシュ重複排除、submission finalization race、永続化、破損復旧、アトミック書き込み。提案 redaction のケースは table-driven に保ち、構造化された PascalCase、snake_case、先頭 underscore 付き、recipe 形式の識別子を negative fixture、不透明な混合文字列と既知の token 形式を positive fixture として含めてください。永続化ケースでは、同じ context 内の識別子を保持しつつ secret を伏字化することを確認します。
- `DataDirectorySecurityTests.cs`、`ProgramCliTests.cs` の suggestion-sidecar coverage
shared-temp database routing、owner-only の directory / file mode、private directory での隣接配置、structured CLI filesystem failure。
suggestion-history query coverage は、全 documented field の NFKC / case-insensitive 照合、決定的 pagination より先の structured filter、aggregate omission reason、compact redaction、進捗可能な continuation、document 全体の UTF-8 byte budget を同じ production-runtime fixture で維持します。
- `SourceCodeDetectorTests.cs`
ソースコード漏洩防止: 許容される自然言語入力 vs 拒否されるコードブロック(フェンス、インデント、import連打等)。
- `ConsoleUiTests.cs`
Expand Down
Loading
Loading