// Typed-edge allowlist — the single source of truth for which
// (sourceLabel, EDGE_TYPE, targetLabel) triples the typed-edge pass may
// MERGE into the graph. The Cypher schema file declares indexes and
// constraints only; edge-type semantics live here.
//
// Used in three places:
//   1. The Haiku system prompt for the typed-edge pass — the model is
//      told to propose only edges from this list.
//   2. Inline validation inside `runTypedEdgePass` — any proposal whose
//      (source, edge, target) is not in this list is rejected and logged
//      with reason "not-in-allowlist".
//   3. The doc generator that emits the edge-types table into
//      `.docs/neo4j.md` and the bundled `platform/plugins/docs/references/neo4j.md`.
//
// Adding a new edge type or label pair: edit this file, run the doc
// generator, ship in one PR. Schema.cypher carries a comment header
// pointing here.
//
// Scope: this constant is the canonical (source, edgeType, target)
// allowlist for every edge type that appears in it — currently
// ATTENDED, WORKS_AT, INVESTED_IN, FOUNDED, ADVISES, MENTIONS, AUTHORED,
// ATTACHED_TO, REFERENCES. Three writers honour it:
//   1. The typed-edge pass (`memory-typed-edge-pass`) — proposes only
//      tuples from this list, rejects others with reason
//      "not-in-allowlist".
//   2. The document-ingest writer (`memory-ingest`) — when the
//      classifier emits a related-edge or documentEdge whose `type`
//      belongs to this allowlist (`isTypedEntityEdgeType` returns
//      true), the writer validates the (source, edge, target) triple
//      and rejects loud on mismatch. Task 482 — closes the
//      `:FOUNDED` → `:Section` writer defect.
//   3. The doc generator that emits the edge-types table into
//      `.docs/neo4j.md` and the bundled `platform/plugins/docs/references/neo4j.md`.
//
// Edge types that do NOT appear in this allowlist (HAS_SECTION, NEXT,
// HAS_POSITION, AT, HOLDS, HAS_SKILL, DESCRIBED_BY, CREATED, UNDER,
// PARTY, PARTICIPANT, FROM/TO/CC, SPEAKER, DEFINES, …) are governed by
// schema-base.md / vertical-schema rules and document-ingest's per-kind
// anchor map — they pass through this allowlist unchecked.
/**
 * The nine edge types ported from gbrain's auto-link layer, with the
 * legal source/target label pairs for each.
 *
 * Order is stable so the prompt and docs render deterministically.
 */
