/**
 * Ontology model for OMK project memory.
 *
 * Defines core node types, relationship types, project-isolation fields,
 * and schema helpers used across all graph-backed memory stores.
 */
export const ONTOLOGY_SCHEMA_VERSION = 1;
export const ONTOLOGY_NODE_TYPES = [
    "Project",
    "Session",
    "Run",
    "Goal",
    "Criterion",
    "Evidence",
    "Decision",
    "Task",
    "Risk",
    "Constraint",
    "File",
    "Symbol",
    "Test",
    "Command",
    "Commit",
    "MCPServer",
    "Skill",
    "Provider",
    "ProviderRoute",
    "ProviderFallback",
    "AuditLink",
];
export const ONTOLOGY_RELATIONSHIP_TYPES = [
    "HAS_GOAL",
    "HAS_RUN",
    "HAS_CRITERION",
    "HAS_EVIDENCE",
    "HAS_DECISION",
    "HAS_TASK",
    "DEPENDS_ON",
    "HAS_RISK",
    "HAS_FILE",
    "HAS_SYMBOL",
    "HAS_TEST",
    "HAS_COMMAND",
    "HAS_COMMIT",
    "USES_MCP",
    "USES_SKILL",
    "USES_PROVIDER",
    "HAS_PROVIDER_ROUTE",
    "ROUTES_TO",
    "FALLS_BACK_TO",
    "HAS_PROVIDER_FALLBACK",
    "HAS_AUDIT_LINK",
    "LINKS_TO",
];
/**
 * Create unique constraints for every ontology node type.
 * Each constraint enforces uniqueness on `(projectId, id)` for the label.
 */
