fix: record affected documents at change time

Edits queue their path; before the next snapshot the engine walks dependents with a frozen copy of every recorded view (each dependent on the graph stack) and stamps affected documents with a sequence. Consumers read them via changes_since(cursor), so queries in between cannot absorb a change. Graph dictionary views now cover the combined import list, matching first-wins resolution.
This commit is contained in:
Stefan
2026-10-01 21:15:43 +02:00
parent 03aa88c41b
commit 2b892e15de
7 changed files with 149 additions and 78 deletions
+5 -1
View File
@@ -118,6 +118,10 @@ export type PolicySlotState =
| 'path';
export type PolicySlotRole = 'unary' | 'condition' | 'value' | 'path';
/** One enum value: `label` for display, `source` the ready-to-splice ZEN literal (null when unquotable). */
export interface PolicyChanges {
cursor: number
paths: Array<string>
}
export interface PolicyValueOption {
value: string;
label: string;
@@ -400,7 +404,7 @@ export declare class Workspace {
isGraph(path: string): boolean
uncheckedNodes(path: string): Array<string>
paths(): Array<string>
affectedBy(paths: Array<string>): Array<string>
changesSince(cursor: number): PolicyChanges
updateBlock(req: PolicyUpdateBlockRequest): void
removeBlock(req: PolicyRemoveBlockRequest): boolean
diagnostics(policyPath: string, maxDiagnostics?: number | undefined | null): Array<PolicyDiagnostic>
+12 -7
View File
@@ -12,6 +12,12 @@ use zen_engine::workspace;
type ResolverRef = FunctionRef<FnArgs<(String, Value)>, Option<String>>;
#[napi(object)]
pub struct PolicyChanges {
pub cursor: i64,
pub paths: Vec<String>,
}
#[napi(object)]
pub struct PolicyExpressionCursor {
pub policy_path: String,
@@ -627,13 +633,12 @@ impl Workspace {
}
#[napi]
pub fn affected_by(&self, paths: Vec<String>) -> Vec<String> {
let paths: Vec<&str> = paths.iter().map(String::as_str).collect();
self.inner
.affected_by(&paths)
.into_iter()
.map(|p| p.to_string())
.collect()
pub fn changes_since(&self, cursor: i64) -> PolicyChanges {
let (next, paths) = self.inner.changes_since(cursor.max(0) as u64);
PolicyChanges {
cursor: next as i64,
paths: paths.into_iter().map(|p| p.to_string()).collect(),
}
}
#[napi]