export const TYPED_EDGE_ALLOWLIST = [
    // ATTENDED — person attended an event.
    { sourceLabel: "Person", edgeType: "ATTENDED", targetLabel: "Event" },
    { sourceLabel: "Person", edgeType: "ATTENDED", targetLabel: "Meeting" },
    // WORKS_AT — person currently works at an organisation.
    { sourceLabel: "Person", edgeType: "WORKS_AT", targetLabel: "Organization" },
    { sourceLabel: "Person", edgeType: "WORKS_AT", targetLabel: "LocalBusiness" },
    // INVESTED_IN — person or organisation invested in an organisation.
    { sourceLabel: "Person", edgeType: "INVESTED_IN", targetLabel: "Organization" },
    { sourceLabel: "Person", edgeType: "INVESTED_IN", targetLabel: "LocalBusiness" },
    { sourceLabel: "Organization", edgeType: "INVESTED_IN", targetLabel: "Organization" },
    { sourceLabel: "Organization", edgeType: "INVESTED_IN", targetLabel: "LocalBusiness" },
    // FOUNDED — person founded an organisation.
    { sourceLabel: "Person", edgeType: "FOUNDED", targetLabel: "Organization" },
    { sourceLabel: "Person", edgeType: "FOUNDED", targetLabel: "LocalBusiness" },
    // ADVISES — person advises an organisation or another person.
    { sourceLabel: "Person", edgeType: "ADVISES", targetLabel: "Organization" },
    { sourceLabel: "Person", edgeType: "ADVISES", targetLabel: "LocalBusiness" },
    { sourceLabel: "Person", edgeType: "ADVISES", targetLabel: "Person" },
    // MENTIONS — prose-bearing node mentions any entity.
    { sourceLabel: "Message", edgeType: "MENTIONS", targetLabel: "Person" },
    { sourceLabel: "Message", edgeType: "MENTIONS", targetLabel: "Organization" },
    { sourceLabel: "Message", edgeType: "MENTIONS", targetLabel: "LocalBusiness" },
    { sourceLabel: "Message", edgeType: "MENTIONS", targetLabel: "Event" },
    { sourceLabel: "Page", edgeType: "MENTIONS", targetLabel: "Person" },
    { sourceLabel: "Page", edgeType: "MENTIONS", targetLabel: "Organization" },
    { sourceLabel: "Page", edgeType: "MENTIONS", targetLabel: "LocalBusiness" },
    { sourceLabel: "Page", edgeType: "MENTIONS", targetLabel: "Event" },
    { sourceLabel: "Meeting", edgeType: "MENTIONS", targetLabel: "Person" },
    { sourceLabel: "Meeting", edgeType: "MENTIONS", targetLabel: "Organization" },
    // Task 321 retired :Email; email threads land as :KnowledgeDocument
    // {source:'email'} and the typed-edge pass picks them up via the
    // KnowledgeDocument tuples below.
    { sourceLabel: "KnowledgeDocument", edgeType: "MENTIONS", targetLabel: "Person" },
    { sourceLabel: "KnowledgeDocument", edgeType: "MENTIONS", targetLabel: "Organization" },
    // Task 397 — conversation transcripts moved off :KnowledgeDocument onto
    // :ConversationArchive. Twin the MENTIONS tuples so the typed-edge pass
    // still picks up entities referenced in chat exports.
    { sourceLabel: "ConversationArchive", edgeType: "MENTIONS", targetLabel: "Person" },
    { sourceLabel: "ConversationArchive", edgeType: "MENTIONS", targetLabel: "Organization" },
    { sourceLabel: "Note", edgeType: "MENTIONS", targetLabel: "Person" },
    { sourceLabel: "Note", edgeType: "MENTIONS", targetLabel: "Organization" },
    { sourceLabel: "Idea", edgeType: "MENTIONS", targetLabel: "Person" },
    { sourceLabel: "Idea", edgeType: "MENTIONS", targetLabel: "Organization" },
    { sourceLabel: "Post", edgeType: "MENTIONS", targetLabel: "Person" },
    { sourceLabel: "Post", edgeType: "MENTIONS", targetLabel: "Organization" },
    { sourceLabel: "Report", edgeType: "MENTIONS", targetLabel: "Person" },
    { sourceLabel: "Report", edgeType: "MENTIONS", targetLabel: "Organization" },
    // AUTHORED — person authored a prose-bearing artefact.
    { sourceLabel: "Person", edgeType: "AUTHORED", targetLabel: "Post" },
    { sourceLabel: "Person", edgeType: "AUTHORED", targetLabel: "Report" },
    { sourceLabel: "Person", edgeType: "AUTHORED", targetLabel: "Page" },
    { sourceLabel: "Person", edgeType: "AUTHORED", targetLabel: "Note" },
    // ATTACHED_TO — document or media attached to a higher-level entity.
    { sourceLabel: "KnowledgeDocument", edgeType: "ATTACHED_TO", targetLabel: "Meeting" },
    { sourceLabel: "Page", edgeType: "ATTACHED_TO", targetLabel: "Project" },
    { sourceLabel: "Note", edgeType: "ATTACHED_TO", targetLabel: "Project" },
    // REFERENCES — one prose-bearing node references another.
    { sourceLabel: "Page", edgeType: "REFERENCES", targetLabel: "Page" },
    { sourceLabel: "Report", edgeType: "REFERENCES", targetLabel: "Report" },
    { sourceLabel: "Report", edgeType: "REFERENCES", targetLabel: "Page" },
];
/** Set form for O(1) lookup during validation. */
const ALLOWLIST_SET = new Set(TYPED_EDGE_ALLOWLIST.map(({ sourceLabel, edgeType, targetLabel }) => `${sourceLabel}|${edgeType}|${targetLabel}`));
/** Returns true when this triple is allowed by the typed-edge pass. */
export function isAllowedTypedEdge(sourceLabel, edgeType, targetLabel) {
    return ALLOWLIST_SET.has(`${sourceLabel}|${edgeType}|${targetLabel}`);
}
/** Edge types the pass may propose, deduplicated and sorted. */
export const TYPED_EDGE_TYPES = Array.from(new Set(TYPED_EDGE_ALLOWLIST.map((p) => p.edgeType))).sort();
/** Set form for O(1) membership test. */
const TYPED_EDGE_TYPES_SET = new Set(TYPED_EDGE_TYPES);
/**
 * True when `edgeType` is governed by this allowlist — i.e. at least one
 * tuple in `TYPED_EDGE_ALLOWLIST` uses it. Callers outside the typed-edge
 * pass (e.g. document-ingest's writer) use this to decide whether to
 * validate a classifier-emitted edge's (source, target) labels against
 * `isAllowedTypedEdge`. Edge types absent from the allowlist (HAS_SECTION,
 * HAS_POSITION, PARTY, PARTICIPANT, …) are not governed and pass through
 * unchecked.
 */
export function isTypedEntityEdgeType(edgeType) {
    return TYPED_EDGE_TYPES_SET.has(edgeType);
}
/** Prose-bearing node labels the pass enumerates. Fixed set; non-prose labels are out of scope. */
export const PROSE_BEARING_LABELS = [
    "Message",
    "Page",
    "Meeting",
    "KnowledgeDocument",
    "ConversationArchive",
    "Idea",
    "Note",
    "Post",
    "Report",
];
//# sourceMappingURL=typed-edge-schema.js.map