Skip to content

feat(knowledge): restore client relationship graph actions#8182

Merged
singlerider merged 4 commits into
zeroclaw-labs:masterfrom
EyrieCommander:codex/issue-6074-knowledge-client-relationships
Jun 23, 2026
Merged

feat(knowledge): restore client relationship graph actions#8182
singlerider merged 4 commits into
zeroclaw-labs:masterfrom
EyrieCommander:codex/issue-6074-knowledge-client-relationships

Conversation

@Audacity88

@Audacity88 Audacity88 commented Jun 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Base branch: master
  • What changed and why:
    • Restores the feat(knowledge): add client relationship node types and tool actions #4507 client relationship knowledge graph surface on the current split-crate architecture.
    • Adds Client, Contact, and Interaction node types plus manages_client, contact_of, and interacted_with relations.
    • Adds graph_neighbors, client_network, and interaction_log knowledge tool actions so agents can inspect generic graph links, a client account's contacts and relationship owner, and recent interactions from the graph.
    • Bounds user-supplied result limits at the tool layer, applies ordered limits in storage, and keeps neighbor ordering deterministic before the tool formats the response.
    • Updates the Postgres knowledge graph converter and localized tool-knowledge descriptions so feature-gated and prompt-visible surfaces do not drift from the new schema.
  • Scope boundary: This PR does not add a UI, importer, CRM sync, external network integration, or automatic client-data capture. It restores graph schema support and agent-facing knowledge tool actions only.
  • Blast radius: zeroclaw-memory graph enum parsing and query helpers, zeroclaw-tools knowledge tool schema/actions, memory-postgres conversion helpers, and localized runtime tool descriptions.
  • Linked issue(s): Related audit: track 153 commits lost in bulk revert c3ff635 for recovery #6074. Supersedes feat(knowledge): add client relationship node types and tool actions #4507.
  • Labels: enhancement, risk: high, size: L, tool, memory, memory: postgres

Validation Evidence

  • Commands run and tail output:
cargo fmt --all -- --check
result: passed

cargo test -p zeroclaw-memory knowledge_graph --lib
result: passed; 14 passed, 0 failed, 315 filtered out

cargo test -p zeroclaw-tools knowledge_tool --lib
result: passed; 14 passed, 0 failed, 1330 filtered out

cargo test -p zeroclaw-memory --features memory-postgres knowledge_graph_pg --lib
result: passed; 5 passed, 0 failed, 336 filtered out

cargo clippy -p zeroclaw-memory -p zeroclaw-tools --lib -- -D warnings
result: passed

cargo clippy -p zeroclaw-memory --features memory-postgres --lib -- -D warnings
result: passed

git diff --check
result: passed

cargo clippy --workspace --exclude zeroclaw-desktop --all-targets --features ci-all -- -D warnings
result: passed; cargo reported Finished dev profile in 6m 56s

cargo nextest run --locked --workspace --exclude zeroclaw-desktop
result: passed; 9443 tests run: 9443 passed, 11 skipped
  • Beyond CI — what did you manually verify? The tests cover the new graph enum round trips, client/contact/interaction relationships, inbound and outbound graph queries, typed relationship filters, ordered and bounded graph_neighbors results, bounded user-supplied limits, client_network, interaction_log, invalid client IDs, malformed manager edges, localized tool description freshness, and Postgres enum conversion behavior.
  • If any command was intentionally skipped, why: None for the local readiness evidence expected for this risk: high PR.

Security & Privacy Impact

  • New permissions, capabilities, or file system access scope? Yes. This adds knowledge tool actions that read existing graph relationships for a supplied node or client ID. It does not add new filesystem access, network access, or a bypass around the existing tool permission path.
  • New external network calls? No
  • Secrets / tokens / credentials handling changed? No
  • PII, real identities, or personal data in diff, tests, fixtures, or docs? No
  • If any Yes, describe the risk and mitigation: The new actions can expose knowledge graph entries to an agent that is already allowed to call the knowledge tool. The implementation validates requested nodes, requires client_id to resolve to a Client node for client-specific actions, bounds result counts, and keeps tests on neutral placeholder data.

Compatibility

  • Backward compatible? Yes
  • Config / env / CLI surface changed? No
  • If No or Yes to either: Existing users do not need migration steps. Existing graph node and relation strings keep their current spelling, and the new variants/actions are additive.

Rollback

  • Fast rollback command/path: Revert the merge commit for this PR.
  • Feature flags or config toggles: None.
  • Observable failure symptoms: Knowledge tool calls to graph_neighbors, client_network, or interaction_log fail or return unexpected graph data. Search logs for knowledge_tool, unknown node type, unknown relation, or client action missing client_id.

Supersede Attribution

  • Superseded PRs + authors: feat(knowledge): add client relationship node types and tool actions #4507 by @theredspoon
  • Scope materially carried forward: Client/contact/interaction graph node types, client relationship relations, typed graph lookup helpers, and the client_network / interaction_log knowledge tool actions were restored on the current split-crate implementation.
  • Co-authored-by trailers added in commit messages for incorporated contributors? Yes
  • If No, why: Not applicable.

