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
564 changes: 339 additions & 225 deletions Cargo.lock

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,10 @@ explicit_into_iter_loop = "warn"
filter_map_next = "warn"
flat_map_option = "warn"
float_cmp_const = "warn"
from_iter_instead_of_collect = "warn"
# from_iter_instead_of_collect — REMOVED in Rust 1.98 ("lint has proved
# problematic"). Requesting it makes every clippy run emit a
# `renamed_and_removed_lints` warning, which notably ignores `-D warnings`,
# so it degraded the signal without ever failing the gate.
get_unwrap = "warn"
implicit_clone = "warn"
implicit_hasher = "warn"
Expand Down
2 changes: 1 addition & 1 deletion crates/cockpit-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ arc-swap = "1.9"
# `lance-graph` -> `lance` -> `arrow` — declaring them directly here changes
# no resolved version, it just makes the capability this crate USES a thing
# this crate ASKS FOR. Same move lance-graph PR #931 made for `object_store`.
lance = "=9.0.0"
lance = "=11.0.0"
arrow = { version = "58", features = ["prettyprint"] }


Expand Down
17 changes: 13 additions & 4 deletions crates/cockpit-server/src/body_lod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use std::sync::LazyLock;

use axum::Json;
use ndarray::hpc::splat3d::depth_cascade::{cascade_blocks, BlockBounds, DepthCascadeBudget};
use ndarray::hpc::splat3d::depth_cascade::{BlockBounds, DepthCascadeBudget, cascade_blocks};
use ndarray::hpc::splat3d::project::Camera;
use serde::{Deserialize, Serialize};

Expand All @@ -25,10 +25,15 @@ static BODY_BLOCKS: &[u8] =

static BLOCKS: LazyLock<Vec<BlockBounds>> = LazyLock::new(|| {
BODY_BLOCKS
.chunks_exact(16)
.as_chunks::<16>()
.0
.iter()
.map(|c| {
let f = |k: usize| f32::from_le_bytes(c[k * 4..k * 4 + 4].try_into().unwrap());
BlockBounds { center: [f(0), f(1), f(2)], radius: f(3).max(1e-4) }
BlockBounds {
center: [f(0), f(1), f(2)],
radius: f(3).max(1e-4),
}
})
.collect()
});
Expand Down Expand Up @@ -87,5 +92,9 @@ pub async fn body_lod_handler(Json(cam): Json<LodCamera>) -> Json<LodResponse> {
tally[a] += 1;
}
}
Json(LodResponse { actions, n_concepts: BLOCKS.len(), tally })
Json(LodResponse {
actions,
n_concepts: BLOCKS.len(),
tally,
})
}
9 changes: 4 additions & 5 deletions crates/cockpit-server/src/codebook.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
//! `lance_graph::thinking_engine::engine::CODEBOOK_SIZE` (currently 4096).
//! If the upstream value changes, update this constant in lockstep.

use std::collections::hash_map::DefaultHasher;
use std::collections::HashSet;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};

/// Codebook width. Mirrors `thinking_engine::engine::CODEBOOK_SIZE`.
Expand All @@ -37,10 +37,9 @@ pub fn default_distance_table() -> Vec<u8> {

/// Cypher keywords excluded from identifier extraction.
const CYPHER_KEYWORDS: &[&str] = &[
"MATCH", "RETURN", "WHERE", "CREATE", "MERGE", "SET", "DELETE", "AS",
"AND", "OR", "NOT", "NULL", "TRUE", "FALSE", "OPTIONAL", "WITH",
"UNWIND", "ORDER", "BY", "ASC", "DESC", "LIMIT", "SKIP", "COUNT",
"COLLECT", "DISTINCT",
"MATCH", "RETURN", "WHERE", "CREATE", "MERGE", "SET", "DELETE", "AS", "AND", "OR", "NOT",
"NULL", "TRUE", "FALSE", "OPTIONAL", "WITH", "UNWIND", "ORDER", "BY", "ASC", "DESC", "LIMIT",
"SKIP", "COUNT", "COLLECT", "DISTINCT",
];

/// Maximum identifiers returned by [`extract_cypher_identifiers`] per call.
Expand Down
11 changes: 9 additions & 2 deletions crates/cockpit-server/src/dto_bridge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,10 @@ mod tests {

assert_eq!(style_selector_str(StyleSelector::Auto), "auto");
assert_eq!(style_selector_str(StyleSelector::Ordinal(7)), "explicit");
assert_eq!(style_selector_str(StyleSelector::Named("focus")), "explicit");
assert_eq!(
style_selector_str(StyleSelector::Named("focus")),
"explicit"
);
}

#[test]
Expand All @@ -431,6 +434,10 @@ mod tests {
assert!(!j.contains("color_acc\":["), "color_acc array leaked: {j}");
assert!(j.contains("\"color_acc_active_dims\":3"));
// Footprint sanity: small struct must serialize tiny.
assert!(j.len() < 256, "alpha composite frame too large: {} B", j.len());
assert!(
j.len() < 256,
"alpha composite frame too large: {} B",
j.len()
);
}
}
54 changes: 42 additions & 12 deletions crates/cockpit-server/src/graph_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
//! Wire JSON keeps the historical field names `truth_f` / `truth_c` so
//! the cockpit React frontend keeps working unchanged.