export async function createOntologyConstraints(executor, database) {
    const options = database ? { database } : undefined;
    for (const nodeType of ONTOLOGY_NODE_TYPES) {
        const label = `Omk${nodeType}`;
        const constraintName = `omk_${nodeType.toLowerCase()}_project_id_unique`;
        await executor.executeQuery(`CREATE CONSTRAINT ${constraintName} IF NOT EXISTS FOR (n:${label}) REQUIRE (n.projectId, n.id) IS UNIQUE`, {}, options);
    }
}
/** Build Kuzu CREATE NODE TABLE / CREATE REL TABLE DDLs from the ontology model. */
export function buildKuzuOntologySchema() {
    const baseProps = "id STRING PRIMARY KEY, projectId STRING, workspaceRootHash STRING, schemaVersion INT64, createdAt STRING, updatedAt STRING";
    const nodeTables = [
        `CREATE NODE TABLE OmkGoal (${baseProps}, goalId STRING, title STRING, objective STRING, status STRING, riskLevel STRING)`,
        `CREATE NODE TABLE OmkCriterion (${baseProps}, criterionId STRING, description STRING, requirement STRING, weight INT64)`,
        `CREATE NODE TABLE OmkEvidence (${baseProps}, evidenceId STRING, passed BOOLEAN, message STRING, checkedAt STRING)`,
        `CREATE NODE TABLE OmkDecision (${baseProps}, decisionId STRING, description STRING, decidedAt STRING)`,
        `CREATE NODE TABLE OmkTask (${baseProps}, taskId STRING, description STRING, status STRING, priority STRING)`,
        `CREATE NODE TABLE OmkRisk (${baseProps}, riskId STRING, description STRING, level STRING)`,
        `CREATE NODE TABLE OmkConstraint (${baseProps}, constraintId STRING, description STRING)`,
        `CREATE NODE TABLE OmkFile (${baseProps}, path STRING, description STRING)`,
        `CREATE NODE TABLE OmkSymbol (${baseProps}, symbolId STRING, name STRING, kind STRING)`,
        `CREATE NODE TABLE OmkTest (${baseProps}, testId STRING, name STRING, status STRING)`,
        `CREATE NODE TABLE OmkCommand (${baseProps}, commandId STRING, command STRING, description STRING)`,
        `CREATE NODE TABLE OmkCommit (${baseProps}, commitId STRING, message STRING, author STRING)`,
        `CREATE NODE TABLE OmkMCPServer (${baseProps}, name STRING, description STRING)`,
        `CREATE NODE TABLE OmkSkill (${baseProps}, name STRING, description STRING)`,
        `CREATE NODE TABLE OmkProvider (${baseProps}, providerId STRING, role STRING, description STRING)`,
        `CREATE NODE TABLE OmkProviderRoute (${baseProps}, routeId STRING, nodeId STRING, requestedProvider STRING, actualProvider STRING, reason STRING, confidence DOUBLE)`,
        `CREATE NODE TABLE OmkProviderFallback (${baseProps}, fallbackId STRING, nodeId STRING, fromProvider STRING, toProvider STRING, reason STRING)`,
        `CREATE NODE TABLE OmkRun (${baseProps}, runId STRING, status STRING, startedAt STRING)`,
        `CREATE NODE TABLE OmkAuditLink (${baseProps}, linkId STRING, label STRING, target STRING, targetType STRING)`,
    ];
    const relTables = [
        `CREATE REL TABLE HAS_GOAL (FROM OmkProject TO OmkGoal)`,
        `CREATE REL TABLE HAS_RUN (FROM OmkProject TO OmkRun)`,
        `CREATE REL TABLE HAS_CRITERION (FROM OmkGoal TO OmkCriterion)`,
        `CREATE REL TABLE HAS_EVIDENCE (FROM OmkCriterion TO OmkEvidence)`,
        `CREATE REL TABLE HAS_DECISION (FROM OmkProject TO OmkDecision)`,
        `CREATE REL TABLE HAS_TASK (FROM OmkProject TO OmkTask)`,
        `CREATE REL TABLE DEPENDS_ON (FROM OmkTask TO OmkTask)`,
        `CREATE REL TABLE HAS_RISK (FROM OmkProject TO OmkRisk)`,
        `CREATE REL TABLE HAS_FILE (FROM OmkProject TO OmkFile)`,
        `CREATE REL TABLE HAS_SYMBOL (FROM OmkFile TO OmkSymbol)`,
        `CREATE REL TABLE HAS_TEST (FROM OmkProject TO OmkTest)`,
        `CREATE REL TABLE HAS_COMMAND (FROM OmkProject TO OmkCommand)`,
        `CREATE REL TABLE HAS_COMMIT (FROM OmkProject TO OmkCommit)`,
        `CREATE REL TABLE USES_MCP (FROM OmkProject TO OmkMCPServer)`,
        `CREATE REL TABLE USES_SKILL (FROM OmkProject TO OmkSkill)`,
        `CREATE REL TABLE USES_PROVIDER (FROM OmkProject TO OmkProvider)`,
        `CREATE REL TABLE HAS_PROVIDER_ROUTE (FROM OmkTask TO OmkProviderRoute)`,
        `CREATE REL TABLE ROUTES_TO (FROM OmkProviderRoute TO OmkProvider)`,
        `CREATE REL TABLE FALLS_BACK_TO (FROM OmkProviderRoute TO OmkProvider)`,
        `CREATE REL TABLE HAS_PROVIDER_FALLBACK (FROM OmkTask TO OmkProviderFallback)`,
        `CREATE REL TABLE HAS_AUDIT_LINK (FROM OmkProject TO OmkAuditLink)`,
        `CREATE REL TABLE LINKS_TO (FROM OmkAuditLink TO OmkFile)`,
    ];
    return { nodeTables, relTables };
}
/** Cypher write keywords rejected by the read-only graph query guard. */
export const MUTATION_KEYWORDS = ["CREATE", "DELETE", "SET", "REMOVE", "MERGE", "DROP"];
/**
 * Return true if the provided Cypher query contains write mutations.
 * Strips line comments and block comments before scanning.
 */
export function containsMutation(query) {
    const normalized = query
        .replace(/\/\/.*$/gm, "")
        .replace(/\/\*[\s\S]*?\*\//g, "")
        .replace(/\s+/g, " ")
        .trim()
        .toUpperCase();
    return MUTATION_KEYWORDS.some((keyword) => normalized.includes(keyword));
}
