import { AppLoggingService } from "../../../core/logging/services/logging.service"; import { ModelService } from "../../../core/llm/services/model.service"; import { HandbookModuleConfig } from "../interfaces/handbook.config.interface"; import { HandbookPageRepository } from "../repositories/handbook-page.repository"; import { HandbookSectionRepository } from "../repositories/handbook-section.repository"; import { HandbookPageService } from "./handbook-page.service"; export type HandbookSyncResult = { created: number; updated: number; unchanged: number; deleted: number; /** Repo-relative paths whose ingest threw. The walk continues past them. */ failed: string[]; }; export declare class HandbookIngestService { private readonly config; private readonly handbookPageRepository; private readonly handbookSectionRepository; private readonly handbookPageService; private readonly modelService; private readonly logger; constructor(config: Required, handbookPageRepository: HandbookPageRepository, handbookSectionRepository: HandbookSectionRepository, handbookPageService: HandbookPageService, modelService: ModelService, logger: AppLoggingService); sync(): Promise; /** * Writes the display translation onto the pages the English walk produced. * * The English tree is the source of truth for WHICH pages exist: a translated * file whose path has no English counterpart is counted and skipped, never * created. Creating it would put an unindexed page in the manual and — worse, * once someone pressed sync again — an English-less page in the retrieval * store. * * Nothing here chunks, embeds or enqueues. `updateDisplay` writes three * properties; `content`, `contentHash` and `aiStatus` are untouched, so the * index after this pass is byte-for-byte the index before it. */ private syncDisplay; private walk; /** * Glob support is deliberately the smallest thing that serves the config: * a literal prefix with a trailing `**`, or an exact path. No dependency, * nothing to misread. */ private isExcluded; /** * Splits a leading YAML frontmatter block off a markdown file and returns its * scalar keys. * * Still not a YAML parser: the block this reads is a handful of `key: value` * lines, and a dependency buys nothing but new failure modes on a malformed * block. Nested structures and lists are ignored rather than half-parsed. */ private splitFrontmatter; /** * The tree's own `README.md` index, parsed — or empty maps when it has none. * * Both roots go through this: the English tree and, when one is configured, * the display tree. A display README's link paths are relative to the display * root, which IS the English relative path, so the summaries it yields key * straight onto the English pages. */ private readIndex; private emptyIndex; /** * Reads the tree's own `README.md` index, when it has one. * * Two maps come out: section key to its heading title and blurb, and * repo-relative path to the one-line description the index gives it. Both are * optional by construction — an application with no README gets empty maps, * prettified section titles and pages with no summary, and the manual still * renders. */ private parseIndex; /** * Splits a section heading into the key it names and the title to print. * * Two forms are accepted: * * - `## 03-backend` — the bare directory key. The title is derived from it, * which is all a tree with no authored section names can offer. * - `## 03-backend — Backend` — the key, a dash, and an authored title. The * title is taken as written. * * The second form is the only place a section name can be written at all: a * section is a DIRECTORY, and a directory has no front matter to carry a * title. It is what lets a translated index name its sections in its own * language, and what lets an English one write "AI" where derivation would * sentence-case `06-ai` into "Ai". * * The separator must carry whitespace on both sides. Keys contain hyphens * (`00-start-here`), so a bare `-` would split the key itself. */ private headingOf; /** * The paragraph beneath a section heading, rebuilt into one sentence. * * A README wraps its prose, so the blurb arrives as several lines; joining * the contiguous run is the difference between a summary and a sentence cut * at "and an index". Collection starts at the first line that is neither * blank, nor a list item, nor inside a fenced code block, and stops at the * first blank line or list item after that. * * Fenced blocks are stepped over whole: a section that opens with one — the * a360 handbook's own `## Checking the handbook` does — must be summarised by * its prose, not by a fence or by the command inside it. */ private blurbOf; /** * `00-start-here` becomes "Start here". The numeric prefix orders the * directories on disk and is noise on screen; a key with no prefix is used * as written. */ private sectionTitle; /** * Frontmatter `title` first, then the first H1, then the filename. The * handbook this was built against uses frontmatter and no H1 at all, so the * H1 branch exists for directories that are written the other way. */ private titleOf; } //# sourceMappingURL=handbook-ingest.service.d.ts.map