use std::sync::{Arc, OnceLock};
use std::collections::HashMap;
use std::sync::{Arc, OnceLock};

use serde::Serialize;
use tokio::sync::RwLock;
Expand Down Expand Up @@ -107,9 +107,13 @@ pub struct GraphEdge {

impl GraphEdge {
/// Convenience: legacy `truth_f` accessor for in-process consumers.
pub fn truth_f(&self) -> f32 { self.truth.frequency }
pub fn truth_f(&self) -> f32 {
self.truth.frequency
}
/// Convenience: legacy `truth_c` accessor for in-process consumers.
pub fn truth_c(&self) -> f32 { self.truth.confidence }
pub fn truth_c(&self) -> f32 {
self.truth.confidence
}
}

impl Serialize for GraphEdge {
Expand Down Expand Up @@ -244,7 +248,11 @@ pub async fn hydrate_from_aiwar_json(path: &str) -> Result<(), String> {
let mut state = graph.write().await;
*state = snapshot;

tracing::info!("hydrated live graph: {} nodes, {} edges", node_count, edge_count);
tracing::info!(
"hydrated live graph: {} nodes, {} edges",
node_count,
edge_count
);
Ok(())
}

Expand All @@ -270,7 +278,9 @@ pub async fn run_nars_deduction(min_confidence: f32, max_hops: usize) -> Vec<Nar
}

// Existing edges for dedup
let existing: std::collections::HashSet<(&str, &str)> = state.edges.iter()
let existing: std::collections::HashSet<(&str, &str)> = state
.edges
.iter()
.map(|e| (e.source.as_str(), e.target.as_str()))
.collect();

Expand All @@ -280,11 +290,17 @@ pub async fn run_nars_deduction(min_confidence: f32, max_hops: usize) -> Vec<Nar
if max_hops >= 2 {
for (a, a_edges) in &adj {
for &(b, _ab_label, ab_truth) in a_edges {
if ab_truth.confidence < min_confidence { continue; }
if ab_truth.confidence < min_confidence {
continue;
}
if let Some(b_edges) = adj.get(b) {
for &(c_node, bc_label, bc_truth) in b_edges {
if bc_truth.confidence < min_confidence { continue; }
if *a == c_node || existing.contains(&(a, c_node)) { continue; }
if bc_truth.confidence < min_confidence {
continue;
}
if *a == c_node || existing.contains(&(a, c_node)) {
continue;
}

// NARS deduction via canonical planner TruthValue::deduction.
let inferred = nars_deduction(&ab_truth, &bc_truth);
Expand Down Expand Up @@ -322,9 +338,15 @@ pub async fn graph_snapshot_handler() -> axum::Json<GraphSnapshot> {
pub async fn nars_infer_handler(
axum::Json(params): axum::Json<serde_json::Value>,
) -> axum::Json<serde_json::Value> {
let min_conf = params.get("min_confidence").and_then(|v| v.as_f64()).unwrap_or(0.4) as f32;
let min_conf = params
.get("min_confidence")
.and_then(|v| v.as_f64())
.unwrap_or(0.4) as f32;
let max_hops = params.get("max_hops").and_then(|v| v.as_u64()).unwrap_or(2) as usize;
let node_id = params.get("node_id").and_then(|v| v.as_str()).map(|s| s.to_string());
let node_id = params
.get("node_id")
.and_then(|v| v.as_str())
.map(|s| s.to_string());

let mut inferences = run_nars_deduction(min_conf, max_hops).await;

Expand Down Expand Up @@ -364,7 +386,15 @@ mod nars_planner_bridge_tests {
let bc = NarsTruth::new(0.7, 0.6);
let result = nars_deduction(&ab, &bc);
// Canonical NARS: f = f1*f2 = 0.63, c = f1*f2*c1*c2 = 0.3024
assert!((result.frequency - 0.63).abs() < 0.01, "f={}", result.frequency);
assert!((result.confidence - 0.3024).abs() < 0.01, "c={}", result.confidence);
assert!(
(result.frequency - 0.63).abs() < 0.01,
"f={}",
result.frequency
);
assert!(
(result.confidence - 0.3024).abs() < 0.01,
"c={}",
result.confidence
);
}
}
Loading