Skip to content

schema: close the post-split audit gaps - #403

Merged
t0k0sh1 merged 3 commits into
mainfrom
402-schema-audit-followups
Aug 4, 2026
Merged

schema: close the post-split audit gaps#403
t0k0sh1 merged 3 commits into
mainfrom
402-schema-audit-followups

Conversation

@t0k0sh1

@t0k0sh1 t0k0sh1 commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Summary

A full audit of the unreleased v0.6.0..HEAD range (the #218/ADR 0009 schema split) found no logic bugs, but five gaps between what shipped and what the ADR/docs promise. This PR closes all of them:

  • unreachable_from joins ADR 0009 §6.3's traversal exclusion. New additive Context::unreachable_from_excluding (same monomorphized-visible-closure pattern as explore_excluding, so the unfiltered path pays nothing); the handler resolves hidden_label before read_context per the documented deadlock rule. Hidden edges are "never a bridge, never reported" — a shared type name can no longer make genuine orphans look covered. Regression test pins the before/after flip in tests/http_api/schema_type_label.rs.
  • Core SDKs stop discarding §8.3's warn-mode carrier (breaking, pre-1.0): add_associations/addAssociations returns AddAssociationsResult {applied, issues, schema_violations}; BatchApplyResult aggregates per chunk; ImportResult gains schemas/issues/schema_violations. Wired through new _request_json_full/_post_full (Python) and requestJsonFull/postFull (TS) beside the existing result-only helpers. Migration: .applied; callers ignoring the return value are unaffected.
  • SDK schema surface parity with HTTP/MCP: put_schema/audit_schema/validate_schema in both SDKs, decoding the shared SchemaAudit shape; recorded in sdk/spec/surface.yaml (both surface checks pass).
  • Live protocol manual (GET /protocol/MCP instructions) catches up: the four schema routes plus the pre-existing /drift/audit gap, schema_mode on GET /contexts' row shape, no_schema in the error-code vocabulary.
  • Doc drift: two TAGURU_MCP_* knobs in README, four missing KNOWN_KEYS in getting-started's env table (all 60 keys now cross-checked), stale PROMPT_VERSION 2 comment fixed in python-langchain.

Closes #402

Test plan

  • cargo fmt --check / cargo clippy --all-targets (zero warnings)
  • cargo test — full suite green, including the new coverage-audit regression test (http_api 453)
  • Python SDK: ruff format --check / ruff check / mypy --strict src / pytest 198 passed (integration spawns the real server binary) / check_surface.py
  • TypeScript SDK: tsc --noEmit / eslint / vitest 186 passed (integration included) / check-surface.ts / tsup build
  • Codex review over the working tree: no actionable findings

https://claude.ai/code/session_01HqB7fXgCKSnDxT58PenLaS

Summary by CodeRabbit

  • 新機能
    • スキーマの登録・監査・検証に対応しました。
    • Python/TypeScript SDKでスキーマ操作APIを利用できます。
    • スキーマ違反や警告、インポート結果を詳細に確認できるようになりました。
  • 改善
    • 関連付け・バッチ処理の結果に適用件数、問題、違反数を含めるよう変更しました。
    • スキーマモードや未設定状態を確認できるようになりました。
  • バグ修正
    • 到達性監査で、対象外の型情報が判定へ影響しないよう改善しました。
  • ドキュメント
    • 環境変数、API、スキーマ監査の説明を更新しました。

- unreachable_from joins ADR 0009 §6.3's traversal exclusion via the
  new Context::unreachable_from_excluding (explore_excluding's
  monomorphized-closure pattern): once a schema exists, schema:type
  edges are never a bridge in the coverage audit's walk and never
  reported as orphans, so a shared type name can no longer hide
  genuine orphans; regression test pins both halves of the flip.
- Both core SDKs surface §8.3's warn-mode carrier instead of stripping
  it with the envelope: add_associations returns
  AddAssociationsResult {applied, issues, schema_violations} (breaking;
  pre-1.0), BatchApplyResult aggregates per chunk, ImportResult gains
  schemas/issues/schema_violations. Plumbed through the helper stack
  (_request_json_full/_post_full, requestJsonFull/postFull) beside the
  existing result-only path, never around it.
- SDK schema surface parity with HTTP/MCP: put_schema, audit_schema,
  validate_schema in Python and TypeScript, decoding the shared
  SchemaAudit shape; recorded in sdk/spec/surface.yaml.
- Live protocol manual catches up: the four schema routes (plus the
  pre-existing /drift/audit gap), schema_mode on GET /contexts' row
  shape, and no_schema in the stable error-code vocabulary.
- Env-var docs: the two TAGURU_MCP_* knobs land in README, four
  missing KNOWN_KEYS land in getting-started's table; python-langchain's
  stale "PROMPT_VERSION 2" comment now matches its constant and its
  TypeScript twin.

Closes #402

Claude-Session: https://claude.ai/code/session_01HqB7fXgCKSnDxT58PenLaS
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3cd5bc31-a1d7-4e77-8512-f385b9eea29f

📥 Commits

Reviewing files that changed from the base of the PR and between 0d679be and 9b647d9.

📒 Files selected for processing (2)
  • sdk/python/tests/unit/test_pagination_and_batching.py
  • sdk/typescript/tests/unit/transport.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • sdk/python/tests/unit/test_pagination_and_batching.py
  • sdk/typescript/tests/unit/transport.test.ts

📝 Walkthrough

Walkthrough

スキーマ登録・監査・検証APIをPython/TypeScript SDKへ追加しました。警告情報とスキーマ違反数をSDK結果へ引き継ぎます。schema:typeを到達性監査から除外し、プロトコルと設定文書を更新しました。

Changes

スキーマ監査と到達性制御、プロトコル記載

Layer / File(s) Summary
スキーマ契約と到達性監査
docs/schema.html, src/llm-protocol.md, src/api/coverage.rs, src/context/traverse.rs, sdk/spec/surface.yaml, tests/http_api/schema_type_label.rs
スキーマAPI、schema_modeno_schemaを文書化しました。schema:typeエッジをunreachable_fromの探索と孤立判定から除外しました。

SDKモデルと応答エンベロープ

Layer / File(s) Summary
型付き結果と警告情報
sdk/python/src/taguru/_models.py, sdk/python/src/taguru/_shared.py, sdk/python/src/taguru/__init__.py, sdk/typescript/src/models.ts, sdk/typescript/src/transport.ts, sdk/typescript/src/index.ts
監査結果、違反、インポート結果、関連追加結果の型を追加しました。完全なレスポンスエンベロープからissuesschema_violationsを復元します。

SDKスキーマ操作と関連追加結果

Layer / File(s) Summary
スキーマAPIと関連追加
sdk/python/src/taguru/_async/client.py, sdk/python/src/taguru/_sync/client.py, sdk/typescript/src/client.ts
スキーマ登録、監査、検証を追加しました。add_associationsは構造化結果を返し、バッチ処理は警告情報を集約します。

SDKのテスト検証

Layer / File(s) Summary
APIリクエスト、復号、警告情報集約の検証
sdk/python/tests/unit/test_get_schema.py, sdk/python/tests/unit/test_pagination_and_batching.py, sdk/python/tests/integration/test_full_loop.py, sdk/python/tests/unit/test_retry.py, sdk/typescript/tests/unit/get-schema.test.ts, sdk/typescript/tests/unit/transport.test.ts, sdk/typescript/tests/integration/client.test.ts, sdk/typescript/tests/unit/retry.test.ts
テストはAPIリクエスト、レスポンス復号、リトライ、チャンク集約を検証します。

文書と設定情報

Layer / File(s) Summary
設定・プロトコル・変更履歴の記載
README.md, docs/getting-started.html, CHANGELOG.md, sdk/python-langchain/src/taguru_langchain/_extract.py
MCPの同時実行数と結果サイズ上限、各環境変数、SDKの変更内容、スキーマ対応、プロンプトバージョンを記載しました。

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SDK as SDK Client
  participant Context
  participant Transport as _post_full
  participant API as HTTP API
  SDK->>Context: put_schema、audit_schema、validate_schema
  Context->>Transport: リクエスト+完全エンベロープ取得
  Transport->>API: スキーマAPIへ送信
  API-->>Transport: result + issues + schema_violations
  Transport-->>Context: 構造化結果
  Context-->>SDK: SchemaDocument / SchemaAudit
  SDK->>Context: add_associations(associations)
  Context->>Transport: 完全エンベロープで送信
  Transport->>API: 関連追加へPOST
  API-->>Transport: applied + issues + schema_violations
  Transport-->>Context: AddAssociationsResult
  Context-->>SDK: {applied, issues, schema_violations}
Loading

Possibly related PRs

  • t0k0sh1/taguru#389: スキーマAPIと監査・検証機能の基盤に直接関連します。
  • t0k0sh1/taguru#395: スキーマ違反情報を関連追加APIへ伝播する変更に直接関連します。
  • t0k0sh1/taguru#398: スキーマ監査・検証APIのSDK対応に直接関連します。
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルは、スキーマ分割後の監査上の未対応事項を解消する主変更を正確かつ簡潔に示しています。
Linked Issues check ✅ Passed 変更はIssue #402の5項目をすべて対象とし、監査除外、SDK警告情報、スキーマAPI、プロトコル文書、環境変数文書を実装しています。
Out of Scope Changes check ✅ Passed コード、SDK、テスト、プロトコル文書、環境変数文書、プロンプトコメントの変更は、Issue #402とPR目的の範囲内です
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 402-schema-audit-followups

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Nitpick comments (1)
src/api/coverage.rs (1)

257-264: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

スキーマなしの監査では非除外経路を使用してください。

Line 258 で hidden がない場合も、空の excludedunreachable_from_excluding に渡しています。これにより、全エッジ走査で HashSet::contains が実行されます。unreachable_from はこの判定を除くため、スキーマなしの大きなコンテキストでは不要な CPU コストになります。

excluded.is_empty() の場合は unreachable_from を呼び、ラベルがある場合だけ除外版を呼んでください。

修正案
                 let origins: Vec<&str> = request.origins.iter().map(String::as_str).collect();
-                context
-                    .unreachable_from_excluding(&origins, deadline, &excluded)
-                    .map_err(|_| AccessError::DeadlineExceeded)
+                let result = if excluded.is_empty() {
+                    context.unreachable_from(&origins, deadline)
+                } else {
+                    context.unreachable_from_excluding(&origins, deadline, &excluded)
+                };
+                result.map_err(|_| AccessError::DeadlineExceeded)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/coverage.rs` around lines 257 - 264, Update the loaded-context
traversal in read_context to call unreachable_from when excluded is empty, and
call unreachable_from_excluding only when hidden labels produced exclusions.
Preserve the existing origins and deadline arguments in both paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sdk/python/tests/unit/test_get_schema.py`:
- Around line 117-140: Extend sdk/python/tests/unit/test_get_schema.py lines
117-140 and sdk/typescript/tests/unit/get-schema.test.ts lines 95-117 to pass
the same non-trivial MatchCursor to audit_schema/auditSchema and
validate_schema/validateSchema, then assert each request body’s after field
exactly matches the cursor’s expected JSON wire representation while retaining
the existing limit and response assertions.

In `@sdk/python/tests/unit/test_pagination_and_batching.py`:
- Around line 162-196: Update
sdk/python/tests/unit/test_pagination_and_batching.py lines 162-196 so the
handler returns chunk-specific Issue.path values and schema_violations counts,
then assert batched issues retain chunk order and the aggregate violation total.
Add an addAssociationsBatched warn-mode test in
sdk/typescript/tests/unit/transport.test.ts lines 384-404 using two distinct
envelopes, asserting issue ordering and summed schema violations.

In `@src/llm-protocol.md`:
- Around line 397-399: Update the documentation for the async client’s
get_schema method to use NotFoundError.code and distinguish no_schema from
no_context without requiring an additional list or get request. Then regenerate
the generated synchronous client with scripts/generate_sync.py; do not edit the
_sync implementation directly.

In `@tests/http_api/schema_type_label.rs`:
- Around line 271-279: The assertion on line 278 only verifies the subject field
of the first match, leaving the label and object fields unvalidated. Expand the
assertion to also verify that after["matches"][0]["label"] equals "schema:type"
and after["matches"][0]["object"] equals "Brewery", ensuring the complete edge
structure is validated and not just a single property that happens to pass by
coincidence.

---

Nitpick comments:
In `@src/api/coverage.rs`:
- Around line 257-264: Update the loaded-context traversal in read_context to
call unreachable_from when excluded is empty, and call
unreachable_from_excluding only when hidden labels produced exclusions. Preserve
the existing origins and deadline arguments in both paths.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: dcff915e-0ea8-4b75-beda-ca6d6b779f17

📥 Commits

Reviewing files that changed from the base of the PR and between aa68ad3 and 8a89407.

📒 Files selected for processing (27)
  • CHANGELOG.md
  • README.md
  • docs/getting-started.html
  • docs/schema.html
  • sdk/python-langchain/src/taguru_langchain/_extract.py
  • sdk/python/src/taguru/__init__.py
  • sdk/python/src/taguru/_async/client.py
  • sdk/python/src/taguru/_models.py
  • sdk/python/src/taguru/_shared.py
  • sdk/python/src/taguru/_sync/client.py
  • sdk/python/tests/integration/test_full_loop.py
  • sdk/python/tests/unit/test_get_schema.py
  • sdk/python/tests/unit/test_pagination_and_batching.py
  • sdk/python/tests/unit/test_retry.py
  • sdk/spec/surface.yaml
  • sdk/typescript/src/client.ts
  • sdk/typescript/src/index.ts
  • sdk/typescript/src/models.ts
  • sdk/typescript/src/transport.ts
  • sdk/typescript/tests/integration/client.test.ts
  • sdk/typescript/tests/unit/get-schema.test.ts
  • sdk/typescript/tests/unit/retry.test.ts
  • sdk/typescript/tests/unit/transport.test.ts
  • src/api/coverage.rs
  • src/context/traverse.rs
  • src/llm-protocol.md
  • tests/http_api/schema_type_label.rs

Comment thread sdk/python/tests/unit/test_get_schema.py
Comment thread sdk/python/tests/unit/test_pagination_and_batching.py Outdated
Comment thread src/llm-protocol.md
Comment thread tests/http_api/schema_type_label.rs
- Pin the reported orphan's whole edge (label/object, not subject
  alone) in the coverage-audit exclusion test.