Restore the client/contact/interaction knowledge graph schema and client_network/interaction_log tool actions from the reverted zeroclaw-labs#4507 work on the current split-crate implementation.

Co-authored-by: Nim G <theredspoon@users.noreply.github.com>
@github-actions github-actions Bot added memory Auto scope: src/memory/** changed. tool Auto scope: src/tools/** changed. labels Jun 22, 2026
@Audacity88 Audacity88 added enhancement New feature or request risk: high Auto risk: security/runtime/gateway/tools/workflows. size: L Auto size: 501-1000 non-doc changed lines. memory: postgres Auto module: memory/postgres changed. labels Jun 22, 2026
)?;

let mut results = Vec::new();
let mut rows = stmt.query(params![node_type.as_str(), limit as i64])?;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is the only new query method that keeps limit as i64 instead of the checked sql_limit(limit)? you introduced for every other new query in this PR. An out-of-range usize wraps silently here rather than returning the clear error the rest of the path produces. Make it let limit = sql_limit(limit)?; for consistency.

@singlerider

Copy link
Copy Markdown
Collaborator

Draft, so direction only, no verdict. I read the full diff: the enum macro consolidation, the new graph query methods, the client/contact/interaction node and relation types, the tool actions, and the locale additions.

Direction notes for when you take this out of draft:

  1. The knowledge_enum! macro is a clean consolidation. ALL, SCHEMA_VALUES, as_str, and parse derived from one source is exactly the right move and kills the parallel hand-written match arms that used to drift. No concern there.

  2. query_by_type is the one new query that still uses limit as i64 instead of the sql_limit(limit)? you added everywhere else. Left an inline note. Tighten it so the whole new surface fails the same clean way on an out-of-range limit.

  3. The action dispatch in knowledge_tool.rs extends the existing string match action block with three new arms (graph_neighbors, client_network, interaction_log) and KNOWLEDGE_ACTIONS is a hardcoded literal list. The string-match dispatch is pre-existing so this PR is not introducing the pattern, but you are growing it. If you have appetite while this is still a draft, lifting the action set into an enum that owns both the dispatch and the schema enum array would remove the hardcoded list and the stringly-typed routing in one move, and it keeps the schema and dispatch from drifting as more actions land. Not required for this PR, but this is the cheapest moment to do it.

  4. Locale parity is clean: one new key added across all five locales (en, es, fr, ja, zh-CN). Good.

  5. find_outbound/find_inbound plus the relation-and-type variants all bound with LIMIT ?2 and deterministic ORDER BY created_at DESC, id ASC. Pagination stability looks right.

Flag me when it is ready for a verdict.

@Audacity88

Copy link
Copy Markdown
Collaborator Author

@singlerider thanks, this was helpful.

I tightened the checked-limit point in 88faab6059: query_by_similarity and query_by_type now pass the checked sql_limit(...) value directly instead of keeping the redundant as i64 cast.

I am going to leave the action-dispatch enum as a follow-up candidate for now. The string dispatch predates this PR, and the current action/schema list is covered by tests, so I do not want to expand this recovery slice further just to reshape that internal routing.

I will flag you again after the broad validation / ready pass.

@Audacity88 Audacity88 marked this pull request as ready for review June 23, 2026 10:07
@Audacity88 Audacity88 requested a review from singlerider June 23, 2026 10:10

@singlerider singlerider left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Re-reviewed at head 88faab6 (was 24416de on my prior COMMENT). The only change since is the limit fix I asked for.

✅ Resolved — checked SQL limits applied consistently

My one blocker was find_inbound_by_relation binding limit as i64 while every other new query routed through sql_limit(limit)?. Fixed: each of the six new query methods now shadows let limit = sql_limit(limit)?; at the function top and binds the checked value, so an out-of-range usize returns the clear "exceeds SQLite range" error instead of wrapping silently. The remaining as i64 is on subgraph depth, which is clamped to MAX_SUBGRAPH_DEPTH (100) and rejects 0, so that cast cannot overflow.

🟢 What looks good — schema additions are additive and the surfaces stay in lockstep

New Client/Contact/Interaction nodes and the three relations keep existing graph strings untouched, so the change is backward compatible. The Postgres converter and all five localized tool-knowledge descriptions move with the schema, so feature-gated and prompt-visible surfaces do not drift. Supersede attribution is honest: #4507 carried forward with a Co-authored-by trailer for @theredspoon.

🟢 What looks good — bounded, validated, deterministic reads

User-supplied limits are bounded at the tool layer and re-checked in storage, client actions require client_id to resolve to a real Client node, and neighbor ordering is deterministic before formatting. The validation battery is thorough for a risk:high change (full workspace clippy + nextest green, plus the Postgres feature path).

Verdict: APPROVED.

@singlerider singlerider merged commit c6906da into zeroclaw-labs:master Jun 23, 2026
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request memory: postgres Auto module: memory/postgres changed. memory Auto scope: src/memory/** changed. risk: high Auto risk: security/runtime/gateway/tools/workflows. size: L Auto size: 501-1000 non-doc changed lines. tool Auto scope: src/tools/** changed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants