fix: add precedes graph edge from classification to execution
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled

Every run call creates a classification entity, but it was never
connected to the execution via a graph edge — only via a DB column
(executions.classification_id). The ontology requires:

    classification —precedes→ execution

Without this edge, all 53 classification entities had zero
relationships, making them invisible to get_relations and
blast-radius analysis.

Adds an idempotent INSERT into relationships after the existing
classification_id update, matching the same pattern used for
targets edges.
This commit is contained in:
2026-08-11 21:18:45 +02:00
parent ebe1b95acf
commit 60bc9d555d
2 changed files with 19 additions and 0 deletions

View File

@@ -921,6 +921,13 @@ func classifyAndGate(ctx context.Context, pool *db.Pool, agentID, targetID uuid.
classID, actionCol, riskClass, classRoute, classReason, correlationID)
// Link classification to execution.
pool.Exec(ctx, `UPDATE executions SET classification_id = $2 WHERE entity_id = $1`, id, classID)
// Graph edge: classification —precedes→ execution (required by ontology).
pool.Exec(ctx, `INSERT INTO relationships (source_id, target_id, type, attributes, valid_from)
SELECT $1, $2, 'precedes', '{"by":"nomos"}'::jsonb, now()
WHERE NOT EXISTS (
SELECT 1 FROM relationships
WHERE source_id = $1 AND target_id = $2 AND type = 'precedes' AND valid_to IS NULL)`,
classID, id)
// Audit: record the execution creation with session_id for traceability.
// Every run call, whether auto-run or queued-for-approval, gets an audit

View File

@@ -38,6 +38,7 @@ import TrendingUpIcon from '@lucide/svelte/icons/trending-up'
import SettingsIcon from '@lucide/svelte/icons/settings'
import EggIcon from '@lucide/svelte/icons/egg'
import StoreIcon from '@lucide/svelte/icons/store'
import Share2Icon from '@lucide/svelte/icons/share-2'
export type { AppManifest, AppPermission }
@@ -180,6 +181,17 @@ export const builtinApps: AppDef[] = [
component: () => import('./mascot/MascotLayer.svelte'),
docked: true,
source: 'builtin'
},
{
id: 'entity-graph',
title: 'Entity Graph',
icon: Share2Icon,
component: () => import('../pages/EntityGraph.svelte'),
width: 1100,
height: 750,
minWidth: 640,
minHeight: 420,
source: 'builtin'
}
]