- Verify audit_schema/validate_schema's `after` cursor reaches the
  wire verbatim in both SDK unit suites.
- Batched warn-carrier aggregation now answers DISTINCT per-chunk
  issues/counts (order + sum visible), and the TypeScript suite gains
  the batched warn test it lacked.
- get_schema's doc now points at the no_schema/no_context error codes
  instead of claiming a second request is needed; sync regenerated.

Skipped the coverage.rs is_empty() branch nitpick: explore/activate
pass a possibly-empty exclusion list unconditionally, and diverging in
one handler would trade a per-edge empty-HashSet probe for an
inconsistency with the established pattern.

Claude-Session: https://claude.ai/code/session_01HqB7fXgCKSnDxT58PenLaS
@t0k0sh1

t0k0sh1 commented Aug 4, 2026

Copy link
Copy Markdown
Owner Author

Addressed the CodeRabbit review in 0d679be:

  • schema_type_label.rs: the orphan assertion now pins the whole edge (label == "l", object == "先"), not the subject alone.
  • Both SDK unit suites: audit_schema/validate_schema now send a non-trivial MatchCursor and the tests compare each request body's after verbatim.
  • Batched warn aggregation: the Python handler now answers distinct per-chunk issue paths and violation counts (order + sum both visible), and the TypeScript suite gains the addAssociationsBatched warn-mode test it lacked.
  • get_schema docstring: now names the no_schema/no_context error codes instead of claiming a second request is needed; edited on the _async source and _sync regenerated via scripts/generate_sync.py.

