feat(entity): Chunk #4 remaining items — consistency UI, context rail, palette search, expanded seed & DATA_MODEL
- Consistency tab in EntitiesView surfacing findInconsistencies() results - ContextRail + MentionPopover wired into WritingView for entity context/hover - CommandPalette indexes entities and chapters for cross-entity search - link field type for entity references in character fields - findDeadCharacterMentions consistency check + tests - Expand seed with a location, note, and a natural Elias Vell mention so the dead-character-after-death case is actually exercised - Author docs/DATA_MODEL.md documenting core schemas, types, storage contract - Rename CharacterMention id attr -> entityId to match core backlinks/consistency
This commit is contained in:
@@ -3,9 +3,11 @@ import {
|
||||
findOrphanedMentions,
|
||||
parseRelationships,
|
||||
findRelationshipAsymmetry,
|
||||
findDeadCharacterMentions,
|
||||
findInconsistencies,
|
||||
SYMMETRIC_RELATIONSHIPS,
|
||||
} from "./consistency.js";
|
||||
import { collectMentionsInDoc } from "./backlinks.js";
|
||||
import type { Character, Entity, ProseMirrorDoc } from "./types.js";
|
||||
|
||||
const doc = (entityId: string | null, name = "Mara"): ProseMirrorDoc => ({
|
||||
@@ -152,12 +154,32 @@ describe("findRelationshipAsymmetry", () => {
|
||||
});
|
||||
|
||||
describe("findInconsistencies", () => {
|
||||
it("combines orphan-mention and relationship-asymmetry issues", () => {
|
||||
const chapters = [{ id: "ch1", title: "Ch 1", doc: doc("ghost") }];
|
||||
it("combines orphan-mention, relationship-asymmetry, and dead-character issues", () => {
|
||||
// Chapter mentions "ghost" (orphan) and "ada" (dead character still alive in prose).
|
||||
const chapters = [
|
||||
{
|
||||
id: "ch1",
|
||||
title: "Ch 1",
|
||||
doc: {
|
||||
type: "doc",
|
||||
content: [
|
||||
{
|
||||
type: "paragraph",
|
||||
content: [
|
||||
{ type: "text", text: "Ada met " },
|
||||
{ type: "CharacterMention", attrs: { entityId: "ada", name: "Ada" } },
|
||||
{ type: "text", text: " and a " },
|
||||
{ type: "CharacterMention", attrs: { entityId: "ghost", name: "ghost" } },
|
||||
],
|
||||
},
|
||||
],
|
||||
} as ProseMirrorDoc,
|
||||
},
|
||||
];
|
||||
const ada: Character = {
|
||||
id: "ada", projectId: "p", name: "Ada", role: "", bio: "", appearance: "", voice: "",
|
||||
relationships: [{ targetId: "maria", kind: "sibling", note: "" }],
|
||||
arc: "", status: "active", tags: [],
|
||||
arc: "", status: "dead", tags: [],
|
||||
};
|
||||
const maria: Character = {
|
||||
id: "maria", projectId: "p", name: "Maria", role: "", bio: "", appearance: "", voice: "",
|
||||
@@ -167,5 +189,36 @@ describe("findInconsistencies", () => {
|
||||
const issues = findInconsistencies(chapters, entities);
|
||||
expect(issues.some((i) => i.kind === "orphan-mention")).toBe(true);
|
||||
expect(issues.some((i) => i.kind === "relationship-asymmetry")).toBe(true);
|
||||
expect(issues.some((i) => i.kind === "dead-character-mentioned")).toBe(true);
|
||||
});
|
||||
|
||||
it("does not flag a dead character who is not mentioned in any chapter", () => {
|
||||
const chapters = [{ id: "ch1", title: "Ch 1", doc: doc("ghost") }];
|
||||
const ada: Character = {
|
||||
id: "ada", projectId: "p", name: "Ada", role: "", bio: "", appearance: "", voice: "",
|
||||
arc: "", status: "dead", tags: [],
|
||||
relationships: [],
|
||||
};
|
||||
const issues = findDeadCharacterMentions(chapters, [ada]);
|
||||
expect(issues).toHaveLength(0);
|
||||
});
|
||||
|
||||
it("collects every entity id referenced in a doc", () => {
|
||||
const docWithTwo = {
|
||||
type: "doc",
|
||||
content: [
|
||||
{
|
||||
type: "paragraph",
|
||||
content: [
|
||||
{ type: "text", text: "Ada and " },
|
||||
{ type: "CharacterMention", attrs: { entityId: "maria", name: "Maria" } },
|
||||
{ type: "text", text: " met " },
|
||||
{ type: "CharacterMention", attrs: { entityId: "brad", name: "Brad" } },
|
||||
],
|
||||
},
|
||||
],
|
||||
} as ProseMirrorDoc;
|
||||
const ids = collectMentionsInDoc(docWithTwo);
|
||||
expect([...ids].sort()).toEqual(["brad", "maria"]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user