nx_narrative_ingest.nx
buildroot/runtime/nx_narrative_ingest.nx
about
nx_narrative_ingest.nx -- DEPRECATED in favor of nx_text_ingest.nx.
>>> NEW CODE: import "nx_text_ingest.nx" and call nx_text_ingest(db, media_id).
>>> Targets the canonical media-agnostic StoryBeat schema
>>> (nx_storybeat.nx + nx_storydb.nx + nx_media_pool.nx).
>>>
>>> This file is kept in tree only to avoid breaking any in-flight
>>> dependents from the concurrent-agent edit window 2026-05-16/17.
>>> Remove after audit that no consumer remains.
----- ORIGINAL HEADER BELOW (predates the multi-media schema) -----
Foundation S-class ingester following the proven nx_coq_ingest /
nx_lean_ingest / nx_rfc_ingest pattern. Takes raw story text
(literotica chapter, hentai script, novel excerpt, fan-fic, etc.)
and parses it into a structured StoryDb of scenes + paragraphs +
beats that downstream extractors / arc recognizers / director
pipelines can consume.
Scope of THIS file: structural ingestion only. No NLP / no
semantic extraction / no domain tagging / no arc recognition.
That's the next layer (nx_story_element_extract.nx,
nx_story_beat_extract.nx, nx_plot_arc_recognize.nx).
Why structural-first: the same prose-tree shape works for ANY
narrative source. Browser-driven URL fetch, manual paste, voice
dictation, file-system batch -- all converge here.
Sources expected:
* URL via nishi-browser fetch (Phase 7)
* Manual paste (user pastes chapter text)
* Voice/conversation ("ingest this scene for me")
* Batch (directory of .txt files)
Substrate-native: no AI, no external network, no libc. Uses
canonical nx_lex / nx_ascii / nx_syscalls per cardinals.
genealogy_id: wiedijk_qed_1994 (the unified-ingestion vision)
+ propp_morphology_1928 (narrative structure roots)
lineage_id: formal_statement_parsing -> narrative_prose_parsing
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnx_lex.nxnx_ascii.nx
imported by: nobody (leaf or entry point)
structs
| 105 | struct StoryBeat |
| 121 | struct StoryScene |
| 131 | struct StoryChapter |
| 148 | struct StoryDb |
consts
| 91 | const NX_NARR_BEAT_UNKNOWN: i64 = 0 // not yet classified |
| 92 | const NX_NARR_BEAT_NARRATION: i64 = 1 // pure prose paragraph |
| 93 | const NX_NARR_BEAT_DIALOGUE: i64 = 2 // contains quoted speech |
| 94 | const NX_NARR_BEAT_ACTION: i64 = 3 // short, verb-heavy |
| 95 | const NX_NARR_BEAT_DESCRIPTION: i64 = 4 // long, adjective-heavy |
| 96 | const NX_NARR_BEAT_TRANSITION: i64 = 5 // scene-break marker (***, ---) |
| 97 | const NX_NARR_BEAT_HEADING: i64 = 6 // chapter/section title |
| 117 | const NX_NARR_BEAT_BYTES: i64 = 72 |
| 129 | const NX_NARR_SCENE_BYTES: i64 = 40 |
| 140 | const NX_NARR_CHAPTER_BYTES: i64 = 48 |
| 144 | const NX_NARR_MAX_BEATS: i64 = 65536 // ~65k paragraphs / chapter book |
| 145 | const NX_NARR_MAX_SCENES: i64 = 4096 |
| 146 | const NX_NARR_MAX_CHAPTERS: i64 = 256 |
functions
| 165 | func nx_narr_db_alloc(src: *u8, src_len: i64) -> *StoryDb |
| 182 | func nx_narr_beat_at(db: *StoryDb, i: i64) -> *StoryBeat called by 1: nx_narr_emit_beat |
| 186 | func nx_narr_scene_at(db: *StoryDb, i: i64) -> *StoryScene called by 1: nx_narr_ingest |
| 190 | func nx_narr_chapter_at(db: *StoryDb, i: i64) -> *StoryChapter called by 1: nx_narr_ingest |
| 203 | func nx_narr_is_scene_break(src: *u8, pos: i64, len: i64) -> i64 called by 1: nx_narr_ingest |
| 235 | func nx_narr_is_heading(src: *u8, pos: i64, len: i64) -> i64 called by 1: nx_narr_ingest |
| 255 | func nx_narr_advance_line(src: *u8, pos: *i64, len: i64) -> i64 |
| 266 | func nx_narr_skip_blank_lines(src: *u8, pos: *i64, len: i64) -> i64 called by 1: nx_narr_ingest |
| 306 | func nx_narr_emit_beat(db: *StoryDb, kind: i64, start: i64, end: i64, |
| 343 | func nx_narr_ingest(src: *u8, src_len: i64) -> *StoryDb |