Skipped the coverage.rs is_empty() nitpick: explore/activate (src/api/explore.rs) pass a possibly-empty exclusion list to their _excluding variants unconditionally, so branching here would trade a per-edge empty-HashSet probe for an inconsistency with the established handler pattern.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@sdk/typescript/tests/unit/transport.test.ts`:
- Around line 410-426: Update the stubClient handler around issueFor and the
response body so it parses each request body, identifies whether it contains
op(0) or op(1), and derives issues and schema_violations from that input
identifier rather than chunksSeen call order. Keep the expected values tied to
the corresponding input chunk so the test detects reordered chunk transmission.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5f254785-b31d-4ce1-a5ae-9354e8570993

📥 Commits

Reviewing files that changed from the base of the PR and between 8a89407 and 0d679be.

📒 Files selected for processing (7)
  • sdk/python/src/taguru/_async/client.py
  • sdk/python/src/taguru/_sync/client.py
  • sdk/python/tests/unit/test_get_schema.py
  • sdk/python/tests/unit/test_pagination_and_batching.py
  • sdk/typescript/tests/unit/get-schema.test.ts
  • sdk/typescript/tests/unit/transport.test.ts
  • tests/http_api/schema_type_label.rs
🚧 Files skipped from review as they are similar to previous changes (6)
  • sdk/python/tests/unit/test_pagination_and_batching.py
  • tests/http_api/schema_type_label.rs
  • sdk/typescript/tests/unit/get-schema.test.ts
  • sdk/python/tests/unit/test_get_schema.py
  • sdk/python/src/taguru/_async/client.py
  • sdk/python/src/taguru/_sync/client.py

Comment thread sdk/typescript/tests/unit/transport.test.ts Outdated
The batched warn-carrier stubs now derive each response from the chunk
the request actually carried (parsed from the body's op subject), not
from handler call order — a reordered transmission, a dropped chunk,
or a double-count are all now distinguishable. Applied to the Python
twin too, which had the same call-order weakness the review caught on
the TypeScript side.

Claude-Session: https://claude.ai/code/session_01HqB7fXgCKSnDxT58PenLaS
@t0k0sh1

t0k0sh1 commented Aug 4, 2026

Copy link
Copy Markdown
Owner Author

Addressed the round-2 comment in 9b647d9: the batched warn-carrier stubs now parse each request body and derive issues/schema_violations from the op subject the chunk actually carried (s0 → 1, s1 → 2), so the expectations are tied to input-chunk identity rather than handler call order — reordered transmission, dropped chunks, and double-counts are all distinguishable now. The Python twin had the same call-order weakness, so it got the identical fix.

@t0k0sh1
t0k0sh1 merged commit 3429d7d into main Aug 4, 2026
9 checks passed
@t0k0sh1
t0k0sh1 deleted the 402-schema-audit-followups branch August 4, 2026 11:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Post-schema-split audit: coverage-audit type-hub exclusion, SDK warn-carrier visibility, schema surface parity, doc drift

1 participant