temporal validity + consolidation audit + promotion runbook (#463 #464 #465) - #468
Conversation
ADR 0011 §4's lib half: a SourceWindow (window-qualifying source names, resolved to interned ids once) and four additive reads — recall_within, query_any_within, explore_within, activate_within. An edge is visible iff at least one in-window source attests it, its weight/count re-derive from the in-window AttributionRecords alone (exact, per-source sums), and a windowed association lists only the in-window attributions, so an excluded citation cannot leak back through the edge it once fed. The existing lanes are untouched in behavior and, by construction, in codegen: explore/activate/recall/query_any now route through an EdgeLens the compiler monomorphizes per call site — the unwindowed FullLens's constant-true alive folds away, the same reasoning explore_excluding's doc records for the visible closure. Eligibility runs inside the walks, not as a post-filter: an out-of-window edge neither bridges explore nor conducts activation, and the fan total uses windowed magnitudes so excluded evidence cannot dilute a neighbor's share either (ADR 0011 §4 step 4, §5). The ghost rule composes for free — a retracted edge's empty attribution chain has no in-window sources. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
…463) S2, registry: window_source_names joins a SourceFilter against the passage store's metadata — the one place SourceMeta lives — and hands the eligible names to a read_context closure to resolve into a SourceWindow; run before read_context like hidden_label/schema_of, for the same lock reasons. Sources with no stored passage have no metadata and are absent by construction, ADR 0011 §4's rule. S3, surface: optional since/until on the four single-context graph lanes (recall/query/explore/activate) over HTTP, MCP inputSchema, and both SDKs (surface.yaml + python sync/async + typescript). The window contract is the passage lane's shared validator (source_filter, since >= until refused as invalid_argument) so the lanes cannot drift; the window enters the recall/query cache params so windowed and unwindowed calls never share an entry, with the existing [graph, passages] lane pair now load-bearing for metadata changes. The cross-context lanes declare since/until and REFUSE them — request bodies ignore unknown fields, and a silently unwindowed result is exactly the failure the no-silent-caps rule exists to prevent. e2e (tests/http_api/temporal_window.rs): as-of and since windows, windowed weight/count/citation re-derivation, the undatable associations-only source invisible to every window, walk lanes not conducting out-of-window evidence, the shared refusal, the cross refusal, and cache-key separation in both directions. SDK checks: check_surface (py+ts), pytest 174 passed, vitest 192 passed. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
README: the sources-metadata section gains the graph-lane half — the same since/until window, one context at a time, assertion-time semantics spelled out (visible iff an in-window source attests, weights/citations re-derived, until alone = as-of, no stored end time, undatable sources invisible). llm-protocol.md: the retrieval loop's expand-and-rank step teaches time-scoped questions (and that judging which dated answer still holds is the client's job, from the citations' dates); the ingest loop's register-originals step makes "declare dates" pay explicitly — date ?? stored_at is what both search surfaces filter on, and a passage-less source is invisible to every window. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
ADR 0012 §4's lib half, three additive reads over live edges: merge_evidence (Jaccard over two concepts' live neighborhoods with the shared/distinct facts listed — capped with exact totals, hidden labels excluded so a shared schema:type edge is not "structure"), contradiction_groups (one O(edges) grouped pass: every (subject, label) holding ≥2 live objects, each label carrying its measured functional tendency so many-valued labels sink), and sign_conflicts (per-source attribution sums disagreeing in sign, both sides named). Candidates, never verdicts, and nothing temporal: rows carry source NAMES for the registry to join against SourceMeta (the ADR 0011 §4 layering) — dates never enter the library. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
POST /contexts/{name}/consolidation/audit (ADR 0012 §4): one route,
three caller-selected sections behind a required `checks` array —
every section is a full-graph pass, so the caller names what it pays
for, and unknown or empty selectors refuse. Role::Read beside the
other audits, the unconditional heavy-ops group (no cheap default to
protect), deadline prechecked, scans under block_in_place.
merge reuses vocabulary_audit's twin sweep (lexical + semantic,
type-name concepts already excluded) as the candidate generator and
corroborates each pair with the lib's structural evidence, types
attached when a schema is installed, ranked structure-first.
contradiction serves the grouped pass ranked by measured functional
tendency — each object row joined with its latest assertion time via
the new source_effective_times registry helper (date ?? stored_at,
the ADR 0011 layering: dates never enter the library) — with
sign-contested edges after them. staleness measures each live edge's
gap against its own subject's newest assertion, worst first, with the
undatable count reported so "no candidates" and "nothing was datable"
never look alike.
Every candidate carries a hex FNV-1a fingerprint over its FULL
evidence (names, never ids — compaction reassigns ids), pair-order
canonicalized for merge, computed in the lib where the uncapped
evidence lives; the detector stamp (consolidation/1) scopes
comparability, the louvain-cc/1 precedent. e2e covers detection,
the time join, honest caps and selectors, and fingerprints that hold
still until the evidence moves.
Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
The communities pattern one shelf over (ADR 0012 §5): the verb runs
the audit, looks every candidate's judgment up by fingerprint
(judgment:{fingerprint} sources in the derived {name}::consolidation
context), judges only what has never been judged — dismissals are
first-class judgments, so a benign candidate never re-costs an LLM
call — and writes back through POST /import, one retract-then-apply
batch per judgment with the taguru_consolidation:1 manifest LAST so
its presence attests a complete artifact. A changed detector marks
every stored judgment incomparable, loudly. Judgments are proposals:
each names its suggested write (alias / retract / negative weight /
re-import); nothing is ever applied by this verb.
The CLI deserializes the real audit response types (api::consolidation
made pub(crate), the resolve/evaluate rule) rather than mirrors that
would drift; strict-JSON verdicts are unwrapped leniently (models
decorate) and re-stored normalized. e2e drives the built binary
against a stub chat: dry-run names the work with zero calls, the
first run judges all five seeded candidates, an unchanged graph
re-runs with zero LLM calls, and one moved fingerprint re-judges
exactly one candidate.
Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
audit_consolidation over MCP — pass-through of the HTTP shape with checks required, the ADR 0005 §3 boundary — and audit_consolidation / auditConsolidation in both SDKs (surface.yaml + python sync/async + typescript), returning the endpoint's own parsed JSON: the report is judge-facing evidence, not a decode surface, so no mirrored model types to drift. README gains the consolidation lane beside the communities one it patterns after; llm-protocol.md's API row landed with S2 (the route-documentation invariant enforced it there). Surface parity checked on both SDKs, pytest 174 and vitest 192 green. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
…465) The conventions-first half of #423, exactly as scoped: scratch is an ordinary context (scratch-{agent}, no TTL — forgetting stays an explicit operation), source ids name their session (session:{id}, so provenance survives promotion through the existing citation machinery), dates are always declared (date ?? stored_at is what ADR 0011's windows and ADR 0012's staleness audit run on — an undatable source is invisible to every window), and promotion is the existing verbs in a fixed order: review → extract (resolve-first, never fork the permanent vocabulary) → import (retract-then-apply, idempotent re-promotion) → consolidation audit on the landing zone → retract the promoted scratch. Ships as docs/promotion.html (site chrome, nav link added across the pages) plus an agent-facing skill template in examples/skills/memory-promotion/ — the taguru-code-nav precedent. The runbook's real-world use is what gates #466 (one-command promotion) and the umbrella's forgetting question, measure-then-build. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 26 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughグラフ検索に Changes時間範囲付きグラフ読み取り
統合監査
メモリ昇格ドキュメント
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant API
participant SourceRegistry
participant Context
Client->>API: recall/query/explore/activate with since/until
API->>SourceRegistry: resolve eligible source names
SourceRegistry-->>API: source window
API->>Context: execute windowed graph read
Context-->>API: recalculated associations and traversal results
API-->>Client: filtered response
sequenceDiagram
participant Operator
participant ConsolidationCLI
participant AuditAPI
participant LLM
participant ImportAPI
Operator->>ConsolidationCLI: run consolidation
ConsolidationCLI->>AuditAPI: request audit sections
AuditAPI-->>ConsolidationCLI: fingerprinted candidates
ConsolidationCLI->>LLM: judge candidates not in cache
LLM-->>ConsolidationCLI: apply or dismiss verdict
ConsolidationCLI->>ImportAPI: import judgment batches and manifest
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Both real findings the local toolchain (clippy 1.96) let through: reject_userinfo's if-let-return collapses to `?`, and the async recall signature goes one-parameter-per-line. No behavior change; the consolidation e2e and unit tests re-run green. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
There was a problem hiding this comment.
Actionable comments posted: 10
🧹 Nitpick comments (4)
src/consolidation.rs (1)
96-135: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winフラグの値が次のフラグを飲み込みます。
--context、--into、--checks、--config、--urlはrest.next()の値を無条件に採用します。taguru consolidation --context --dry-run sakeは、コンテキスト名として--dry-runを採用し、sakeを位置指定 URL として扱います。src/calibrate.rsとsrc/communities.rsの同じ引数は!value.starts_with('-')で守っています。同じガードを追加すると、この取り違えを使用法エラーとして拒否できます。🤖 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/consolidation.rs` around lines 96 - 135, Update the argument parsing matches for --context, --into, --checks, --config, and --url so their consumed values are accepted only when they do not start with a dash, matching the guards in calibrate.rs and communities.rs. Return the existing option-specific usage error when the next token is another flag or missing, rather than consuming it as a value; preserve duplicate-option handling for valid values.sdk/typescript/src/client.ts (1)
923-934: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
since/untilの意味を JSDoc に記載してください。Python SDK の
recall/query/explore/activateは、半開区間[since, until)、epoch 秒、ADR 0011 の重み再計算、until単独は as-of である点を docstring に記載しています。TypeScript 側の同じ 4 メソッドには記載がありません。同じファイル内のsearchPassagesは窓の契約を詳細に記載しているため、記載方針も一貫していません。📝 JSDoc の追記例
/** * Associations whose subject/object entry-matches the cue. `after` * resumes past the previous page's last match; `total` stays constant * across pages. + * + * `since`/`until` (epoch seconds, half-open `[since, until)`) window + * the graph by assertion time: only facts an in-window-dated source + * attests, weights re-derived from those attributions alone (ADR + * 0011). `until` alone reads as-of. */ async recall(同じ追記を
query、explore、activateにも適用してください。🤖 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 `@sdk/typescript/src/client.ts` around lines 923 - 934, Update the JSDoc for the TypeScript methods recall, query, explore, and activate to document that since and until define the half-open interval [since, until) in epoch seconds, that the interval triggers ADR 0011 weight recomputation, and that specifying until without since performs an as-of query. Follow the detailed window-contract style already used by searchPassages.src/context/window.rs (2)
83-93: 🚀 Performance & Scalability | 🔵 Trivial | ⚖️ Poor tradeoff窓付き経路で
windowed_totalsが同一エッジに対し繰り返し実行されます。
WindowLens::aliveとWindowLens::magnitudeはどちらもwindowed_totalsを呼び、エッジの帰属チェーン全体を走査します。activate_implはファン合計のfilterとmap、および伝播ループのfilterとscoreで、同じエッジに対してこれらを最大 4 回呼びます。エッジあたりの帰属数を N とすると、窓付き活性化のホットループのコストが O(1) から O(N) に増えます。無窓経路はFullLensで畳み込まれるため影響を受けません。帰属数が多いコーパスで窓付き
activateの遅延が問題になる場合は、settled 概念ごとに(count, sum)を一度計算して再利用する形を検討してください。現時点では計測結果に基づく判断で構いません。🤖 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/context/window.rs` around lines 83 - 93, Measure the windowed activation path before changing behavior, focusing on repeated calls from WindowLens::alive and WindowLens::magnitude to windowed_totals during activate_impl. If profiling confirms this hotspot, compute each edge’s windowed (count, sum) totals once per settled concept and reuse them across the fan-sum and propagation filters/scoring, while leaving the FullLens path unchanged.
391-399: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win未インターンのソース名と全ソース窓のケースがテストされていません。
モジュール doc は 2 つの不変条件を宣言しています。1 つ目は「このグラフでインターンされていない名前は黙って脱落する」です。
an_empty_window_answers_empty_everywhereは空のイテレータを渡すため、source_windowのfilter_mapが未知の名前を落とす分岐は実行されません。2 つ目は「無窓の読み取りは不変」です。全ソースを含む窓が無窓の結果と一致することを検証するテストもありません。🧪 追加テストの例
#[test] fn unknown_source_names_drop_out_of_the_window() { let context = corpus(); let window = context.source_window(["doc-old", "存在しないソース"]); let hits = context.query_any_within(&["蔵"], &["杜氏"], &[], &window); assert_eq!(hits.len(), 1, "未知の名前は窓を広げない"); assert_eq!(hits[0].object, "高瀬"); } #[test] fn a_window_holding_every_source_matches_the_unwindowed_read() { let context = corpus(); let window = context.source_window(["doc-old", "doc-new"]); assert_eq!( context.query_any_within(&["蔵"], &[], &[], &window), context.query_any(&["蔵"], &[], &[]), ); }パス指示「テストされていないエッジケース・失敗系…の欠落…を指摘してください」に基づく指摘です。
🤖 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/context/window.rs` around lines 391 - 399, Add tests alongside an_empty_window_answers_empty_everywhere covering both documented invariants: verify source_window drops unknown names while retaining valid sources, and verify a window containing every known source produces the same query_any_within result as unwindowed query_any. Use the existing corpus source names and assert both result count/content and equality of the full-source query.Source: Path instructions
🤖 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 `@docs/promotion.html`:
- Around line 92-95: Document in docs/promotion.html lines 92-95 that the
session {id} in session:{id} and session:{id}/{doc} must be globally unique
across agents and permanent contexts, using a value such as a UUID. Add the same
global-uniqueness requirement to examples/skills/memory-promotion/SKILL.md lines
19-22; no other changes are needed.
In `@src/api/consolidation.rs`:
- Around line 208-209: Clamp the optional evidence_cap in the consolidation
request setup, alongside limit, using DEFAULT_EVIDENCE_CAP as the fallback and
the established maximum evidence-cap bound. Ensure oversized caller-provided
values are capped before merge_evidence processes them.
- Around line 62-71: ConsolidationAudit の互換レスポンスを golden fixture
に追加してください。tests/http_api/contract.rs に監査エンドポイントの契約テストを追加し、HTTP fixture と MCP ツール
audit_consolidation のスキーマを固定してください。HTTP_CONTRACT と MCP_CONTRACT は引き続き 1 のままにします。
In `@src/consolidation.rs`:
- Around line 425-437: Update parse_judgment to return None when the first
opening-brace index is after the last closing-brace index, using an ordering
check or safe slice access before constructing the JSON slice. Add a regression
test covering input such as "} 判定できません {" and verify it does not panic and
returns None.
In `@src/context/consolidation.rs`:
- Around line 371-492: Extend the tests around merge_evidence,
contradiction_groups, and sign_conflicts to cover the missing contracts: verify
capped evidence lists retain exact uncapped totals, fingerprints remain
identical across different caps and reversed entity order, and expired deadlines
cause both graph-scan methods to return errors. Use the existing
deadline-expiration test helper and preserve the current success-case
assertions.
- Around line 224-228: Update the documentation comment for the consolidation
audit result to describe the candidates as deterministically sorted by (label,
subject), matching the sort_unstable_by_key logic applied to groups; remove the
inaccurate “insertion order” wording while preserving the rest of the documented
behavior.
In `@src/mcp/schema.rs`:
- Around line 386-387: Update the MCP route parameter allowlists in route.rs,
specifically the pick lists used by query, recall, activate, and explore, to
include both "since" and "until". Ensure these client-provided time-window
parameters are forwarded instead of discarded.
In `@tests/http_api/consolidation.rs`:
- Around line 144-167: Extend the consolidation audit test around the existing
selector checks to call the endpoint with checks containing “contradiction” and
limit set to 1, then assert that the response has exactly one candidate while
its total remains 2. Use the existing audit/server response helpers and preserve
the current selector validation assertions.
- Around line 169-206: Extend the consolidation HTTP API tests with a second
judge stub, alongside stub_judge, that returns a model response containing no
JSON. Add a test covering the judgment failure path through
src/consolidation.rs::judge and the CLI, asserting exit code 1 and verifying
that no output artifact is written.
In `@tests/http_api/temporal_window.rs`:
- Around line 51-119: テストの時間窓境界を実際のソース日付に一致させ、半開区間 [since, until)
の上限排他を検証してください。tests/http_api/temporal_window.rs の temporal-window テストでは until:
1000 で doc-2019 を除外し、since: 1000 で含め、since と until の同時指定および date なし・stored_at
のみのソースも追加検証してください。src/registry/passages.rs の SourceFilter テストでは until: Some(200)
により date 200 の doc-new を除外して doc-old のみ残ることを確認し、追加された source_effective_times
のテストも実装してください。
---
Nitpick comments:
In `@sdk/typescript/src/client.ts`:
- Around line 923-934: Update the JSDoc for the TypeScript methods recall,
query, explore, and activate to document that since and until define the
half-open interval [since, until) in epoch seconds, that the interval triggers
ADR 0011 weight recomputation, and that specifying until without since performs
an as-of query. Follow the detailed window-contract style already used by
searchPassages.
In `@src/consolidation.rs`:
- Around line 96-135: Update the argument parsing matches for --context, --into,
--checks, --config, and --url so their consumed values are accepted only when
they do not start with a dash, matching the guards in calibrate.rs and
communities.rs. Return the existing option-specific usage error when the next
token is another flag or missing, rather than consuming it as a value; preserve
duplicate-option handling for valid values.
In `@src/context/window.rs`:
- Around line 83-93: Measure the windowed activation path before changing
behavior, focusing on repeated calls from WindowLens::alive and
WindowLens::magnitude to windowed_totals during activate_impl. If profiling
confirms this hotspot, compute each edge’s windowed (count, sum) totals once per
settled concept and reuse them across the fan-sum and propagation
filters/scoring, while leaving the FullLens path unchanged.
- Around line 391-399: Add tests alongside
an_empty_window_answers_empty_everywhere covering both documented invariants:
verify source_window drops unknown names while retaining valid sources, and
verify a window containing every known source produces the same query_any_within
result as unwindowed query_any. Use the existing corpus source names and assert
both result count/content and equality of the full-source query.
🪄 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: 7f3b6559-5f4d-46e1-84c3-784ecf590d36
📒 Files selected for processing (52)
README.mddocs/architecture.htmldocs/aws.htmldocs/azure.htmldocs/bedrock.htmldocs/benchmark.htmldocs/concepts.htmldocs/connectors.htmldocs/docker-compose.htmldocs/evaluate.htmldocs/evidence.htmldocs/extract.htmldocs/gcp.htmldocs/getting-started.htmldocs/import.htmldocs/index.htmldocs/kubernetes.htmldocs/local-rag-walkthrough.htmldocs/long-running.htmldocs/mcp-rag-walkthrough.htmldocs/modeling.htmldocs/promotion.htmldocs/schema.htmldocs/tracing.htmlexamples/skills/memory-promotion/SKILL.mdsdk/python/src/taguru/_async/client.pysdk/python/src/taguru/_sync/client.pysdk/spec/surface.yamlsdk/typescript/src/client.tssrc/api.rssrc/api/consolidation.rssrc/api/explore.rssrc/api/recall.rssrc/api/sources.rssrc/api/vocabulary.rssrc/auth.rssrc/cli.rssrc/consolidation.rssrc/context.rssrc/context/consolidation.rssrc/context/query.rssrc/context/traverse.rssrc/context/window.rssrc/llm-protocol.mdsrc/main.rssrc/mcp.rssrc/mcp/route.rssrc/mcp/schema.rssrc/registry/passages.rstests/http_api/consolidation.rstests/http_api/main.rstests/http_api/temporal_window.rs
…ardenings
The real one: the MCP router never forwarded since/until on
recall/query/activate/explore — advertised in the inputSchema, dropped
by pick(), which is precisely the silently-unwindowed failure the
cross refusal exists to prevent. Forwarded now, with an e2e asserting
a windowed query through /mcp actually filters.
The rest: parse_judgment no longer panics on reversed delimiters ("}
… {" from an untrusted model) — get() instead of slicing, with the
test; evidence_cap is clamped like limit; the session source-id
convention now requires global uniqueness (session:{agent}:{id}, docs
and skill both) because import replaces per source id;
contradiction_groups' doc credits the sort, not insertion order, for
determinism; and the test gaps are closed — merge_evidence cap vs
exact totals and cap/pair-order-invariant fingerprints, expired
deadlines on both full-graph passes, limit truncation never touching
total, the shapeless-judgment run failing loudly with no artifact,
the [since, until) boundary AT the boundary plus the stored_at
fallback, and golden wire fixtures pinning the consolidation audit's
HTTP shape and the audit_consolidation MCP tool schema (contracts
stay at 1; both SDK structural checks pass).
Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
.claude/skills/ is operator-local configuration, deliberately untracked (the mutants sweep already dropped this same file once); the file stays on disk, only the accidental tracking is undone. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
format! already satisfies associate's generic bound; the borrows were noise the local 1.96 toolchain let through, same as the last round. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
The still-open findings from the second CodeRabbit pass: - taguru consolidation's value-taking flags no longer swallow a following flag as their value (--context --dry-run is now a usage error, not a context named "--dry-run") — the --url dash guard calibrate/communities already carry, extended to all five. - The registry layer gets its own [since, until) upper-bound-AT-the- boundary witness (until == doc-new's date excludes it) plus the missing source_effective_times test (dated mapped, undated absent, unknown context None). - window.rs pins its two documented invariants: unknown source names drop out without widening the window, and a window holding every source reproduces the plain read exactly. - The four TS graph methods document the window contract in JSDoc, matching the Python docstrings and searchPassages' own style. Skipped with reasons: evidence_cap's clamp already landed in 6bd5d33 (the reviewer's list lagged), and the windowed_totals-per-edge memo stays unbuilt per the finding's own "measure first" framing — ADR 0012 §8 already records it as a contained optimization gated on a real hot path. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/context/consolidation.rs (1)
178-205: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
merge_evidenceの fingerprint 衝突を防止してください。Line 178-205 は
direction、label、otherを|で連結します。概念名とラベル名は|を含められるため、(label = "a|b", other = "c")と(label = "a", other = "b|c")は同じ文字列になります。この衝突は異なる候補に同じ fingerprint を与えます。CLI はその fingerprint で過去の判定を再利用するため、別の証拠へ誤った判定を再利用します。各フィールドを
fold_fieldで個別にハッシュしてください。ソートには区切り文字で連結した文字列ではなく、(direction, label_name, concept_name)のタプルを使用してください。🤖 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/context/consolidation.rs` around lines 178 - 205, Update the fact fingerprinting in merge_evidence so direction, label_name, and concept_name are passed to fold_field as separate fields rather than joined with "|" delimiters. Sort facts by the tuple (direction, label_name, concept_name) before hashing, preserving deterministic ordering while preventing delimiter-induced collisions.Source: Path instructions
src/api/consolidation.rs (1)
274-278: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift監査全体で deadline を強制してください。
staleness_sectionはDeadlineを受け取りません。contradiction_groupsとsign_conflictsは各 edge の開始時だけを確認します。その後の候補展開と attribution chain の走査中に deadline が過ぎても、リクエストはDeadlineExceededになりません。
src/api/consolidation.rs#L274-L278:Deadlineをstaleness_sectionへ渡し、その全グラフ走査で期限を確認してください。src/context/consolidation.rs#L269-L300: 候補と source の展開中にも期限を確認し、期限超過を呼び出し元へ返してください。src/context/consolidation.rs#L331-L337: attribution chain の走査中にも期限を確認し、期限超過を返してください。開始時点で期限切れのケースに加えて、走査途中で期限を超えるケースをテストしてください。
🤖 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/consolidation.rs` around lines 274 - 278, 監査全体で期限超過を確実に伝播するよう、src/api/consolidation.rs の274-278行では staleness_section に Deadline を渡してください。src/context/consolidation.rs の269-300行では候補・source 展開中に期限を確認し、超過時は呼び出し元へ返してください。331-337行では attribution chain の各走査中にも同様に確認・伝播し、開始時および走査途中の期限超過を検証するテストを追加してください。Source: Path instructions
🤖 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 `@tests/fixtures/wire/mcp/audit_consolidation_tool_schema.json`:
- Around line 11-21: Update the audit consolidation tool schema’s checks array
to require at least one item by adding the minItems constraint with value 1, and
apply the same constraint to the generated/source schema and this fixture so
empty checks arrays are rejected consistently.
In `@tests/http_api/temporal_window.rs`:
- Around line 183-195: Extend the MCP query coverage in the temporal window test
around server.call_tool to add a since-only request and assert its expected
result, then add a request containing both since and until and verify both
bounds are applied. Preserve the existing until-only assertions.
---
Outside diff comments:
In `@src/api/consolidation.rs`:
- Around line 274-278: 監査全体で期限超過を確実に伝播するよう、src/api/consolidation.rs の274-278行では
staleness_section に Deadline を渡してください。src/context/consolidation.rs
の269-300行では候補・source 展開中に期限を確認し、超過時は呼び出し元へ返してください。331-337行では attribution chain
の各走査中にも同様に確認・伝播し、開始時および走査途中の期限超過を検証するテストを追加してください。
In `@src/context/consolidation.rs`:
- Around line 178-205: Update the fact fingerprinting in merge_evidence so
direction, label_name, and concept_name are passed to fold_field as separate
fields rather than joined with "|" delimiters. Sort facts by the tuple
(direction, label_name, concept_name) before hashing, preserving deterministic
ordering while preventing delimiter-induced collisions.
🪄 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: 77400038-0476-4822-9fd9-a713595d22fb
📒 Files selected for processing (14)
docs/promotion.htmlexamples/skills/memory-promotion/SKILL.mdsdk/typescript/src/client.tssrc/api/consolidation.rssrc/consolidation.rssrc/context/consolidation.rssrc/context/window.rssrc/mcp/route.rssrc/registry/passages.rstests/fixtures/wire/http/consolidation_audit.jsontests/fixtures/wire/mcp/audit_consolidation_tool_schema.jsontests/http_api/consolidation.rstests/http_api/contract.rstests/http_api/temporal_window.rs
🚧 Files skipped from review as they are similar to previous changes (6)
- examples/skills/memory-promotion/SKILL.md
- docs/promotion.html
- sdk/typescript/src/client.ts
- src/registry/passages.rs
- src/context/window.rs
- src/consolidation.rs
The MCP inputSchema now says what the server enforces — checks with minItems: 1, so a client cannot generate the empty selector the endpoint refuses — with the golden fixture regenerated to match. And the MCP window e2e sends a closed [since, until) window, so a router that forwarded until while dropping since can no longer pass. Claude-Session: https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
|
第3ラウンドの2件を 7cf01c7 で対応しました: |
Summary
GitHub Actions 停止中のため、指示どおり1ブランチ・対応ごとコミットで #463 → #464 → #465 を実装(7コミット)。各コミット時点でローカルの
cargo fmt/cargo clippy --all-targets(警告ゼロ)/cargo test全スイート、および SDK チェック(surface parity py+ts / pytest 174 / vitest 192 / tsc)を通過済み。#463 — ADR 0011 実装(3コミット)
SourceWindow+ 4つの*_within読み取り。EdgeLens で monomorphize し既存レーンのコード生成は不変。窓内 attribution からの正確な weight 再計算、walk 内での eligibility(窓外エッジは報告も伝導もしない)、ghost ルールと合成window_source_names(SourceFilter × SourceMeta join)、HTTP/MCP/SDK の optionalsince/until(共有バリデータ再利用、cross は明示拒否 — silent unwindowed 防止)、キャッシュキー分離。e2e 9項目#464 — ADR 0012 実装(4コミット)
merge_evidence(構造 Jaccard+証拠リスト、hidden label 除外)/contradiction_groups(実測 functional tendency)/sign_conflicts。fingerprint は名前ベース FNV-1a(compaction の id 再割当に不変、pair-order 正規化)POST /contexts/{name}/consolidation/audit—checks必須の3セクション、assertion-time join、undatable 明示、Role::Read + 無条件 heavy-ops。検出器スタンプconsolidation/1taguru consolidation— communities パターンの judge。fingerprint 一致で LLM ゼロ、dismiss 一級、{name}::consolidationへ import(manifest 最後)。e2e はスタブ chat で incremental 性質を検証(変更なし再実行 = 0 呼び出し、1 fingerprint 移動 = 1 再判定)audit_consolidation+ SDKaudit_consolidation/auditConsolidation+ README#465 — 昇格 runbook(1コミット)
docs/promotion.html(サイト chrome、全ページに nav 追加)+examples/skills/memory-promotion/SKILL.md。規約(scratch=通常 context /session:{id}/ date 必須)と手順(review → extract → import → audit → retract)、サーバ変更ゼロ#466 について
着手していません — 自身のゲート(#465 runbook の実運用実績)が未充足のため。#464 実装済みなので、runbook 運用後に判断・着手できます。
Closes #463
Closes #464
Closes #465
https://claude.ai/code/session_015xiMrm5VWArTNfQJyyMuym
Summary by CodeRabbit
新機能
since/untilによる時間範囲指定に対応しました。ドキュメント