@saasontools/strauss-kb 0.1.18 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.26_supports-color@8.1.1_typescript@6.0.3_yaml@2.9.0/node_modules/tsup/assets/cjs_shims.js","../src/mcp.ts","../src/decision-record.ts","../src/compose.ts","../src/kb-record.schema.ts","../src/record-types.ts","../src/commands/anchor-resolve.ts","../src/concurrency.ts","../src/remote-repo/cache.ts","../src/anchor-resolver/repo-identity.ts","../src/remote-repo/model.ts","../src/remote-repo/read.ts","../src/remote-repo/git.ts","../src/anchor-resolver/model.ts","../src/remote-repo/validate.ts","../src/anchor-resolver/read.ts","../src/anchor-resolver/resolver.ts","../src/tree-sitter-resolver/languages.ts","../src/grammars/index.ts","../src/grammars/store.ts","../src/grammars/fetch.ts","../src/grammars/manifest.ts","../src/grammars/model.ts","../src/tree-sitter-resolver/resolver.ts","../src/tree-sitter-resolver/definitions.ts","../src/tree-sitter-resolver/tokens.ts","../src/anchor-resolver/drift.ts","../src/errors.ts","../src/kb-errors.ts","../src/kb-pins/budgets.ts","../src/kb-pins/errors.ts","../src/kb-pins/frozen.ts","../src/kb-pins/layers.ts","../src/kb-pins/model.ts","../src/kb-pins/list.ts","../src/kb-pins/pin.ts","../src/kb-pins/unpin.ts","../src/commands/model.ts","../src/commands/answer.ts","../src/commands/backlinks.ts","../src/commands/catalog.ts","../src/adjudicate.ts","../src/catalog.ts","../src/commands/context.ts","../src/kb-context.ts","../src/kb-index.ts","../src/commands/doctor.ts","../src/drift/git.ts","../src/drift/moved.ts","../src/drift/classify.ts","../src/drift/diff.ts","../src/drift/packet.ts","../src/kb-edges.ts","../src/validate.ts","../src/doctor.ts","../src/commands/reassess.ts","../src/commands/impact.ts","../src/commands/list.ts","../src/commands/load.ts","../src/commands/log.ts","../src/commands/no-decision.ts","../src/commands/pack.ts","../src/commands/pin.ts","../src/commands/pins.ts","../src/commands/query.ts","../src/commands/read-index.ts","../src/commands/schema.ts","../src/json-schema.ts","../src/kb-log.ts","../src/commands/stamp.ts","../src/commands/status.ts","../src/commands/supersede.ts","../src/commands/sync-instructions.ts","../src/commands/trace.ts","../src/trace.ts","../src/commands/types.ts","../src/commands/unpin.ts","../src/commands/validate.ts","../src/commands/verify.ts","../src/commands/write.ts","../src/commands/write-decision.ts","../src/commands/index.ts","../src/kb-store.ts","../src/markdown.ts","../src/kb-stamp.ts","../src/search-index.ts","../src/pack.ts","../src/kb-links/inbound.ts","../src/kb-links/backlinks.ts","../src/kb-links/impact.ts","../src/kb-gitattributes.ts","../src/version.ts","../src/mcp-main.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { KB_COMMANDS } from \"./commands/index.js\";\nimport { KbStore } from \"./kb-store.js\";\nimport { VERSION } from \"./version.js\";\n\n/**\n * A knowledge base's own MCP server, over stdio.\n *\n * Standalone because a base is self-contained: a directory of markdown that\n * needs no database, no HTTP surface, and no running service to read. Folding\n * these tools into a larger server would make every consumer start that server\n * to open files it could open itself.\n *\n * Every tool is a projection of `KB_COMMANDS`, which the CLI also projects, so\n * the two cannot drift.\n */\nexport function createKbMcpServer(): McpServer {\n const server = new McpServer({ name: \"strauss-kb\", version: VERSION });\n const store = new KbStore({\n warn: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n });\n const ctx = {\n store,\n actor: process.env.STRAUSS_KB_ACTOR ?? \"mcp\",\n now: () => new Date().toISOString(),\n };\n\n for (const command of KB_COMMANDS) {\n // CLI-only plumbing (sync-instructions) edits files for hooks and\n // instruction blocks; the agent capability it serves is kb_context.\n if (!command.tool) continue;\n server.registerTool(\n command.tool,\n { description: command.description, inputSchema: command.input.shape },\n async (args: unknown) => {\n const result = await command.run(ctx, command.input.parse(args));\n return {\n content: [\n {\n type: \"text\" as const,\n text:\n typeof result === \"string\"\n ? result\n : JSON.stringify(result, null, 2),\n },\n ],\n };\n },\n );\n }\n\n return server;\n}\n\nexport async function runKbMcpServer(): Promise<void> {\n await createKbMcpServer().connect(new StdioServerTransport());\n}\n","import { z } from \"zod\";\nimport {\n composeInputSchema,\n composeRecord,\n type ComposedRecord,\n} from \"./compose.js\";\nimport type { KbRecord } from \"./kb-record.schema.js\";\n\n/**\n * The record written while a change is being made: why it is shaped the way it\n * is, anchored to the symbols it touches.\n *\n * A decision is the one thing a later pass cannot recover. The diff shows what\n * changed; nothing in it says which alternative was rejected, or which\n * constraint a future reader would otherwise \"simplify\" away. Everything else a\n * review needs — categories, moves, formatting — is derivable from the finished\n * diff and does not belong here.\n */\nexport const DECISION_TYPE = \"decision\";\n\n/**\n * Slug for the explicit \"nothing to record here\" answer.\n *\n * Gating on \"did you write a decision?\" rewards writing a junk decision. Gating\n * on \"did you answer?\" does not, so silence has to be expressible as a claim:\n * one record, one sentence, auditable after the fact. Work that genuinely\n * needed no decision says so; work that says nothing at all is the case worth\n * surfacing.\n */\nexport const NO_DECISION_SLUG = \"none\";\n\n/**\n * Decisions keep a typed input of their own where the generic composer takes a\n * section map. `alternative` is not a nicety here — \"what was rejected\" is the\n * part of a decision that a later reader cannot reconstruct, so it gets a field\n * rather than a heading a writer may forget to fill.\n */\nexport const decisionInputSchema = composeInputSchema\n .omit({ sections: true })\n .extend({\n alternative: z.string().min(1).optional(),\n impact: z.string().min(1).optional(),\n })\n .strict();\n\nexport type DecisionInput = z.infer<typeof decisionInputSchema>;\n\nexport function composeDecisionRecord(\n input: DecisionInput,\n writtenBy: string,\n writtenAt: string,\n): ComposedRecord {\n const { alternative, impact, ...rest } = input;\n return composeRecord(\n DECISION_TYPE,\n {\n ...rest,\n sections: {\n Decision: input.title,\n Rationale: input.why,\n ...(alternative ? { Rejected: alternative } : {}),\n ...(impact ? { Impact: impact } : {}),\n },\n },\n writtenBy,\n writtenAt,\n );\n}\n\n/** The explicit no-decision claim, so an absence and an answer stay distinct. */\nexport function composeNoDecisionRecord(\n reason: string,\n writtenBy: string,\n writtenAt: string,\n): ComposedRecord {\n return composeRecord(\n DECISION_TYPE,\n {\n slug: NO_DECISION_SLUG,\n title: \"No decision to record\",\n why: reason,\n sections: { Decision: reason },\n },\n writtenBy,\n writtenAt,\n );\n}\n\n/** Whether a record is the explicit no-decision claim rather than a decision. */\nexport function isNoDecisionRecord(record: KbRecord): boolean {\n return record.conceptId === `${DECISION_TYPE}.${NO_DECISION_SLUG}`;\n}\n\n/**\n * Decisions in the bundle, excluding the no-decision claim.\n *\n * Callers asking \"what was decided\" must not be handed the record that exists\n * precisely to say nothing was.\n */\nexport function selectDecisions(records: KbRecord[]): KbRecord[] {\n return records.filter(\n (record) =>\n record.conceptId.startsWith(`${DECISION_TYPE}.`) &&\n !isNoDecisionRecord(record),\n );\n}\n","import { z } from \"zod\";\nimport {\n kbAnchorSchema,\n kbConceptIdSchema,\n kbSourceSchema,\n KB_CONFIDENCES,\n KB_MATERIALITIES,\n type KbRecordFrontmatter,\n type KbRecordType,\n} from \"./kb-record.schema.js\";\nimport { KB_LINK_RELS, LINK_RELS, RECORD_TYPES } from \"./record-types.js\";\n\n/**\n * One typed causal edge, as a producer states it.\n *\n * Strict where `kbLinkSchema` is tolerant, the same split\n * `kbVerifiedEventSchema` makes against `kbActorStampSchema`: what this package\n * writes must be inside the closed vocabulary, what it reads may not be, since\n * a foreign record has to stay loadable for `kb_validate` to fault it.\n */\nexport const composeLinkSchema = z\n .object({\n target: kbConceptIdSchema,\n rel: z.enum(KB_LINK_RELS),\n })\n .strict();\n\nexport type ComposeLink = z.infer<typeof composeLinkSchema>;\n\nexport const composeInputSchema = z\n .object({\n slug: z.string().min(1),\n /** One line, in the reader's terms. Becomes OKF `title`. */\n title: z.string().min(1),\n /** The consequence — what breaks if this is wrong. Becomes `description`. */\n why: z.string().min(1),\n /** Keyed by section heading from the type's spec. Unknown keys rejected. */\n sections: z.record(z.string(), z.string().min(1)).optional(),\n anchors: z.array(kbAnchorSchema).optional(),\n sources: z.array(kbSourceSchema).optional(),\n /** No source exists, as a claim rather than a sentinel in `sources`. */\n assumption: z.boolean().optional(),\n /**\n * OKF `stale_after`: the absolute date this record stops being trusted.\n * Anything the outside world can change — pricing, quotas, versions,\n * reception counts — should carry one.\n */\n stale_after: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, {\n message: \"stale_after must be YYYY-MM-DD\",\n })\n .refine((date) => !Number.isNaN(Date.parse(date)), {\n message: \"stale_after must be a real date\",\n })\n .optional(),\n verify: z.array(z.string().min(1)).optional(),\n tags: z.array(z.string().min(1)).optional(),\n /** Concept ids this record relates to; rendered as body links. */\n relatedConceptIds: z.array(kbConceptIdSchema).optional(),\n /**\n * Typed causal edges, source → target: `{ target: \"fact.b\", rel:\n * \"depends_on\" }` on record A says A needs B. Stored in frontmatter and\n * also rendered as one prose sentence each, so the meaning survives a\n * reader that knows only OKF. The vocabulary goes into the description from\n * the same table the walk uses, so `kb_schema` emits it.\n */\n links: z\n .array(composeLinkSchema)\n .max(64)\n .optional()\n .describe(\n `Typed causal edges, source → target — a link on this record says this record <rel> the target. ${KB_LINK_RELS.map(\n (rel) => `${rel}: ${LINK_RELS[rel].purpose}`,\n ).join(\"; \")}.`,\n ),\n /** Concept ids this record replaces. The store settles the backlinks. */\n supersedes: z.array(kbConceptIdSchema).max(32).optional(),\n materiality: z.enum(KB_MATERIALITIES).optional(),\n confidence: z.enum(KB_CONFIDENCES).optional(),\n owner: z.string().min(1).optional(),\n })\n .strict();\n\nexport type ComposeInput = z.infer<typeof composeInputSchema>;\n\nexport type ComposedRecord = {\n type: string;\n slug: string;\n frontmatter: Omit<KbRecordFrontmatter, \"type\">;\n body: string;\n};\n\n/**\n * Builds one record's frontmatter and body from its type's spec.\n *\n * Edges go in the body rather than frontmatter because that is where OKF puts\n * them: consumers read markdown links as directed but untyped relationships,\n * with \"the specific kind conveyed by the surrounding prose, not by the link\n * itself\". Broken links are explicitly legal, which matters here — records are\n * routinely written before the ones they point at exist.\n */\nexport function composeRecord(\n type: KbRecordType,\n input: ComposeInput,\n writtenBy: string,\n writtenAt: string,\n): ComposedRecord {\n // Parsed here rather than trusted from the caller: the CLI validates its own\n // stdin, but a library caller has no such gate, and `relatedConceptIds` is\n // interpolated into a markdown link unescaped a few lines down.\n const parsed = composeInputSchema.parse(input);\n const spec = RECORD_TYPES[type];\n const sections = parsed.sections ?? {};\n\n const unknown = Object.keys(sections).filter(\n (heading) => !spec.sections.includes(heading),\n );\n if (unknown.length) {\n throw new Error(\n `kb: ${type} has no section ${unknown.join(\", \")} — expected one of ${spec.sections.join(\", \")}`,\n );\n }\n\n const frontmatter: Omit<KbRecordFrontmatter, \"type\"> = {\n title: parsed.title,\n description: parsed.why,\n generated: { by: writtenBy, at: writtenAt },\n // Empty rather than absent: a later verification pass appends here, and an\n // empty list says \"not yet verified\" where a missing key would only say\n // \"this producer didn't think about it\".\n verified: [],\n strauss_status: spec.initialStatus,\n };\n if (parsed.stale_after) frontmatter.stale_after = parsed.stale_after;\n if (parsed.anchors?.length) frontmatter.strauss_anchors = parsed.anchors;\n if (parsed.verify?.length) frontmatter.strauss_verify = parsed.verify;\n if (parsed.tags?.length) frontmatter.tags = parsed.tags;\n if (parsed.sources?.length) frontmatter.sources = parsed.sources;\n if (parsed.assumption) frontmatter.strauss_assumption = true;\n if (parsed.materiality) frontmatter.strauss_materiality = parsed.materiality;\n if (parsed.confidence) frontmatter.strauss_confidence = parsed.confidence;\n if (parsed.owner) frontmatter.strauss_owner = parsed.owner;\n if (parsed.supersedes?.length)\n frontmatter.strauss_supersedes = parsed.supersedes;\n // Refused on the write path, where the caller can still fix it: a self-link\n // asserts a record depends on itself, which every walk skips. `kb_validate`\n // keeps it a warning, since by then the choice is between reporting it and\n // refusing to load the file.\n const selfLink = parsed.links?.find(\n (link) => link.target === `${type}.${parsed.slug}`,\n );\n if (selfLink) {\n throw new Error(\n `kb: ${type}.${parsed.slug} cannot ${selfLink.rel} itself — a link must name another record`,\n );\n }\n if (parsed.links?.length) frontmatter.strauss_links = parsed.links;\n\n const blocks: string[] = [];\n for (const heading of spec.sections) {\n const text = sections[heading];\n // Omitted rather than stubbed: an empty \"## Evidence\" reads as evidence\n // that was sought and not found.\n if (text) blocks.push(`## ${heading}\\n\\n${text}`);\n }\n if (!blocks.length) blocks.push(parsed.why);\n\n for (const related of parsed.relatedConceptIds ?? []) {\n blocks.push(`Relates to [${related}](${related}.md).`);\n }\n\n // One sentence per typed link, from a fixed template per rel. A walk reads\n // the edge from frontmatter, but a plain-OKF consumer ignores frontmatter it\n // does not recognise, so the claim is also stated as prose around a markdown\n // link — OKF's own spelling for a typed relationship. Fixed rather than free\n // text so the sentence cannot say something the rel does not.\n for (const link of parsed.links ?? []) {\n blocks.push(\n `${LINK_RELS[link.rel].phrase} [${link.target}](${link.target}.md).`,\n );\n }\n\n if (parsed.sources?.length) {\n blocks.push(\n parsed.sources\n .map((source) => `[^${source.id}]: ${source.title ?? source.resource}`)\n .join(\"\\n\"),\n );\n }\n\n return {\n type,\n slug: parsed.slug,\n frontmatter,\n body: `${blocks.join(\"\\n\\n\")}\\n`,\n };\n}\n","import { z } from \"zod\";\n\n/**\n * Knowledge records, shaped as OKF v0.2 concepts.\n *\n * OKF (Google Cloud `knowledge-catalog`) requires exactly one key — `type` —\n * and explicitly permits extension: \"Producers MAY include any additional keys.\n * Consumers SHOULD preserve unknown keys when round-tripping and MUST NOT\n * reject documents with unrecognized fields.\"\n *\n * A record's identity is its `concept_id`: the file path within the bundle with\n * `.md` removed. `<type>.<slug>.md` therefore yields `decision.some-slug`.\n *\n * Keys prefixed `strauss_` are this package's extensions rather than\n * conformance, and are namespaced so a later OKF version defining the same\n * names cannot collide: OKF names files through path-valued `resource` fields\n * and has no notion of a span, so anchoring a concept to a range of code has no\n * standard spelling, and standing has none either.\n */\n\n/** A source the record draws on. Footnotes in the body key to `id`. */\nexport const kbSourceSchema = z\n .object({\n id: z.string().min(1),\n resource: z.string().min(1),\n title: z.string().min(1).optional(),\n author: z.string().min(1).optional(),\n last_modified: z.string().min(1).optional(),\n })\n .passthrough();\n\n/** An actor/time pair — OKF's shape for both `generated` and `verified[]`. */\nexport const kbActorStampSchema = z\n .object({\n by: z.string().min(1),\n at: z.string().min(1),\n })\n .passthrough();\n\n/**\n * A `verified[]` event as this package writes one: the actor stamp plus a\n * required note saying what the check found. Write-side only — the frontmatter\n * keeps reading `verified` with `kbActorStampSchema`, because OKF-native\n * entries carry no note and a consumer must not reject conformant records.\n */\nexport const kbVerifiedEventSchema = kbActorStampSchema.extend({\n note: z.string().refine((s) => s.trim().length > 0, {\n message: \"note must say what the check found\",\n }),\n});\n\n/**\n * Where a record attaches in the code.\n *\n * Symbolic on purpose. These are written while the code is still moving: a\n * `line: 379` recorded at minute five is wrong by minute forty, but\n * `OrderService.cancel` survives every edit that does not rename it. Once the\n * change settles, a resolution pass (`anchor-resolver/`) stamps `hash`,\n * `resolved_at`, and `lines`; drift detection later re-resolves and compares.\n *\n * `hash` is prefixed with the algorithm so a future one can coexist with\n * stored values. `lines` exists because the anchor keeps a hash, not the text:\n * without the line count at hash time, a drift report could say \"changed\" but\n * never how much.\n *\n * `repo` and `ref` say *which* code, for bases that describe more than one\n * repository. They are author-owned identity: a resolver stamps `hash`,\n * `lines`, and `resolved_at`, and never writes these two. Both are optional and\n * independent of each other, so every anchor written before they existed stays\n * valid.\n */\nexport const kbAnchorSchema = z\n .object({\n file: z.string().min(1),\n symbol: z.string().min(1).optional(),\n /**\n * Which repository the file lives in — a remote URL\n * (`https://github.com/org/name`) or a short name. Absent means the base's\n * own repository, which is what nearly every anchor means.\n *\n * Unvalidated beyond not-blank: one repository has many spellings, matched\n * after normalisation. Only a full URL can be fetched from, so `validate`\n * warns on a short one; see ARCHITECTURE.\n */\n repo: z.string().trim().min(1).optional(),\n /**\n * The git rev the evidence was taken at. Prefer a commit SHA: a branch\n * name is a moving pointer, so an anchor pinned to one says the evidence\n * came from wherever that branch happens to be now, which is not a\n * baseline. A foreign anchor is checked at this rev, and compared against\n * the remote's default branch on top of it.\n */\n ref: z.string().trim().min(1).optional(),\n hash: z\n .string()\n .regex(/^sha256:[0-9a-f]{64}$/, {\n message: \"hash must be sha256:<64 hex chars>\",\n })\n .optional(),\n /**\n * What `hash` was taken over: the span's raw text, or the normalised token\n * stream a parser sees (`ast`). Absent means `raw`, which is what every\n * anchor stamped before this field carries, so old hashes keep comparing\n * the way they were written. An `ast` hash is blind to whitespace and\n * comments, so reformatting the anchored code is not drift.\n */\n hash_kind: z.enum([\"raw\", \"ast\"]).optional(),\n /** ISO 8601 timestamp of the last successful resolution. */\n resolved_at: z.string().min(1).optional(),\n /** Line count of the text the hash was taken over. */\n lines: z.number().int().positive().optional(),\n /**\n * Which resolver produced the hashed span. Absent means an anchor stamped\n * before resolvers were named, which is read as `regex` — the only one\n * there was. A hash from a different resolver is drift, not a match.\n */\n resolver: z.enum([\"tree-sitter\", \"regex\"]).optional(),\n })\n .strict();\n\n/**\n * One typed causal edge, as the frontmatter stores it.\n *\n * Read-side, and therefore tolerant: `rel` is a plain string here even though\n * the vocabulary is closed, for the same reason `type` is. Rejecting an unknown\n * rel at parse time would make the file vanish from `list()`, and a bundle\n * cannot report a defect in a record it refuses to load. `kb_validate` turns an\n * unknown rel into an error; `composeRecord` stops one being written.\n *\n * `target` is likewise not required to resolve — a dangling target is a\n * validation warning rather than a parse failure.\n */\nexport const kbLinkSchema = z\n .object({\n target: z.string().min(1),\n rel: z.string().min(1),\n })\n .passthrough();\n\nexport const KB_RECORD_TYPES = [\n \"fact\",\n \"requirement\",\n \"constraint\",\n \"decision\",\n \"assumption\",\n \"open-question\",\n \"risk\",\n \"contract\",\n \"flow\",\n \"affected-system\",\n \"test-obligation\",\n \"source-note\",\n] as const;\n\nexport type KbRecordType = (typeof KB_RECORD_TYPES)[number];\n\n/** Both halves of `<type>.<slug>` are kebab-case, and neither may be empty. */\nexport const KB_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nexport const KB_CONCEPT_ID_PATTERN =\n /^[a-z0-9]+(?:-[a-z0-9]+)*\\.[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n/**\n * Concept ids are rendered into markdown links unescaped, so an id carrying a\n * `]` or `)` would emit a broken edge rather than fail. Validating at the entry\n * point keeps the renderer from having to care.\n */\nexport const kbConceptIdSchema = z.string().regex(KB_CONCEPT_ID_PATTERN, {\n message: \"concept id must be <type>.<slug>, both kebab-case\",\n});\n\n/**\n * Standing, not freshness.\n *\n * OKF's `verified[]` and `stale_after` answer \"is this still true?\"; nothing in\n * the spec answers \"is this settled, and does it still apply?\". A base\n * supersedes its own conclusions as work proceeds, so that second question\n * needs an answer, and it is this package's to define — hence `strauss_`.\n */\nexport const KB_RECORD_STATUSES = [\n \"draft\",\n \"proposed\",\n \"accepted\",\n \"open\",\n \"resolved\",\n \"rejected\",\n \"superseded\",\n] as const;\n\nexport type KbRecordStatus = (typeof KB_RECORD_STATUSES)[number];\n\nexport const KB_MATERIALITIES = [\n \"blocking\",\n \"important\",\n \"non-blocking\",\n] as const;\nexport const KB_CONFIDENCES = [\"low\", \"medium\", \"high\"] as const;\n\nexport const kbRecordFrontmatterSchema = z\n .object({\n // OKF: the only always-required key. A concept carrying just `type` is\n // fully conformant, so everything below stays optional.\n type: z.string().min(1),\n\n // OKF recommended.\n title: z.string().min(1).optional(),\n description: z.string().min(1).optional(),\n resource: z.string().min(1).optional(),\n tags: z.array(z.string()).optional(),\n\n // OKF optional: provenance and freshness.\n sources: z.array(kbSourceSchema).optional(),\n generated: kbActorStampSchema.optional(),\n verified: z.array(kbActorStampSchema).optional(),\n stale_after: z.string().min(1).optional(),\n\n // strauss extensions — see the module comment.\n strauss_anchors: z.array(kbAnchorSchema).optional(),\n strauss_verify: z.array(z.string().min(1)).optional(),\n\n // Typed causal edges, source → target, living on the source. `A depends_on\n // B` means A needs B, so `kb_impact` walks these inbound: what breaks if B\n // changes is whatever declared a dependence on it.\n strauss_links: z.array(kbLinkSchema).optional(),\n\n // Total after parsing, tolerant before it. Our producers must supply a\n // status — an absent one would leave every reader inventing its own default\n // — but OKF calls a concept carrying only `type` fully conformant, so\n // rejecting a foreign record for the lack of one would put us outside the\n // spec. The default resolves it in the single place that can: here.\n strauss_status: z.enum(KB_RECORD_STATUSES).default(\"draft\"),\n strauss_supersedes: z.array(z.string().min(1)).optional(),\n strauss_superseded_by: z.string().min(1).optional(),\n strauss_answered: kbActorStampSchema.optional(),\n strauss_materiality: z.enum(KB_MATERIALITIES).optional(),\n strauss_confidence: z.enum(KB_CONFIDENCES).optional(),\n strauss_owner: z.string().min(1).optional(),\n\n // \"No source exists\" as a field rather than a sentinel entry inside\n // `sources`. A sentinel in a reference list is a value doing work a field\n // should do; as a field, `sources` may be legitimately empty.\n strauss_assumption: z.boolean().optional(),\n })\n // Unknown keys are kept rather than stripped: OKF requires consumers to\n // preserve them when round-tripping, and a producer we don't know about may\n // be writing into the same bundle.\n .passthrough();\n\nexport type KbSource = z.infer<typeof kbSourceSchema>;\nexport type KbActorStamp = z.infer<typeof kbActorStampSchema>;\nexport type KbVerifiedEvent = z.infer<typeof kbVerifiedEventSchema>;\nexport type KbAnchor = z.infer<typeof kbAnchorSchema>;\nexport type KbLink = z.infer<typeof kbLinkSchema>;\nexport type KbRecordFrontmatter = z.infer<typeof kbRecordFrontmatterSchema>;\n\nexport type KbRecord = {\n /** Path minus `.md`, relative to the bundle root. OKF's concept identity. */\n conceptId: string;\n frontmatter: KbRecordFrontmatter;\n body: string;\n};\n","import type { KbRecordStatus, KbRecordType } from \"./kb-record.schema.js\";\n\n/**\n * What each record type is for, and the shape of its body.\n *\n * A table rather than twelve composer modules. The types differ only in which\n * questions their body answers and where they start in the lifecycle; encoding\n * that as data keeps the one composer honest and makes adding a type an edit\n * rather than a file.\n *\n * `sections` are ordered. A section the caller leaves empty is omitted rather\n * than rendered with a placeholder — an empty \"## Evidence\" reads as evidence\n * that was looked for and not found.\n */\nexport type KbRecordTypeSpec = {\n /** One line, for `INDEX.md` legends and CLI help. */\n purpose: string;\n /** Ordered body headings. The first is the record's central claim. */\n sections: readonly string[];\n /** Where a freshly written record of this type starts. */\n initialStatus: KbRecordStatus;\n};\n\nexport const RECORD_TYPES: Readonly<Record<KbRecordType, KbRecordTypeSpec>> = {\n fact: {\n purpose: \"Observed or sourced fact\",\n sections: [\"Claim\", \"Evidence\", \"Implication\"],\n initialStatus: \"accepted\",\n },\n requirement: {\n purpose: \"Required behavior or outcome\",\n sections: [\"Claim\", \"Evidence\", \"Implication\"],\n initialStatus: \"proposed\",\n },\n constraint: {\n purpose: \"Limitation, compatibility boundary, policy, or restriction\",\n sections: [\"Claim\", \"Evidence\", \"Implication\"],\n initialStatus: \"accepted\",\n },\n decision: {\n purpose: \"Chosen or proposed direction\",\n sections: [\"Decision\", \"Rationale\", \"Rejected\", \"Impact\"],\n initialStatus: \"accepted\",\n },\n assumption: {\n purpose: \"Unsourced or not-yet-confirmed working assumption\",\n sections: [\"Claim\", \"Why we think so\", \"What would falsify it\"],\n initialStatus: \"draft\",\n },\n \"open-question\": {\n purpose: \"Question needing resolution\",\n sections: [\"Question\", \"Why it matters\", \"Default assumption\"],\n initialStatus: \"open\",\n },\n risk: {\n purpose: \"Something that can go wrong\",\n sections: [\"Risk\", \"Why it matters\", \"Mitigation\", \"Verification\"],\n initialStatus: \"open\",\n },\n contract: {\n purpose: \"API, data, event, schema, or permission contract\",\n sections: [\"Contract\", \"Producer\", \"Consumer\", \"Compatibility\"],\n initialStatus: \"proposed\",\n },\n flow: {\n purpose: \"Sequence, lifecycle, or state behavior\",\n sections: [\"Flow\", \"Trigger\", \"Steps\", \"Failure modes\"],\n initialStatus: \"accepted\",\n },\n \"affected-system\": {\n purpose: \"Component, service, package, integration, or external system\",\n sections: [\"System\", \"How it is affected\", \"Blast radius\"],\n initialStatus: \"accepted\",\n },\n \"test-obligation\": {\n purpose: \"Behavior or contract that must be verified\",\n sections: [\"Obligation\", \"Why it matters\", \"How to verify\"],\n initialStatus: \"open\",\n },\n \"source-note\": {\n purpose: \"Extracted note from source material\",\n sections: [\"Note\", \"Where it came from\"],\n initialStatus: \"accepted\",\n },\n};\n\nexport function isKbRecordType(value: string): value is KbRecordType {\n return Object.prototype.hasOwnProperty.call(RECORD_TYPES, value);\n}\n\n/**\n * The closed vocabulary of typed causal edges — `strauss_links[].rel` — which a\n * producer may not extend. `related_to` is the non-dependence escape hatch and\n * the one rel `kb_impact` does not follow. Every edge lives on the source's\n * frontmatter, source → target; `phrase` is the template compose.ts renders.\n */\nexport type KbLinkRelSpec = {\n /** One line, for schema output and CLI help. */\n purpose: string;\n /** Sentence stem: `<phrase> [target](target.md).` */\n phrase: string;\n /**\n * Which end of the edge breaks when the other end changes.\n *\n * The rel's *direction of dependence*, which does not follow the edge's own\n * direction. `A depends_on B` puts the dependant at the source: A breaks when\n * B moves. `A informs B` puts it at the target. A walk that treated both as\n * \"inbound\" would report the blast radius of `informs`, `blocks`,\n * `invalidates` and `constrains` backwards.\n *\n * `null` means the rel asserts no dependence either way, so nothing\n * propagates along it. `related_to` is the only such rel.\n */\n dependant: \"source\" | \"target\" | null;\n};\n\nexport const KB_LINK_RELS = [\n \"depends_on\",\n \"constrains\",\n \"informs\",\n \"blocks\",\n \"invalidates\",\n \"verified_by\",\n \"satisfies\",\n \"related_to\",\n] as const;\n\nexport type KbLinkRel = (typeof KB_LINK_RELS)[number];\n\nexport const LINK_RELS: Readonly<Record<KbLinkRel, KbLinkRelSpec>> = {\n depends_on: {\n purpose:\n \"The source needs the target to hold; the source breaks if the target changes\",\n phrase: \"Depends on\",\n dependant: \"source\",\n },\n constrains: {\n purpose:\n \"The source bounds what the target may do; the target breaks if the constraint changes\",\n phrase: \"Constrains\",\n dependant: \"target\",\n },\n informs: {\n purpose:\n \"The source shaped the target without binding it; the target is what needs revisiting\",\n phrase: \"Informs\",\n dependant: \"target\",\n },\n blocks: {\n purpose:\n \"The target cannot proceed until the source is settled; the target is what waits\",\n phrase: \"Blocks\",\n dependant: \"target\",\n },\n invalidates: {\n purpose:\n \"The source makes the target no longer hold; the target is what stops holding\",\n phrase: \"Invalidates\",\n dependant: \"target\",\n },\n verified_by: {\n purpose:\n \"The target is the check that confirms the source; the source's confirmation moves with it\",\n phrase: \"Verified by\",\n dependant: \"source\",\n },\n satisfies: {\n purpose:\n \"The source discharges the target's requirement; the source must change if the requirement does\",\n phrase: \"Satisfies\",\n dependant: \"source\",\n },\n related_to: {\n purpose: \"A pointer worth following, with no claim of dependence\",\n phrase: \"Relates to\",\n dependant: null,\n },\n};\n\n/**\n * The rels that carry a direction of dependence, and therefore the only ones\n * anything can propagate along. `kb_impact`'s default edge set, and what\n * `trace` follows.\n *\n * Derived from the table rather than restated, so a rel cannot be causal in one\n * place and inert in another. The cast is a non-emptiness assertion for\n * `z.enum`.\n */\nexport const KB_CAUSAL_LINK_RELS = KB_LINK_RELS.filter(\n (rel) => LINK_RELS[rel].dependant !== null,\n) as [KbLinkRel, ...KbLinkRel[]];\n\nexport function isKbLinkRel(value: string): value is KbLinkRel {\n return Object.prototype.hasOwnProperty.call(LINK_RELS, value);\n}\n","import { z } from \"zod\";\nimport {\n anchorFileReader,\n anchorHashOf,\n defaultAnchorResolvers,\n hashAnchorText,\n LazyOrigin,\n normalizeRepoUrl,\n prepareResolvers,\n readAnchorFiles,\n remoteWants,\n resolveAnchorSpan,\n resolverChanged,\n type AnchorDriftReason,\n type AnchorHashKind,\n type AnchorRead,\n type AnchorResolver,\n type AnchorResolverName,\n type AnchorUnresolvedReason,\n type RemoteAnchorState,\n} from \"../anchor-resolver/index.js\";\nimport { grammarHints } from \"../grammars/index.js\";\nimport {\n KbRecordNotFoundError,\n KbSelfVerificationError,\n} from \"../kb-errors.js\";\nimport { assertBaseNotFrozen, KbBaseFrozenError } from \"../kb-pins/index.js\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport {\n isUncheckedReason,\n readRemoteAnchors,\n wantKey,\n} from \"../remote-repo/index.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\ntype AnchorResolveResult = {\n file: string;\n symbol?: string;\n state: \"stamped\" | \"match\" | \"drifted\" | \"unresolved\";\n storedHash?: string;\n currentHash?: string;\n /** What the compared hashes were taken over. */\n hashKind?: AnchorHashKind;\n /** `null` when the anchor recorded no `lines` — size unknown, not zero. */\n diffSize?: number | null;\n reason?: AnchorUnresolvedReason | AnchorDriftReason;\n resolver?: AnchorResolverName;\n rebaselined?: boolean;\n /** Set only when the anchor was resolved against another repository. */\n repo?: string;\n remoteState?: RemoteAnchorState;\n};\n\n/** What one anchor was compared against, and what \"current\" is beside it. */\ntype AnchorSource =\n | { ok: true; source: string; repo?: string; head?: string }\n | { ok: false; reason: AnchorUnresolvedReason; repo?: string };\n\n/** Which resolvers produced this run's spans, for the verify note. */\nfunction resolverSummary(results: AnchorResolveResult[]): string {\n const names = [\n ...new Set(\n results.flatMap((entry) => (entry.resolver ? [entry.resolver] : [])),\n ),\n ].sort();\n return names.length ? `${names.join(\" + \")} resolver` : \"whole-file\";\n}\n\nexport const anchorResolveCommand = define({\n name: \"anchor-resolve\",\n tool: \"kb_anchor_resolve\",\n usage:\n \"anchor-resolve <concept-id> [--repo-root <path>] [--offline] [--rebaseline] [--restamp]\",\n description:\n \"Resolve a record's anchors: stamp a hash onto anchors that lack one, report drift where the code moved. An anchor naming another repository is read from that remote through a bare cache; --offline uses the cache only. kb_verify's mechanical counterpart — reach for it when the question is whether the code still is what it was. Exits non-zero on drift.\",\n input: z.object({\n bundlePath,\n conceptId,\n repoRoot: z.string().min(1).optional(),\n offline: z\n .boolean()\n .optional()\n .describe(\n \"Resolve foreign anchors from the local repo cache only, never fetching.\",\n ),\n rebaseline: z\n .boolean()\n .optional()\n .describe(\n \"Accept the current code as the new baseline for anchors that drifted.\",\n ),\n restamp: z\n .boolean()\n .optional()\n .describe(\n \"Refresh `resolved_at` on anchors that already match. Off by default, so a green run writes nothing.\",\n ),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n repoRoot: argvFlag(argv, \"--repo-root\"),\n offline: argv.includes(\"--offline\"),\n rebaseline: argv.includes(\"--rebaseline\"),\n restamp: argv.includes(\"--restamp\"),\n }),\n run: async (\n { store, actor, now },\n { bundlePath: path, conceptId: id, repoRoot, offline, rebaseline, restamp },\n ) => {\n const root = repoRoot ?? process.cwd();\n const record = await store.read(path, id);\n if (!record) throw new KbRecordNotFoundError(id);\n\n const anchors = record.frontmatter.strauss_anchors ?? [];\n if (!anchors.length) {\n return {\n conceptId: id,\n results: [] as AnchorResolveResult[],\n verified: false,\n note: \"record has no anchors\",\n };\n }\n\n const results: AnchorResolveResult[] = [];\n const updated: KbAnchor[] = [];\n let dirty = false;\n\n const sources = await readSources(anchors, root, offline === true);\n const resolvers = defaultAnchorResolvers({ offline: offline === true });\n await prepareResolvers(\n resolvers,\n anchors.map((anchor) => anchor.file),\n );\n\n for (const anchor of anchors) {\n const base: Pick<\n AnchorResolveResult,\n \"file\" | \"symbol\" | \"storedHash\" | \"repo\"\n > = {\n file: anchor.file,\n ...(anchor.symbol ? { symbol: anchor.symbol } : {}),\n // Carried onto unresolved findings too: an anchor that once hashed\n // and now resolves to nothing is a broken anchor, and the exit code\n // has to be able to tell it from one nobody ever stamped.\n ...(anchor.hash ? { storedHash: anchor.hash } : {}),\n };\n const source = sources.get(anchor) as AnchorSource;\n if (source.repo) base.repo = source.repo;\n\n if (!source.ok) {\n results.push({ ...base, state: \"unresolved\", reason: source.reason });\n updated.push(anchor);\n continue;\n }\n\n const outcome = resolveAnchorSpan(source.source, anchor, resolvers);\n if (!outcome.ok) {\n results.push({\n ...base,\n state: \"unresolved\",\n reason: outcome.reason,\n });\n updated.push(anchor);\n continue;\n }\n\n const resolved = outcome.span;\n const producedBy = outcome.resolver;\n const { hash: currentHash, kind } = anchorHashOf(anchor, outcome);\n const currentLines = resolved.endLine - resolved.startLine + 1;\n // A fresh or rebaselined stamp takes the strongest hash the resolver can\n // offer: `hash_kind: \"ast\"` is over the parsed token stream, so\n // reformatting the anchored code stops registering as drift. An anchor\n // already carrying a raw hash keeps comparing raw until it is\n // rebaselined — see `anchorHashOf`.\n const stampedKind = outcome.normalized ? \"ast\" : \"raw\";\n const stampedHash = outcome.normalized\n ? anchorHashOf({ ...anchor, hash: undefined }, outcome).hash\n : currentHash;\n // `resolver` records which resolver the stored hash came from, so a\n // later run can tell a precise span from a heuristic one.\n const stamped: KbAnchor = {\n ...anchor,\n hash: stampedHash,\n hash_kind: stampedKind,\n lines: currentLines,\n resolved_at: now(),\n ...(producedBy ? { resolver: producedBy } : {}),\n };\n const pinned = anchor.ref !== undefined && source.repo !== undefined;\n\n if (!anchor.hash) {\n // The write path for hashes: kb_write callers record symbols, not\n // digests, and this pass fills them in once the code settles.\n results.push({\n ...base,\n state: \"stamped\",\n currentHash: stampedHash,\n hashKind: stampedKind,\n ...(producedBy ? { resolver: producedBy } : {}),\n });\n updated.push(stamped);\n dirty = true;\n continue;\n }\n\n if (anchor.hash !== currentHash) {\n results.push({\n ...base,\n state: \"drifted\",\n currentHash,\n hashKind: kind,\n diffSize: lineDelta(anchor, currentLines),\n ...(producedBy ? { resolver: producedBy } : {}),\n // A regex-stamped anchor re-read by tree-sitter drifts because the\n // resolver changed, not because the code did.\n ...(resolverChanged(source.source, anchor, producedBy)\n ? { reason: \"resolver-changed\" as const }\n : {}),\n ...(pinned ? { remoteState: \"drifted-from-ref\" as const } : {}),\n ...(rebaseline ? { rebaselined: true } : {}),\n });\n updated.push(rebaseline ? stamped : anchor);\n if (rebaseline) dirty = true;\n continue;\n }\n\n // The evidence still holds at the pinned commit and the default branch\n // has moved past it. Never rebaselined: the repair is to move `ref`,\n // which is the author's field, not this command's.\n const onDefault = pinned\n ? headHash(source, anchor, resolvers)\n : undefined;\n if (onDefault && onDefault.hash !== anchor.hash) {\n results.push({\n ...base,\n state: \"drifted\",\n currentHash: onDefault.hash,\n diffSize: lineDelta(anchor, onDefault.lines),\n remoteState: \"drifted-on-default\",\n });\n updated.push(anchor);\n continue;\n }\n\n results.push({\n ...base,\n state: \"match\",\n currentHash,\n hashKind: kind,\n ...(producedBy ? { resolver: producedBy } : {}),\n ...(pinned ? { remoteState: \"matches-ref\" as const } : {}),\n });\n // Nothing changed, so nothing is written: a re-dated record on every\n // green CI run would be a mutation, a log line, and a git diff saying\n // only that a check ran. `resolved_at` is filled in when it is absent\n // (the anchor predates hashing), or on request.\n const refresh = restamp || anchor.resolved_at === undefined;\n updated.push(refresh ? { ...anchor, resolved_at: now() } : anchor);\n if (refresh) dirty = true;\n }\n\n // Frozen bases refuse writes, not reads: pure drift reporting is\n // legitimate on a concluded base, so the report is computed first and the\n // freeze only costs the mutation. Reported rather than thrown — a caller\n // asking a concluded base whether its code moved deserves the answer.\n let frozen = false;\n if (dirty) {\n try {\n await assertBaseNotFrozen(process.cwd(), path);\n } catch (error) {\n if (!(error instanceof KbBaseFrozenError)) throw error;\n frozen = true;\n }\n if (!frozen) await store.updateAnchors(path, id, updated, actor);\n }\n const frozenNote = frozen\n ? { frozen: true, note: \"base is frozen: nothing was stamped\" }\n : {};\n // What to do about a grammar this run could not obtain. Written once, in\n // the grammars module, so doctor and this command say the same thing.\n const hints = grammarHints();\n const hintNote = hints.length ? { hints } : {};\n\n // Evidence only when every checkable anchor already matched: a freshly\n // stamped anchor is a baseline nobody has checked. An anchor nothing could\n // reach stays outside the denominator rather than against it, and also\n // keeps the run from verifying — \"could not look\" is not \"matches\".\n const unreachable = results.filter((entry) =>\n isUncheckedReason(entry.reason),\n ).length;\n const checked = results.length - unreachable;\n const matches = results.filter((entry) => entry.state === \"match\").length;\n const note = `${matches}/${checked} anchors match${\n unreachable ? `, ${unreachable} unreachable` : \"\"\n }`;\n const clean = checked > 0 && matches === checked && unreachable === 0;\n if (clean) {\n try {\n await store.verify(\n path,\n id,\n `anchor-resolve: ${note} (${resolverSummary(results)})`,\n actor,\n now(),\n );\n } catch (error) {\n // A mechanical resolve run by the record's own generator is still a\n // useful drift report; only the verified[] stamp is refused.\n if (!(error instanceof KbSelfVerificationError)) throw error;\n return {\n conceptId: id,\n results,\n verified: false,\n verifyRefused: \"self-verification\",\n ...frozenNote,\n ...hintNote,\n };\n }\n return {\n conceptId: id,\n results,\n verified: true,\n ...frozenNote,\n ...hintNote,\n };\n }\n\n return {\n conceptId: id,\n results,\n verified: false,\n ...(unreachable ? { note } : {}),\n ...frozenNote,\n ...hintNote,\n };\n },\n // A stored hash that no longer resolves is a broken anchor, not an absence:\n // the file was deleted or the symbol renamed, and exiting zero on it would\n // let the one edit that destroys an anchor pass the gate that exists to\n // catch it. An anchor nobody ever stamped is still just unstamped, and one\n // whose remote nothing could reach was never checked — failing CI on either\n // would gate on work this command did not do.\n failsWhen: (result) =>\n (result as { results: AnchorResolveResult[] }).results.some(\n (entry) =>\n entry.state === \"drifted\" ||\n (entry.state === \"unresolved\" &&\n entry.storedHash !== undefined &&\n !isUncheckedReason(entry.reason)),\n ),\n});\n\nfunction lineDelta(anchor: KbAnchor, current: number): number | null {\n return anchor.lines === undefined ? null : Math.abs(current - anchor.lines);\n}\n\n/** The anchor's hash on the remote's default branch, when one was read. */\nfunction headHash(\n source: { head?: string },\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n): { hash: string; lines: number } | undefined {\n if (source.head === undefined) return undefined;\n const outcome = resolveAnchorSpan(source.head, anchor, resolvers);\n if (!outcome.ok) return undefined;\n return {\n hash: hashAnchorText(outcome.span.text),\n lines: outcome.span.endLine - outcome.span.startLine + 1,\n };\n}\n\n/**\n * What each anchor is read from: the working tree for this repository's own\n * anchors, a bare remote cache for every other. Both sets are collected first,\n * so git is spawned once per (repo, rev) and never inside the loop.\n */\nasync function readSources(\n anchors: readonly KbAnchor[],\n root: string,\n offline: boolean,\n): Promise<Map<KbAnchor, AnchorSource>> {\n const origin = new LazyOrigin(root);\n if (anchors.some((anchor) => anchor.repo)) await origin.prime();\n const foreign = new Map(\n anchors.map((anchor) => [anchor, origin.isForeign(anchor)] as const),\n );\n\n const local = anchors.filter((anchor) => !foreign.get(anchor));\n const remote = anchors.filter((anchor) => foreign.get(anchor));\n const reads = await readAnchorFiles(\n local.map((anchor) => anchor.file),\n anchorFileReader(root),\n );\n const blobs = await readRemoteAnchors(remote.flatMap(remoteWants), {\n offline,\n });\n\n const sources = new Map<KbAnchor, AnchorSource>();\n for (const anchor of local) {\n const read = reads.get(anchor.file) as AnchorRead;\n sources.set(\n anchor,\n read.ok\n ? { ok: true, source: read.source }\n : { ok: false, reason: read.reason },\n );\n }\n for (const anchor of remote) {\n const repo = anchor.repo as string;\n const key = normalizeRepoUrl(repo);\n const atDefault = blobs.get(wantKey(key, undefined, anchor.file));\n const primary = anchor.ref\n ? blobs.get(wantKey(key, anchor.ref, anchor.file))\n : atDefault;\n if (!primary?.ok) {\n sources.set(anchor, {\n ok: false,\n reason: primary?.ok === false ? primary.reason : \"remote-unreachable\",\n repo,\n });\n continue;\n }\n sources.set(anchor, {\n ok: true,\n source: primary.source,\n repo,\n ...(anchor.ref && atDefault?.ok ? { head: atDefault.source } : {}),\n });\n }\n return sources;\n}\n","/**\n * Bounded fan-out for the store's I/O paths.\n *\n * Unbounded `Promise.all` over a bundle hits EMFILE on a large base; a serial\n * loop pays full syscall latency per file. One shared pool sits between them.\n */\n\n/** Default in-flight file operations. Bounded so a large base cannot hit EMFILE. */\nexport const DEFAULT_IO_CONCURRENCY = 16;\n\n/**\n * Runs `fn` over `items` with at most `limit` in flight.\n *\n * Results are index-aligned with `items` regardless of completion order. A\n * rejection propagates; a caller wanting per-item isolation catches inside `fn`.\n */\nexport async function mapLimit<T, R>(\n items: readonly T[],\n limit: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n if (!Number.isInteger(limit) || limit < 1) {\n throw new RangeError(\n `mapLimit: \"limit\" must be a positive integer, got ${limit}`,\n );\n }\n const out = new Array<R>(items.length);\n let next = 0;\n let failed = false;\n const runners = Array.from(\n { length: Math.min(limit, items.length) },\n async () => {\n while (!failed && next < items.length) {\n const at = next++;\n try {\n out[at] = await fn(items[at] as T, at);\n } catch (error) {\n failed = true;\n throw error;\n }\n }\n },\n );\n await Promise.all(runners);\n return out;\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { normalizeRepoUrl } from \"../anchor-resolver/repo-identity.js\";\n\n/** Where bare mirrors live. Overridable so a test never writes to `$HOME`. */\nexport function repoCacheDir(override?: string): string {\n return (\n override ??\n process.env[\"STRAUSS_KB_REPO_CACHE\"] ??\n join(homedir(), \".strauss\", \"repo-cache\")\n );\n}\n\n/** Fetch timeout in ms; a remote that hangs must not hang the run. */\nexport const DEFAULT_FETCH_TIMEOUT_MS = 30_000;\n\nexport function fetchTimeoutMs(override?: number): number {\n if (override !== undefined) return override;\n const fromEnv = Number(process.env[\"STRAUSS_KB_FETCH_TIMEOUT_MS\"]);\n return Number.isFinite(fromEnv) && fromEnv > 0\n ? fromEnv\n : DEFAULT_FETCH_TIMEOUT_MS;\n}\n\n/**\n * `<cache>/<host>/<org>/<name>.git` for a repository URL.\n *\n * `null` when the declared `repo` carries no path git could fetch — a short\n * form like `org/name` names a repository without saying where it lives.\n */\nexport function cachePathFor(repo: string, cacheDir: string): string | null {\n const normalized = normalizeRepoUrl(repo);\n const scheme = /^[a-z0-9+.-]+:\\/\\//.exec(normalized);\n if (!scheme) return null;\n const segments = normalized\n .slice(scheme[0].length)\n .split(\"/\")\n .filter(Boolean)\n .map((segment: string) => safeSegment(segment));\n if (segments.length < 2 || segments.some((segment) => segment === null)) {\n return null;\n }\n const path = segments as string[];\n return join(cacheDir, ...path.slice(0, -1), `${path[path.length - 1]}.git`);\n}\n\n/**\n * A path segment a repository URL may contribute to a directory name. A\n * Windows `file:///C:/…` contributes its drive as the first one, and `:` is\n * not legal in a directory name there, so it is folded like any other\n * separator rather than special-cased.\n */\nfunction safeSegment(value: string): string | null {\n return value === \".\" || value === \"..\" || value.includes(\"\\0\")\n ? null\n : value.replace(/[/\\\\:]/g, \"-\");\n}\n\n/**\n * A git ref name holding one fetched rev, stable across runs so a second run\n * reads the cache instead of fetching again.\n */\nexport function revRef(rev: string): string {\n // `.` is dropped rather than kept: `v1..2` would be an invalid ref name.\n const safe = rev.replace(/[^A-Za-z0-9_-]/g, \"-\").slice(0, 64);\n let hash = 5381;\n for (let at = 0; at < rev.length; at++) {\n hash = ((hash * 33) ^ rev.charCodeAt(at)) >>> 0;\n }\n return `refs/strauss/${safe}-${hash.toString(16)}`;\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/* -------------------------------------------------------------------------\n * Which repository is this?\n * ---------------------------------------------------------------------- */\n\n/**\n * Repository identity, normalised on both sides and compared rather than\n * parsed; see ARCHITECTURE.\n *\n * Trailing slashes come off in a loop rather than with `/\\/+$/`, which\n * backtracks quadratically on untrusted bundle data.\n */\nexport function normalizeRepoUrl(value: string): string {\n let url = value.trim().replace(/^git\\+/, \"\");\n // scp-style: git@host:org/name\n const scp = /^[\\w.-]+@([\\w.-]+):(.+)$/.exec(url);\n if (scp) url = `https://${scp[1]}/${scp[2]}`;\n url = url.replace(/^ssh:\\/\\/(?:[^@/]+@)?/, \"https://\");\n // Slashes, then `.git`, then slashes again: a remote is written `…/name`,\n // `…/name.git`, and `…/name.git/` interchangeably, and all three name one\n // repository.\n url = trimTrailingSlashes(url);\n if (url.endsWith(\".git\")) url = url.slice(0, -4);\n return trimTrailingSlashes(url).toLowerCase();\n}\n\nfunction trimTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n}\n\n/**\n * Does this spelling say where the repository lives?\n *\n * Only a full URL can be fetched from. A short form still matches this root's\n * own origin, which is why `validate` warns rather than rejects.\n */\nexport function isCanonicalRepoUrl(value: string): boolean {\n return /^[a-z0-9+.-]+:\\/\\//.test(normalizeRepoUrl(value));\n}\n\n/** `org/name` from a normalized URL, or \"\" when it carries no host. */\nfunction repoPath(normalized: string): string {\n const withoutScheme = normalized.replace(/^[a-z0-9+.-]+:\\/\\//, \"\");\n const segments = withoutScheme.split(\"/\").filter(Boolean);\n return segments.length > 1 ? segments.slice(1).join(\"/\") : \"\";\n}\n\n/**\n * Does `declared` name the repository `originUrl` points at?\n *\n * Three spellings are accepted, narrowest first: the whole URL, the `org/name`\n * path, and the bare repository name. The bare name is the loosest and could\n * in principle collide across organisations; it is accepted because it is what\n * people actually write, and the cost of a false positive here is resolving an\n * anchor that was already meant for a repository of that name.\n */\nexport function repoIdentifies(\n declared: string,\n originUrl: string | null,\n): boolean {\n if (!originUrl) return false;\n const origin = normalizeRepoUrl(originUrl);\n const want = normalizeRepoUrl(declared);\n if (!want || !origin) return false;\n if (want === origin) return true;\n\n const path = repoPath(origin);\n if (!path) return false;\n return want === path || want === (path.split(\"/\").pop() ?? \"\");\n}\n\n/**\n * The `origin` remote of the tree at `repoRoot`, or `null`.\n *\n * `null` for anything that is not a git checkout, has no `origin`, or where\n * git is unavailable — all of which mean the same thing here: this root cannot\n * prove which repository it is. An anchor naming a repository is then treated\n * as foreign rather than resolved hopefully, because a hash that matched by\n * coincidence would be recorded as evidence.\n */\nexport async function repoOriginUrl(repoRoot: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"-C\", repoRoot, \"config\", \"--get\", \"remote.origin.url\"],\n { timeout: 5_000 },\n );\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * \"Is this anchor for another repository?\", answered without asking git until\n * an anchor actually declares a `repo`, and only once per run after that.\n */\nexport class LazyOrigin {\n private url: string | null = null;\n private asked = false;\n\n constructor(private readonly repoRoot: string) {}\n\n /** Asks git once, so later `isForeign` calls need no await. */\n async prime(): Promise<void> {\n if (this.asked) return;\n this.url = await repoOriginUrl(this.repoRoot);\n this.asked = true;\n }\n\n /** Only meaningful after `prime`; an unprimed origin identifies nothing. */\n isForeign(anchor: KbAnchor): boolean {\n if (!anchor.repo) return false;\n return !repoIdentifies(anchor.repo, this.url);\n }\n\n async foreign(anchor: KbAnchor): Promise<boolean> {\n if (!anchor.repo) return false;\n await this.prime();\n return this.isForeign(anchor);\n }\n}\n","import type {\n AnchorDriftReason,\n AnchorUnresolvedReason,\n} from \"../anchor-resolver/model.js\";\n\n/**\n * A foreign anchor's file at one rev. `ref` absent means the remote's default\n * branch — the \"current\" side of a ref-pinned comparison.\n */\nexport type RemoteWant = { repo: string; ref?: string; file: string };\n\nexport type RemoteRead =\n { ok: true; source: string } | { ok: false; reason: AnchorUnresolvedReason };\n\nexport type RemoteOptions = {\n /** Cache only: no `fetch`, no `ls-remote`. */\n offline?: boolean;\n cacheDir?: string;\n fetchTimeoutMs?: number;\n /** Repositories worked on at once; fetches within one repo stay serial. */\n concurrency?: number;\n};\n\n/** Reasons that mean \"not checked\", as opposed to evidence that moved. */\nexport const UNCHECKED_REASONS: readonly AnchorUnresolvedReason[] = [\n \"remote-unreachable\",\n \"repo-unauthorized\",\n \"default-branch-unknown\",\n];\n\nexport function isUncheckedReason(\n reason: AnchorUnresolvedReason | AnchorDriftReason | undefined,\n): boolean {\n return (\n reason !== undefined &&\n UNCHECKED_REASONS.includes(reason as AnchorUnresolvedReason)\n );\n}\n\n/** One key per (repo, rev, file); `ref` absent is the default branch. */\nexport function wantKey(\n repo: string,\n ref: string | undefined,\n file: string,\n): string {\n return `${repo}\\u0000${ref ?? \"\"}\\u0000${file}`;\n}\n","import { mkdir } from \"node:fs/promises\";\nimport type { AnchorUnresolvedReason } from \"../anchor-resolver/model.js\";\nimport { normalizeRepoUrl } from \"../anchor-resolver/repo-identity.js\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport { cachePathFor, fetchTimeoutMs, repoCacheDir, revRef } from \"./cache.js\";\nimport { git, transportReason } from \"./git.js\";\nimport {\n wantKey,\n type RemoteOptions,\n type RemoteRead,\n type RemoteWant,\n} from \"./model.js\";\nimport {\n filePathIsSafe,\n isShortRepoName,\n protocolArgs,\n refIsWellFormed,\n refShapeIsSafe,\n repoUrlIsSafe,\n} from \"./validate.js\";\n\n/** Repositories fetched at once. Fetches within one repo stay serial. */\nconst DEFAULT_REPO_CONCURRENCY = 4;\n\n/** A full commit sha can never mean different content, so it is fetched once. */\nconst IMMUTABLE_REV = /^[0-9a-f]{40}$/;\n\n/**\n * Reads each wanted (repo, rev, file) out of a bare cache under\n * `~/.strauss/repo-cache`, fetching once per (repo, rev) and never per anchor.\n *\n * Every failure lands as an `unresolved` reason on the wants it affects; no\n * path is read from disk, so containment does not apply here.\n */\nexport async function readRemoteAnchors(\n wants: readonly RemoteWant[],\n options: RemoteOptions = {},\n): Promise<Map<string, RemoteRead>> {\n const out = new Map<string, RemoteRead>();\n if (!wants.length) return out;\n\n const cacheDir = repoCacheDir(options.cacheDir);\n const timeoutMs = fetchTimeoutMs(options.fetchTimeoutMs);\n const byRepo = new Map<string, { url: string; wants: RemoteWant[] }>();\n for (const want of wants) {\n const key = normalizeRepoUrl(want.repo);\n const group = byRepo.get(key) ?? { url: want.repo.trim(), wants: [] };\n group.wants.push(want);\n byRepo.set(key, group);\n }\n\n const groups = [...byRepo.entries()];\n const results = await mapLimit(\n groups,\n Math.max(1, options.concurrency ?? DEFAULT_REPO_CONCURRENCY),\n ([repo, group]) =>\n readOneRepo(repo, group.url, group.wants, {\n cacheDir,\n timeoutMs,\n offline: options.offline === true,\n }),\n );\n for (const result of results) {\n for (const [key, read] of result) out.set(key, read);\n }\n return out;\n}\n\ntype RepoContext = { cacheDir: string; timeoutMs: number; offline: boolean };\n\nasync function readOneRepo(\n repo: string,\n url: string,\n declared: readonly RemoteWant[],\n context: RepoContext,\n): Promise<Map<string, RemoteRead>> {\n let wants: readonly RemoteWant[] = declared;\n const all = (read: RemoteRead) =>\n new Map(wants.map((want) => [wantKey(repo, want.ref, want.file), read]));\n\n // A short `repo` (`org/name`) names a repository without saying where it\n // lives, so there is nothing to fetch from. `validate` warns on the spelling.\n if (isShortRepoName(url)) {\n return all({ ok: false, reason: \"remote-unreachable\" });\n }\n // Anything else that is not a remote we will fetch over is a finding about\n // the record, decided before a single `git` runs.\n if (!repoUrlIsSafe(url)) return all({ ok: false, reason: \"repo-invalid\" });\n\n const cache = cachePathFor(repo, context.cacheDir);\n if (!cache) return all({ ok: false, reason: \"remote-unreachable\" });\n\n // Ref and path shapes are checked with no subprocess, so a want carrying an\n // option-shaped `ref` or `file` never reaches git — not even `git init`.\n const rejected = new Map<string, RemoteRead>();\n const usable: RemoteWant[] = [];\n for (const want of wants) {\n const reason = wantReason(want);\n if (reason)\n rejected.set(wantKey(repo, want.ref, want.file), { ok: false, reason });\n else usable.push(want);\n }\n if (!usable.length) return rejected;\n wants = usable;\n\n const opened = await openCache(cache, url, context);\n if (opened) return new Map([...rejected, ...all(opened)]);\n\n const wantsDefault = wants.some((want) => want.ref === undefined);\n const branch: Branch = wantsDefault\n ? await defaultBranch(cache, context)\n : {};\n\n // One fetch per rev, serial: two `git fetch` in one bare repo race for the\n // same lock.\n const revs = new Map<string, RemoteRead | undefined>();\n for (const rev of distinctRevs(wants, branch.name)) {\n revs.set(\n rev,\n (await refIsWellFormed(rev))\n ? await ensureRev(cache, rev, context)\n : { ok: false, reason: \"ref-invalid\" },\n );\n }\n\n const reads = await mapLimit(\n wants,\n DEFAULT_IO_CONCURRENCY,\n async (want): Promise<RemoteRead> => {\n const rev = want.ref ?? branch.name;\n if (rev === undefined) {\n return {\n ok: false,\n reason: branch.reason ?? \"default-branch-unknown\",\n };\n }\n const failed = revs.get(rev);\n if (failed) return failed;\n return readBlob(cache, rev, want.file, context);\n },\n );\n return new Map([\n ...rejected,\n ...wants.map(\n (want, at) =>\n [wantKey(repo, want.ref, want.file), reads[at] as RemoteRead] as const,\n ),\n ]);\n}\n\n/**\n * Why this want cannot be handed to git, or `undefined`. A ref that would be\n * read as an option (`--upload-pack=…`) or a range (`a..b`) is a finding on the\n * record; a `file` that would be read as an option or climbs out of the tree is\n * the same `outside-repo` a working-tree read reports.\n */\nfunction wantReason(want: RemoteWant): AnchorUnresolvedReason | undefined {\n if (want.ref !== undefined && !refShapeIsSafe(want.ref)) return \"ref-invalid\";\n return filePathIsSafe(want.file) ? undefined : \"outside-repo\";\n}\n\nfunction distinctRevs(\n wants: readonly RemoteWant[],\n branch: string | undefined,\n): string[] {\n const revs = new Set<string>();\n for (const want of wants) {\n if (want.ref !== undefined) revs.add(want.ref);\n else if (branch) revs.add(branch);\n }\n return [...revs];\n}\n\n/** Creates the bare mirror if it is not there and points it at `url`. */\nasync function openCache(\n cache: string,\n url: string,\n context: RepoContext,\n): Promise<RemoteRead | undefined> {\n try {\n await mkdir(cache, { recursive: true });\n } catch {\n return { ok: false, reason: \"remote-unreachable\" };\n }\n const init = await git([\"init\", \"--bare\", \"--quiet\", cache], {\n timeoutMs: context.timeoutMs,\n });\n if (!init.ok) return { ok: false, reason: \"remote-unreachable\" };\n // `config`, not `remote add` or `remote set-url`: the first run has no\n // `origin` to set and the second must not fail because the first added it.\n // The URL is safe to pass unguarded only because the allowlist has already\n // run — nothing starting with `-` reaches here.\n const remote = await git([\"config\", \"remote.origin.url\", url], {\n cwd: cache,\n timeoutMs: context.timeoutMs,\n });\n return remote.ok ? undefined : { ok: false, reason: \"remote-unreachable\" };\n}\n\ntype Branch = { name?: string; reason?: AnchorUnresolvedReason };\n\n/**\n * The remote's default branch: asked once per repo per run, then remembered in\n * the cache so `--offline` and the next run have an answer.\n */\nasync function defaultBranch(\n cache: string,\n context: RepoContext,\n): Promise<Branch> {\n if (!context.offline) {\n const listed = await git(\n [...protocolArgs(), \"ls-remote\", \"--symref\", \"origin\", \"HEAD\"],\n {\n cwd: cache,\n timeoutMs: context.timeoutMs,\n },\n );\n const found = /^ref:\\s+refs\\/heads\\/(\\S+)\\s+HEAD$/m.exec(listed.stdout);\n if (listed.ok && found?.[1]) {\n const name = found[1];\n await git([\"config\", \"strauss.defaultBranch\", name], { cwd: cache });\n return { name };\n }\n if (!listed.ok) {\n const reason = transportReason(listed.stderr);\n if (reason !== \"ref-not-found\") {\n const cached = await cachedBranch(cache);\n return cached ? { name: cached } : { reason };\n }\n }\n }\n const cached = await cachedBranch(cache);\n if (cached) return { name: cached };\n // Offline with nothing cached is not a repository without a HEAD: the cause\n // is that nothing was reached, and that is what the finding should say.\n return {\n reason: context.offline ? \"remote-unreachable\" : \"default-branch-unknown\",\n };\n}\n\nasync function cachedBranch(cache: string): Promise<string | undefined> {\n const stored = await git([\"config\", \"--get\", \"strauss.defaultBranch\"], {\n cwd: cache,\n });\n if (stored.ok && stored.stdout.trim()) return stored.stdout.trim();\n const head = await git(\n [\"symbolic-ref\", \"--short\", \"refs/remotes/origin/HEAD\"],\n {\n cwd: cache,\n },\n );\n const name = head.stdout.trim().replace(/^origin\\//, \"\");\n return head.ok && name ? name : undefined;\n}\n\n/**\n * Fetches `rev` into a stable local ref, or reports why it could not.\n *\n * A full commit sha already in the cache is never refetched — its content\n * cannot change — while a branch is fetched every online run, because \"current\"\n * is exactly what a branch means.\n */\nasync function ensureRev(\n cache: string,\n rev: string,\n context: RepoContext,\n): Promise<RemoteRead | undefined> {\n const ref = revRef(rev);\n const have = await git(\n [\"rev-parse\", \"--verify\", \"--quiet\", `${ref}^{commit}`],\n {\n cwd: cache,\n },\n );\n const cached = have.ok && have.stdout.trim().length > 0;\n if (cached && (context.offline || IMMUTABLE_REV.test(rev))) return undefined;\n if (context.offline) return { ok: false, reason: \"remote-unreachable\" };\n\n // `--end-of-options` is what stops a rev from being parsed as an option; the\n // ref shape already refused one, and this is the layer that does not depend\n // on the shape being right.\n const fetched = await git(\n [\n ...protocolArgs(),\n \"fetch\",\n \"--depth\",\n \"1\",\n \"origin\",\n \"--end-of-options\",\n rev,\n ],\n { cwd: cache, timeoutMs: context.timeoutMs },\n );\n if (!fetched.ok) {\n // A stale cached copy beats no answer when the network is the problem;\n // a rev the remote no longer has is a finding either way.\n const reason = transportReason(fetched.stderr);\n if (cached && reason !== \"ref-not-found\") return undefined;\n return { ok: false, reason };\n }\n const head = await git([\"rev-parse\", \"FETCH_HEAD\"], { cwd: cache });\n const sha = head.stdout.trim();\n if (!head.ok || !sha) return { ok: false, reason: \"remote-unreachable\" };\n const updated = await git([\"update-ref\", ref, sha], { cwd: cache });\n return updated.ok ? undefined : { ok: false, reason: \"remote-unreachable\" };\n}\n\n/** `git cat-file blob <rev>:<file>`, capped at the same 1 MiB as a local read. */\nasync function readBlob(\n cache: string,\n rev: string,\n file: string,\n context: RepoContext,\n): Promise<RemoteRead> {\n const path = file.replace(/^\\.\\//, \"\");\n const blob = await git(\n [\"cat-file\", \"blob\", \"--end-of-options\", `${revRef(rev)}:${path}`],\n {\n cwd: cache,\n timeoutMs: context.timeoutMs,\n },\n );\n if (blob.ok) return { ok: true, source: blob.stdout };\n if (blob.overflowed) return { ok: false, reason: \"file-too-large\" };\n const text = blob.stderr.toLowerCase();\n return text.includes(\"does not exist\") || text.includes(\"not a valid object\")\n ? { ok: false, reason: \"file-missing\" }\n : { ok: false, reason: \"file-unreadable\" };\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport {\n MAX_ANCHOR_FILE_BYTES,\n type AnchorUnresolvedReason,\n} from \"../anchor-resolver/model.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type GitRun = {\n ok: boolean;\n stdout: string;\n stderr: string;\n /** Set when the child died because its output passed the blob cap. */\n overflowed: boolean;\n};\n\n/**\n * The environment a `git` child gets. `GIT_TERMINAL_PROMPT` is cleared so a\n * credential helper that decides to prompt cannot block the run forever on a\n * repository the caller has no access to. `GIT_DIR`, `GIT_WORK_TREE`, and\n * `GIT_INDEX_FILE` are stripped because they override `cwd` — a caller's\n * environment must not be able to redirect a cache operation at another\n * repository. The global config stays: it is where the user's own credential\n * helper lives.\n */\nfunction childEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...process.env, GIT_TERMINAL_PROMPT: \"0\" };\n for (const name of [\"GIT_DIR\", \"GIT_WORK_TREE\", \"GIT_INDEX_FILE\"]) {\n delete env[name];\n }\n return env;\n}\n\n/**\n * One `git` invocation, argv only — never a shell, because `repo`, `ref`, and\n * `file` are bundle data. A non-zero exit is a result, not a throw.\n */\nexport async function git(\n args: string[],\n options: { cwd?: string; timeoutMs?: number; maxBytes?: number } = {},\n): Promise<GitRun> {\n try {\n const { stdout, stderr } = await execFileAsync(\"git\", args, {\n ...(options.cwd ? { cwd: options.cwd } : {}),\n timeout: options.timeoutMs ?? 30_000,\n maxBuffer: options.maxBytes ?? MAX_ANCHOR_FILE_BYTES,\n encoding: \"utf8\",\n windowsHide: true,\n env: childEnv(),\n });\n return { ok: true, stdout, stderr, overflowed: false };\n } catch (error) {\n const failure = error as {\n stdout?: string;\n stderr?: string;\n code?: string | number;\n };\n return {\n ok: false,\n stdout: failure.stdout ?? \"\",\n stderr: failure.stderr ?? \"\",\n overflowed: failure.code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\",\n };\n }\n}\n\n/**\n * Which failure a git transport error was. Matched on message text because\n * git returns 128 for all of them; an unrecognised failure is unreachable,\n * the reason that never accuses the record of being wrong.\n */\nexport function transportReason(stderr: string): AnchorUnresolvedReason {\n const text = stderr.toLowerCase();\n if (\n text.includes(\"authentication failed\") ||\n text.includes(\"permission denied\") ||\n text.includes(\"could not read username\") ||\n text.includes(\"403 forbidden\") ||\n text.includes(\"access denied\")\n ) {\n return \"repo-unauthorized\";\n }\n if (\n text.includes(\"couldn't find remote ref\") ||\n text.includes(\"unadvertised object\") ||\n text.includes(\"not our ref\")\n ) {\n return \"ref-not-found\";\n }\n return \"remote-unreachable\";\n}\n","/**\n * The vocabulary anchor resolution is reported in.\n *\n * Every failure is a finding with a reason, never a throw: a record pointing\n * at code that moved is information, not a broken run.\n */\n\nexport type ResolvedSymbol = {\n text: string;\n /** 1-based, inclusive. */\n startLine: number;\n endLine: number;\n};\n\n/** Which resolver produced a span. Stamped on the anchor. */\nexport type AnchorResolverName = \"tree-sitter\" | \"regex\";\n\n/**\n * A resolver's verdict. `abstain` (\"not my language\") and `symbol-not-found`\n * (\"nothing I recognize declares this\") both pass the symbol down the chain;\n * `symbol-ambiguous` and `resolver-unavailable` end it, because neither may be\n * answered by a looser resolver guessing.\n */\nexport type ResolverAttempt =\n | { kind: \"resolved\"; span: ResolvedSymbol }\n | {\n kind: \"unresolved\";\n reason: \"symbol-not-found\" | \"symbol-ambiguous\" | \"resolver-unavailable\";\n }\n | { kind: \"abstain\" };\n\nexport interface AnchorResolver {\n name: string;\n /** Loads whatever these files need, before any `resolve` call. Optional. */\n prepare?(files: readonly string[]): Promise<void>;\n /** The richer verdict the chain uses; defaults to `resolve`. */\n attempt?(source: string, symbol: string, file?: string): ResolverAttempt;\n resolve(source: string, symbol: string, file?: string): ResolvedSymbol | null;\n /**\n * The span's normalised token stream — comments dropped, runs of whitespace\n * collapsed — or `null` when this resolver cannot parse the text.\n *\n * Only a resolver that understands the language can offer one, which is why\n * it is optional: a text heuristic normalising by guess would call two\n * different programs equal.\n */\n normalize?(text: string, file?: string): string | null;\n}\n\n/** A resolved span, and which resolver produced it. */\nexport type AnchorResolution =\n | {\n ok: true;\n span: ResolvedSymbol;\n resolver?: AnchorResolverName;\n /** The span's token stream, when the resolver that spanned it can parse. */\n normalized?: string;\n }\n | { ok: false; reason: AnchorUnresolvedReason };\n\n/** Why an anchor could not be compared. Never an error — always a finding. */\nexport type AnchorUnresolvedReason =\n | \"file-missing\"\n | \"symbol-not-found\"\n /** More than one definition carries the name, and guessing is not allowed. */\n | \"symbol-ambiguous\"\n /** The extension has a grammar, but it would not load. Never a throw. */\n | \"resolver-unavailable\"\n | \"outside-repo\"\n | \"file-too-large\"\n | \"file-unreadable\"\n /** The remote could not be fetched, or `--offline` found nothing cached. */\n | \"remote-unreachable\"\n /** The anchor's `ref` is not on the remote any more. */\n | \"ref-not-found\"\n | \"repo-unauthorized\"\n /** No default branch, so there is no \"current\" to compare against. */\n | \"default-branch-unknown\"\n /** The anchor's `ref` is not a name git may safely be handed. */\n | \"ref-invalid\"\n /** The anchor's `repo` is not a remote we will fetch from. */\n | \"repo-invalid\";\n\n/**\n * A hash that changed because a more precise resolver took over, not because\n * the code did. Reported as drift so nothing is restamped silently, and\n * accepted by `--rebaseline` like any other.\n */\nexport type AnchorDriftReason = \"resolver-changed\";\n\n/**\n * How a ref-pinned foreign anchor stands. `drifted-on-default` is the one a\n * working-tree anchor has no equivalent of: the evidence is still true at the\n * commit it was taken from, and the code has moved since.\n */\nexport type RemoteAnchorState =\n \"matches-ref\" | \"drifted-from-ref\" | \"drifted-on-default\";\n\n/** Big enough for any hand-written source file, small enough to read eagerly. */\nexport const MAX_ANCHOR_FILE_BYTES = 1_048_576;\n\n/** What `hash` was taken over. Absent on an anchor means `raw`. */\nexport type AnchorHashKind = \"raw\" | \"ast\";\n\n/**\n * How an anchor's code changed, once the bytes are known to differ.\n *\n * The classes a machine can settle, so a reader only sees the ones it cannot:\n * `moved` and `cosmetic` are answered and closed, `gone` and `changed` are\n * handed on. Deliberately shallow — whether the record's *claim* still holds\n * is a reading, and no hash can stand in for one.\n */\nexport const KB_DRIFT_CLASSES = [\n \"moved\",\n \"cosmetic\",\n \"gone\",\n \"changed\",\n] as const;\n\nexport type KbDriftClass = (typeof KB_DRIFT_CLASSES)[number];\n\n/** Where a `moved` anchor's stored hash turned up. */\nexport type KbDriftMovedTo = {\n file: string;\n symbol?: string;\n startLine: number;\n endLine: number;\n};\n\nexport type KbAnchorDriftEntry = {\n file: string;\n symbol?: string;\n state: \"match\" | \"drifted\" | \"unresolved\";\n storedHash: string;\n currentHash?: string;\n /** `null` when the anchor recorded no `lines` — size unknown, not zero. */\n diffSize: number | null;\n reason?: AnchorUnresolvedReason | AnchorDriftReason;\n /** Which resolver produced `currentHash`. Absent for a whole-file anchor. */\n resolver?: AnchorResolverName;\n /** Set only when the anchor was resolved against another repository. */\n repo?: string;\n remoteState?: RemoteAnchorState;\n /** What the compared hashes were taken over. */\n hashKind?: AnchorHashKind;\n /**\n * Provisional: `gone` or `changed`, the two a hash comparison alone can\n * settle. `moved` and `cosmetic` cost a repository search and a git read, so\n * `classifyDrift` refines this on the reassessment path rather than on every\n * `load`.\n */\n class?: KbDriftClass;\n /** Set by `classifyDrift` when the class is `moved`. */\n movedTo?: KbDriftMovedTo;\n};\n\nexport type AnchorRead =\n { ok: true; source: string } | { ok: false; reason: AnchorUnresolvedReason };\n\nexport type AnchorFileReader = (file: string) => Promise<AnchorRead>;\n","import { git } from \"./git.js\";\n\n/**\n * `repo`, `ref`, and `file` are bundle data — a `.md` file the reader did not\n * write — and every one of them reaches `git` argv. An argv array stops the\n * shell, not git's own option parsing: `git fetch origin --upload-pack=<cmd>`\n * runs `<cmd>`, `ext::sh -c <cmd>` is a transport that does the same, and\n * `file:///` reads any repository the process can see. So each value is checked\n * against a shape before git ever sees it, and a value that fails is a finding\n * on the record rather than a command.\n */\n\n/** Long enough for any real branch, short enough to bound the argv. */\nconst MAX_REF_LENGTH = 200;\n\n/**\n * The shape a `ref` must have to reach git at all. The leading character class\n * excludes `-`, so no ref can be read as an option; `@`, `{`, `\\`, spaces, and\n * control characters are outside the class entirely.\n */\nconst REF_SHAPE = /^[A-Za-z0-9][A-Za-z0-9._/-]*$/;\n\n/** Checked with no subprocess, so an invalid ref never spawns git. */\nexport function refShapeIsSafe(ref: string): boolean {\n if (!ref || ref.length > MAX_REF_LENGTH) return false;\n // `a..b` is a range, not a rev, and `git fetch` would resolve it as one.\n if (ref.includes(\"..\")) return false;\n return REF_SHAPE.test(ref);\n}\n\n/**\n * git's own opinion of the name, asked only once the shape has made it safe to\n * pass. `--allow-onelevel` because `main` and a bare sha are both legal here.\n */\nexport async function refIsWellFormed(ref: string): Promise<boolean> {\n if (!refShapeIsSafe(ref)) return false;\n const checked = await git([\"check-ref-format\", \"--allow-onelevel\", ref]);\n return checked.ok;\n}\n\n/**\n * A `file` that may become the path half of `<rev>:<path>`. A leading `-` would\n * be an option; `..` would climb out of the tree the anchor describes.\n */\nexport function filePathIsSafe(file: string): boolean {\n const path = file.replace(/^\\.\\//, \"\");\n if (!path || path.startsWith(\"-\") || path.includes(\"\\0\")) return false;\n return !path.split(\"/\").includes(\"..\");\n}\n\n/** Transports a remote may be fetched over. Plaintext `http` is not one. */\nconst DEFAULT_PROTOCOLS = [\"https\", \"ssh\", \"git\"] as const;\n\n/**\n * `STRAUSS_KB_REPO_PROTOCOLS` widens the set — a comma list. It exists so the\n * test suite can serve `file://` remotes off disk; it is not a production knob,\n * because every protocol it can add is one that reads or runs something local.\n */\nexport function allowedProtocols(): string[] {\n const raw = process.env[\"STRAUSS_KB_REPO_PROTOCOLS\"];\n if (raw === undefined) return [...DEFAULT_PROTOCOLS];\n const listed = raw\n .split(\",\")\n .map((entry) => entry.trim().toLowerCase())\n .filter(Boolean);\n return listed.length ? listed : [...DEFAULT_PROTOCOLS];\n}\n\n/**\n * A `repo` naming a repository without saying where it lives (`org/name`).\n * There is nothing to fetch from, which is not the same finding as a `repo`\n * spelled in a transport we refuse to use.\n */\nexport function isShortRepoName(repo: string): boolean {\n return /^[A-Za-z0-9._-]+(?:\\/[A-Za-z0-9._-]+)*$/.test(repo.trim());\n}\n\n/** scp-style `git@host:org/name`, which git reads as ssh. */\nconst SCP_LIKE = /^[\\w.-]+@[\\w.-]+:(?!\\/)\\S+$/;\n\nconst URL_SCHEME = /^([A-Za-z0-9+.-]+):\\/\\//;\n\n// eslint-disable-next-line no-control-regex -- refusing control bytes is the point\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/;\n\n/** Checked with no subprocess, so a rejected URL never reaches a git remote. */\nexport function repoUrlIsSafe(repo: string): boolean {\n const url = repo.trim();\n if (!url || url.startsWith(\"-\") || CONTROL_CHARS.test(url)) return false;\n\n const allowed = allowedProtocols();\n if (SCP_LIKE.test(url)) return allowed.includes(\"ssh\");\n\n const scheme = URL_SCHEME.exec(url);\n // No `://` means no transport we recognise — `ext::sh -c …` lands here.\n if (!scheme?.[1]) return false;\n if (!allowed.includes(scheme[1].toLowerCase())) return false;\n\n // `https://user:password@host/…` puts a secret in a URL a bundle wrote; a\n // credential belongs in git's own helper, not in a record.\n const authority = url.slice(scheme[0].length).split(\"/\")[0] ?? \"\";\n const at = authority.lastIndexOf(\"@\");\n return at < 0 || !authority.slice(0, at).includes(\":\");\n}\n\n/**\n * Defence in depth behind the allowlist: even if a URL slipped past it, git\n * itself refuses the two transports that run or read something local.\n */\nexport function protocolArgs(): string[] {\n const allowed = allowedProtocols();\n return [\n \"-c\",\n \"protocol.ext.allow=never\",\n \"-c\",\n `protocol.file.allow=${allowed.includes(\"file\") ? \"user\" : \"never\"}`,\n ];\n}\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport {\n MAX_ANCHOR_FILE_BYTES,\n type AnchorFileReader,\n type AnchorRead,\n type KbAnchorDriftEntry,\n} from \"./model.js\";\n\n/**\n * An anchor's `file` must stay inside the repository root — a record points\n * at code, not at arbitrary files on the machine reading it. Bundles are\n * data, so a traversal or absolute path here is untrusted input, not a bug\n * in the caller. Returns the resolved path, or `null` when it escapes.\n *\n * Lexical only, and therefore not the whole containment check: see\n * `readAnchorFile`, which re-tests the real path after following symlinks.\n */\nexport function anchorFilePath(repoRoot: string, file: string): string | null {\n // Anchors are repo-relative, hand-written often enough that `./` shows up.\n const path = resolve(repoRoot, file.replace(/^\\.\\//, \"\"));\n const rel = relative(resolve(repoRoot), path);\n if (\n rel === \"\" ||\n rel === \"..\" ||\n rel.startsWith(`..${sep}`) ||\n isAbsolute(rel)\n ) {\n return null;\n }\n return path;\n}\n\nfunction contains(root: string, path: string): boolean {\n const rel = relative(root, path);\n return (\n rel !== \"\" &&\n rel !== \"..\" &&\n !rel.startsWith(`..${sep}`) &&\n !isAbsolute(rel)\n );\n}\n\nfunction errorCode(error: unknown): string | undefined {\n return typeof error === \"object\" && error !== null && \"code\" in error\n ? String((error as { code: unknown }).code)\n : undefined;\n}\n\n/** Resolves the repo root once, then reads anchor files against it. */\nexport function anchorFileReader(repoRoot: string): AnchorFileReader {\n let rootOnce: Promise<string> | undefined;\n const realRoot = (): Promise<string> => {\n rootOnce ??= realpath(resolve(repoRoot)).catch((error: unknown) => {\n // A rejected promise stays cached forever if left as-is — clear it so\n // the next read retries realpath instead of replaying one transient\n // failure for the rest of the run. This read still reports its own\n // file-missing/file-unreadable result via the catch below.\n rootOnce = undefined;\n throw error;\n });\n return rootOnce;\n };\n return (file) => readAnchorFileWithRoot(repoRoot, file, realRoot);\n}\n\n/** Convenience wrapper: resolves the repo root fresh on every call. */\nexport async function readAnchorFile(\n repoRoot: string,\n file: string,\n): Promise<AnchorRead> {\n return readAnchorFileWithRoot(repoRoot, file, () =>\n realpath(resolve(repoRoot)),\n );\n}\n\n/**\n * Containment is checked twice: lexically, then again against the realpath'd\n * path — a symlink inside the repo pointing out must not leak reads. Only\n * ENOENT/ENOTDIR is `file-missing`; other read errors are `file-unreadable`.\n */\nasync function readAnchorFileWithRoot(\n repoRoot: string,\n file: string,\n realRoot: () => Promise<string>,\n): Promise<AnchorRead> {\n const lexical = anchorFilePath(repoRoot, file);\n if (lexical === null) return { ok: false, reason: \"outside-repo\" };\n\n let root: string;\n let path: string;\n try {\n root = await realRoot();\n path = await realpath(lexical);\n } catch (error) {\n const code = errorCode(error);\n if (code === \"ENOENT\" || code === \"ENOTDIR\") {\n return { ok: false, reason: \"file-missing\" };\n }\n return { ok: false, reason: \"file-unreadable\" };\n }\n if (!contains(root, path)) return { ok: false, reason: \"outside-repo\" };\n\n try {\n const stats = await stat(path);\n if (!stats.isFile()) return { ok: false, reason: \"file-unreadable\" };\n // Anchors point at source. Reading a bundled artefact or a checked-in\n // binary into memory on a read path is a cost with no finding behind it.\n if (stats.size > MAX_ANCHOR_FILE_BYTES) {\n return { ok: false, reason: \"file-too-large\" };\n }\n return { ok: true, source: await readFile(path, \"utf8\") };\n } catch (error) {\n const code = errorCode(error);\n if (code === \"ENOENT\" || code === \"ENOTDIR\") {\n return { ok: false, reason: \"file-missing\" };\n }\n return { ok: false, reason: \"file-unreadable\" };\n }\n}\n\n/**\n * Every checked anchor failed to find its file at all.\n *\n * The signature of a repo root that was never given rather than of code that\n * moved: a bundle read from somewhere other than the tree it describes misses\n * every file, and reporting that as base-wide drift would train a reader to\n * ignore the warning. One file found anywhere makes the root plausible, and\n * the misses become real findings again.\n */\nexport function looksLikeWrongRepoRoot(\n drift: Map<string, KbAnchorDriftEntry[]>,\n): boolean {\n let checked = 0;\n for (const entries of drift.values()) {\n for (const entry of entries) {\n // An anchor read from another repository's remote says nothing about\n // this root. Counting it either way would be wrong: as a miss it would\n // make a correct root look wrong, and as a hit it would keep a\n // genuinely wrong root from being spotted.\n if (entry.repo !== undefined) continue;\n checked += 1;\n if (entry.state !== \"unresolved\" || entry.reason !== \"file-missing\") {\n return false;\n }\n }\n }\n return checked > 0;\n}\n\n/**\n * Reads each distinct file once with at most `concurrency` in flight.\n *\n * A reader that throws is one unreadable file, not a failed run.\n */\nexport async function readAnchorFiles(\n files: readonly string[],\n read: AnchorFileReader,\n concurrency: number = DEFAULT_IO_CONCURRENCY,\n): Promise<Map<string, AnchorRead>> {\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new RangeError(\n `readAnchorFiles: option \"concurrency\" must be a positive integer, got ${concurrency}`,\n );\n }\n const wanted = [...new Set(files)];\n const results = await mapLimit(wanted, concurrency, async (file) => {\n try {\n return await read(file);\n } catch {\n return { ok: false, reason: \"file-unreadable\" } as AnchorRead;\n }\n });\n return new Map(wanted.map((file, at) => [file, results[at] as AnchorRead]));\n}\n","import { createHash } from \"node:crypto\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport type { GrammarOptions } from \"../grammars/index.js\";\nimport { TreeSitterResolver } from \"../tree-sitter-resolver/index.js\";\nimport type {\n AnchorHashKind,\n AnchorResolution,\n AnchorResolverName,\n AnchorResolver,\n ResolvedSymbol,\n ResolverAttempt,\n} from \"./model.js\";\n\n/**\n * Symbol → text, and text → hash.\n *\n * Resolvers are pure: source string in, range out. Any shape the lexer cannot\n * handle confidently returns `null` and is reported `unresolved`, never guessed.\n */\n\n/**\n * How far above a candidate the parent of a dotted symbol may sit and still\n * be taken as scoping it. Crude on purpose: a real parser owns this question,\n * and until one takes the seat a fixed window is at least predictable.\n */\nconst PARENT_SCOPE_LINES = 50;\n\n/* -------------------------------------------------------------------------\n * A crude lexer, sufficient for counting braces\n * ---------------------------------------------------------------------- */\n\ntype ScanState = { blockComment: boolean; template: boolean };\n\nconst CLEAN_STATE: ScanState = { blockComment: false, template: false };\n\n/**\n * Strips comments and string literals from one line, carrying block-comment\n * and template-literal state across lines.\n *\n * Brace counting over raw text is wrong in both directions: a `}` inside a\n * string or a comment ends a block early — the truncation that hashes as\n * stable — and a `{` inside one opens a block that never closes. This is not\n * a tokenizer: a regex literal containing a brace (`/}/`) still fools it, and\n * `#` is left alone because TypeScript spells private fields with it. Both\n * limits are documented in the README.\n */\nfunction stripLine(\n line: string,\n state: ScanState,\n): { code: string; state: ScanState } {\n let out = \"\";\n let index = 0;\n let { blockComment, template } = state;\n\n while (index < line.length) {\n const char = line[index];\n const next = line[index + 1];\n\n if (blockComment) {\n if (char === \"*\" && next === \"/\") {\n blockComment = false;\n index += 2;\n continue;\n }\n index += 1;\n continue;\n }\n\n // Braces inside `${...}` are balanced by construction, so ignoring the\n // whole template rather than re-entering code inside it is safe here.\n if (template) {\n if (char === \"\\\\\") {\n index += 2;\n continue;\n }\n if (char === \"`\") template = false;\n index += 1;\n continue;\n }\n\n if (char === \"/\" && next === \"*\") {\n blockComment = true;\n index += 2;\n continue;\n }\n if (char === \"/\" && next === \"/\") break;\n if (char === \"`\") {\n template = true;\n index += 1;\n continue;\n }\n if (char === \"'\" || char === '\"') {\n const quote = char;\n index += 1;\n while (index < line.length) {\n if (line[index] === \"\\\\\") {\n index += 2;\n continue;\n }\n if (line[index] === quote) {\n index += 1;\n break;\n }\n index += 1;\n }\n continue;\n }\n\n out += char;\n index += 1;\n }\n\n return { code: out, state: { blockComment, template } };\n}\n\n/* -------------------------------------------------------------------------\n * Span capture\n * ---------------------------------------------------------------------- */\n\nfunction span(lines: string[], from: number, to: number): ResolvedSymbol {\n return {\n text: lines.slice(from, to + 1).join(\"\\n\"),\n startLine: from + 1,\n endLine: to + 1,\n };\n}\n\n/**\n * From the matched line to the line where brace depth returns to zero.\n *\n * Depth is tested at end of line, never mid-line, so a destructured signature\n * (`function f({ a, b }) {`) does not end the span. A top-level `;` before any\n * brace opens is a braceless declaration and the matched line alone is the\n * span. Everything else is `null`.\n */\nfunction captureBraceBlock(\n lines: string[],\n matchLine: number,\n): ResolvedSymbol | null {\n let depth = 0;\n let opened = false;\n let state = CLEAN_STATE;\n\n for (let index = matchLine; index < lines.length; index++) {\n const stripped = stripLine(lines[index] ?? \"\", state);\n state = stripped.state;\n\n for (const char of stripped.code) {\n if (char === \"{\") {\n depth += 1;\n opened = true;\n } else if (char === \"}\") {\n depth = Math.max(0, depth - 1);\n } else if (char === \";\" && !opened) {\n return span(lines, matchLine, index);\n }\n }\n\n if (opened && depth === 0) return span(lines, matchLine, index);\n }\n\n return null;\n}\n\n/** `def f(...)` / `class C:` — a header ending in a colon, body by indent. */\nconst PYTHON_HEADER = /^\\s*(?:async\\s+)?(?:def|class)\\s+[A-Za-z_]\\w*\\s*[(:]/;\n\n/**\n * A Python block: the header, however many lines its signature runs to, plus\n * every following line that is blank or indented past the header.\n *\n * Brace counting would capture a `def` line and nothing else — a signature\n * hash that never sees a body change, which is worse than no anchor at all.\n * A header whose body never arrives is `null` for the same reason.\n */\nfunction captureIndentedBlock(\n lines: string[],\n matchLine: number,\n): ResolvedSymbol | null {\n const header = lines[matchLine] ?? \"\";\n const indent = header.length - header.trimStart().length;\n\n let headerEnd = -1;\n for (\n let index = matchLine;\n index < lines.length && index <= matchLine + 20;\n index++\n ) {\n const code = stripLine(lines[index] ?? \"\", CLEAN_STATE).code.trimEnd();\n if (code.endsWith(\":\")) {\n headerEnd = index;\n break;\n }\n // `def f(): pass` — the body is on the header line, so the line is the span.\n if (code.includes(\":\")) return span(lines, matchLine, index);\n }\n if (headerEnd === -1) return null;\n\n let end = headerEnd;\n for (let index = headerEnd + 1; index < lines.length; index++) {\n const line = lines[index] ?? \"\";\n if (line.trim() === \"\") continue;\n const lineIndent = line.length - line.trimStart().length;\n if (lineIndent <= indent) break;\n end = index;\n }\n\n // A signature with no body under it is the false-stability case again.\n return end === headerEnd ? null : span(lines, matchLine, end);\n}\n\n/* -------------------------------------------------------------------------\n * The v1 resolver\n * ---------------------------------------------------------------------- */\n\n/**\n * Candidate lines, best shape first. A declaration outranks an assignment,\n * which outranks a call-shaped line, which outranks a bare mention — so an\n * anchor lands on where a symbol is defined rather than the first place it is\n * used, which `findIndex` over one loose pattern used to do.\n */\nconst TIERS: ((name: string) => RegExp)[] = [\n (name) =>\n new RegExp(\n `(?:function|class|interface|type|enum|const|let|var|def)\\\\s+${name}\\\\b`,\n ),\n (name) => new RegExp(`\\\\b${name}\\\\s*[:=]`),\n (name) => new RegExp(`\\\\b${name}\\\\s*\\\\(`),\n (name) => new RegExp(`\\\\b${name}\\\\b`),\n];\n\n/**\n * v1 heuristic resolver. A dotted symbol like `OrderService.cancel` matches on\n * its last segment, with the parent used to scope the search: a candidate\n * counts only if the parent name appears in the fifty lines above it, when any\n * candidate satisfies that at all.\n *\n * Deterministic, and ambiguity is not resolved by guessing — two lines of\n * equally good shape mean the resolver cannot tell which one the record meant,\n * and it says so by returning `null`.\n */\nexport const regexResolver: AnchorResolver = {\n name: \"regex\",\n resolve(source, symbol) {\n const segments = symbol.split(\".\");\n const name = segments[segments.length - 1];\n if (!name) return null;\n const parent =\n segments.length > 1 ? segments[segments.length - 2] : undefined;\n\n const escaped = escapeRegExp(name);\n const parentPattern = parent\n ? new RegExp(`\\\\b${escapeRegExp(parent)}\\\\b`)\n : null;\n const lines = source.split(\"\\n\");\n\n for (const tier of TIERS) {\n const pattern = tier(escaped);\n let candidates = lines\n .map((line, index) => ({ line, index }))\n .filter((entry) => pattern.test(entry.line))\n .map((entry) => entry.index);\n if (!candidates.length) continue;\n\n // Nearest enclosing parent wins, not merely a parent somewhere above:\n // two classes in one file each declaring `cancel` both see the first\n // class's name in the window, and only distance tells them apart.\n if (parentPattern && candidates.length > 1) {\n const distances = candidates.map((index) =>\n distanceToParent(lines, index, parentPattern),\n );\n const nearest = Math.min(...distances);\n if (Number.isFinite(nearest)) {\n candidates = candidates.filter((_, at) => distances[at] === nearest);\n }\n }\n\n // Two lines of the same shape: which one the record meant is a guess,\n // and a guessed anchor hashes as evidence.\n if (candidates.length !== 1) return null;\n\n const matchLine = candidates[0] as number;\n return PYTHON_HEADER.test(lines[matchLine] ?? \"\")\n ? captureIndentedBlock(lines, matchLine)\n : captureBraceBlock(lines, matchLine);\n }\n\n return null;\n },\n};\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/** Lines from the nearest parent mention at or above `index`, or Infinity. */\nfunction distanceToParent(\n lines: string[],\n index: number,\n parent: RegExp,\n): number {\n const floor = Math.max(0, index - PARENT_SCOPE_LINES);\n for (let at = index; at >= floor; at--) {\n if (parent.test(lines[at] ?? \"\")) return index - at;\n }\n return Number.POSITIVE_INFINITY;\n}\n\n/** CRLF normalized to LF before hashing, so checkout style cannot read as drift. */\nexport function hashAnchorText(text: string): string {\n return `sha256:${createHash(\"sha256\")\n .update(text.replace(/\\r\\n/g, \"\\n\"))\n .digest(\"hex\")}`;\n}\n\n/**\n * An anchor without a symbol is about the whole file; with one, the resolver\n * decides. Source newlines are normalized first so line counts and hashes\n * agree with `hashAnchorText`.\n *\n * A file's last line is the last line with content: a trailing newline is a\n * terminator, not an empty line, and counting it would have made every\n * whole-file anchor's `lines` one larger than the file.\n */\nexport function resolveAnchor(\n source: string,\n anchor: KbAnchor,\n resolver: AnchorResolver = regexResolver,\n): ResolvedSymbol | null {\n const outcome = resolveAnchorSpan(source, anchor, [resolver]);\n return outcome.ok ? outcome.span : null;\n}\n\n/**\n * Walks the resolver chain: tree-sitter, then regex, then a whole-file span\n * when the anchor names no symbol.\n *\n * `symbol-not-found` falls through (a tags query defines functions and types,\n * not constants or fields) and the anchor records the resolver that answered.\n * `symbol-ambiguous` and `resolver-unavailable` end the chain: one would be\n * settled by guessing, the other would trade a precise span for a guessed one.\n */\nexport function resolveAnchorSpan(\n source: string,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[] = [regexResolver],\n): AnchorResolution {\n const normalized = source.replace(/\\r\\n/g, \"\\n\");\n if (!anchor.symbol) {\n const lines = normalized.split(\"\\n\");\n if (lines.length > 1 && lines[lines.length - 1] === \"\") lines.pop();\n return {\n ok: true,\n span: {\n text: normalized,\n startLine: 1,\n endLine: Math.max(1, lines.length),\n },\n };\n }\n\n for (const resolver of resolvers) {\n const attempt = resolver.attempt\n ? resolver.attempt(normalized, anchor.symbol, anchor.file)\n : fromResolve(resolver, normalized, anchor.symbol, anchor.file);\n if (attempt.kind === \"abstain\") continue;\n if (attempt.kind === \"unresolved\") {\n if (attempt.reason === \"symbol-not-found\") continue;\n return { ok: false, reason: attempt.reason };\n }\n const tokens = resolver.normalize?.(attempt.span.text, anchor.file);\n return {\n ok: true,\n span: attempt.span,\n ...(isResolverName(resolver.name) ? { resolver: resolver.name } : {}),\n ...(tokens ? { normalized: tokens } : {}),\n };\n }\n return { ok: false, reason: \"symbol-not-found\" };\n}\n\n/** A resolver with no `attempt`: a span or a plain miss, never an abstain. */\nfunction fromResolve(\n resolver: AnchorResolver,\n source: string,\n symbol: string,\n file: string,\n): ResolverAttempt {\n const span = resolver.resolve(source, symbol, file);\n return span\n ? { kind: \"resolved\", span }\n : { kind: \"unresolved\", reason: \"symbol-not-found\" };\n}\n\nfunction isResolverName(name: string): name is AnchorResolverName {\n return name === \"tree-sitter\" || name === \"regex\";\n}\n\n/** Loads every chained resolver's per-language assets, once. */\nexport async function prepareResolvers(\n resolvers: readonly AnchorResolver[],\n files: readonly string[],\n): Promise<void> {\n for (const resolver of resolvers) await resolver.prepare?.(files);\n}\n\n/**\n * The read-path chain. A fresh tree-sitter resolver per call, so its parse\n * cache lives exactly as long as the run that owns it. `offline` rides down to\n * grammar loading: a run that may not reach the network uses the cache or\n * reports `resolver-unavailable`.\n */\nexport function defaultAnchorResolvers(\n grammars: GrammarOptions = {},\n): AnchorResolver[] {\n return [new TreeSitterResolver(grammars), regexResolver];\n}\n\n/**\n * Was the swap the whole story?\n *\n * Only when the resolver that stamped the anchor still reproduces the stored\n * hash against this very source. Otherwise the code moved too, and calling it\n * a resolver change would hide the edit behind a bookkeeping note.\n */\nexport function resolverChanged(\n source: string,\n anchor: KbAnchor,\n produced: AnchorResolverName | undefined,\n): boolean {\n const previous = anchor.resolver ?? \"regex\";\n if (!produced || !anchor.symbol || previous === produced) return false;\n if (previous !== \"regex\") return false;\n const before = regexResolver.resolve(\n source.replace(/\\r\\n/g, \"\\n\"),\n anchor.symbol,\n );\n return before !== null && hashAnchorText(before.text) === anchor.hash;\n}\n\n/**\n * Which hash to compare, and over what.\n *\n * A stored hash is only ever compared against a hash of the same kind — an\n * `ast` hash and a `raw` hash of the same code differ by construction, and\n * treating that as drift would report every anchor once. An anchor with no\n * hash yet takes the strongest kind the resolver can offer, so newly stamped\n * anchors stop drifting on reformatting.\n */\nexport function anchorHashOf(\n anchor: KbAnchor,\n outcome: { span: ResolvedSymbol; normalized?: string },\n): { hash: string; kind: AnchorHashKind } {\n const stored = anchor.hash ? (anchor.hash_kind ?? \"raw\") : undefined;\n const wanted = stored ?? (outcome.normalized ? \"ast\" : \"raw\");\n return wanted === \"ast\" && outcome.normalized\n ? { hash: hashAnchorText(outcome.normalized), kind: \"ast\" }\n : { hash: hashAnchorText(outcome.span.text), kind: \"raw\" };\n}\n","import { extname } from \"node:path\";\nimport { grammarManifest, type GrammarManifest } from \"../grammars/index.js\";\n\n/**\n * Which grammar a file extension is parsed with, and whether a definitions\n * query runs over it. Both are generated — `pnpm grammars pin` — from GitHub\n * Linguist and from each pack's own tags query, so adding a language is a pin\n * run rather than a hand-written query.\n */\n\n/** Inverted once per lock — the lock a test stands in is a different object. */\nlet table:\n { of: GrammarManifest; extensions: Record<string, string> } | undefined;\n\nfunction extensionTable(): Record<string, string> {\n const manifest = grammarManifest();\n if (table?.of !== manifest)\n table = {\n of: manifest,\n extensions: Object.fromEntries(\n Object.entries(manifest.packs).flatMap(([language, pack]) =>\n pack.extensions.map((extension) => [extension, language]),\n ),\n ),\n };\n return table.extensions;\n}\n\n/** Does the lock pin a tags query for this language? The query itself downloads. */\nfunction hasQuery(language: string): boolean {\n return (grammarManifest().packs[language]?.tags.length ?? 0) > 0;\n}\n\n/**\n * Grammar for a path, or `undefined` when the extension has none — or when the\n * pinned grammar release ships no tags query for it, so the regex heuristic\n * keeps those files, as before the resolver existed.\n */\nexport function languageForFile(file: string): string | undefined {\n const language = extensionTable()[extname(file).toLowerCase()];\n return language && hasQuery(language) ? language : undefined;\n}\n\n/** Every language the resolver can resolve in: a grammar and a tags query. */\nexport function treeSitterLanguages(): string[] {\n return [...new Set(Object.values(extensionTable()))].filter(hasQuery).sort();\n}\n","import { readFile } from \"node:fs/promises\";\nimport { downloadPart, grammarsBaseUrl, grammarUrl } from \"./fetch.js\";\nimport { grammarManifest } from \"./manifest.js\";\nimport type { Grammar, GrammarOptions, Pinned } from \"./model.js\";\nimport {\n grammarCachePath,\n grammarsCacheRoot,\n verifyCached,\n writeCached,\n} from \"./store.js\";\n\nexport { grammarsBaseUrl, grammarUrl } from \"./fetch.js\";\nexport {\n grammarManifest,\n grammarsDataPath,\n setGrammarManifest,\n} from \"./manifest.js\";\nexport {\n grammarManifestSchema,\n type Grammar,\n type GrammarManifest,\n type GrammarPack,\n type GrammarOptions,\n} from \"./model.js\";\nexport { grammarCachePath, grammarsCacheRoot } from \"./store.js\";\n\n/** One download per pack per process, however many callers ask at once. */\nconst inFlight = new Map<string, Promise<Grammar | null>>();\n\n/** Packs this process wanted and could not get, and why, for the hint. */\nconst missing = new Map<string, { subject: string; cause?: string }>();\n\n/** Languages whose pinned tags query would not compile, and why. */\nconst uncompilable = new Map<string, string>();\n\n/** Languages whose pinned grammar this runtime refused to load, and why. */\nconst rejected = new Map<string, string>();\n\n/** `STRAUSS_KB_GRAMMARS=off` keeps a run off the wire; the cache still counts. */\nexport function grammarsDownloadDisabled(): boolean {\n return process.env[\"STRAUSS_KB_GRAMMARS\"] === \"off\";\n}\n\n/**\n * Both halves of a verified pack (cached WASM path, tags query text), each\n * downloaded once. `null` on any refused, disabled or mismatched part is what\n * the resolver reports as `resolver-unavailable`; a miss is not remembered.\n */\nexport async function ensureGrammar(\n language: string,\n options: GrammarOptions = {},\n): Promise<Grammar | null> {\n const pack = grammarManifest().packs[language];\n if (!pack) return null;\n\n const root = grammarsCacheRoot(options.cacheRoot);\n const wasm = grammarCachePath(root, language, pack.wasm.sha256);\n // Keyed on the pack rather than the part, so a pack downloads once however\n // many parts it has.\n const key = `${wasm} ${grammarsBaseUrl(options.baseUrl) ?? \"\"}`;\n const existing = inFlight.get(key);\n if (existing) return existing;\n\n const pending = (async () => {\n const grammar = await ensurePart(\n wasm,\n `tree-sitter-${language}`,\n pack.wasm,\n options,\n );\n if (grammar !== true)\n return miss(language, `grammar tree-sitter-${language}`, grammar);\n\n const parts: string[] = [];\n const total = pack.tags.length;\n for (const [at, part] of pack.tags.entries()) {\n const name = `${language} tags${total > 1 ? ` part ${at + 1}/${total}` : \"\"}`;\n const path = grammarCachePath(root, language, part.sha256, \"scm\");\n const held = await ensurePart(path, name, part, options);\n if (held !== true) return miss(language, name, held);\n parts.push(`; ${part.url}\\n${lf(await readFile(path, \"utf8\"))}`);\n }\n\n missing.delete(language);\n return { wasm, query: total ? parts.join(\"\\n\") : undefined };\n })();\n inFlight.set(key, pending);\n const result = await pending;\n if (result === null) inFlight.delete(key);\n return result;\n}\n\n/** `true` once the part is cached and hashes as the lock says, else why not. */\nasync function ensurePart(\n path: string,\n name: string,\n entry: Pinned & { url: string },\n options: GrammarOptions,\n): Promise<true | { cause?: string }> {\n if (await verifyCached(path, entry)) return true;\n if (options.offline === true || grammarsDownloadDisabled()) return {};\n const download = await downloadPart(\n grammarUrl(entry.url, options.baseUrl),\n name,\n entry,\n options,\n );\n if (\"cause\" in download) return { cause: download.cause };\n await writeCached(path, download.bytes).catch(() => null);\n return true;\n}\n\n/** Records which part of the pack this run could not get, for the hint. */\nfunction miss(\n language: string,\n subject: string,\n failure: { cause?: string },\n): null {\n missing.set(language, { subject, ...failure });\n return null;\n}\n\n/** The pin concatenates parts LF-normalised; the runtime must compile the same. */\nfunction lf(body: string): string {\n return body.replace(/\\r\\n/g, \"\\n\");\n}\n\n/**\n * A tags query that will not compile against the grammar release it is pinned\n * to. The resolver reports the language unavailable; the repair is a re-pin.\n */\nexport function noteUncompilableQuery(language: string, cause: string): void {\n uncompilable.set(language, cause);\n}\n\n/**\n * A grammar the runtime will not load — a WASM built at an ABI outside the\n * range this `web-tree-sitter` accepts. The resolver reports the language\n * unavailable; the repair is a re-pin against the installed runtime.\n */\nexport function noteRejectedGrammar(language: string, cause: string): void {\n rejected.set(language, cause);\n}\n\n/**\n * One line per grammar this process could not use, for the doctor and\n * anchor-resolve reports. The only place a repair is spelled out.\n */\nexport function grammarHints(): string[] {\n const manifest = grammarManifest();\n const packs = manifest.packs;\n const lines = new Map<string, string>();\n for (const [language, { subject, cause }] of missing)\n lines.set(\n language,\n `${subject} not cached${cause ? ` (${cause})` : \"\"}; run online once, or set STRAUSS_KB_GRAMMARS_DIR`,\n );\n for (const [language, cause] of rejected)\n lines.set(\n language,\n `${packs[language]?.package ?? `tree-sitter-${language}`} rejected by web-tree-sitter ${manifest.webTreeSitter}${cause ? `: ${cause}` : \"\"}; re-pin with pnpm grammars pin ${language}`,\n );\n for (const [language, cause] of uncompilable)\n lines.set(\n language,\n `tags query for ${language} does not compile against ${packs[language]?.package ?? `tree-sitter-${language}`}: ${cause}; re-pin with pnpm grammars pin ${language}`,\n );\n return [...lines]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([, line]) => line);\n}\n\n/** Test seam: forgets this process's downloads, misses and query failures. */\nexport function resetGrammarState(): void {\n inFlight.clear();\n missing.clear();\n uncompilable.clear();\n rejected.clear();\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { Pinned } from \"./model.js\";\n\n/** Where downloaded grammars live. Overridable so a test never writes to `$HOME`. */\nexport function grammarsCacheRoot(override?: string): string {\n return (\n override ??\n process.env[\"STRAUSS_KB_GRAMMARS_DIR\"] ??\n join(homedir(), \".strauss\", \"grammars\")\n );\n}\n\n/**\n * Named by the hash the manifest pins, so a re-pin downloads beside the old\n * file instead of over it and a rollback finds its own still there. Both parts\n * of a pack share the layout: `<root>/<language>/<sha12>.wasm|.scm`.\n */\nexport function grammarCachePath(\n root: string,\n language: string,\n sha256: string,\n extension: \"wasm\" | \"scm\" = \"wasm\",\n): string {\n return join(root, language, `${sha256.slice(0, 12)}.${extension}`);\n}\n\nexport function sha256(bytes: Uint8Array): string {\n return createHash(\"sha256\").update(bytes).digest(\"hex\");\n}\n\nexport function matches(bytes: Uint8Array, entry: Pinned): boolean {\n if (entry.bytes !== undefined && bytes.byteLength !== entry.bytes)\n return false;\n return sha256(bytes) === entry.sha256;\n}\n\n/**\n * `true` when the cached file hashes as the manifest says. Checked on every\n * load, not only on download: `$HOME` is writable by anything the user runs\n * and a grammar is code the parser executes. A failing file is deleted.\n */\nexport async function verifyCached(\n path: string,\n entry: Pinned,\n): Promise<boolean> {\n let bytes: Uint8Array;\n try {\n bytes = await readFile(path);\n } catch {\n return false;\n }\n if (matches(bytes, entry)) return true;\n await rm(path, { force: true });\n return false;\n}\n\n/**\n * Write then `rename`, which is atomic within a filesystem: a second process\n * either sees the old file or the whole new one, never a half-written parser.\n */\nexport async function writeCached(\n path: string,\n bytes: Uint8Array,\n): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const temporary = `${path}.${process.pid}.${randomBytes(4).toString(\"hex\")}.tmp`;\n try {\n await writeFile(temporary, bytes);\n await rename(temporary, path);\n } catch (error) {\n await rm(temporary, { force: true });\n throw error;\n }\n}\n","import { fetchTimeoutMs } from \"../remote-repo/index.js\";\nimport type { GrammarOptions, Pinned } from \"./model.js\";\nimport { matches } from \"./store.js\";\n\n/** Attempts per grammar, and the pause after attempt `n`. */\nconst ATTEMPTS = 3;\nconst BACKOFF_MS = 250;\n\n/**\n * The manifest pins a fully resolved URL per pack. An override — a mirror, or\n * the suite's own server — replaces its scheme and host and nothing else, so\n * one setting redirects every pack whatever CDN it was pinned from.\n */\nexport function grammarUrl(url: string, override?: string): string {\n const base = grammarsBaseUrl(override);\n if (!base) return url;\n let root = base;\n while (root.endsWith(\"/\")) root = root.slice(0, -1);\n const pinned = new URL(url);\n return `${root}${pinned.pathname}${pinned.search}`;\n}\n\nexport function grammarsBaseUrl(override?: string): string | undefined {\n return override ?? process.env[\"STRAUSS_KB_GRAMMARS_URL\"];\n}\n\n/** Bytes, or why the last attempt failed — for the log line and the hint. */\nexport type Download = { bytes: Uint8Array } | { cause: string };\n\n/**\n * A pinned part's bytes, or a cause — never a throw. Grammar and tags query\n * take the same path: a hash mismatch is not retried (the CDN will serve the\n * same file again; the manifest is the safety), while timeouts, dropped\n * connections, 5xx and 429 get `ATTEMPTS` tries.\n */\nexport async function downloadPart(\n url: string,\n name: string,\n entry: Pinned,\n options: GrammarOptions = {},\n): Promise<Download> {\n const log =\n options.log ?? ((line: string) => void process.stderr.write(line));\n const weight =\n entry.bytes === undefined ? \"\" : ` (${size(entry.bytes)} from manifest)`;\n log(`strauss-kb: downloading ${name}${weight} from ${url}\\n`);\n\n let cause = \"\";\n for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {\n const outcome = await attemptDownload(url, entry, options.fetchTimeoutMs);\n if (\"bytes\" in outcome) return outcome;\n cause = outcome.cause;\n log(\n `strauss-kb: ${name} attempt ${attempt}/${ATTEMPTS} failed: ${cause}\\n`,\n );\n if (!outcome.retry) break;\n if (attempt < ATTEMPTS) await pause(BACKOFF_MS * attempt);\n }\n log(`strauss-kb: ${name} not downloaded: ${cause}\\n`);\n return { cause };\n}\n\nasync function attemptDownload(\n url: string,\n entry: Pinned,\n timeoutMs: number | undefined,\n): Promise<{ bytes: Uint8Array } | { cause: string; retry: boolean }> {\n try {\n const response = await fetch(url, {\n signal: AbortSignal.timeout(fetchTimeoutMs(timeoutMs)),\n });\n if (!response.ok) {\n return {\n cause: `HTTP ${response.status}`,\n retry: response.status >= 500 || response.status === 429,\n };\n }\n const bytes = new Uint8Array(await response.arrayBuffer());\n if (!matches(bytes, entry))\n return { cause: \"sha256 mismatch\", retry: false };\n return { bytes };\n } catch (error) {\n const timedOut =\n error instanceof Error &&\n (error.name === \"TimeoutError\" || error.name === \"AbortError\");\n return { cause: timedOut ? \"timeout\" : \"network error\", retry: true };\n }\n}\n\n/** What the manifest says the file weighs, for the download line. */\nfunction size(bytes: number): string {\n return bytes >= 1024 * 1024\n ? `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n : `${Math.round(bytes / 1024)} KB`;\n}\n\nfunction pause(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { grammarManifestSchema, type GrammarManifest } from \"./model.js\";\n\nlet cached: GrammarManifest | undefined;\n\n/**\n * The shipped `grammars/manifest.json`: the URL, hash and extensions of every\n * language pack. Read once per process.\n */\nexport function grammarManifest(): GrammarManifest {\n cached ??= grammarManifestSchema.parse(\n JSON.parse(readFileSync(grammarsDataPath(\"manifest.json\"), \"utf8\")),\n );\n return cached;\n}\n\n/**\n * Test seam: stands a lock of the test's own in for the shipped one, so a\n * suite can pin a part the shipped lock does not carry. `undefined` restores.\n */\nexport function setGrammarManifest(manifest?: GrammarManifest): void {\n cached = manifest;\n}\n\n/**\n * A path under the package's shipped `grammars/` directory.\n *\n * Source and bundle sit at different depths under the package root — `src/\n * grammars/` and `dist/` — so the directory is found by walking up rather than\n * by a fixed `..`.\n */\nexport function grammarsDataPath(...segments: string[]): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let up = 0; up < 5; up++) {\n const candidate = join(dir, \"grammars\");\n if (existsSync(join(candidate, \"manifest.json\")))\n return join(candidate, ...segments);\n dir = dirname(dir);\n }\n throw new Error(\"grammars/manifest.json is missing from the package\");\n}\n","import { z } from \"zod\";\n\nconst sha256 = z.string().regex(/^[0-9a-f]{64}$/);\n\n/**\n * The WASM half of a pack as the lock records it: the URL it was pinned from\n * and what it hashed to. `bytes` is checked before the hash so a truncated\n * response is rejected without hashing megabytes.\n */\nexport const grammarWasmSchema = z.object({\n url: z.string().min(1),\n sha256,\n bytes: z.number().int().positive(),\n});\n\n/**\n * One part of the tags query. A query is kilobytes, so the hash alone settles\n * it and the lock carries no byte count.\n */\nexport const grammarTagsSchema = z.object({ url: z.string().min(1), sha256 });\n\n/**\n * A language pack: a grammar and the definitions query that runs over it,\n * pinned together at one `package@version`. `tags` is empty where upstream\n * ships no query — that language parses but resolves nothing.\n */\nexport const grammarPackSchema = z.object({\n package: z.string().min(1),\n wasm: grammarWasmSchema,\n tags: z.array(grammarTagsSchema),\n license: z.string().min(1),\n extensions: z.array(z.string().min(1)),\n});\n\nexport const grammarManifestSchema = z.object({\n /** The runtime the packs were proved against. */\n webTreeSitter: z.string().min(1),\n linguist: z.object({ tag: z.string().min(1), commit: z.string().min(1) }),\n packs: z.record(z.string().min(1), grammarPackSchema),\n});\n\nexport type GrammarWasm = z.infer<typeof grammarWasmSchema>;\nexport type GrammarTags = z.infer<typeof grammarTagsSchema>;\n/** What a cached file is checked against: a hash, and a size where one is known. */\nexport type Pinned = { sha256: string; bytes?: number };\nexport type GrammarPack = z.infer<typeof grammarPackSchema>;\nexport type GrammarManifest = z.infer<typeof grammarManifestSchema>;\n\n/** A grammar and the query that runs over it, both verified, both on disk. */\nexport type Grammar = {\n /** Path to the cached WASM. */\n wasm: string;\n /** The pack's tags parts as one query, or `undefined` where it declares none. */\n query: string | undefined;\n};\n\n/** Where a grammar comes from and whether it may be fetched at all. */\nexport type GrammarOptions = {\n /** Cache root; defaults to `STRAUSS_KB_GRAMMARS_DIR` then `~/.strauss/grammars`. */\n cacheRoot?: string;\n /** Replaces the scheme and host of every manifest URL. For tests and mirrors. */\n baseUrl?: string;\n /** Cache only, never the network — what `--offline` passes down. */\n offline?: boolean;\n fetchTimeoutMs?: number;\n /** Where the download lines go. Defaults to stderr, never stdout. */\n log?: (line: string) => void;\n};\n","import { createHash } from \"node:crypto\";\nimport { Language, Parser, Query, type Tree } from \"web-tree-sitter\";\nimport type {\n AnchorResolver,\n ResolvedSymbol,\n ResolverAttempt,\n} from \"../anchor-resolver/index.js\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport {\n ensureGrammar,\n noteRejectedGrammar,\n noteUncompilableQuery,\n type Grammar,\n type GrammarOptions,\n} from \"../grammars/index.js\";\nimport {\n chainOf,\n index,\n select,\n spanOf,\n type Definition,\n type ParsedFile,\n} from \"./definitions.js\";\nimport { languageForFile } from \"./languages.js\";\nimport { tokens } from \"./tokens.js\";\n\n/**\n * AST-backed anchor resolution: a symbol resolves to the byte range of the\n * definition node that declares it, or to nothing.\n *\n * `resolve` stays synchronous because the read path resolves inside a loop;\n * grammar loading is the async part and happens once, in `prepare`.\n */\n\n/** How many parsed trees to keep. Trees are large; anchors cluster in few files. */\nconst TREE_CACHE_LIMIT = 32;\n\ntype Loaded = { language: Language; query: Query };\n\nexport type TreeSitterStats = { parses: number; cacheHits: number };\n\n/** Where both halves of a pack come from, and whether they may be fetched. */\nexport type TreeSitterOptions = GrammarOptions;\n\nexport class TreeSitterResolver implements AnchorResolver {\n readonly name = \"tree-sitter\";\n\n private readonly grammars: GrammarOptions;\n private readonly loaded = new Map<string, Loaded | null>();\n private readonly trees = new Map<string, ParsedFile>();\n private parser: Parser | undefined;\n private initialized = false;\n\n /** Cache effectiveness, for tests and for the latency numbers. */\n readonly stats: TreeSitterStats = { parses: 0, cacheHits: 0 };\n\n constructor(options: TreeSitterOptions = {}) {\n this.grammars = options;\n }\n\n /**\n * Loads the grammars these files need, once per language per process,\n * downloading each one on first use.\n *\n * A grammar that will not load is remembered as unavailable rather than\n * retried per anchor, and never throws: an unobtainable WASM is a finding.\n */\n async prepare(files: readonly string[]): Promise<void> {\n const wanted = new Set<string>();\n for (const file of files) {\n const language = languageForFile(file);\n if (language && !this.loaded.has(language)) wanted.add(language);\n }\n if (!wanted.size) return;\n\n if (!this.initialized) {\n try {\n await Parser.init();\n this.parser = new Parser();\n this.initialized = true;\n } catch {\n for (const language of wanted) this.loaded.set(language, null);\n return;\n }\n }\n\n // Downloads dominate a cold first run, so the languages a bundle needs\n // are fetched together rather than one after another.\n const languages = [...wanted];\n const loaded = await mapLimit(\n languages,\n Math.min(DEFAULT_IO_CONCURRENCY, languages.length),\n (language) => this.load(language),\n );\n languages.forEach((language, at) =>\n this.loaded.set(language, loaded[at] ?? null),\n );\n }\n\n /**\n * An unobtainable grammar, one this runtime refuses, and a query that will\n * not compile are three faults with three repairs; all are reported through\n * the grammars module so every hint has one home.\n */\n private async load(language: string): Promise<Loaded | null> {\n let pack: Grammar | null;\n try {\n pack = await ensureGrammar(language, this.grammars);\n } catch {\n return null;\n }\n if (!pack?.query) return null;\n\n let grammar: Language;\n try {\n grammar = await Language.load(pack.wasm);\n } catch (error) {\n noteRejectedGrammar(language, why(error));\n return null;\n }\n try {\n return { language: grammar, query: new Query(grammar, pack.query) };\n } catch (error) {\n noteUncompilableQuery(language, why(error));\n return null;\n }\n }\n\n /**\n * Abstains on an extension with no grammar so the regex resolver gets a\n * turn; reports `resolver-unavailable` when the grammar exists in principle\n * but could not be loaded, because falling back there would silently trade a\n * precise span for a guessed one.\n */\n attempt(source: string, symbol: string, file?: string): ResolverAttempt {\n const language = file ? languageForFile(file) : undefined;\n if (!language) return { kind: \"abstain\" };\n if (!this.loaded.has(language)) return { kind: \"abstain\" };\n const loaded = this.loaded.get(language);\n if (!loaded) return { kind: \"unresolved\", reason: \"resolver-unavailable\" };\n\n const parsed = this.parse(language, loaded, source);\n if (!parsed) return { kind: \"unresolved\", reason: \"resolver-unavailable\" };\n\n const wanted = symbol.split(\".\").filter(Boolean);\n if (!wanted.length)\n return { kind: \"unresolved\", reason: \"symbol-not-found\" };\n\n const matches = select(parsed, wanted);\n if (!matches.length)\n return { kind: \"unresolved\", reason: \"symbol-not-found\" };\n if (matches.length > 1)\n return { kind: \"unresolved\", reason: \"symbol-ambiguous\" };\n return { kind: \"resolved\", span: spanOf(matches[0] as Definition, source) };\n }\n\n resolve(\n source: string,\n symbol: string,\n file?: string,\n ): ResolvedSymbol | null {\n const attempt = this.attempt(source, symbol, file);\n return attempt.kind === \"resolved\" ? attempt.span : null;\n }\n\n /** Parsed trees are keyed by content hash, so an unchanged file parses once. */\n private parse(\n language: string,\n loaded: Loaded,\n source: string,\n ): ParsedFile | null {\n const key = `${language}:${createHash(\"sha256\").update(source).digest(\"hex\")}`;\n const cached = this.trees.get(key);\n if (cached) {\n this.stats.cacheHits += 1;\n return cached;\n }\n\n const parser = this.parser;\n if (!parser) return null;\n let parsed: ParsedFile;\n try {\n parser.setLanguage(loaded.language);\n const tree = parser.parse(source);\n if (!tree) return null;\n parsed = index(tree, loaded.query);\n } catch {\n return null;\n }\n this.stats.parses += 1;\n\n if (this.trees.size >= TREE_CACHE_LIMIT) {\n const oldest = this.trees.keys().next();\n if (!oldest.done) {\n this.trees.get(oldest.value)?.tree.delete();\n this.trees.delete(oldest.value);\n }\n }\n this.trees.set(key, parsed);\n return parsed;\n }\n\n /**\n * Every definition this file declares, as dotted symbol and span.\n *\n * The inverse of `attempt`: that asks \"where is this name\", this asks \"what\n * names are here\". `moved` needs the second — the stored hash has to be\n * looked for at every definition in the repository, and there is no name to\n * ask about, since the whole question is which name now carries that code.\n */\n spans(\n source: string,\n file: string,\n ): { symbol: string; span: ResolvedSymbol }[] {\n const language = languageForFile(file);\n if (!language) return [];\n const loaded = this.loaded.get(language);\n if (!loaded) return [];\n const parsed = this.parse(language, loaded, source);\n if (!parsed) return [];\n\n return parsed.definitions\n .filter((definition) => definition.target)\n .map((definition) => ({\n symbol: chainOf(definition, parsed.byNodeId).join(\".\"),\n span: spanOf(definition, source),\n }));\n }\n\n /**\n * The token stream of a span: every leaf the parser sees, comments dropped,\n * joined by single spaces.\n *\n * This is what makes a reformat not be drift. Hashing it rather than the raw\n * text means indentation, line breaks, trailing commas the formatter moved,\n * and every comment above or inside the definition are outside the hash —\n * and a renamed identifier or a changed literal is still inside it, because\n * those are leaves.\n *\n * `null` when the file has no grammar, the grammar would not load, or the\n * text will not parse: no normalisation is better than a guessed one.\n */\n normalize(text: string, file?: string): string | null {\n const language = file ? languageForFile(file) : undefined;\n if (!language) return null;\n const loaded = this.loaded.get(language);\n if (!loaded) return null;\n\n const parser = this.parser;\n if (!parser) return null;\n let tree: Tree | null;\n try {\n parser.setLanguage(loaded.language);\n tree = parser.parse(text);\n } catch {\n return null;\n }\n if (!tree) return null;\n try {\n return tokens(tree.rootNode).join(\" \");\n } finally {\n tree.delete();\n }\n }\n\n /** Drops cached trees. Grammars stay loaded — they are immutable. */\n reset(): void {\n for (const parsed of this.trees.values()) parsed.tree.delete();\n this.trees.clear();\n this.stats.parses = 0;\n this.stats.cacheHits = 0;\n }\n}\n\n/** web-tree-sitter throws bare Errors for a rejected module; say so. */\nfunction why(error: unknown): string {\n const text = error instanceof Error ? error.message : String(error);\n return text || \"no reason given\";\n}\n","import type { Node, Query, Tree } from \"web-tree-sitter\";\nimport type { ResolvedSymbol } from \"../anchor-resolver/index.js\";\n\n/**\n * Upstream `tags.scm` vocabulary: `@name` is the symbol, `@definition.*` the\n * node a reader points at, `@reference.*` a use. `@reference.implementation`\n * (a Rust `impl Foo`) scopes the chain without being a target.\n */\n\nconst SCOPE_ONLY = \"reference.implementation\";\n\n/** A definition site, with the node whose range becomes the anchor span. */\nexport type Definition = {\n node: Node;\n name: string;\n /** `false` for chain-only scopes such as a Rust `impl` block. */\n target: boolean;\n};\n\nexport type ParsedFile = {\n tree: Tree;\n /** Definitions by node id, for walking a node's enclosing chain. */\n byNodeId: Map<number, Definition>;\n definitions: Definition[];\n};\n\n/**\n * One definition per name site, innermost node wins — a query that captures\n * the same name twice (upstream Rust makes every `fn` both a function and,\n * inside its `impl` block's `declaration_list`, a method) means the tightest\n * node around the name, never the block that holds its siblings too.\n */\nexport function index(tree: Tree, query: Query): ParsedFile {\n const byName = new Map<number, Definition>();\n\n for (const match of query.matches(tree.rootNode)) {\n const nameNode = match.captures.find((capture) => capture.name === \"name\");\n const defNode = match.captures.find(\n (capture) =>\n capture.name.startsWith(\"definition.\") || capture.name === SCOPE_ONLY,\n );\n if (!nameNode || !defNode) continue;\n\n const candidate: Definition = {\n node: defNode.node,\n name: nameNode.node.text,\n target: defNode.name !== SCOPE_ONLY,\n };\n const existing = byName.get(nameNode.node.id);\n if (existing && width(existing.node) <= width(candidate.node)) continue;\n byName.set(nameNode.node.id, candidate);\n }\n\n const definitions = [...byName.values()];\n return {\n tree,\n byNodeId: new Map(\n definitions.map((definition) => [definition.node.id, definition]),\n ),\n definitions,\n };\n}\n\n/**\n * Definitions whose chain ends with `wanted`. When several match, the ones\n * with a body win: an overload signature declares the same chain as the\n * implementation, and the implementation is what a reader means.\n */\nexport function select(\n parsed: ParsedFile,\n wanted: readonly string[],\n): Definition[] {\n const matches = parsed.definitions.filter(\n (definition) =>\n definition.target &&\n endsWith(chainOf(definition, parsed.byNodeId), wanted),\n );\n if (matches.length < 2) return matches;\n const bodied = matches.filter(\n (definition) => definition.node.childForFieldName(\"body\") !== null,\n );\n return bodied.length === 1 ? bodied : matches;\n}\n\n/**\n * The definition's enclosing chain, outermost first: `[\"OrderService\",\n * \"cancel\"]` for a method of that class.\n *\n * A receiver stands in for an ancestor where a grammar has one — Go's\n * `func (s *Server) Cancel` chains as `Server.Cancel`.\n */\nexport function chainOf(\n definition: Definition,\n byNodeId: Map<number, Definition>,\n): string[] {\n const chain = [definition.name];\n\n const receiver = definition.node.childForFieldName(\"receiver\");\n const type = receiver && typeNameIn(receiver);\n if (type) chain.unshift(type);\n\n for (let node = definition.node.parent; node; node = node.parent) {\n const enclosing = byNodeId.get(node.id);\n if (enclosing && enclosing.node !== definition.node)\n chain.unshift(enclosing.name);\n }\n return chain;\n}\n\n/** `(s *Server)` and `(s Server)` both name `Server`. */\nfunction typeNameIn(receiver: Node): string | undefined {\n const stack: Node[] = [receiver];\n while (stack.length) {\n const node = stack.pop() as Node;\n if (node.type === \"type_identifier\") return node.text;\n for (let at = 0; at < node.childCount; at++) {\n const child = node.child(at);\n if (child) stack.push(child);\n }\n }\n return undefined;\n}\n\n/** Does `chain` end with every segment of `wanted`, in order? */\nfunction endsWith(chain: string[], wanted: readonly string[]): boolean {\n if (wanted.length > chain.length) return false;\n const offset = chain.length - wanted.length;\n return wanted.every((segment, at) => chain[offset + at] === segment);\n}\n\nfunction width(node: Node): number {\n return node.endIndex - node.startIndex;\n}\n\n/**\n * The definition node's lines, widened to what a reader would call the\n * declaration: preceding decorators, and the `export` that fronts it.\n */\nexport function spanOf(definition: Definition, source: string): ResolvedSymbol {\n let start = definition.node;\n let end = definition.node;\n\n for (\n let sibling = start.previousSibling;\n sibling?.type === \"decorator\";\n sibling = sibling.previousSibling\n ) {\n start = sibling;\n }\n\n const parent = end.parent;\n if (\n parent?.type === \"export_statement\" &&\n parent.childForFieldName(\"declaration\")?.id === end.id\n ) {\n start = parent;\n end = parent;\n }\n\n const lines = source.split(\"\\n\");\n const startLine = start.startPosition.row;\n // A node ending at column 0 ends on the previous line's newline.\n const endLine =\n end.endPosition.column === 0 && end.endPosition.row > startLine\n ? end.endPosition.row - 1\n : end.endPosition.row;\n\n return {\n text: lines.slice(startLine, endLine + 1).join(\"\\n\"),\n startLine: startLine + 1,\n endLine: endLine + 1,\n };\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/**\n * Leaf text in source order, comments skipped whole.\n *\n * Iterative rather than recursive: a span is bounded by `MAX_ANCHOR_FILE_BYTES`\n * but its nesting depth is not, and a deeply nested literal must not be able to\n * overflow the stack on a read path.\n */\nexport function tokens(root: Node): string[] {\n const out: string[] = [];\n const stack: Node[] = [root];\n while (stack.length) {\n const node = stack.pop() as Node;\n if (node.type.includes(\"comment\")) continue;\n if (node.childCount === 0) {\n const text = node.text.trim();\n if (text) out.push(text);\n continue;\n }\n for (let at = node.childCount - 1; at >= 0; at--) {\n const child = node.child(at);\n if (child) stack.push(child);\n }\n }\n return out;\n}\n","import { DEFAULT_IO_CONCURRENCY } from \"../concurrency.js\";\nimport type { KbAnchor, KbRecord } from \"../kb-record.schema.js\";\nimport {\n readRemoteAnchors,\n wantKey,\n type RemoteOptions,\n type RemoteRead,\n type RemoteWant,\n} from \"../remote-repo/index.js\";\nimport type {\n AnchorFileReader,\n AnchorHashKind,\n AnchorRead,\n AnchorResolver,\n AnchorResolverName,\n KbAnchorDriftEntry,\n KbDriftClass,\n} from \"./model.js\";\nimport { anchorFileReader, readAnchorFiles } from \"./read.js\";\nimport { LazyOrigin, normalizeRepoUrl } from \"./repo-identity.js\";\nimport {\n anchorHashOf,\n defaultAnchorResolvers,\n prepareResolvers,\n resolveAnchorSpan,\n resolverChanged,\n} from \"./resolver.js\";\n\nexport type AnchorDriftOptions = {\n repoRoot?: string;\n /** Single resolver, no chain. Convenience for tests. */\n resolver?: AnchorResolver;\n /** The chain, tried in order. Defaults to tree-sitter then regex. */\n resolvers?: readonly AnchorResolver[];\n concurrency?: number;\n /** Test seam: replaces the disk reader. */\n reader?: AnchorFileReader;\n /** Remote resolution of foreign anchors; `offline` keeps a run off the wire. */\n remote?: RemoteOptions;\n /** Test seam: replaces the remote blob reader. */\n readRemote?: typeof readRemoteAnchors;\n};\n\ntype Planned = { anchor: KbAnchor; foreign: boolean };\n\n/**\n * Re-resolves every hash-carrying anchor and compares against the stored hash.\n *\n * An anchor naming another repository is read from that repository's remote\n * through a bare cache; everything else is read from the working tree. A\n * missing file, an unreachable remote, or an unresolvable symbol is a finding\n * (`unresolved`), never a throw.\n *\n * Four phases: collect the checkable anchors, read the working tree's distinct\n * files and the remotes' distinct (repo, rev, file) blobs, then resolve and\n * hash in record order — so the output never depends on which read finished\n * first.\n */\nexport async function detectAnchorDrift(\n records: KbRecord[],\n options: AnchorDriftOptions = {},\n): Promise<Map<string, KbAnchorDriftEntry[]>> {\n const repoRoot = options.repoRoot ?? process.cwd();\n const resolvers =\n options.resolvers ??\n (options.resolver\n ? [options.resolver]\n : defaultAnchorResolvers({\n offline: options.remote?.offline === true,\n }));\n const origin = new LazyOrigin(repoRoot);\n\n const planned = new Map<string, Planned[]>();\n let declaresRepo = false;\n for (const record of records) {\n const anchors = (record.frontmatter.strauss_anchors ?? []).filter(\n (anchor) => anchor.hash,\n );\n if (!anchors.length) continue;\n if (anchors.some((anchor) => anchor.repo)) declaresRepo = true;\n planned.set(\n record.conceptId,\n anchors.map((anchor) => ({ anchor, foreign: false })),\n );\n }\n if (declaresRepo) {\n await origin.prime();\n for (const entries of planned.values()) {\n for (const entry of entries)\n entry.foreign = origin.isForeign(entry.anchor);\n }\n }\n\n const files: string[] = [];\n const wants: RemoteWant[] = [];\n for (const entries of planned.values()) {\n for (const { anchor, foreign } of entries) {\n if (!foreign) files.push(anchor.file);\n else wants.push(...remoteWants(anchor));\n }\n }\n\n // Disk and network are independent; neither waits for the other.\n const [reads, remote] = await Promise.all([\n readAnchorFiles(\n files,\n options.reader ?? anchorFileReader(repoRoot),\n options.concurrency ?? DEFAULT_IO_CONCURRENCY,\n ),\n (options.readRemote ?? readRemoteAnchors)(wants, options.remote ?? {}),\n ]);\n await prepareResolvers(resolvers, [\n ...files,\n ...wants.map((want) => want.file),\n ]);\n\n const drift = new Map<string, KbAnchorDriftEntry[]>();\n for (const record of records) {\n const entries: KbAnchorDriftEntry[] = [];\n for (const { anchor, foreign } of planned.get(record.conceptId) ?? []) {\n entries.push(\n foreign\n ? remoteEntry(anchor, remote, resolvers)\n : localEntry(anchor, reads.get(anchor.file) as AnchorRead, resolvers),\n );\n }\n if (entries.length) drift.set(record.conceptId, entries);\n }\n return drift;\n}\n\n/**\n * What must be read for one foreign anchor: the pinned commit, plus the\n * default branch it is \"current\" against when the anchor pins one at all.\n */\nexport function remoteWants(anchor: KbAnchor): RemoteWant[] {\n const repo = anchor.repo as string;\n const wants: RemoteWant[] = [{ repo, file: anchor.file }];\n if (anchor.ref) wants.unshift({ repo, ref: anchor.ref, file: anchor.file });\n return wants;\n}\n\nfunction base(\n anchor: KbAnchor,\n): Pick<KbAnchorDriftEntry, \"file\" | \"symbol\" | \"storedHash\"> {\n return {\n file: anchor.file,\n ...(anchor.symbol ? { symbol: anchor.symbol } : {}),\n storedHash: anchor.hash as string,\n };\n}\n\nfunction unresolved(\n anchor: KbAnchor,\n reason: KbAnchorDriftEntry[\"reason\"],\n repo?: string,\n): KbAnchorDriftEntry {\n return {\n ...base(anchor),\n state: \"unresolved\",\n diffSize: null,\n ...(reason ? { reason } : {}),\n ...(repo ? { repo } : {}),\n ...classOf(reason),\n };\n}\n\n/**\n * The class a hash comparison alone can settle.\n *\n * A vanished file or an undefined symbol is `gone` — the strongest signal\n * there is, because the described code does not exist to be re-read. Anything\n * that resolved and hashed differently is `changed` until a search proves it\n * only moved.\n */\nexport function provisionalDriftClass(\n entry: Pick<KbAnchorDriftEntry, \"state\" | \"reason\">,\n): KbDriftClass | undefined {\n if (entry.state === \"unresolved\") {\n return entry.reason === \"file-missing\" ||\n entry.reason === \"symbol-not-found\"\n ? \"gone\"\n : undefined;\n }\n return entry.state === \"drifted\" ? \"changed\" : undefined;\n}\n\n/** `class` for an unresolved reason, or nothing to spread. */\nfunction classOf(reason: KbAnchorDriftEntry[\"reason\"]): {\n class?: KbDriftClass;\n} {\n const settled = provisionalDriftClass({ state: \"unresolved\", reason });\n return settled ? { class: settled } : {};\n}\n\ntype Current = {\n hash: string;\n kind: AnchorHashKind;\n lines: number;\n resolver?: AnchorResolverName;\n};\n\n/** The hash of an anchor's text in one source, or the reason it has none. */\nfunction hashIn(\n source: string,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n):\n | { ok: true; current: Current }\n | { ok: false; reason: KbAnchorDriftEntry[\"reason\"] } {\n const outcome = resolveAnchorSpan(source, anchor, resolvers);\n if (!outcome.ok) return { ok: false, reason: outcome.reason };\n const { hash, kind } = anchorHashOf(anchor, outcome);\n return {\n ok: true,\n current: {\n hash,\n kind,\n lines: outcome.span.endLine - outcome.span.startLine + 1,\n ...(outcome.resolver ? { resolver: outcome.resolver } : {}),\n },\n };\n}\n\n/**\n * Which resolver produced the hash, and — when it differs from the stored one\n * — whether that swap is the whole difference. A regex-stamped anchor re-read\n * by tree-sitter drifts because the resolver changed, not because the code\n * did; named so a reader can tell the two apart before reaching for\n * `--rebaseline`.\n */\nfunction resolverExtras(\n source: string,\n anchor: KbAnchor,\n current: Current,\n): Partial<KbAnchorDriftEntry> {\n return {\n ...(current.resolver ? { resolver: current.resolver } : {}),\n ...(current.hash !== anchor.hash &&\n resolverChanged(source, anchor, current.resolver)\n ? { reason: \"resolver-changed\" as const }\n : {}),\n };\n}\n\nfunction compared(\n anchor: KbAnchor,\n current: Current,\n extra: Partial<KbAnchorDriftEntry> = {},\n): KbAnchorDriftEntry {\n const matched = current.hash === anchor.hash;\n return {\n ...base(anchor),\n state: matched ? \"match\" : \"drifted\",\n currentHash: current.hash,\n hashKind: current.kind,\n diffSize:\n anchor.lines === undefined\n ? null\n : Math.abs(current.lines - anchor.lines),\n ...(matched ? {} : { class: \"changed\" as const }),\n ...extra,\n };\n}\n\nfunction localEntry(\n anchor: KbAnchor,\n read: AnchorRead,\n resolvers: readonly AnchorResolver[],\n): KbAnchorDriftEntry {\n if (!read.ok) return unresolved(anchor, read.reason);\n const found = hashIn(read.source, anchor, resolvers);\n if (!found.ok) return unresolved(anchor, found.reason);\n return compared(\n anchor,\n found.current,\n resolverExtras(read.source, anchor, found.current),\n );\n}\n\n/**\n * A foreign anchor's three states.\n *\n * The pinned commit decides whether the evidence still holds; the default\n * branch only adds `drifted-on-default` on top of a ref that still matches. A\n * default branch that could not be read therefore never downgrades a `ref` hit\n * — offline, a pinned anchor still verifies.\n */\nfunction remoteEntry(\n anchor: KbAnchor,\n remote: Map<string, RemoteRead>,\n resolvers: readonly AnchorResolver[],\n): KbAnchorDriftEntry {\n const repo = anchor.repo as string;\n const key = normalizeRepoUrl(repo);\n const atDefault = remote.get(wantKey(key, undefined, anchor.file));\n const primary = anchor.ref\n ? remote.get(wantKey(key, anchor.ref, anchor.file))\n : atDefault;\n\n if (!primary) return unresolved(anchor, \"remote-unreachable\", repo);\n if (!primary.ok) return unresolved(anchor, primary.reason, repo);\n\n const found = hashIn(primary.source, anchor, resolvers);\n if (!found.ok) return unresolved(anchor, found.reason, repo);\n const current = found.current;\n const extras = resolverExtras(primary.source, anchor, current);\n if (!anchor.ref) return compared(anchor, current, { repo, ...extras });\n if (current.hash !== anchor.hash) {\n return compared(anchor, current, {\n repo,\n ...extras,\n remoteState: \"drifted-from-ref\",\n });\n }\n\n const head = atDefault?.ok\n ? hashIn(atDefault.source, anchor, resolvers)\n : null;\n return head?.ok && head.current.hash !== anchor.hash\n ? {\n ...compared(anchor, head.current, {\n repo,\n ...(head.current.resolver ? { resolver: head.current.resolver } : {}),\n }),\n state: \"drifted\",\n remoteState: \"drifted-on-default\",\n }\n : compared(anchor, current, {\n repo,\n ...extras,\n remoteState: \"matches-ref\",\n });\n}\n","/**\n * The error shape the store throws.\n *\n * Every caller here is an agent, reached through a CLI or a stdio MCP server,\n * so a bare `Error` arrives as an opaque string. What a caller has to act on is\n * carried as fields instead: `code` separates \"pick a different slug and retry\"\n * from \"this input was never going to work\", and `retriable` says whether\n * re-running the same call could succeed.\n *\n * No dependency, deliberately. This is four fields and a constructor; an error\n * library would be a runtime dependency in aid of that.\n */\nexport enum Fault {\n /** The environment is wrong — a path, a permission, a missing directory. */\n Configuration = \"Configuration\",\n /** Nothing the caller did; retrying may work. */\n System = \"System\",\n /** The call was malformed or asked for something impossible. */\n User = \"User\",\n}\n\n/** Machine-readable discriminant, stable across message rewording. */\nexport enum ErrorTypes {\n KbRecordAlreadyExists = \"KbRecordAlreadyExists\",\n KbInvalidConceptId = \"KbInvalidConceptId\",\n KbMissingFlagValue = \"KbMissingFlagValue\",\n KbPackBudgetExceeded = \"KbPackBudgetExceeded\",\n KbRecordNotFound = \"KbRecordNotFound\",\n KbSelfVerification = \"KbSelfVerification\",\n KbStampBaselineUnreadable = \"KbStampBaselineUnreadable\",\n KbStampDigestBaselineAmbiguous = \"KbStampDigestBaselineAmbiguous\",\n KbUnknownLinkRel = \"KbUnknownLinkRel\",\n KbWriteConflict = \"KbWriteConflict\",\n}\n\nexport type ErrorDetails = Record<\n string,\n string | boolean | number | string[] | boolean[] | number[]\n>;\n\nexport interface ErrorProps {\n message: string;\n errorType?: ErrorTypes;\n details?: ErrorDetails;\n name?: string;\n code?: number;\n fault?: Fault;\n retriable?: boolean;\n reportToUser?: boolean;\n}\n\nexport class BaseError extends Error {\n code: number;\n errorType?: ErrorTypes;\n fault?: Fault;\n retriable: boolean;\n reportToUser: boolean;\n details?: ErrorDetails;\n\n constructor(props: ErrorProps) {\n super(props.message);\n this.name = props.name ?? this.constructor.name;\n this.code = props.code ?? 500;\n this.errorType = props.errorType;\n this.fault = props.fault;\n this.retriable = props.retriable ?? true;\n this.reportToUser = props.reportToUser ?? false;\n this.details = props.details;\n }\n}\n","import { BaseError, ErrorTypes, Fault } from \"./errors.js\";\n\n/**\n * Every caller of this store is an agent, reached through a CLI or a stdio MCP\n * server, so a bare `Error` reaches it as an opaque string. The `code` carries\n * the distinction the caller has to act on: 409 means pick a different slug and\n * retry, 400 means the input was never going to work.\n */\nexport class KbRecordAlreadyExistsError extends BaseError {\n constructor(readonly conceptId: string) {\n super({\n message: `kb: ${conceptId} already exists — choose a more specific slug, or write with overwrite`,\n errorType: ErrorTypes.KbRecordAlreadyExists,\n code: 409,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId, action: \"refused\" },\n });\n }\n}\n\nexport class KbRecordNotFoundError extends BaseError {\n constructor(readonly conceptId: string) {\n super({\n message: `kb: ${conceptId} does not exist`,\n errorType: ErrorTypes.KbRecordNotFound,\n code: 404,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId },\n });\n }\n}\n\n/** Retriable, unlike the others: re-reading and re-applying usually succeeds. */\nexport class KbWriteConflictError extends BaseError {\n constructor(readonly conceptId: string) {\n super({\n message: `kb: ${conceptId} changed while it was being updated — re-read and retry`,\n errorType: ErrorTypes.KbWriteConflict,\n code: 409,\n fault: Fault.System,\n retriable: true,\n reportToUser: true,\n details: { conceptId },\n });\n }\n}\n\n/** A generator confirming its own record adds no independent check. */\nexport class KbSelfVerificationError extends BaseError {\n constructor(\n readonly conceptId: string,\n readonly actor: string,\n readonly generatedBy: string,\n ) {\n super({\n message: `kb: ${conceptId} was generated by ${generatedBy}, and a record's generator cannot verify it — only a human or a different actor can`,\n errorType: ErrorTypes.KbSelfVerification,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId, actor, generatedBy, action: \"refused\" },\n });\n }\n}\n\n/**\n * A pack that will not fit its token budget. Refusal, not truncation: a\n * partial pack is indistinguishable from a complete one, so the caller gets\n * the full picture — how many records, how many tokens, and every id the\n * walk's own limits already cut — and decides whether to raise the budget or\n * tighten the walk.\n */\nexport class KbPackBudgetExceededError extends BaseError {\n constructor(\n readonly recordCount: number,\n readonly approxTokens: number,\n readonly budgetTokens: number,\n readonly excluded: string[],\n ) {\n super({\n message: `kb: a pack of ${recordCount} records is ~${approxTokens} tokens against a budget of ${budgetTokens} — lower hops or maxNodes, or raise the budget`,\n errorType: ErrorTypes.KbPackBudgetExceeded,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { recordCount, approxTokens, budgetTokens, excluded },\n });\n }\n}\n\n/**\n * A `rels` option naming something the walk can never follow.\n *\n * Refused rather than ignored: dropping an unrecognised rel would return an\n * empty impact set — \"nothing breaks\" — indistinguishable from a genuine\n * result. `related_to` is refused here too, since it asserts no dependence and\n * following it can only produce that same empty set.\n */\nexport class KbUnknownLinkRelError extends BaseError {\n constructor(\n readonly rel: string,\n readonly expected: readonly string[],\n ) {\n super({\n message: `kb: ${rel} is not a rel a walk can follow — expected one of ${expected.join(\", \")}`,\n errorType: ErrorTypes.KbUnknownLinkRel,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { rel, expected: expected.join(\", \") },\n });\n }\n}\n\n/**\n * A flag that takes a value, given none.\n *\n * `strauss-kb load --budget` used to read the next argv entry, find\n * nothing, and quietly fall back to the default — so a caller who meant to\n * raise a ceiling got the ceiling they were trying to move, and a typo looked\n * exactly like success. Refusing is the only way that stays visible.\n */\nexport class KbMissingFlagValueError extends BaseError {\n constructor(readonly flag: string) {\n super({\n message: `kb: ${flag} needs a value — pass ${flag} <value> or ${flag}=<value>`,\n errorType: ErrorTypes.KbMissingFlagValue,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { flag },\n });\n }\n}\n\nexport class KbInvalidConceptIdError extends BaseError {\n constructor(message: string, details: Record<string, string>) {\n super({\n message: `kb: ${message}`,\n errorType: ErrorTypes.KbInvalidConceptId,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details,\n });\n }\n}\n\n/** `--since` named a baseline that is neither a digest nor a readable stamp. */\nexport class KbStampBaselineError extends BaseError {\n constructor(readonly since: string) {\n super({\n message: `kb: --since ${since} is neither a 64-character digest nor a readable stamp file`,\n errorType: ErrorTypes.KbStampBaselineUnreadable,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { since },\n });\n }\n}\n\n/** `--since` named a digest while more than one base is being stamped. */\nexport class KbStampDigestBaselineError extends BaseError {\n constructor(readonly since: string) {\n super({\n message: `kb: --since ${since} is a digest, which needs --bundle (one base) — a file baseline works for many`,\n errorType: ErrorTypes.KbStampDigestBaselineAmbiguous,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { since },\n });\n }\n}\n","import type {\n KbContextBudgets,\n KbMergedPins,\n KbPinsManifest,\n} from \"./model.js\";\n\n/** Sane integers only; anything else is ignored, not an error. */\nfunction asBudgets(value: unknown): KbContextBudgets {\n if (value === null || typeof value !== \"object\") return {};\n const table = value as Record<string, unknown>;\n const pick = (key: string, min: number) => {\n const raw = table[key];\n return typeof raw === \"number\" && Number.isInteger(raw) && raw >= min\n ? raw\n : undefined;\n };\n const budgetTokens = pick(\"budgetTokens\", 1);\n // 0 is meaningful — \"full-under off\", overriding a `default` that set it.\n const fullUnderTokens = pick(\"fullUnderTokens\", 0);\n return {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens !== undefined ? { fullUnderTokens } : {}),\n };\n}\n\n/**\n * One manifest's budgets for one profile: the named profile's values over the\n * manifest's `\"default\"` entry. What is absent here falls through to the\n * caller's built-ins — a manifest narrows, it never has to be complete.\n */\nexport function contextProfileBudgets(\n manifest: KbPinsManifest,\n profile?: string,\n): KbContextBudgets {\n const table = manifest.context;\n if (table === null || typeof table !== \"object\") return {};\n const entries = table as Record<string, unknown>;\n return {\n ...asBudgets(entries[\"default\"]),\n ...(profile ? asBudgets(entries[profile]) : {}),\n };\n}\n\n/**\n * Budgets across the layers: user underneath, local over it, project on top —\n * the committed file is the workspace's word — and explicit flags above all\n * of this, applied by the caller.\n */\nexport function mergedContextBudgets(\n merged: KbMergedPins,\n profile?: string,\n): KbContextBudgets {\n const layered = ([\"user\", \"local\", \"project\"] as const).map((layer) => {\n const manifest = merged.manifests[layer];\n return manifest ? contextProfileBudgets(manifest, profile) : {};\n });\n return { ...layered[0], ...layered[1], ...layered[2] };\n}\n","import type { KbPinLayer } from \"./model.js\";\n\nexport class KbPinsMalformedError extends Error {\n constructor(file: string, cause: string) {\n super(`pin manifest ${file} is not readable (${cause}) — fix or remove it`);\n this.name = \"KbPinsMalformedError\";\n }\n}\n\nexport class KbBaseFrozenError extends Error {\n constructor(bundlePath: string, layer: KbPinLayer) {\n super(\n `${bundlePath} is frozen (read-only) by this workspace's ${layer} pin manifest — re-pin with --unfreeze, or unpin, to change it`,\n );\n this.name = \"KbBaseFrozenError\";\n }\n}\n","import { resolve } from \"node:path\";\nimport { KbBaseFrozenError } from \"./errors.js\";\nimport { readMergedPins } from \"./layers.js\";\n\n/**\n * Refuses when a write would land in a base this workspace froze. Called by\n * every mutating command; a workspace that pinned a base `--frozen` said the\n * base is concluded, and a quiet write past that would be exactly the silent\n * drift the pin was meant to stop.\n */\nexport async function assertBaseNotFrozen(\n workspaceDir: string,\n bundlePath: string,\n): Promise<void> {\n const merged = await readMergedPins(workspaceDir);\n const absolute = resolve(bundlePath);\n const pin = merged.pins.find((entry) => entry.absolutePath === absolute);\n if (pin?.frozen === true) {\n throw new KbBaseFrozenError(pin.path, pin.layer);\n }\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { KbPinsMalformedError } from \"./errors.js\";\nimport {\n PIN_LAYERS,\n PINS_FILE,\n PINS_LOCAL_FILE,\n pinsManifestSchema,\n type KbMergedPin,\n type KbMergedPins,\n type KbPinLayer,\n type KbPinsManifest,\n} from \"./model.js\";\n\nfunction userRoot(): string {\n return process.env.STRAUSS_KB_USER_ROOT || homedir();\n}\n\n/** The directory a layer's stored paths resolve against. */\nexport function layerRoot(workspaceDir: string, layer: KbPinLayer): string {\n return layer === \"user\" ? userRoot() : resolve(workspaceDir);\n}\n\nfunction layerFile(workspaceDir: string, layer: KbPinLayer): string {\n return join(\n layerRoot(workspaceDir, layer),\n layer === \"local\" ? PINS_LOCAL_FILE : PINS_FILE,\n );\n}\n\n/**\n * One layer's manifest, or an empty one when the file is missing.\n *\n * A malformed file throws rather than being treated as empty: every write path\n * does a full rewrite, and rewriting over content we could not read would\n * destroy the one copy of it. Read-only consumers that must stay silent\n * (`context` from a session hook, the merged reader) skip malformed layers\n * themselves.\n */\nexport async function readPinsLayer(\n workspaceDir: string,\n layer: KbPinLayer,\n): Promise<KbPinsManifest> {\n const file = layerFile(workspaceDir, layer);\n let raw: string;\n try {\n raw = await readFile(file, \"utf8\");\n } catch {\n return { pins: [] };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new KbPinsMalformedError(\n file,\n error instanceof Error ? error.message : \"invalid JSON\",\n );\n }\n const manifest = pinsManifestSchema.safeParse(parsed);\n if (!manifest.success) {\n throw new KbPinsMalformedError(\n file,\n manifest.error.issues[0]?.message ?? \"invalid shape\",\n );\n }\n return manifest.data;\n}\n\nexport async function writePinsLayer(\n workspaceDir: string,\n layer: KbPinLayer,\n manifest: KbPinsManifest,\n): Promise<void> {\n const file = layerFile(workspaceDir, layer);\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, `${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\");\n}\n\n/** Where a stored pin points, resolved against its layer's root. */\nexport function resolvePinPath(rootDir: string, path: string): string {\n return isAbsolute(path)\n ? resolve(path)\n : resolve(rootDir, path.split(\"/\").join(sep));\n}\n\n/** How a base is spelled in a manifest: relative to the layer root, forward slashes. */\nexport function storablePath(rootDir: string, bundlePath: string): string {\n const rel = relative(resolve(rootDir), resolve(bundlePath));\n return (rel === \"\" ? \".\" : rel).split(sep).join(\"/\");\n}\n\n/**\n * All three layers, merged. A malformed layer is skipped rather than thrown:\n * this feeds hooks at every session start, and one broken personal file must\n * not silence the team's pins — `pin`/`unpin` against the broken layer still\n * refuse loudly.\n */\nexport async function readMergedPins(\n workspaceDir: string,\n): Promise<KbMergedPins> {\n const manifests: Partial<Record<KbPinLayer, KbPinsManifest>> = {};\n const pins: KbMergedPin[] = [];\n const seen = new Set<string>();\n\n for (const layer of PIN_LAYERS) {\n let manifest: KbPinsManifest;\n try {\n manifest = await readPinsLayer(workspaceDir, layer);\n } catch {\n continue;\n }\n manifests[layer] = manifest;\n const root = layerRoot(workspaceDir, layer);\n for (const entry of manifest.pins) {\n const absolutePath = resolvePinPath(root, entry.path);\n if (seen.has(absolutePath)) continue;\n seen.add(absolutePath);\n pins.push({ ...entry, layer, absolutePath });\n }\n }\n return { pins, manifests };\n}\n","import { join } from \"node:path\";\nimport { z } from \"zod\";\n\n/**\n * Pin manifests, in three layers.\n *\n * Pins are workspace state, not base state: they record which bases a session\n * should be shown at every context birth. The pinned base is never touched —\n * not even its log — because a base must remain copyable without knowing who\n * pins it.\n *\n * The layers, nearest wins when the same base appears in more than one:\n *\n * | layer | file | for |\n * | ------- | --------------------------------------- | -------------------------- |\n * | project | <workspace>/.strauss/kb-pins.json | committed, the team's pins |\n * | local | <workspace>/.strauss/kb-pins.local.json | personal, gitignored |\n * | user | ~/.strauss/kb-pins.json | personal, every workspace |\n *\n * Every manifest's paths resolve against its own root — the workspace for\n * project and local, the home directory for user — so each file is portable\n * with the tree it belongs to. `STRAUSS_KB_USER_ROOT` overrides the user root\n * (tests, unusual homes).\n */\nexport const PINS_FILE = join(\".strauss\", \"kb-pins.json\");\nexport const PINS_LOCAL_FILE = join(\".strauss\", \"kb-pins.local.json\");\n\nexport const PIN_LAYERS = [\"project\", \"local\", \"user\"] as const;\nexport type KbPinLayer = (typeof PIN_LAYERS)[number];\n\n/**\n * Primary state — it records an intent nothing else holds — but trivially\n * rewritable, so a full rewrite on change is fine and no append log is needed.\n * Unknown keys are preserved on rewrite, the same tolerance the record reader\n * extends to frontmatter it did not write.\n */\nexport const pinSchema = z\n .object({\n /** Relative to the manifest's root, so the file is committable. */\n path: z.string().min(1),\n pinnedAt: z.string().min(1).optional(),\n /**\n * How `context` renders this base. `full` preloads the whole base into\n * the block regardless of the full-under threshold — for a base whose\n * contents should simply be present, the way an ADR base should be —\n * still answering to the block budget, with an index fallback that says\n * so when it cannot fit. `index` never upgrades, whatever the threshold.\n * Absent: the profile's full-under threshold decides. Invalid values\n * degrade to absent rather than failing the manifest.\n */\n mode: z.enum([\"full\", \"index\"]).optional().catch(undefined),\n /**\n * Context profiles this pin surfaces in (e.g. only at session-start,\n * not per turn). Absent: every profile. A run without a profile sees\n * every pin. A base that only matters to one skill is better loaded by\n * that skill at point of use than pinned at all — pins are what every\n * session should see.\n */\n profiles: z.array(z.string()).optional().catch(undefined),\n /**\n * The base is concluded — a finished piece of research, a frozen ADR\n * set. Write commands against it refuse while this workspace holds the\n * pin, and `context` labels it read-only. Workspace policy, not base\n * state: the base itself stays copyable and writable elsewhere.\n */\n frozen: z.boolean().optional().catch(undefined),\n })\n .passthrough();\n\nexport const pinsManifestSchema = z\n .object({\n pins: z.array(pinSchema).default([]),\n /**\n * Per-repo budgets for the `context` command, keyed by profile —\n * `\"session-start\"`, `\"compact\"`, `\"turn\"`, or `\"default\"` for all of\n * them. Deliberately untyped here: a typo'd budget must degrade to the\n * built-in default, not make the whole manifest unreadable and silence\n * the index at every session start. `contextProfileBudgets` does the\n * tolerant read.\n */\n context: z.unknown().optional(),\n })\n .passthrough();\n\nexport type KbPin = z.infer<typeof pinSchema>;\nexport type KbPinsManifest = z.infer<typeof pinsManifestSchema>;\n\nexport type KbContextBudgets = {\n budgetTokens?: number;\n fullUnderTokens?: number;\n};\n\n/** A pin as the merged view hands it back: entry + where it came from. */\nexport type KbMergedPin = KbPin & {\n layer: KbPinLayer;\n absolutePath: string;\n};\n\nexport type KbMergedPins = {\n /** Effective pins after dedup — nearest layer wins per resolved path. */\n pins: KbMergedPin[];\n /** Per-layer manifests that parsed, for budget merging. */\n manifests: Partial<Record<KbPinLayer, KbPinsManifest>>;\n};\n\n/** One pinned base, with whether it currently resolves to anything readable. */\nexport type KbPinStatus = {\n /** As stored — relative to its layer's root. */\n path: string;\n layer: KbPinLayer;\n pinnedAt: string | null;\n absolutePath: string;\n /** The directory exists and yielded at least one parseable record. */\n valid: boolean;\n recordCount: number;\n mode: \"full\" | \"index\" | null;\n profiles: string[] | null;\n frozen: boolean;\n};\n\nexport type KbPinResult = {\n path: string;\n layer: KbPinLayer;\n pinnedAt: string;\n alreadyPinned: boolean;\n mode?: \"full\" | \"index\";\n profiles?: string[];\n frozen?: boolean;\n /** Set when the path holds no readable records — pinned anyway. */\n warning?: string;\n};\n\nexport type KbPinOptions = {\n mode?: \"full\" | \"index\";\n profiles?: string[];\n frozen?: boolean;\n /** Which manifest to write. Defaults to the committed project layer. */\n layer?: KbPinLayer;\n};\n","import type { KbStore } from \"../kb-store.js\";\nimport { readMergedPins } from \"./layers.js\";\nimport type { KbPinStatus } from \"./model.js\";\n\n/** Every effective pin across the layers, with whether it points at records. */\nexport async function listPins(\n store: KbStore,\n workspaceDir: string,\n): Promise<KbPinStatus[]> {\n const merged = await readMergedPins(workspaceDir);\n return Promise.all(\n merged.pins.map(async (entry) => {\n const records = await store.list(entry.absolutePath);\n return {\n path: entry.path,\n layer: entry.layer,\n pinnedAt: entry.pinnedAt ?? null,\n absolutePath: entry.absolutePath,\n valid: records.length > 0,\n recordCount: records.length,\n mode: entry.mode ?? null,\n profiles: entry.profiles ?? null,\n frozen: entry.frozen === true,\n };\n }),\n );\n}\n","import type { KbStore } from \"../kb-store.js\";\nimport {\n layerRoot,\n readPinsLayer,\n resolvePinPath,\n storablePath,\n writePinsLayer,\n} from \"./layers.js\";\nimport type { KbPin, KbPinOptions, KbPinResult } from \"./model.js\";\n\n/**\n * Adds a base to one layer's manifest. Idempotent — re-pinning a pinned path\n * with no options returns the existing entry untouched, and re-pinning with\n * `mode`, `profiles`, or `frozen` updates just those fields, which is how a\n * pin's rendering or writability is changed. A path that is not (yet) a valid\n * base succeeds with a warning: bases are routinely pinned before they are\n * populated, the same way records link to records that do not exist yet.\n */\nexport async function pinBase(\n store: KbStore,\n workspaceDir: string,\n bundlePath: string,\n at: string,\n options: KbPinOptions = {},\n): Promise<KbPinResult> {\n const layer = options.layer ?? \"project\";\n const root = layerRoot(workspaceDir, layer);\n const manifest = await readPinsLayer(workspaceDir, layer);\n const absolute = resolvePinPath(root, storablePath(root, bundlePath));\n\n const existing = manifest.pins.find(\n (entry) => resolvePinPath(root, entry.path) === absolute,\n );\n const records = await store.list(absolute);\n const warning =\n records.length === 0\n ? `no records found at ${absolute} — pinned anyway; bases are routinely pinned before they are populated`\n : undefined;\n\n const fields = {\n ...(options.mode ? { mode: options.mode } : {}),\n ...(options.profiles?.length ? { profiles: options.profiles } : {}),\n ...(options.frozen !== undefined ? { frozen: options.frozen } : {}),\n };\n\n if (existing) {\n const updated: KbPin = { ...existing, ...fields };\n if (Object.keys(fields).length) {\n await writePinsLayer(workspaceDir, layer, {\n ...manifest,\n pins: manifest.pins.map((entry) =>\n entry === existing ? updated : entry,\n ),\n });\n }\n return {\n path: existing.path,\n layer,\n pinnedAt: existing.pinnedAt ?? at,\n alreadyPinned: true,\n ...(updated.mode ? { mode: updated.mode } : {}),\n ...(updated.profiles ? { profiles: updated.profiles } : {}),\n ...(updated.frozen !== undefined ? { frozen: updated.frozen } : {}),\n ...(warning ? { warning } : {}),\n };\n }\n\n const entry: KbPin = {\n path: storablePath(root, bundlePath),\n pinnedAt: at,\n ...fields,\n };\n await writePinsLayer(workspaceDir, layer, {\n ...manifest,\n pins: [...manifest.pins, entry],\n });\n return {\n path: entry.path,\n layer,\n pinnedAt: at,\n alreadyPinned: false,\n ...fields,\n ...(warning ? { warning } : {}),\n };\n}\n","import { resolve } from \"node:path\";\nimport {\n layerRoot,\n readPinsLayer,\n resolvePinPath,\n storablePath,\n writePinsLayer,\n} from \"./layers.js\";\nimport { PIN_LAYERS, type KbPinLayer, type KbPinsManifest } from \"./model.js\";\n\n/**\n * Removes a base from every layer that holds it — unpinned means gone, not\n * \"gone from one file and still injected from another\". A malformed layer is\n * skipped (it cannot be rewritten safely); the layers actually touched are\n * reported.\n */\nexport async function unpinBase(\n workspaceDir: string,\n bundlePath: string,\n): Promise<{ path: string; removed: boolean; layers: KbPinLayer[] }> {\n const layers: KbPinLayer[] = [];\n for (const layer of PIN_LAYERS) {\n const root = layerRoot(workspaceDir, layer);\n let manifest: KbPinsManifest;\n try {\n manifest = await readPinsLayer(workspaceDir, layer);\n } catch {\n continue;\n }\n const absolute = resolvePinPath(root, storablePath(root, bundlePath));\n const kept = manifest.pins.filter(\n (entry) => resolvePinPath(root, entry.path) !== absolute,\n );\n if (kept.length !== manifest.pins.length) {\n await writePinsLayer(workspaceDir, layer, { ...manifest, pins: kept });\n layers.push(layer);\n }\n }\n return {\n path: storablePath(resolve(workspaceDir), bundlePath),\n removed: layers.length > 0,\n layers,\n };\n}\n","import { z } from \"zod\";\nimport { KbMissingFlagValueError } from \"../kb-errors.js\";\nimport type { KbStore } from \"../kb-store.js\";\n\n/**\n * Every operation a knowledge base exposes, defined once.\n *\n * The CLI and the MCP server are both projections of this table. Kept apart\n * they drift within a day — fourteen commands against six tools — which is the\n * same failure as a schema restated in prose beside the code that enforces it,\n * one level up. A command added to the table appears in both surfaces or in\n * neither, and a test asserts exactly that.\n *\n * The two differ only in how arguments arrive: MCP passes an object matching\n * `input`, while the CLI has to turn positional argv into the same object.\n * `fromArgv` is that adapter and is the only per-surface code a command needs.\n *\n * One file per command in this folder; `index.ts` assembles the table.\n */\nexport type KbCommandContext = {\n store: KbStore;\n actor: string;\n now: () => string;\n};\n\nexport type KbCommand<Shape extends z.ZodRawShape = z.ZodRawShape> = {\n /** CLI verb. */\n name: string;\n /**\n * MCP tool name. Absent only for CLI-only plumbing (`sync-instructions`),\n * which exists to edit files for hooks and instruction blocks rather than to\n * give an agent a capability — the capability, \"get the pinned context\n * block\", is `kb_context`.\n */\n tool?: string;\n /** Argument spelling for CLI usage output. */\n usage: string;\n /** Shown to an agent choosing a tool, so it carries the judgment too. */\n description: string;\n input: z.ZodObject<Shape>;\n /**\n * Positional argv → the same object MCP receives. `bundleExplicit` says\n * whether `--bundle` was actually passed, for the one command whose meaning\n * turns on it: `stamp` with no bundle stamps every pinned base.\n */\n fromArgv(\n argv: string[],\n bundlePath: string,\n stdin: () => Promise<string>,\n bundleExplicit?: boolean,\n ): Promise<unknown> | unknown;\n run(\n ctx: KbCommandContext,\n input: z.infer<z.ZodObject<Shape>>,\n ): Promise<unknown>;\n /**\n * A human-readable form of the result, for the CLI. Where it exists the CLI\n * prints it and `--json` asks for the machine shape instead; MCP always gets\n * the machine shape, since a tool result is parsed rather than read.\n *\n * Separate from `run` rather than rendered inside it — as `pack` does, whose\n * result *is* a document — because a command whose result is a report needs\n * both forms: the table for a person, and the object for `failsWhen` and for\n * anything downstream.\n */\n render?(result: unknown): string;\n /**\n * Turns a result into a non-zero exit for the CLI. A check that reports a\n * problem has succeeded as a command and failed as a check, and a shell\n * caller can only see the difference through the exit code.\n *\n * The input comes too, so a command can make the exit conditional on a flag\n * the caller passed rather than on the result alone.\n */\n failsWhen?(result: unknown, input: z.infer<z.ZodObject<Shape>>): boolean;\n};\n\nexport const bundlePath = z\n .string()\n .min(1)\n .describe(\"Absolute path to the knowledge base directory.\");\n\nexport const conceptId = z.string().min(1).describe(\"e.g. decision.cursor-v2\");\n\n/**\n * Where the code an anchor points at lives, for the drift check.\n *\n * Pass it whenever the base is not inside the tree it describes: the default is\n * the working directory, where a bundle read from elsewhere finds none of its\n * anchored files. `KbStore.detectDrift` suppresses that case rather than\n * reporting the whole base as drifted.\n */\nexport const REPO_ROOT = z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Where the anchored source lives, for the drift check. Defaults to the working directory.\",\n );\n\nexport function define<Shape extends z.ZodRawShape>(\n command: KbCommand<Shape>,\n): KbCommand<z.ZodRawShape> {\n return command as unknown as KbCommand<z.ZodRawShape>;\n}\n\n/**\n * The value of `--name`, in either spelling, or undefined when it is absent.\n *\n * Both `--name value` and `--name=value` are accepted, because a caller who\n * writes the second and is silently given the default has been told the\n * opposite of what happened.\n *\n * A flag present with no value is an error rather than an absent flag, for the\n * same reason. `strauss-kb load --budget` reading past the end of argv and\n * falling back to the default would hand the caller the exact ceiling they were\n * trying to move, and a trailing typo would be indistinguishable from success.\n * Note\n * that a following token starting with `--` counts as no value: `--budget\n * --all` is a missing value, not a budget of \"--all\".\n */\nexport function argvFlag(argv: string[], name: string): string | undefined {\n const joined = argv.find((arg) => arg.startsWith(`${name}=`));\n if (joined !== undefined) {\n const value = joined.slice(name.length + 1);\n if (!value) throw new KbMissingFlagValueError(name);\n return value;\n }\n\n const at = argv.indexOf(name);\n if (at === -1) return undefined;\n\n const value = argv[at + 1];\n if (value === undefined || value.startsWith(\"--\")) {\n throw new KbMissingFlagValueError(name);\n }\n return value;\n}\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const answerCommand = define({\n name: \"answer\",\n tool: \"kb_answer\",\n usage: \"answer <concept-id> <answer...>\",\n description:\n \"Resolve an open question: set status, stamp who and when, append an Answer section. If the answer overturns a decision or assumption, supersede that record explicitly.\",\n input: z.object({ bundlePath, conceptId, answer: z.string().min(1) }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n answer: argv.slice(2).join(\" \").trim(),\n }),\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, answer },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.answer(path, id, answer, actor);\n return { conceptId: record.conceptId };\n },\n});\n","import { z } from \"zod\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const backlinksCommand = define({\n name: \"backlinks\",\n tool: \"kb_backlinks\",\n usage: \"backlinks <concept-id>\",\n description:\n \"Who points at this record: every inbound typed causal link (`strauss_links`), one hop, every rel including `related_to`, each with its rel and the standing of the record that made it. Use it when you need the exact edges — reviewing or renaming a record.\",\n input: z.object({ bundlePath, conceptId }),\n fromArgv: (argv, path) => ({ bundlePath: path, conceptId: argv[1] }),\n run: async ({ store }, { bundlePath: path, conceptId: id }) =>\n store.backlinks(path, id),\n});\n","import { z } from \"zod\";\nimport type { KbStanding } from \"../adjudicate.js\";\nimport { renderCatalogLine, type KbCatalogResult } from \"../catalog.js\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const catalogCommand = define({\n name: \"catalog\",\n tool: \"kb_catalog\",\n usage: \"catalog [type]\",\n description:\n \"Lists every record as one line — concept id, type, title, standing, and a stale flag — at roughly thirty tokens each. Pick this over kb_load once kb_load refuses: kb_catalog never refuses. Superseded records show only their replacement; fetch bodies with kb_load, kb_pack, kb_query, or kb_trace.\",\n input: z.object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES).optional(),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n ...(argv[1] && !argv[1].startsWith(\"--\") ? { type: argv[1] } : {}),\n }),\n run: async ({ store }, { bundlePath: path, type }) =>\n render(\n await store.catalog(path, { ...(type ? { type } : {}) }),\n path,\n type,\n ),\n});\n\n/**\n * Markdown, like `index` and `pack`, because the value is one line per record\n * and JSON would spend a third of the tokens on repeated key names.\n */\nfunction render(\n result: KbCatalogResult,\n bundle: string,\n type?: string,\n): string {\n const lines = [\n `# KB Catalog${type ? ` — ${type}` : \"\"}`,\n `bundle: ${bundle}`,\n `${count(result.recordCount, \"record\")}: ${standingCounts(result)}`,\n ];\n\n // Staleness is a flag over a standing, not a standing — a current record can\n // be stale. Adding it to the run above would make the counts stop summing to\n // the record count, which is the one thing that line is for.\n if (result.staleCount) {\n lines.push(\n `${result.staleCount} stale — a flag over the standings above, not one of them`,\n );\n }\n\n lines.push(\"\");\n\n if (!result.entries.length) {\n lines.push(\n type\n ? `(no records of type ${type})`\n : \"(no records — this base is empty)\",\n );\n } else {\n for (const entry of result.entries) lines.push(renderCatalogLine(entry));\n }\n\n lines.push(\n \"\",\n \"Bodies are not here: kb_pack <conceptId> for the neighbourhood around one record, kb_load for the whole base when it fits the budget, kb_query for a lookup by wording, kb_trace <conceptId> for how a position was arrived at.\",\n );\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Every standing that has a record, in order of how live it is. Zero counts are\n * dropped as noise, and what remains sums to the record count — a reader can\n * add the line up and see that nothing went missing.\n */\nfunction standingCounts(result: KbCatalogResult): string {\n const ORDER: readonly KbStanding[] = [\n \"current\",\n \"open\",\n \"unsettled\",\n \"rejected\",\n \"superseded\",\n ];\n const parts = ORDER.filter((standing) => result.standings[standing]).map(\n (standing) => `${result.standings[standing]} ${standing}`,\n );\n return parts.length ? parts.join(\" · \") : \"none\";\n}\n\nfunction count(value: number, noun: string): string {\n return `${value} ${value === 1 ? noun : `${noun}s`}`;\n}\n","import type {\n KbAnchorDriftEntry,\n KbDriftClass,\n} from \"./anchor-resolver/index.js\";\nimport { isUncheckedReason } from \"./remote-repo/index.js\";\nimport type { KbRecord, KbRecordStatus } from \"./kb-record.schema.js\";\n\n/**\n * Why a matched record must not be read as a plain answer.\n *\n * Relevance and standing are different questions, and ranking answers only the\n * first. A superseded record is usually the older, longer, more general one and\n * its replacement is usually a narrowing, so any similarity measure favours the\n * record that is no longer true. Every hit therefore carries its standing, and\n * the caller is never handed a bare match.\n */\nexport type KbWarning =\n /** Explicitly not adopted. The most dangerous status to return unmarked: a\n * well-formed assertion of what someone decided *not* to do. */\n | { kind: \"rejected\" }\n | { kind: \"superseded\"; by: string[] }\n /** Not settled. Acting on a proposal as though it were a decision is a defect. */\n | { kind: \"unsettled\"; status: KbRecordStatus }\n /** Says a matter is unresolved. Valuable as a result, never as an answer. */\n | { kind: \"unresolved-question\" }\n /** `strauss_superseded_by` names a record that is not in the bundle. */\n | { kind: \"broken-chain\"; missing: string }\n | { kind: \"chain-cycle\"; through: string[] }\n /** Two records claim to replace this one; picking either would be a guess. */\n | { kind: \"forked-chain\"; heads: string[] }\n | { kind: \"stale\"; staleAfter: string }\n | { kind: \"unverified\" }\n /** The code this record anchors to has changed since its hash was recorded —\n * the record may describe code that no longer exists in that form. */\n | { kind: \"drifted\"; anchors: KbWarningAnchor[] }\n /** A foreign anchor nothing could check: the remote was unreachable, refused,\n * or the run was offline. Neither drift nor a clean match. */\n | { kind: \"unchecked\"; anchors: KbWarningAnchor[] };\n\nexport type KbWarningAnchor = {\n file: string;\n symbol?: string;\n /** `null` when the anchor recorded no line count — size unknown. */\n diffSize: number | null;\n reason?: string;\n /** Set only for an anchor resolved against another repository. */\n repo?: string;\n remoteState?: string;\n /**\n * `gone` or `changed` — what a hash comparison alone can settle. `moved` and\n * `cosmetic` cost a repository search and a git read, so they are\n * `kb_reassess`'s answer, not a read path's.\n */\n class?: KbDriftClass;\n};\n\nexport type KbStanding =\n \"current\" | \"superseded\" | \"rejected\" | \"unsettled\" | \"open\";\n\nexport type KbAdjudicated = {\n record: KbRecord;\n standing: KbStanding;\n /** Where the supersession chain ends. Empty when it is broken or cyclic. */\n heads: KbRecord[];\n warnings: KbWarning[];\n};\n\nconst STANDING: Record<KbRecordStatus, KbStanding> = {\n accepted: \"current\",\n resolved: \"current\",\n draft: \"unsettled\",\n proposed: \"unsettled\",\n open: \"open\",\n rejected: \"rejected\",\n superseded: \"superseded\",\n};\n\n/**\n * Attaches standing to records a search returned.\n *\n * Adjudicating rather than filtering, deliberately. A filtered result set is\n * invisible: the caller cannot tell it missed anything, so a dropped record is\n * worse than a flagged one — it turns a knowable gap into an unknowable one.\n */\nexport function adjudicate(\n hits: KbRecord[],\n bundle: KbRecord[],\n now = new Date(),\n // Precomputed by the caller: this function stays pure and sync, and the fs\n // work of re-resolving anchors lives in detectAnchorDrift.\n anchorDrift?: Map<string, KbAnchorDriftEntry[]>,\n): KbAdjudicated[] {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n return hits.map((record) => {\n const status = record.frontmatter.strauss_status;\n const warnings: KbWarning[] = [];\n let heads: KbRecord[] = [];\n\n if (status === \"superseded\") {\n const resolved = resolveHeads(record, byId);\n heads = resolved.heads;\n warnings.push(...resolved.warnings);\n if (heads.length) {\n warnings.push({\n kind: \"superseded\",\n by: heads.map((head) => head.conceptId),\n });\n }\n } else if (status === \"rejected\") {\n warnings.push({ kind: \"rejected\" });\n } else if (status === \"draft\" || status === \"proposed\") {\n warnings.push({ kind: \"unsettled\", status });\n } else if (status === \"open\") {\n warnings.push({ kind: \"unresolved-question\" });\n }\n\n const staleAfter = record.frontmatter.stale_after;\n if (staleAfter && Date.parse(staleAfter) < now.getTime()) {\n warnings.push({ kind: \"stale\", staleAfter });\n }\n if (!record.frontmatter.verified?.length) {\n warnings.push({ kind: \"unverified\" });\n }\n\n // Split at the one point every read path and `doctor` share, so none of\n // them can report \"no drift\" for an anchor nobody could reach.\n const found = (anchorDrift?.get(record.conceptId) ?? []).filter(\n (entry) => entry.state !== \"match\",\n );\n const unchecked = found.filter((entry) => isUncheckedReason(entry.reason));\n const moved = found.filter((entry) => !isUncheckedReason(entry.reason));\n if (moved.length) {\n warnings.push({ kind: \"drifted\", anchors: moved.map(warningAnchor) });\n }\n if (unchecked.length) {\n warnings.push({\n kind: \"unchecked\",\n anchors: unchecked.map(warningAnchor),\n });\n }\n\n return { record, standing: STANDING[status], heads, warnings };\n });\n}\n\nfunction warningAnchor(entry: KbAnchorDriftEntry): KbWarningAnchor {\n const { file, symbol, diffSize, reason, repo, remoteState } = entry;\n return {\n file,\n ...(symbol !== undefined ? { symbol } : {}),\n diffSize,\n ...(reason !== undefined ? { reason } : {}),\n ...(repo !== undefined ? { repo } : {}),\n ...(remoteState !== undefined ? { remoteState } : {}),\n ...(entry.class !== undefined ? { class: entry.class } : {}),\n };\n}\n\n/**\n * Walks a supersession chain to whatever currently stands in its place.\n *\n * Both directions are followed, not just `strauss_superseded_by`. `supersede()`\n * writes the pair, but a hand-edit can leave one side behind, and a walk that\n * trusts only the forward pointer would silently return a record that something\n * in the bundle openly claims to replace.\n *\n * Resolution happens here rather than being denormalised onto records at write\n * time: a stored head would have to be rewritten on every ancestor whenever a\n * chain grows, which is derived state that goes stale — the failure this design\n * keeps avoiding elsewhere.\n */\nexport function resolveHeads(\n from: KbRecord,\n byId: Map<string, KbRecord>,\n): { heads: KbRecord[]; warnings: KbWarning[] } {\n const warnings: KbWarning[] = [];\n const heads = new Map<string, KbRecord>();\n const seen = new Set<string>([from.conceptId]);\n const queue: KbRecord[] = [from];\n\n while (queue.length) {\n const current = queue.shift() as KbRecord;\n const next = successors(current, byId);\n\n for (const missing of next.missing) {\n warnings.push({ kind: \"broken-chain\", missing });\n }\n if (!next.records.length) {\n if (current.conceptId !== from.conceptId)\n heads.set(current.conceptId, current);\n continue;\n }\n for (const record of next.records) {\n if (seen.has(record.conceptId)) {\n warnings.push({ kind: \"chain-cycle\", through: [...seen] });\n continue;\n }\n seen.add(record.conceptId);\n queue.push(record);\n }\n }\n\n if (heads.size > 1) {\n warnings.push({ kind: \"forked-chain\", heads: [...heads.keys()] });\n }\n return { heads: [...heads.values()], warnings };\n}\n\nfunction successors(\n record: KbRecord,\n byId: Map<string, KbRecord>,\n): { records: KbRecord[]; missing: string[] } {\n const ids = new Set<string>();\n const forward = record.frontmatter.strauss_superseded_by;\n if (forward) ids.add(forward);\n for (const [id, candidate] of byId) {\n if (candidate.frontmatter.strauss_supersedes?.includes(record.conceptId)) {\n ids.add(id);\n }\n }\n\n const records: KbRecord[] = [];\n const missing: string[] = [];\n for (const id of ids) {\n const found = byId.get(id);\n if (found) records.push(found);\n else missing.push(id);\n }\n return { records, missing };\n}\n","import { adjudicate, type KbStanding } from \"./adjudicate.js\";\nimport type { KbRecord } from \"./kb-record.schema.js\";\n\n/** One record as the catalog names it — no body, no description, one line. */\nexport type KbCatalogEntry = {\n conceptId: string;\n type: string;\n title: string | null;\n standing: KbStanding;\n /** Where the supersession chain ends. Empty when broken, cyclic, or n/a. */\n supersededBy: string[];\n /** `stale_after` is in the past. The one freshness signal a line can carry. */\n stale: boolean;\n};\n\nexport type KbCatalogResult = {\n entries: KbCatalogEntry[];\n /** Every record the catalog names, filter applied. */\n recordCount: number;\n /**\n * How many records hold each standing. Sums to `recordCount` — every record\n * has exactly one standing, so the reader can see that nothing went missing.\n */\n standings: Record<KbStanding, number>;\n /** Shorthand for `standings.current` — records that simply hold. */\n currentCount: number;\n /** Shorthand for `standings.superseded`. */\n supersededCount: number;\n /**\n * Records whose `stale_after` has passed. A flag over the standings rather\n * than one of them — a current record can be stale — so this deliberately\n * does not participate in the sum.\n */\n staleCount: number;\n};\n\nconst EMPTY_STANDINGS: Record<KbStanding, number> = {\n current: 0,\n superseded: 0,\n rejected: 0,\n unsettled: 0,\n open: 0,\n};\n\n/**\n * The tier-one listing: every record named, nothing spelled out.\n *\n * `load` hands over bodies and `pack` hands over a neighbourhood; both have to\n * decide what the reader can afford. The catalog is the rung below either — one\n * line per record at roughly thirty tokens, so a base far past `load`'s gate\n * still fits in a single call. What it buys is the ability to choose: a reader\n * that can see every id, type, title and standing knows which record to `pack`\n * and knows when no record covers the question at all, which is the conclusion\n * a truncated read can never support.\n *\n * Standing travels on the line for the same reason it travels with every other\n * result here: a title is a claim, and a superseded claim reads exactly like a\n * live one. A superseded entry names its replacement, so the line the reader\n * should follow instead is already in front of them.\n *\n * Unbounded, alone among the read paths. `load` and `pack` refuse past a\n * ceiling because a partial body set reads as a complete one; a catalog has no\n * such failure — it is the rung a caller lands on *because* something else\n * refused, and a second refusal there would leave nowhere to go. The cost is\n * linear and cheap: roughly thirty tokens a record, so a thousand-record base\n * is about 30k and five thousand about 150k. Past that the `type` filter\n * narrows it, and no ceiling is needed to make that available.\n *\n * Deterministic given a fixed `now`: no timestamp is emitted, and the ordering\n * is total down to the concept id, so two catalogs of an unchanged base within\n * one `stale_after` window are byte-identical and diff to nothing. The default\n * clock is the wall clock, so a line can still flip to stale as a date passes —\n * pass `now` when byte-equality has to hold across that boundary.\n */\nexport function catalog(\n bundle: KbRecord[],\n options: { type?: string; now?: Date } = {},\n): KbCatalogResult {\n const wanted = options.type\n ? bundle.filter((record) => record.frontmatter.type === options.type)\n : bundle;\n\n // Adjudicated against the whole base, not the filtered slice: a record's\n // replacement may be of another type, and a filter must not turn a\n // superseded record into a current-looking one.\n const entries = adjudicate(wanted, bundle, options.now ?? new Date())\n .map((hit) => ({\n conceptId: hit.record.conceptId,\n type: hit.record.frontmatter.type,\n title: hit.record.frontmatter.title ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n stale: hit.warnings.some((warning) => warning.kind === \"stale\"),\n }))\n .sort(byTypeThenTitle);\n\n const standings = { ...EMPTY_STANDINGS };\n for (const entry of entries) standings[entry.standing] += 1;\n\n return {\n entries,\n recordCount: entries.length,\n standings,\n currentCount: standings.current,\n supersededCount: standings.superseded,\n staleCount: entries.filter((entry) => entry.stale).length,\n };\n}\n\n/** Concept id is the tiebreak, so the order is total and therefore stable. */\nfunction byTypeThenTitle(left: KbCatalogEntry, right: KbCatalogEntry): number {\n return (\n byCodeUnit(left.type, right.type) ||\n byCodeUnit(left.title ?? \"\", right.title ?? \"\") ||\n byCodeUnit(left.conceptId, right.conceptId)\n );\n}\n\n/**\n * Code-unit order, not `localeCompare`.\n *\n * `localeCompare` without an explicit locale reads the host's, so the same\n * base sorts differently on two machines — and this output's whole contract is\n * that two catalogs of an unchanged base diff to nothing. A collation nobody\n * configured is not worth a determinism claim that quietly does not hold.\n */\nfunction byCodeUnit(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\n/**\n * One entry, as one line.\n *\n * ` · `-separated rather than a table: a table pays for column alignment on\n * every row, and nothing downstream parses these.\n */\nexport function renderCatalogLine(entry: KbCatalogEntry): string {\n const parts = [\n entry.conceptId,\n entry.type,\n entry.title ?? \"(untitled)\",\n entry.standing === \"superseded\"\n ? `superseded → ${entry.supersededBy.join(\", \") || \"(no surviving head)\"}`\n : entry.standing,\n ];\n if (entry.stale) parts.push(\"stale\");\n return `- ${parts.join(\" · \")}`;\n}\n","import { z } from \"zod\";\nimport { buildContext, toHookJson } from \"../kb-context.js\";\nimport { argvFlag, define } from \"./model.js\";\n\nexport const contextCommand = define({\n name: \"context\",\n tool: \"kb_context\",\n usage:\n \"context [--profile NAME] [--budget N] [--full-under N] [--format json] [--event NAME]\",\n description:\n \"Index block of pinned bases (ids, titles, standing) for injection at context birth. Takes no bundlePath — reads the workspace pin manifests. Empty when nothing is pinned; refuses over budget rather than truncating. Budget precedence: flags, then the manifest `context[profile]` over `context.default`, then the built-in profile, then package defaults.\",\n input: z.object({\n budgetTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Ceiling on the whole emitted block; past it the command refuses with a list of bases rather than truncating. Defaults to 4000.\",\n ),\n fullUnderTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Per-base rendering threshold, applied before the budget: a base whose complete load fits under this arrives as full records instead of index lines, and the whole block still answers to budgetTokens. Off by default — index-only is the safe default at a context birth, because injected bodies outlive the qualifiers on them; the session-start profile opts tiny bases in at 1500.\",\n ),\n profile: z\n .string()\n .optional()\n .describe(\n \"Named budget set: built-ins are session-start (full-under 1500), compact and turn (budget 2500); the manifests' `context` tables override per repo. Unknown names fall through to defaults rather than failing.\",\n ),\n format: z\n .enum([\"markdown\", \"json\"])\n .optional()\n .describe(\n \"CLI envelope for hook protocols that require strict JSON on stdout. MCP callers omit this — the block itself is identical.\",\n ),\n event: z\n .string()\n .optional()\n .describe(\n \"hookEventName stamped into the JSON envelope. Only meaningful with format=json.\",\n ),\n }),\n fromArgv: (argv) => {\n const budget = argvFlag(argv, \"--budget\");\n const fullUnder = argvFlag(argv, \"--full-under\");\n const profile = argvFlag(argv, \"--profile\");\n const format = argvFlag(argv, \"--format\");\n const event = argvFlag(argv, \"--event\");\n return {\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(fullUnder ? { fullUnderTokens: Number(fullUnder) } : {}),\n ...(profile ? { profile } : {}),\n ...(format ? { format } : {}),\n ...(event ? { event } : {}),\n };\n },\n run: async (\n { store },\n { budgetTokens, fullUnderTokens, profile, format, event },\n ) => {\n const result = await buildContext(store, process.cwd(), {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens ? { fullUnderTokens } : {}),\n ...(profile ? { profile } : {}),\n // Degradations — a full pin that could not fit, a refused block — go\n // to stderr as well as into the block itself: stderr is diagnostics on\n // both surfaces (hooks discard it, MCP logs it), so an operator can\n // see budget pressure without reading injected context.\n warn: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n });\n // Empty means empty in both formats: this runs from hooks at every\n // session start and must be silent when there is nothing to say.\n if (!result.block) return \"\";\n return format === \"json\"\n ? toHookJson(result.block, event ?? \"SessionStart\")\n : result.block;\n },\n});\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { adjudicate } from \"./adjudicate.js\";\nimport { renderIndexLine } from \"./kb-index.js\";\nimport {\n mergedContextBudgets,\n readMergedPins,\n type KbContextBudgets,\n} from \"./kb-pins/index.js\";\nimport type { KbStore } from \"./kb-store.js\";\n\n/**\n * The context block: an index of every pinned base, emitted at context birth.\n *\n * Two failure modes lose a knowledge base to a long session — attention decay,\n * and compaction, which summarises away both loaded records and the early\n * instruction that said to consult them. This block is the layer against both:\n * small enough to re-inject at every session start, and self-instructing, so a\n * re-injection after compaction reads as a refresh rather than a contradiction.\n *\n * It is an index, not the content: concept ids, titles and standing. The\n * bodies stay behind the tools, loaded at the point of use.\n */\n\n/** A stable heading, so re-injection reads as a refresh. */\nconst HEADING = \"## Knowledge bases (pinned)\";\n\n/**\n * Small by design — this block is paid at every context birth, and on some\n * runtimes on every turn. A base wanting more space is `--full-under`'s job.\n */\nconst DEFAULT_CONTEXT_BUDGET = 4_000;\n\n/**\n * What the hooks ask for by name, so the numbers live in one place and a repo\n * can override them in its pin manifest rather than editing hook commands.\n * `session-start` is a fresh window — room for tiny bases to arrive whole.\n * `compact` competes with a summary for a smaller window — index only.\n * `turn` is per-turn injection (Antigravity) — same tight stance as compact.\n */\nexport const CONTEXT_PROFILES: Record<string, KbContextBudgets> = {\n \"session-start\": { fullUnderTokens: 1_500 },\n compact: { budgetTokens: 2_500 },\n turn: { budgetTokens: 2_500 },\n};\n\nexport type KbContextOptions = {\n /** Refuse past this. Defaults to 4000 tokens. */\n budgetTokens?: number;\n /** Emit bases whose full `load` fits under this as records, not index. 0 = off. */\n fullUnderTokens?: number;\n /**\n * A named budget set. Resolution, most specific wins: explicit options,\n * then the manifest's `context[profile]` over its `context.default`, then\n * the built-in profile, then the package defaults. An unknown profile is\n * not an error — it simply falls through; hooks must never break over a\n * name.\n */\n profile?: string;\n /**\n * Where budget pressure is reported outside the block itself: a full pin\n * that had to degrade to an index, a block that refused. The block already\n * says both to the agent; this says them to the operator's log.\n */\n warn?: (entry: Record<string, unknown>) => void;\n};\n\nexport type KbContextResult = {\n /** The markdown block. Empty when there are no pins — silence, not a stub. */\n block: string;\n /** Refused: over budget. The block then lists the bases instead of the index. */\n refused: boolean;\n approxTokens: number;\n budgetTokens: number;\n bases: { path: string; absolutePath: string; approxTokens: number }[];\n};\n\n/** The crude estimator everything here shares — see kb-store.ts on why. */\nfunction approxTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\nfunction preamble(): string {\n return [\n HEADING,\n \"\",\n \"What follows is an index of this workspace's pinned knowledge bases —\",\n \"concept ids, titles and standing only. The record bodies are NOT in this\",\n \"context.\",\n \"\",\n \"Consult records only through the strauss-kb MCP tools: `kb_load` (the\",\n \"preferred first call), `kb_query`, and `kb_trace`, passing the\",\n \"`bundlePath` listed with each base. Do not read record files directly:\",\n \"a raw file read bypasses supersession resolution, and a superseded or\",\n \"rejected record file reads exactly like a current one — only the store\",\n \"resolves chains and standing.\",\n \"\",\n \"KB content loaded earlier in a long session may have been compacted\",\n \"away. Before answering a question one of these bases governs, load it\",\n \"again at the point of use — reloading a small base costs a few thousand\",\n \"tokens.\",\n ].join(\"\\n\");\n}\n\ntype BaseSection = {\n path: string;\n absolutePath: string;\n body: string;\n mode: \"index\" | \"full\" | \"empty\";\n /**\n * A `mode: full` pin whose bodies exceeded the block budget, emitted as an\n * index instead. Flagged in the section label, never silent — the reader\n * asked for the whole base and must know it is not looking at it.\n */\n degradedFrom?: { approxTokens: number };\n};\n\nasync function renderBase(\n store: KbStore,\n path: string,\n absolutePath: string,\n fullUnderTokens: number,\n pinMode: \"full\" | \"index\" | undefined,\n budgetTokens: number,\n): Promise<BaseSection> {\n const bundle = await store.list(absolutePath);\n if (bundle.length === 0) {\n return {\n path,\n absolutePath,\n mode: \"empty\",\n body: \"No readable records yet — pinned ahead of being populated.\",\n };\n }\n\n // A pin's own mode outranks the threshold. `full` preloads the base whole —\n // capped only by the block budget, because past that the whole block\n // refuses anyway; when even that fails, the base degrades to an index and\n // the label says so, never silently. `index` never upgrades.\n const fullCap =\n pinMode === \"full\"\n ? budgetTokens\n : pinMode === \"index\"\n ? 0\n : fullUnderTokens;\n\n let degradedFrom: { approxTokens: number } | undefined;\n if (fullCap > 0) {\n const full = await store.load(absolutePath, {\n budgetTokens: fullCap,\n });\n if (!full.loaded && pinMode === \"full\") {\n degradedFrom = { approxTokens: full.approxTokens };\n }\n if (full.loaded) {\n const records = full.records.map((hit) =>\n [\n `#### ${hit.record.conceptId} — ${hit.record.frontmatter.title ?? \"(untitled)\"} (${hit.standing})`,\n \"\",\n hit.record.body.trim(),\n ].join(\"\\n\"),\n );\n const superseded = full.superseded.map(\n (entry) =>\n `- \\`${entry.conceptId}\\` → superseded by ${entry.supersededBy.map((id) => `\\`${id}\\``).join(\", \") || \"(missing replacement)\"}`,\n );\n return {\n path,\n absolutePath,\n mode: \"full\",\n body: [\n ...records,\n ...(superseded.length\n ? [\n \"#### Superseded (bodies withheld — kb_trace reaches them)\",\n ...superseded,\n ]\n : []),\n ].join(\"\\n\\n\"),\n };\n }\n }\n\n // Adjudicated against the whole base so a superseded record collapses to an\n // id and its replacement — the same shape `load` hands back, for the same\n // reason: a body outlives the qualifier that said it no longer holds.\n const adjudicated = adjudicate(bundle, bundle);\n const lines = adjudicated\n .filter((hit) => hit.standing !== \"superseded\")\n .map((hit) => renderIndexLine(hit.record));\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(\n (hit) =>\n `- \\`${hit.record.conceptId}\\` → superseded by ${hit.heads.map((head) => `\\`${head.conceptId}\\``).join(\", \") || \"(missing replacement)\"}`,\n );\n return {\n path,\n absolutePath,\n mode: \"index\",\n body: [...lines, ...superseded].join(\"\\n\"),\n ...(degradedFrom ? { degradedFrom } : {}),\n };\n}\n\n/**\n * Builds the block, or a refusal that lists the bases — never a truncation. A\n * truncated index is indistinguishable from a complete one, so a reader would\n * take a slice for the whole, which is `load`'s argument one layer up.\n */\nexport async function buildContext(\n store: KbStore,\n workspaceDir: string,\n options: KbContextOptions = {},\n): Promise<KbContextResult> {\n const builtin = options.profile\n ? (CONTEXT_PROFILES[options.profile] ?? {})\n : {};\n let budgetTokens =\n options.budgetTokens ?? builtin.budgetTokens ?? DEFAULT_CONTEXT_BUDGET;\n let fullUnderTokens = options.fullUnderTokens ?? builtin.fullUnderTokens ?? 0;\n\n // All three manifest layers, merged — nearest wins. The reader skips a\n // malformed layer rather than throwing: this runs from hooks at every\n // session start, and one broken personal file must not silence the team's\n // pins. `pin`/`unpin` are what surface the broken layer, loudly.\n const merged = await readMergedPins(workspaceDir);\n\n // The workspace's own numbers, from the manifests — above the built-ins,\n // below anything passed explicitly.\n const fromManifest = mergedContextBudgets(merged, options.profile);\n budgetTokens =\n options.budgetTokens ??\n fromManifest.budgetTokens ??\n builtin.budgetTokens ??\n DEFAULT_CONTEXT_BUDGET;\n fullUnderTokens =\n options.fullUnderTokens ??\n fromManifest.fullUnderTokens ??\n builtin.fullUnderTokens ??\n 0;\n\n // A pin scoped to named profiles surfaces only in those; unscoped pins\n // surface everywhere, and a run without a profile sees everything — the\n // explicit full view.\n const pins = merged.pins.filter(\n (pin) =>\n !pin.profiles?.length ||\n !options.profile ||\n pin.profiles.includes(options.profile),\n );\n if (pins.length === 0) {\n return {\n block: \"\",\n refused: false,\n approxTokens: 0,\n budgetTokens,\n bases: [],\n };\n }\n\n const sections = await Promise.all(\n pins.map(async (pin) => ({\n section: await renderBase(\n store,\n pin.path,\n pin.absolutePath,\n fullUnderTokens,\n pin.mode,\n budgetTokens,\n ),\n frozen: pin.frozen === true,\n })),\n );\n\n const modeLabel = {\n index: \"index only — record bodies are not here\",\n full: \"full records — this base arrives whole\",\n empty: \"empty\",\n } as const;\n\n // A full pin that could not fit is loudly labelled, in the block and in the\n // log: the reader asked for the whole base and must know it is not looking\n // at it, and the operator must see the budget pressure without reading\n // injected context.\n for (const { section } of sections) {\n if (section.degradedFrom) {\n options.warn?.({\n operation: \"kb.context.full-pin-degraded\",\n path: section.path,\n approxTokens: section.degradedFrom.approxTokens,\n budgetTokens,\n });\n }\n }\n\n const rendered = sections.map(({ section, frozen }) => {\n const label = section.degradedFrom\n ? `index only — pinned \\`mode: full\\`, but its ~${section.degradedFrom.approxTokens} tokens exceed this block's ${budgetTokens}-token budget; kb_load it directly (load's budget is separate), or raise this profile's budget`\n : modeLabel[section.mode];\n return [\n `### ${section.path} (${label}${frozen ? \" · frozen, read-only\" : \"\"})`,\n \"\",\n `bundlePath: \\`${section.absolutePath}\\``,\n \"\",\n section.body,\n ].join(\"\\n\");\n });\n\n const block = [preamble(), \"\", rendered.join(\"\\n\\n\"), \"\"].join(\"\\n\");\n const bases = sections.map(({ section }) => ({\n path: section.path,\n absolutePath: section.absolutePath,\n approxTokens: approxTokens(section.body),\n }));\n const total = approxTokens(block);\n\n if (total > budgetTokens) {\n options.warn?.({\n operation: \"kb.context.refused\",\n approxTokens: total,\n budgetTokens,\n bases: bases.map((base) => base.path),\n });\n // A refusal, not a lock: the budget guards what is injected at every\n // context birth, never a deliberate read. So the refusal carries both\n // moves — read what the question needs right now, and shrink the\n // recurring block so the next session does not land here.\n const refusal = [\n HEADING,\n \"\",\n `The pinned index runs to ~${total} tokens, past the ${budgetTokens}-token`,\n \"budget, and was not emitted — a truncated index is indistinguishable\",\n \"from a complete one. The pinned bases:\",\n \"\",\n ...bases.map(\n (base) =>\n `- ${base.path} — ~${base.approxTokens} tokens (bundlePath: \\`${base.absolutePath}\\`)`,\n ),\n \"\",\n \"For the question at hand, read what you need now — `kb_load` a base\",\n \"(its own budget is separate), or `kb_index` for one base's shape.\",\n \"\",\n \"To bring this block back under budget, in order of preference:\",\n \"- supersede or resolve stale records — the base shrinks, the knowledge keeps\",\n \"- force a large base to index lines: `strauss-kb pin <path> --mode index`\",\n \"- scope a pin to the profiles that need it: `strauss-kb pin <path> --profiles session-start`\",\n \"- raise this profile's budget under `context` in .strauss/kb-pins.json\",\n \"- unpin what no session actually needs\",\n \"\",\n ].join(\"\\n\");\n return {\n block: refusal,\n refused: true,\n approxTokens: total,\n budgetTokens,\n bases,\n };\n }\n\n return { block, refused: false, approxTokens: total, budgetTokens, bases };\n}\n\n/**\n * The same block in the envelope hook protocols that demand strict JSON on\n * stdout require:\n * those protocols treat non-JSON stdout as a violation, where Claude Code and\n * Codex take plain text. One canonical writer for the block; this is wrapping.\n */\nexport function toHookJson(block: string, event: string): string {\n return JSON.stringify({\n hookSpecificOutput: {\n hookEventName: event,\n additionalContext: block,\n },\n });\n}\n\nexport const CONTEXT_BEGIN = \"<!-- strauss-kb:begin -->\";\nexport const CONTEXT_END = \"<!-- strauss-kb:end -->\";\n\nexport type KbSyncResult = {\n file: string;\n action: \"created\" | \"replaced\" | \"appended\" | \"removed\" | \"unchanged\";\n};\n\n/**\n * Idempotently plants the block between sentinels in an instruction file\n * (AGENTS.md, CLAUDE.md). This is how a runtime without a reliable\n * post-compact hook keeps a refreshable index: the file is re-read where the\n * conversation is not. Everything outside the sentinels is left alone.\n */\nexport async function syncInstructions(\n file: string,\n block: string,\n): Promise<KbSyncResult> {\n const existing = await readFile(file, \"utf8\").catch(() => null);\n const region = block\n ? `${CONTEXT_BEGIN}\\n${block.trim()}\\n${CONTEXT_END}`\n : null;\n\n if (existing === null) {\n if (!region) return { file, action: \"unchanged\" };\n await writeFile(file, `${region}\\n`, \"utf8\");\n return { file, action: \"created\" };\n }\n\n const begin = existing.indexOf(CONTEXT_BEGIN);\n const end = existing.indexOf(CONTEXT_END);\n if (begin !== -1 && end !== -1 && end >= begin) {\n const before = existing.slice(0, begin);\n const after = existing.slice(end + CONTEXT_END.length);\n const next = region\n ? `${before}${region}${after}`\n : `${before.replace(/\\n+$/, \"\\n\")}${after.replace(/^\\n+/, \"\\n\")}`;\n if (next === existing) return { file, action: \"unchanged\" };\n await writeFile(file, next, \"utf8\");\n return { file, action: region ? \"replaced\" : \"removed\" };\n }\n\n if (!region) return { file, action: \"unchanged\" };\n await writeFile(\n file,\n `${existing.replace(/\\n*$/, \"\\n\\n\")}${region}\\n`,\n \"utf8\",\n );\n return { file, action: \"appended\" };\n}\n","import type { KbRecord } from \"./kb-record.schema.js\";\n\nexport const INDEX_FILE = \"INDEX.md\";\n\nconst HEADING = \"# KB Index\";\n\n/**\n * `INDEX.md` is a projection — every byte recomputable from record frontmatter.\n *\n * That is what lets parallel writers regenerate it without a lock: they compute\n * the same function of the same records, so two concurrent regenerations differ\n * only in how recent each writer's scan was, and the next read settles it. The\n * file is therefore eventually correct rather than always correct, which is the\n * right trade for something nothing reads transactionally.\n *\n * Lines carry `description`, not just a title. A reader consults the index to\n * decide what is worth opening, and a list of titles does not answer that.\n */\nexport function renderIndex(records: KbRecord[]): string {\n const lines = [...records]\n .sort((left, right) => left.conceptId.localeCompare(right.conceptId))\n .map(renderIndexLine);\n\n return `${HEADING}\\n\\n${lines.join(\"\\n\")}\\n`;\n}\n\n/**\n * One record's index line. The single writer of this shape — `context` emits\n * the same line rather than growing a second index renderer that would drift\n * from this one.\n */\nexport function renderIndexLine(record: KbRecord): string {\n const { frontmatter: fm } = record;\n const parts = [fm.type, fm.strauss_status];\n if (fm.tags?.length) parts.push(`tags: ${fm.tags.join(\", \")}`);\n if (fm.description) parts.push(fm.description);\n return `- [${fm.title ?? record.conceptId}](${record.conceptId}.md) — ${parts.join(\" · \")}`;\n}\n\n/** Whether the stored projection still matches the records it claims to index. */\nexport function indexIsStale(stored: string | null, expected: string): boolean {\n return stored !== expected;\n}\n","import { z } from \"zod\";\nimport { adjudicate } from \"../adjudicate.js\";\nimport {\n movedSearch,\n reassessPacket,\n type KbReassessPacket,\n} from \"../drift/index.js\";\nimport {\n doctor,\n DEFAULT_AGING_DAYS,\n DEFAULT_EXPIRING_DAYS,\n DEFAULT_UNVERIFIED_DAYS,\n type KbDoctorReport,\n} from \"../doctor.js\";\nimport { renderReassess } from \"./reassess.js\";\nimport { grammarHints } from \"../grammars/index.js\";\nimport { argvFlag, bundlePath, define, REPO_ROOT } from \"./model.js\";\n\nexport type KbDoctorCommandResult = KbDoctorReport & {\n bundlePath: string;\n checkedAt: string;\n /**\n * One per drifted record that still needs a reading, present only under\n * `--drifted`. Records whose every drifted anchor was `moved` or `cosmetic`\n * produce no packet — that is the classification earning its keep.\n */\n packets?: KbReassessPacket[];\n /**\n * Records carrying an anchor whose code turned up unchanged elsewhere.\n * `doctor` never writes, so it names them and stops; `kb_reassess <id>` is\n * the verb that moves the anchor.\n */\n rebaselinable?: string[];\n /** What to do about a grammar this run could not obtain. */\n hints?: string[];\n};\n\nconst days = (what: string, fallback: number) =>\n z\n .number()\n .int()\n .positive()\n .optional()\n .describe(`${what} Defaults to ${fallback}.`);\n\nexport const doctorCommand = define({\n name: \"doctor\",\n tool: \"kb_doctor\",\n usage:\n \"doctor [--expiring-days N] [--unverified-days N] [--aging-days N] [--repo-root PATH] [--offline] [--strict] [--drifted [--with-diff]]\",\n description:\n \"Read-only health sweep: expired, expiring, unverified, aging, orphaned, broken-supersession, superseded-but-cited, drifted and unchecked anchors. Every group is reported even when empty; nothing is written or re-stamped. `drifted` narrows it to a reassessment packet per drifted record, `with_diff` adding each anchor's old-vs-new span.\",\n input: z.object({\n bundlePath,\n repoRoot: REPO_ROOT,\n expiringDays: days(\n \"How far ahead `expiring` looks, in days.\",\n DEFAULT_EXPIRING_DAYS,\n ),\n unverifiedDays: days(\n \"How old an unconfirmed record must be before `unverified` reports it, in days.\",\n DEFAULT_UNVERIFIED_DAYS,\n ),\n agingDays: days(\n \"How long a record may stay `open` or `proposed` before `aging` reports it, in days.\",\n DEFAULT_AGING_DAYS,\n ),\n offline: z\n .boolean()\n .optional()\n .describe(\n \"Read foreign anchors from the local repo cache only, never fetching.\",\n ),\n strict: z\n .boolean()\n .optional()\n .describe(\n \"Turn an expired record into a non-zero exit for the CLI. No effect on the report itself.\",\n ),\n drifted: z\n .boolean()\n .optional()\n .describe(\n \"Report only drift, as a reassessment packet per record: claim, per-anchor class, and what depends on it.\",\n ),\n withDiff: z\n .boolean()\n .optional()\n .describe(\n \"With `drifted`: recover each anchor's committed span and render the old-vs-new diff. Reads git history.\",\n ),\n }),\n // Presence, not truthiness: `--expiring-days \"\"` is a caller who meant\n // something and mistyped it, and a falsy test would answer by quietly\n // sweeping at the default. Passed through as given, the schema rejects it\n // and says which field.\n fromArgv: (argv, path) => {\n const expiring = argvFlag(argv, \"--expiring-days\");\n const unverified = argvFlag(argv, \"--unverified-days\");\n const agingDays = argvFlag(argv, \"--aging-days\");\n const repoRoot = argvFlag(argv, \"--repo-root\");\n return {\n bundlePath: path,\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n ...(expiring !== undefined ? { expiringDays: Number(expiring) } : {}),\n ...(unverified !== undefined\n ? { unverifiedDays: Number(unverified) }\n : {}),\n ...(agingDays !== undefined ? { agingDays: Number(agingDays) } : {}),\n ...(argv.includes(\"--offline\") ? { offline: true } : {}),\n ...(argv.includes(\"--strict\") ? { strict: true } : {}),\n ...(argv.includes(\"--drifted\") ? { drifted: true } : {}),\n ...(argv.includes(\"--with-diff\") ? { withDiff: true } : {}),\n };\n },\n run: async (\n { store, now },\n {\n bundlePath: path,\n expiringDays,\n unverifiedDays,\n agingDays,\n repoRoot,\n offline,\n drifted,\n withDiff,\n },\n ) => {\n const checkedAt = now();\n const records = await store.list(path);\n // Read-only, like every other check here: the sweep names the drifted\n // anchors and leaves the re-stamp to `anchor-resolve`, which is the verb\n // that writes.\n const anchorDrift = await store.detectDrift(records, repoRoot, {\n offline: offline === true,\n });\n const report = doctor(records, {\n ...(expiringDays !== undefined ? { expiringDays } : {}),\n ...(unverifiedDays !== undefined ? { unverifiedDays } : {}),\n ...(agingDays !== undefined ? { agingDays } : {}),\n ...(anchorDrift !== undefined ? { anchorDrift } : {}),\n now: new Date(checkedAt),\n });\n const hints = grammarHints();\n if (!drifted) {\n return {\n bundlePath: path,\n checkedAt,\n ...report,\n ...(hints.length ? { hints } : {}),\n };\n }\n\n // Read-only, like the rest of the sweep: packets are built, `moved`\n // anchors are named, and not one anchor is rewritten.\n const standings = new Map(\n adjudicate(records, records, new Date(checkedAt)).map((hit) => [\n hit.record.conceptId,\n hit.standing,\n ]),\n );\n const packets: KbReassessPacket[] = [];\n const rebaselinable: string[] = [];\n // One search for the whole sweep: the repository is listed once, and a\n // candidate file is parsed once however many records anchor into it.\n const search = movedSearch(repoRoot ?? process.cwd());\n for (const found of report.groups.find((g) => g.check === \"drifted\")\n ?.findings ?? []) {\n const record = records.find(\n (entry) => entry.conceptId === found.conceptId,\n );\n if (!record) continue;\n const standing = standings.get(record.conceptId);\n const built = await reassessPacket(\n repoRoot ?? process.cwd(),\n record,\n anchorDrift?.get(record.conceptId) ?? [],\n {\n ...(withDiff ? { withDiff: true } : {}),\n impact: await store.impact(path, record.conceptId),\n ...(standing ? { standing } : {}),\n search,\n },\n );\n if (built.packet) packets.push(built.packet);\n if (built.classified.some((entry) => entry.class === \"moved\")) {\n rebaselinable.push(record.conceptId);\n }\n }\n return {\n bundlePath: path,\n checkedAt,\n ...report,\n packets,\n rebaselinable,\n ...(hints.length ? { hints } : {}),\n };\n },\n render: (result) => render(result as KbDoctorCommandResult),\n // Only expiry, and only under --strict. The other seven checks report debt a\n // reader decides about; an expired record is the base asserting something it\n // already said it would stop standing behind, which is the one finding a\n // pipeline can act on without a judgment call. Drift has its own gate —\n // `anchor-resolve` exits non-zero on it, against a repo root the caller\n // named, which is the run a CI pipeline should be making anyway.\n failsWhen: (result, input) =>\n input.strict === true &&\n (result as KbDoctorCommandResult).counts.expired > 0,\n});\n\n/**\n * The summary table first, then only the groups that found something.\n *\n * The table carries every check including the empty ones — that is what makes\n * \"checked and clean\" legible — while the detail below stays as short as the\n * base's actual health.\n */\nfunction render(result: KbDoctorCommandResult): string {\n if (result.packets) return renderPackets(result);\n const { thresholds } = result;\n const lines = [\n `# KB Doctor — ${result.bundlePath}`,\n `records: ${result.recordCount}`,\n `thresholds: expiring within ${thresholds.expiringDays}d, unverified over ${thresholds.unverifiedDays}d, aging over ${thresholds.agingDays}d`,\n `checked: ${result.checkedAt}`,\n ...(result.anchorResolvers.total\n ? [\n `anchors: ${result.anchorResolvers.total} hashed — ${result.anchorResolvers.treeSitter} tree-sitter, ${result.anchorResolvers.regex} regex`,\n ]\n : []),\n \"\",\n ];\n\n const width = Math.max(...result.groups.map((group) => group.check.length));\n for (const group of result.groups) {\n lines.push(\n ` ${group.check.padEnd(width)} ${String(group.count).padStart(3)} ${group.headline}`,\n );\n }\n\n for (const group of result.groups) {\n if (!group.count) continue;\n lines.push(\"\", `## ${group.check} (${group.count})`);\n for (const found of group.findings) {\n lines.push(\n `- ${found.conceptId}${found.title ? ` — ${found.title}` : \"\"}: ${found.note}`,\n );\n }\n }\n\n for (const hint of result.hints ?? []) lines.push(\"\", hint);\n\n lines.push(\n \"\",\n result.healthy\n ? \"Nothing to repair.\"\n : `${result.findingCount} finding${result.findingCount === 1 ? \"\" : \"s\"} across ${\n result.groups.filter((group) => group.count).length\n } of ${result.groups.length} checks.`,\n );\n\n return lines.join(\"\\n\");\n}\n\n/**\n * `--drifted` answers a different question from the sweep, so it prints a\n * different report: not \"what is wrong with this base\" but \"here is what to\n * read, and what the code did\".\n */\nfunction renderPackets(result: KbDoctorCommandResult): string {\n const packets = result.packets ?? [];\n const lines = [\n `# KB Drift — ${result.bundlePath}`,\n `checked: ${result.checkedAt}`,\n `${packets.length} record${packets.length === 1 ? \"\" : \"s\"} need a reading; ${\n result.counts.drifted\n } drifted in all.`,\n ];\n if (result.rebaselinable?.length) {\n lines.push(\n `moved, rebaseline with \\`kb_reassess\\`: ${result.rebaselinable.join(\", \")}`,\n );\n }\n for (const packet of packets) {\n lines.push(\n renderReassess({\n conceptId: packet.conceptId,\n packet,\n rebaselined: [],\n cosmetic: 0,\n }),\n );\n }\n return lines.join(\"\\n\");\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { filePathIsSafe, refShapeIsSafe } from \"../remote-repo/validate.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Reading a committed file, for the one thing a working tree cannot answer:\n * what the anchored code looked like when the record was written.\n *\n * `ref` and `file` come off an anchor, which is a `.md` file the reader did not\n * write. An argv array stops a shell; it does not stop git's own option\n * parsing, so every positional that derives from bundle data goes after\n * `--end-of-options` and is shape-checked before a subprocess exists. Nothing\n * here fetches — a rev this checkout does not have is a finding, never a\n * network call.\n *\n * The shape checks themselves are `remote-repo/validate.ts`'s: one definition\n * of what a `ref` and a `file` may be, whichever read path asks.\n */\n\n/** Output cap. A recovered file is source, and source this large is not. */\nexport const MAX_GIT_OUTPUT_BYTES = 1_048_576;\n\nconst GIT_TIMEOUT_MS = 5_000;\n\ntype GitResult = { ok: true; stdout: string } | { ok: false };\n\n/**\n * `GIT_DIR`, `GIT_WORK_TREE` and `GIT_INDEX_FILE` are stripped from the child:\n * a caller's environment must not be able to redirect a read that `-C` already\n * addressed.\n */\nasync function git(cwd: string, args: string[]): Promise<GitResult> {\n const env = { ...process.env };\n delete env[\"GIT_DIR\"];\n delete env[\"GIT_WORK_TREE\"];\n delete env[\"GIT_INDEX_FILE\"];\n try {\n const { stdout } = await execFileAsync(\"git\", [\"-C\", cwd, ...args], {\n timeout: GIT_TIMEOUT_MS,\n maxBuffer: MAX_GIT_OUTPUT_BYTES,\n env,\n });\n return { ok: true, stdout };\n } catch {\n return { ok: false };\n }\n}\n\n/** Repository-relative paths, for the `moved` search. Empty when git fails. */\nexport async function listRepoFiles(repoRoot: string): Promise<string[]> {\n const result = await git(repoRoot, [\"ls-files\", \"-z\", \"--cached\"]);\n if (!result.ok) return [];\n return result.stdout.split(\"\\0\").filter(Boolean);\n}\n\n/** Where a recovered file came from, so a packet can say how far back it looked. */\nexport type OldSourceOrigin =\n /** `git show <anchor.ref>:<file>` — the rev the record itself named. */\n | { kind: \"ref\"; ref: string }\n /** The last commit touching the path before `resolved_at`. */\n | { kind: \"history\"; ref: string };\n\nexport type OldSource =\n | { ok: true; source: string; origin: OldSourceOrigin }\n /**\n * No committed text to diff against: no usable `ref`, no history before\n * `resolved_at`, or the path did not exist at the rev that was found.\n */\n | { ok: false; reason: \"unrecoverable\" };\n\n/**\n * The anchored file as it was, `ref` first and the record's own timestamp\n * second.\n *\n * `ref` is what the record asserted the evidence was taken at, so it is tried\n * before anything inferred. Falling back to `git log --before=<resolved_at>`\n * recovers the far commoner case of an anchor that was stamped but never\n * pinned; it is weaker — the last commit before a timestamp is a guess about\n * which tree the reader had — which is why the origin travels with the text.\n */\nexport async function readOldSource(\n repoRoot: string,\n anchor: { file: string; ref?: string; resolved_at?: string },\n): Promise<OldSource> {\n if (!filePathIsSafe(anchor.file))\n return { ok: false, reason: \"unrecoverable\" };\n\n if (anchor.ref && refShapeIsSafe(anchor.ref)) {\n const shown = await showFile(repoRoot, anchor.ref, anchor.file);\n if (shown !== null) {\n return {\n ok: true,\n source: shown,\n origin: { kind: \"ref\", ref: anchor.ref },\n };\n }\n }\n\n const at = anchor.resolved_at;\n if (!at || Number.isNaN(Date.parse(at))) {\n return { ok: false, reason: \"unrecoverable\" };\n }\n // `--before` is a git-parsed value, not a path or a rev, and it is passed as\n // one `--before=<date>` token so it can never be read as two arguments.\n const found = await git(repoRoot, [\n \"log\",\n \"-1\",\n \"--format=%H\",\n `--before=${at}`,\n \"--end-of-options\",\n \"HEAD\",\n \"--\",\n anchor.file,\n ]);\n const sha = found.ok ? found.stdout.trim() : \"\";\n if (!sha || !refShapeIsSafe(sha))\n return { ok: false, reason: \"unrecoverable\" };\n\n const shown = await showFile(repoRoot, sha, anchor.file);\n if (shown === null) return { ok: false, reason: \"unrecoverable\" };\n return { ok: true, source: shown, origin: { kind: \"history\", ref: sha } };\n}\n\n/** `<rev>:<path>` is one positional, so both halves are validated together. */\nasync function showFile(\n repoRoot: string,\n ref: string,\n file: string,\n): Promise<string | null> {\n const path = file.replace(/^\\.\\//, \"\");\n const result = await git(repoRoot, [\n \"show\",\n \"--end-of-options\",\n `${ref}:${path}`,\n ]);\n return result.ok ? result.stdout : null;\n}\n","import { stat } from \"node:fs/promises\";\nimport {\n anchorFilePath,\n anchorFileReader,\n hashAnchorText,\n type AnchorFileReader,\n type KbDriftMovedTo,\n} from \"../anchor-resolver/index.js\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport {\n languageForFile,\n TreeSitterResolver,\n} from \"../tree-sitter-resolver/index.js\";\nimport { listRepoFiles } from \"./git.js\";\n\n/**\n * Did this exact code turn up somewhere else?\n *\n * The one drift question a machine can close on its own. A file renamed, a\n * function lifted into a new module, a block reordered — the bytes are\n * identical, so the record still describes them, and asking a reader to\n * re-read what they already read would train them to skip the ones that\n * matter.\n *\n * Identity is the stored hash, never a similarity score: \"nearly the same\n * code\" is exactly the case a reader has to judge.\n */\n\n/**\n * How many repository files one search may parse.\n *\n * The search runs on a reassessment path a person is waiting on, and a\n * repository is not bounded. Past the cap the answer is \"not found\", which is\n * the same answer the reader gets today.\n */\nexport const MAX_MOVED_SEARCH_FILES = 2_000;\n\n/**\n * How many candidates are dispatched before the result is checked.\n *\n * The batch is the unit of wasted work: a hit in the first file still costs a\n * whole batch of reads, and a miss in the whole repository costs one round of\n * latency per batch. Large enough that the pool stays fed, small enough that\n * an early hit does not read a repository to find it.\n */\nconst SEARCH_BATCH = 64;\n\nexport type MovedSearch = {\n /**\n * Where this anchor's stored hash turned up, or `undefined`.\n *\n * Shared across every anchor of a run: one `git ls-files`, one parse cache,\n * one set of loaded grammars. A `doctor --drifted` sweep over a base whose\n * records anchor into the same few languages parses each candidate once, not\n * once per drifted anchor.\n */\n find(anchor: KbAnchor): Promise<KbDriftMovedTo | undefined>;\n};\n\nexport type MovedSearchOptions = {\n /** Test seam: replaces the disk reader. */\n reader?: AnchorFileReader;\n /** Test seam: a candidate's byte size, or `null` when it cannot be known. */\n sizeOf?: (file: string) => Promise<number | null>;\n};\n\n/**\n * Repository-wide through tree-sitter, same-file-only without it.\n *\n * The fallback is narrow on purpose. Without a parser there are no definition\n * boundaries, so the only honest search is a sliding window of the recorded\n * line count over one file — which finds a block that moved within its file\n * and nothing else. Widening that to the repository would be a hash collision\n * hunt across every line offset of every file, for an answer no more certain.\n */\nexport function movedSearch(\n repoRoot: string,\n options: MovedSearchOptions = {},\n): MovedSearch {\n const read = options.reader ?? anchorFileReader(repoRoot);\n const sizeOf = options.sizeOf ?? diskSize(repoRoot);\n const resolver = new TreeSitterResolver();\n let repoFiles: Promise<string[]> | undefined;\n const prepared = new Set<string>();\n\n const filesForLanguage = async (language: string): Promise<string[]> => {\n repoFiles ??= listRepoFiles(repoRoot);\n return (await repoFiles)\n .filter((file) => languageForFile(file) === language)\n .slice(0, MAX_MOVED_SEARCH_FILES);\n };\n\n return {\n async find(anchor) {\n const stored = anchor.hash;\n if (!stored) return undefined;\n\n const language = languageForFile(anchor.file);\n // No grammar means no token stream, and an `ast` hash can only be\n // compared against one. Comparing it to a raw hash would be comparing\n // two different measurements and calling a mismatch a move.\n if (!language) return sameFileWindow(anchor, read, stored);\n\n const candidates = await filesForLanguage(language);\n if (!prepared.has(language)) {\n await resolver.prepare(candidates.length ? candidates : [anchor.file]);\n prepared.add(language);\n }\n // A file smaller than the span cannot contain it. One `stat` is far\n // cheaper than a read and a parse, and in a repository of small modules\n // it is most of the candidates.\n const floor = anchor.lines ?? 0;\n\n for (let at = 0; at < candidates.length; at += SEARCH_BATCH) {\n const batch = candidates.slice(at, at + SEARCH_BATCH);\n const hits = await mapLimit(\n batch,\n DEFAULT_IO_CONCURRENCY,\n async (file) => {\n const size = await sizeOf(file);\n // One byte per line is the floor a file of that many lines cannot\n // go under. `null` is \"unknown\", which reads rather than skips.\n if (size !== null && size < floor) return undefined;\n return matchIn(resolver, read, anchor, stored, file);\n },\n );\n // Index order, not completion order: the same repository must always\n // report the same destination.\n const found = hits.find((hit) => hit !== undefined);\n if (found) return found;\n }\n return undefined;\n },\n };\n}\n\n/** The stored hash at some definition in `file`, or `undefined`. */\nasync function matchIn(\n resolver: TreeSitterResolver,\n read: AnchorFileReader,\n anchor: KbAnchor,\n stored: string,\n file: string,\n): Promise<KbDriftMovedTo | undefined> {\n const source = await read(file);\n if (!source.ok) return undefined;\n const normalized = source.source.replace(/\\r\\n/g, \"\\n\");\n\n for (const found of resolver.spans(normalized, file)) {\n // Hashed the way the anchor was stamped: an `ast` hash is only ever\n // compared against a token stream, a raw hash only against raw text.\n const text =\n anchor.hash_kind === \"ast\"\n ? resolver.normalize(found.span.text, file)\n : found.span.text;\n if (text === null || hashAnchorText(text) !== stored) continue;\n // The anchor's own place is where it already looked; finding the hash\n // there would mean it never drifted.\n if (file === anchor.file && found.symbol === anchor.symbol) continue;\n return {\n file,\n symbol: found.symbol,\n startLine: found.span.startLine,\n endLine: found.span.endLine,\n };\n }\n return undefined;\n}\n\n/** `stat` under the repository root; `null` for anything it cannot size. */\nfunction diskSize(repoRoot: string): (file: string) => Promise<number | null> {\n return async (file) => {\n const path = anchorFilePath(repoRoot, file);\n if (path === null) return null;\n try {\n return (await stat(path)).size;\n } catch {\n return null;\n }\n };\n}\n\n/** A block of the recorded line count, at some other offset in the same file. */\nasync function sameFileWindow(\n anchor: KbAnchor,\n read: AnchorFileReader,\n stored: string,\n): Promise<KbDriftMovedTo | undefined> {\n const height = anchor.lines;\n // Without a recorded line count there is no window to slide, and guessing\n // one would make the search's negative answer meaningless. An `ast` hash is\n // over a token stream, which has no line offsets to slide over at all.\n if (!height || anchor.hash_kind === \"ast\") return undefined;\n\n const source = await read(anchor.file);\n if (!source.ok) return undefined;\n const lines = source.source.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n\n for (let at = 0; at + height <= lines.length; at++) {\n if (hashAnchorText(lines.slice(at, at + height).join(\"\\n\")) !== stored) {\n continue;\n }\n return {\n file: anchor.file,\n ...(anchor.symbol ? { symbol: anchor.symbol } : {}),\n startLine: at + 1,\n endLine: at + height,\n };\n }\n return undefined;\n}\n","import {\n anchorFileReader,\n prepareResolvers,\n regexResolver,\n resolveAnchorSpan,\n type AnchorFileReader,\n type AnchorResolver,\n type KbAnchorDriftEntry,\n type KbDriftClass,\n} from \"../anchor-resolver/index.js\";\nimport type { KbAnchor, KbRecord } from \"../kb-record.schema.js\";\nimport { isUncheckedReason } from \"../remote-repo/index.js\";\nimport { TreeSitterResolver } from \"../tree-sitter-resolver/index.js\";\nimport { readOldSource, type OldSourceOrigin } from \"./git.js\";\nimport { movedSearch, type MovedSearch } from \"./moved.js\";\n\n/**\n * Turning \"the bytes changed\" into one of four answers, two of which end the\n * matter.\n *\n * The order is not arbitrary: `moved` is asked first because it is the only\n * class that needs no history at all, and `cosmetic` second because it is the\n * only one that needs the old text. What survives both is what a reader has to\n * read — and the whole point of asking the cheap questions first is that most\n * drift never reaches them.\n *\n * Everything here is read-only. Rebaselining a `moved` anchor is a write, and\n * writes belong to the verb the caller named.\n */\n\nexport type ClassifiedAnchor = {\n anchor: KbAnchor;\n entry: KbAnchorDriftEntry;\n /** Resolved class. Never `undefined` — every reported anchor gets one. */\n class: KbDriftClass;\n /** The anchored text as it stands now. Absent when the class is `gone`. */\n newText?: string;\n /** The anchored text as it was, when history could produce it. */\n oldText?: string;\n oldOrigin?: OldSourceOrigin;\n};\n\nexport type ClassifyOptions = {\n /** Test seam: replaces the disk reader. */\n reader?: AnchorFileReader;\n /** Skip the history read. `cosmetic` cannot be reached without it. */\n withHistory?: boolean;\n /**\n * The run's shared `moved` search. A sweep classifying many records passes\n * one, so the repository is listed once and each candidate file is parsed\n * once for the whole sweep rather than once per record.\n */\n search?: MovedSearch;\n};\n\n/**\n * Refines one record's drift entries. Anchors that matched, or that name\n * another repository, are not drift and never appear.\n */\nexport async function classifyDrift(\n repoRoot: string,\n record: KbRecord,\n entries: readonly KbAnchorDriftEntry[],\n options: ClassifyOptions = {},\n): Promise<ClassifiedAnchor[]> {\n // `detectAnchorDrift` walks the hash-carrying anchors in frontmatter order\n // and emits one entry each, so index is identity here.\n const anchors = (record.frontmatter.strauss_anchors ?? []).filter(\n (anchor) => anchor.hash,\n );\n const reader = options.reader ?? anchorFileReader(repoRoot);\n const treeSitter = new TreeSitterResolver();\n const resolvers: AnchorResolver[] = [treeSitter, regexResolver];\n const search =\n options.search ??\n movedSearch(repoRoot, { ...(options.reader ? { reader } : {}) });\n\n const wanted: { anchor: KbAnchor; entry: KbAnchorDriftEntry }[] = [];\n entries.forEach((entry, at) => {\n const anchor = anchors[at];\n if (!anchor) return;\n if (entry.state === \"match\" || isUncheckedReason(entry.reason)) return;\n wanted.push({ anchor, entry });\n });\n if (!wanted.length) return [];\n\n await prepareResolvers(\n resolvers,\n wanted.map(({ anchor }) => anchor.file),\n );\n\n const out: ClassifiedAnchor[] = [];\n for (const { anchor, entry } of wanted) {\n const movedTo = await search.find(anchor);\n if (movedTo) {\n out.push({\n anchor,\n entry: { ...entry, class: \"moved\", movedTo },\n class: \"moved\",\n });\n continue;\n }\n\n const newText = await currentText(reader, anchor, resolvers);\n const old =\n options.withHistory === false\n ? { ok: false as const, reason: \"unrecoverable\" as const }\n : await readOldSource(repoRoot, anchor);\n const oldText = old.ok ? spanIn(old.source, anchor, resolvers) : undefined;\n\n const settled: KbDriftClass =\n newText !== undefined &&\n oldText !== undefined &&\n sameTokens(treeSitter, anchor.file, oldText, newText)\n ? \"cosmetic\"\n : (entry.class ?? \"changed\");\n\n out.push({\n anchor,\n entry: { ...entry, class: settled },\n class: settled,\n ...(newText !== undefined ? { newText } : {}),\n ...(oldText !== undefined ? { oldText } : {}),\n ...(old.ok ? { oldOrigin: old.origin } : {}),\n });\n }\n return out;\n}\n\n/**\n * Only a parser can say two spellings are one program. Without one — a file\n * with no grammar, or text that will not parse — the answer is no, which\n * leaves the class where it was rather than inventing a reassurance.\n */\nfunction sameTokens(\n resolver: TreeSitterResolver,\n file: string,\n before: string,\n after: string,\n): boolean {\n if (before === after) return false;\n const left = resolver.normalize(before, file);\n const right = resolver.normalize(after, file);\n return left !== null && left === right;\n}\n\nasync function currentText(\n reader: AnchorFileReader,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n): Promise<string | undefined> {\n const read = await reader(anchor.file);\n if (!read.ok) return undefined;\n return spanIn(read.source, anchor, resolvers);\n}\n\n/** The anchor's span within some version of its file, current or committed. */\nfunction spanIn(\n source: string,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n): string | undefined {\n const outcome = resolveAnchorSpan(source, anchor, resolvers);\n return outcome.ok ? outcome.span.text : undefined;\n}\n","/**\n * A unified diff of two spans, bounded on purpose.\n *\n * The packet exists so a reader can judge without opening the repository, and\n * a diff that has to be scrolled past defeats that as surely as no diff at all.\n * Both caps below are line counts rather than bytes, because what a reader\n * runs out of is attention.\n */\n\n/** Never more than this from one anchor, whatever the record's shape. */\nexport const MAX_ANCHOR_DIFF_LINES = 200;\n\n/**\n * Shared across a record's anchors, so a ten-anchor record stays as readable as\n * a one-anchor record is. `kb_reassess`'s size ceiling is a whole-packet\n * number, and only a whole-packet budget can hold it.\n */\nexport const PACKET_DIFF_LINE_BUDGET = 200;\n\n/** Below this an anchor is better dropped than shown as a stub. */\nexport const MIN_ANCHOR_DIFF_LINES = 12;\n\n/** Each anchor's share of the budget, never above the per-anchor cap. */\nexport function diffBudget(anchors: number): number {\n if (anchors <= 0) return MAX_ANCHOR_DIFF_LINES;\n return Math.min(\n MAX_ANCHOR_DIFF_LINES,\n Math.max(\n MIN_ANCHOR_DIFF_LINES,\n Math.floor(PACKET_DIFF_LINE_BUDGET / anchors),\n ),\n );\n}\n\nexport type UnifiedDiff = {\n /** `-`/`+`/` ` prefixed lines, with a `@@` header. */\n text: string;\n added: number;\n removed: number;\n /** Whether the cap cut it short. */\n truncated: boolean;\n};\n\n/**\n * One hunk, no context trimming: the two sides are already a symbol's span,\n * so the whole of both is the context a reader wants.\n *\n * The common subsequence is computed over line *hashes* through a simple\n * O(n·m) table. Spans are bounded by the anchor file cap, and a smarter\n * algorithm would be a second thing to be wrong about for a saving nobody can\n * measure at this size.\n */\nexport function unifiedDiff(\n before: string,\n after: string,\n options: { maxLines?: number; oldLabel?: string; newLabel?: string } = {},\n): UnifiedDiff {\n const max = options.maxLines ?? MAX_ANCHOR_DIFF_LINES;\n const left = before.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n const right = after.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n\n const body: string[] = [];\n let added = 0;\n let removed = 0;\n for (const edit of edits(left, right)) {\n if (edit.kind === \"same\") body.push(` ${edit.line}`);\n else if (edit.kind === \"remove\") {\n body.push(`-${edit.line}`);\n removed += 1;\n } else {\n body.push(`+${edit.line}`);\n added += 1;\n }\n }\n\n const truncated = body.length > max;\n const shown = truncated ? body.slice(0, max) : body;\n const header = `@@ -1,${left.length} +1,${right.length} @@${\n options.oldLabel\n ? ` ${options.oldLabel} → ${options.newLabel ?? \"\"}`.trimEnd()\n : \"\"\n }`;\n const lines = [header, ...shown];\n if (truncated) lines.push(`… ${body.length - max} more diff lines`);\n\n return { text: lines.join(\"\\n\"), added, removed, truncated };\n}\n\ntype Edit = { kind: \"same\" | \"remove\" | \"add\"; line: string };\n\n/** Longest-common-subsequence backtrack, emitted in source order. */\nfunction edits(left: string[], right: string[]): Edit[] {\n const rows = left.length;\n const cols = right.length;\n const table: number[][] = Array.from({ length: rows + 1 }, () =>\n new Array<number>(cols + 1).fill(0),\n );\n for (let row = rows - 1; row >= 0; row--) {\n for (let col = cols - 1; col >= 0; col--) {\n (table[row] as number[])[col] =\n left[row] === right[col]\n ? ((table[row + 1] as number[])[col + 1] as number) + 1\n : Math.max(\n (table[row + 1] as number[])[col] as number,\n (table[row] as number[])[col + 1] as number,\n );\n }\n }\n\n const out: Edit[] = [];\n let row = 0;\n let col = 0;\n while (row < rows && col < cols) {\n if (left[row] === right[col]) {\n out.push({ kind: \"same\", line: left[row] as string });\n row += 1;\n col += 1;\n } else if (\n ((table[row + 1] as number[])[col] as number) >=\n ((table[row] as number[])[col + 1] as number)\n ) {\n out.push({ kind: \"remove\", line: left[row] as string });\n row += 1;\n } else {\n out.push({ kind: \"add\", line: right[col] as string });\n col += 1;\n }\n }\n for (; row < rows; row++)\n out.push({ kind: \"remove\", line: left[row] as string });\n for (; col < cols; col++)\n out.push({ kind: \"add\", line: right[col] as string });\n return out;\n}\n","import type { KbStanding } from \"../adjudicate.js\";\nimport type {\n KbAnchorDriftEntry,\n KbDriftClass,\n KbDriftMovedTo,\n} from \"../anchor-resolver/index.js\";\nimport type { KbRecord, KbRecordType } from \"../kb-record.schema.js\";\nimport type { KbImpactResult } from \"../kb-links/index.js\";\nimport { isKbRecordType, RECORD_TYPES } from \"../record-types.js\";\nimport {\n classifyDrift,\n type ClassifiedAnchor,\n type ClassifyOptions,\n} from \"./classify.js\";\nimport { diffBudget, unifiedDiff } from \"./diff.js\";\n\n/**\n * What a reader needs in order to decide whether a record still holds, without\n * opening the repository.\n *\n * A drift finding today says two hashes disagree, which is not a thing anyone\n * can judge. The packet is the same finding with the three pieces judgment\n * actually takes: what the record claims, what the code did, and what depends\n * on the answer. It stops there — the reading itself is the reader's, and\n * every default below is a starting point the protocol expects to be argued\n * with.\n */\n\nexport type KbReassessDiff =\n | {\n status: \"ok\";\n /** `ref` when the anchor pinned one, `history` when it was inferred. */\n source: \"ref\" | \"history\";\n /** The rev the old side was read at. */\n ref: string;\n unified: string;\n added: number;\n removed: number;\n truncated: boolean;\n }\n /** No committed text to diff against; see `readOldSource`. */\n | { status: \"unrecoverable\" };\n\nexport type KbReassessAnchor = {\n file: string;\n symbol?: string;\n class: KbDriftClass;\n reason?: string;\n storedHash: string;\n currentHash?: string;\n diffSize: number | null;\n movedTo?: KbDriftMovedTo;\n diff?: KbReassessDiff;\n};\n\n/**\n * What the type says about a record whose code changed under it.\n *\n * A `fact` is a claim about the world that the code was the evidence for, so\n * changed evidence presumptively unmakes it. A `decision` is a claim about a\n * choice, and the reasoning for a choice routinely outlives the code that\n * implemented it. Neither is a verdict — they are which way to lean while\n * reading, and naming the lean is what keeps it arguable.\n */\nexport type KbReassessDefault =\n \"presumed-invalidated\" | \"rationale-may-survive\" | \"review\";\n\nconst PRESUMED_INVALID: readonly KbRecordType[] = [\n \"fact\",\n \"constraint\",\n \"contract\",\n];\nconst RATIONALE_SURVIVES: readonly KbRecordType[] = [\"decision\", \"risk\"];\n\nconst DEFAULT_NOTES: Record<KbReassessDefault, string> = {\n \"presumed-invalidated\":\n \"the code this claim was taken from changed; presume it no longer holds until re-read\",\n \"rationale-may-survive\":\n \"the reasoning may outlive the code that implemented it; check whether it does\",\n review: \"re-read the record against the new code\",\n};\n\nexport type KbReassessPacket = {\n conceptId: string;\n title: string | null;\n type: string;\n standing: KbStanding;\n /** What breaks if this record is wrong — the record's `why`, stored as `description`. */\n why: string | null;\n /** The type's claim section — the sentence being reassessed. */\n claim: { section: string; text: string } | null;\n anchors: KbReassessAnchor[];\n /**\n * The record's dependants. A fact that stopped holding did not stop holding\n * alone, and a reader deciding about it is deciding about these too.\n */\n impact: {\n conceptId: string;\n title: string | null;\n standing: KbStanding;\n depth: number;\n }[];\n impactTruncated: boolean;\n default: KbReassessDefault;\n defaultNote: string;\n};\n\nexport type PacketOptions = ClassifyOptions & {\n /** Recover and render the old-vs-new span diff. Off by default: it reads git. */\n withDiff?: boolean;\n impact?: KbImpactResult;\n standing?: KbStanding;\n};\n\n/**\n * One record's packet, or `null` when nothing survived classification.\n *\n * A record whose every drifted anchor turned out to be `moved` or `cosmetic`\n * is a record with no reassessment work, and emitting an empty packet for it\n * would put it back in front of the reader the classification just cleared it\n * from.\n */\nexport async function reassessPacket(\n repoRoot: string,\n record: KbRecord,\n entries: readonly KbAnchorDriftEntry[],\n options: PacketOptions = {},\n): Promise<{\n packet: KbReassessPacket | null;\n classified: ClassifiedAnchor[];\n}> {\n const classified = await classifyDrift(repoRoot, record, entries, {\n ...(options.reader ? { reader: options.reader } : {}),\n ...(options.search ? { search: options.search } : {}),\n withHistory: options.withDiff !== false,\n });\n\n const open = classified.filter(\n (found) => found.class === \"changed\" || found.class === \"gone\",\n );\n if (!open.length) return { packet: null, classified };\n\n const budget = diffBudget(open.length);\n const anchors = open.map((found) =>\n anchorPacket(found, options.withDiff === true, budget),\n );\n\n const type = record.frontmatter.type;\n const fallback: KbReassessDefault = isKbRecordType(type)\n ? PRESUMED_INVALID.includes(type)\n ? \"presumed-invalidated\"\n : RATIONALE_SURVIVES.includes(type)\n ? \"rationale-may-survive\"\n : \"review\"\n : \"review\";\n\n return {\n classified,\n packet: {\n conceptId: record.conceptId,\n title: record.frontmatter.title ?? null,\n type,\n standing: options.standing ?? \"unsettled\",\n why: record.frontmatter.description ?? null,\n claim: claimOf(record),\n anchors,\n impact: (options.impact?.impacted ?? []).map((entry) => ({\n conceptId: entry.conceptId,\n title: entry.title,\n standing: entry.standing,\n depth: entry.depth,\n })),\n impactTruncated: options.impact?.truncated ?? false,\n default: fallback,\n defaultNote: DEFAULT_NOTES[fallback],\n },\n };\n}\n\nfunction anchorPacket(\n found: ClassifiedAnchor,\n withDiff: boolean,\n maxLines: number,\n): KbReassessAnchor {\n const { entry } = found;\n const base: KbReassessAnchor = {\n file: entry.file,\n ...(entry.symbol ? { symbol: entry.symbol } : {}),\n class: found.class,\n ...(entry.reason ? { reason: entry.reason } : {}),\n storedHash: entry.storedHash,\n ...(entry.currentHash ? { currentHash: entry.currentHash } : {}),\n diffSize: entry.diffSize,\n ...(entry.movedTo ? { movedTo: entry.movedTo } : {}),\n };\n if (!withDiff) return base;\n\n if (found.oldText === undefined || !found.oldOrigin) {\n return { ...base, diff: { status: \"unrecoverable\" } };\n }\n // A `gone` anchor has no new side; the diff is the whole old span removed,\n // which is exactly what the reader has to weigh.\n const rendered = unifiedDiff(found.oldText, found.newText ?? \"\", {\n maxLines,\n });\n return {\n ...base,\n diff: {\n status: \"ok\",\n source: found.oldOrigin.kind,\n ref: found.oldOrigin.ref,\n unified: rendered.text,\n added: rendered.added,\n removed: rendered.removed,\n truncated: rendered.truncated,\n },\n };\n}\n\n/**\n * The first section of the record's type — its central claim, per the type\n * table — pulled out of the body so the packet carries the sentence being\n * judged rather than the whole record.\n */\nfunction claimOf(record: KbRecord): { section: string; text: string } | null {\n const type = record.frontmatter.type;\n const section = isKbRecordType(type)\n ? RECORD_TYPES[type].sections[0]\n : undefined;\n if (!section) return null;\n\n const lines = record.body.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n const start = lines.findIndex(\n (line) => line.trim().toLowerCase() === `## ${section}`.toLowerCase(),\n );\n if (start < 0) return null;\n const rest = lines.slice(start + 1);\n const end = rest.findIndex((line) => line.startsWith(\"## \"));\n const text = (end < 0 ? rest : rest.slice(0, end)).join(\"\\n\").trim();\n return text ? { section, text } : null;\n}\n","import { KB_CONCEPT_ID_PATTERN, type KbRecord } from \"./kb-record.schema.js\";\nimport { KB_LINK_RELS } from \"./record-types.js\";\n\n/**\n * The edges between records in one bundle, defined once.\n *\n * Both walks — `trace` and `pack` — consume this module, so they cannot drift\n * into disagreeing about what makes two records neighbours, and a diagnostic\n * pass over the graph can reuse the same definition.\n *\n * There is no separate `related` kind: compose.ts renders `relatedConceptIds`\n * as body links (`Relates to [id](id.md).`), so in stored form a related edge\n * IS a body link, and a distinct kind would count the same markdown twice.\n *\n * `typed-link` is not that case, despite compose.ts also rendering a sentence\n * per link. The edge is `strauss_links` in the frontmatter — the authoritative,\n * typed form — and the sentence is its rendering for a reader that only knows\n * OKF. A record can carry the frontmatter without the prose (hand-written, or\n * from a producer we did not write), so reading only the body would miss it.\n * A pair connected both ways comes back with both kinds in `via`, which is the\n * honest answer: it was declared, and it was written about.\n *\n * `body-link` and `typed-link` are DIRECTED — the edges a record itself makes,\n * read off its own body or frontmatter. `supersession`, `anchor` and `source`\n * are symmetric: they hold between two records because both name the same\n * thing, so either end sees the other. Callers wanting the inbound half of a\n * typed edge use `kb-links/` (`kb_backlinks`, `kb_impact`) rather than this\n * module, which answers \"what does this record point at\".\n */\nexport const KB_EDGE_KINDS = [\n \"body-link\",\n \"typed-link\",\n \"supersession\",\n \"anchor\",\n \"source\",\n] as const;\n\nexport type KbEdgeKind = (typeof KB_EDGE_KINDS)[number];\n\nexport type KbNeighbour = {\n record: KbRecord;\n /** Every edge kind that connects it to the record asked about. */\n via: KbEdgeKind[];\n};\n\n// The target of any markdown link whose href is a record filename:\n// `](<concept-id>.md)`. Built from the id pattern with its anchors stripped so\n// the id can be matched mid-body.\nconst BODY_LINK_TARGET = new RegExp(\n `\\\\]\\\\((${KB_CONCEPT_ID_PATTERN.source.replace(/^\\^|\\$$/g, \"\")})\\\\.md\\\\)`,\n \"g\",\n);\n\n/**\n * Which rels a `typed-link` walk may follow.\n *\n * Defaults to the whole known vocabulary — including `related_to`, since a\n * neighbourhood is the one place a bibliography belongs. It never includes an\n * unknown rel: a rel outside the vocabulary is not a claim any walk can\n * interpret, so no walk traverses it anywhere, and `kb_validate` reports it as\n * an error rather than a walk quietly acting on it.\n */\nexport const DEFAULT_TYPED_LINK_RELS: readonly string[] = KB_LINK_RELS;\n\n/**\n * Every record `from` touches, each carrying the full set of edge kinds that\n * connect the pair. Order is deterministic: bundle order per kind, kinds in\n * the order given.\n */\nexport function neighbours(\n from: KbRecord,\n bundle: KbRecord[],\n kinds: readonly KbEdgeKind[] = KB_EDGE_KINDS,\n linkRels: readonly string[] = DEFAULT_TYPED_LINK_RELS,\n): KbNeighbour[] {\n const found = new Map<string, KbNeighbour>();\n for (const kind of kinds) {\n for (const record of edgeNeighbours(from, bundle, kind, linkRels)) {\n const existing = found.get(record.conceptId);\n if (existing) {\n if (!existing.via.includes(kind)) existing.via.push(kind);\n continue;\n }\n found.set(record.conceptId, { record, via: [kind] });\n }\n }\n return [...found.values()];\n}\n\n/**\n * The records one edge kind connects `from` to, in bundle order.\n *\n * `linkRels` narrows the `typed-link` kind and is ignored by the others —\n * `trace` passes the causal rels, `pack` takes the default.\n */\nexport function edgeNeighbours(\n from: KbRecord,\n bundle: KbRecord[],\n kind: KbEdgeKind,\n linkRels: readonly string[] = DEFAULT_TYPED_LINK_RELS,\n): KbRecord[] {\n switch (kind) {\n // A link whose target is not in the bundle is legal per compose.ts —\n // records are routinely written before the ones they point at exist — so\n // missing targets are skipped, never an error.\n case \"body-link\": {\n const targets = new Set(\n [...from.body.matchAll(BODY_LINK_TARGET)].map((match) => match[1]),\n );\n if (!targets.size) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n targets.has(candidate.conceptId),\n );\n }\n\n // Outbound only, like `body-link`, and for the same reason: this is what\n // the record declares about itself. A missing target is legal — the walk\n // skips it, and `kb_validate` is what reports it as a warning. A rel\n // outside `linkRels` is skipped too, which is how an unknown rel stays\n // untraversable everywhere rather than one walk at a time.\n case \"typed-link\": {\n const allowed = new Set(linkRels);\n const targets = new Set(\n (from.frontmatter.strauss_links ?? [])\n .filter((link) => allowed.has(link.rel))\n .map((link) => link.target),\n );\n if (!targets.size) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n targets.has(candidate.conceptId),\n );\n }\n\n // Both directions and both pointers: `supersede()` writes the pair, but a\n // hand-edit can leave one side behind, and a walk trusting one pointer\n // would miss a replacement the bundle openly declares.\n case \"supersession\":\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n (candidate.conceptId === from.frontmatter.strauss_superseded_by ||\n from.frontmatter.strauss_supersedes?.includes(\n candidate.conceptId,\n ) ||\n candidate.frontmatter.strauss_superseded_by === from.conceptId ||\n candidate.frontmatter.strauss_supersedes?.includes(from.conceptId)),\n );\n\n // The edge that answers \"why is this code shaped this way\": every record\n // attached to the same file or symbol, whatever its standing.\n case \"anchor\": {\n const mine = from.frontmatter.strauss_anchors ?? [];\n if (!mine.length) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n (candidate.frontmatter.strauss_anchors ?? []).some((theirs) =>\n mine.some((ours) => anchorsTouch(ours, theirs)),\n ),\n );\n }\n\n case \"source\": {\n const mine = new Set((from.frontmatter.sources ?? []).map((s) => s.id));\n if (!mine.size) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n (candidate.frontmatter.sources ?? []).some((source) =>\n mine.has(source.id),\n ),\n );\n }\n }\n}\n\n/**\n * Two anchors touch when they name the same file and do not name different\n * symbols within it.\n *\n * An anchor without a symbol means \"this record is about this file\", so it\n * relates to everything anchored inside it. Requiring an exact match instead\n * would hide the file-level record from every symbol-level walk, which is the\n * direction a reviewer actually reads.\n */\nfunction anchorsTouch(\n left: { file: string; symbol?: string },\n right: { file: string; symbol?: string },\n): boolean {\n if (left.file !== right.file) return false;\n if (!left.symbol || !right.symbol) return true;\n return left.symbol === right.symbol;\n}\n","import { isCanonicalRepoUrl } from \"./anchor-resolver/index.js\";\nimport { KB_CONCEPT_ID_PATTERN, type KbRecord } from \"./kb-record.schema.js\";\nimport { isKbLinkRel, isKbRecordType, KB_LINK_RELS } from \"./record-types.js\";\n\n/** `error` fails the check; `warning` does not. */\nexport type KbValidationSeverity = \"error\" | \"warning\";\n\nexport type KbValidationProblem = {\n check: string;\n conceptId: string;\n note: string;\n severity: KbValidationSeverity;\n};\n\n/**\n * Checks that only hold across the whole bundle: whether one record's pointers\n * agree with another's. Per-record shape is the schema's job, enforced on every\n * read, so nothing here re-states it.\n */\nexport function validateBundle(records: KbRecord[]): KbValidationProblem[] {\n const byId = new Map(records.map((record) => [record.conceptId, record]));\n const problems: KbValidationProblem[] = [];\n const report = (\n check: string,\n conceptId: string,\n note: string,\n severity: KbValidationSeverity = \"error\",\n ) => problems.push({ check, conceptId, note, severity });\n\n for (const record of records) {\n const { conceptId, frontmatter: fm } = record;\n\n // OKF permits any `type`, so an unrecognised one is a note, not a failure:\n // another producer may legitimately be writing into this bundle.\n if (!isKbRecordType(fm.type)) {\n report(\"type\", conceptId, `unrecognised type \"${fm.type}\"`);\n }\n\n if (fm.strauss_status === \"superseded\") {\n const by = fm.strauss_superseded_by;\n if (!by) {\n report(\"superseded_by\", conceptId, \"superseded with no replacement\");\n } else if (!byId.has(by)) {\n report(\"superseded_by\", conceptId, `replacement ${by} is missing`);\n } else if (\n !byId.get(by)?.frontmatter.strauss_supersedes?.includes(conceptId)\n ) {\n report(\"backlink\", by, `does not list ${conceptId} in supersedes`);\n }\n }\n\n for (const old of fm.strauss_supersedes ?? []) {\n const previous = byId.get(old);\n if (!previous) {\n report(\"supersedes\", conceptId, `target ${old} is missing`);\n } else if (previous.frontmatter.strauss_status !== \"superseded\") {\n report(\"supersedes\", conceptId, `${old} is not marked superseded`);\n }\n }\n\n for (const link of fm.strauss_links ?? []) {\n // The vocabulary is closed, and this is where that is enforced. An\n // unknown rel is not a record another producer wrote in good faith the\n // way an unknown `type` is — `rel` is this package's own extension, so\n // there is no spec under which a foreign spelling is legitimate, and\n // every walk over the graph would silently skip it.\n if (!isKbLinkRel(link.rel)) {\n report(\n \"link_rel\",\n conceptId,\n `unknown rel \"${link.rel}\" on link to ${link.target} — expected one of ${KB_LINK_RELS.join(\", \")}`,\n );\n }\n\n // A target is an error or a warning depending on whether time can fix\n // it. An id that does not match the concept-id pattern can never name a\n // record — no write could produce that filename — so it is a defect\n // now and forever. A well-formed id that is simply absent is the\n // ordinary state of a base being written, and the same tolerance body\n // links already have.\n if (!KB_CONCEPT_ID_PATTERN.test(link.target)) {\n report(\n \"link_target\",\n conceptId,\n `target \"${link.target}\" is not a valid concept id — expected <type>.<slug>, both kebab-case`,\n );\n } else if (link.target === conceptId) {\n // The composer refuses this outright; reaching it means a hand-edit,\n // and a self-link is inert rather than wrong — nothing traverses it.\n report(\n \"link_target\",\n conceptId,\n `links to itself (${link.rel})`,\n \"warning\",\n );\n } else if (!byId.has(link.target)) {\n report(\n \"link_target\",\n conceptId,\n `target ${link.target} is not in the bundle`,\n \"warning\",\n );\n }\n }\n\n // A short `repo` names a repository without saying where it lives, so a\n // foreign anchor carrying one can never be fetched. A warning, not an\n // error: it still matches this root's own origin, and records are never\n // rewritten under an author.\n for (const anchor of fm.strauss_anchors ?? []) {\n if (anchor.repo && !isCanonicalRepoUrl(anchor.repo)) {\n report(\n \"anchor_repo\",\n conceptId,\n `anchor repo \"${anchor.repo}\" is not a full remote URL, so it cannot be resolved against a remote`,\n \"warning\",\n );\n }\n }\n\n // An assumption with sources is a fact that forgot to change its mind.\n if (fm.strauss_assumption && fm.sources?.length) {\n report(\"assumption\", conceptId, \"marked an assumption but cites sources\");\n }\n }\n\n return problems;\n}\n","import {\n adjudicate,\n type KbStanding,\n type KbWarning,\n type KbWarningAnchor,\n} from \"./adjudicate.js\";\nimport type { KbAnchorDriftEntry } from \"./anchor-resolver/index.js\";\nimport { edgeNeighbours } from \"./kb-edges.js\";\nimport type { KbRecord, KbRecordStatus } from \"./kb-record.schema.js\";\nimport { validateBundle } from \"./validate.js\";\n\n/**\n * A health sweep over a whole base — read-only, and never a mutation.\n *\n * Every other read answers a question a caller already had. This one asks the\n * questions nobody thinks to: which records the calendar has already retired,\n * which nobody ever confirmed, which have been open long enough that \"open\" is\n * now the answer, and which the graph has quietly dropped on the floor. Those\n * decay silently, because a stale record reads exactly like a live one and a\n * question nobody answered reads exactly like one nobody asked.\n *\n * Grouped and counted rather than merged into one list: the eight checks are\n * eight different repairs — re-verify, re-date, answer, link, supersede, or\n * re-anchor — and a flat list of \"problems\" would leave the reader sorting\n * them again.\n *\n * Every group is emitted even when empty. A check that found nothing and a\n * check that never ran look identical in a report that only lists findings,\n * and the difference is the whole value of a sweep.\n */\n\nexport const DEFAULT_EXPIRING_DAYS = 30;\nexport const DEFAULT_UNVERIFIED_DAYS = 90;\nexport const DEFAULT_AGING_DAYS = 90;\n\nexport const KB_DOCTOR_CHECKS = [\n \"expired\",\n \"expiring\",\n \"unverified\",\n \"aging\",\n \"orphaned\",\n \"broken-supersession\",\n \"superseded-but-cited\",\n \"drifted\",\n \"unchecked\",\n] as const;\n\nexport type KbDoctorCheck = (typeof KB_DOCTOR_CHECKS)[number];\n\n/** What each check looks for, in the words the report prints. */\nconst CHECK_HEADLINES: Record<KbDoctorCheck, string> = {\n expired: \"past its stale_after date\",\n expiring: \"stale_after falls within the window\",\n unverified: \"nobody has ever confirmed it, and it is old enough to matter\",\n aging: \"still open or still proposed long after it was written\",\n orphaned: \"no other record links to it\",\n \"broken-supersession\": \"the supersession pointers do not resolve\",\n \"superseded-but-cited\":\n \"a live record's body links to one that no longer holds\",\n drifted: \"the code an anchor points at moved out from under its hash\",\n unchecked: \"an anchor in another repository nothing could reach\",\n};\n\nexport type KbDoctorFinding = {\n conceptId: string;\n title: string | null;\n status: KbRecordStatus;\n /** Why this record is in this group, in one phrase a reader can act on. */\n note: string;\n};\n\nexport type KbDoctorGroup = {\n check: KbDoctorCheck;\n /** What the check looks for, so a zero count still says something. */\n headline: string;\n count: number;\n findings: KbDoctorFinding[];\n};\n\nexport type KbDoctorThresholds = {\n expiringDays: number;\n unverifiedDays: number;\n agingDays: number;\n};\n\nexport type KbDoctorReport = {\n recordCount: number;\n thresholds: KbDoctorThresholds;\n counts: Record<KbDoctorCheck, number>;\n /** All eight, in `KB_DOCTOR_CHECKS` order, empty ones included. */\n groups: KbDoctorGroup[];\n findingCount: number;\n healthy: boolean;\n /**\n * Anchors carrying a hash, by the resolver that produced it. A heuristic\n * span is weaker evidence than a parsed one, so a base still leaning on the\n * regex resolver is worth re-resolving. Not a finding: a regex-stamped\n * anchor is not broken.\n */\n anchorResolvers: KbAnchorResolverCounts;\n};\n\nexport type KbAnchorResolverCounts = {\n total: number;\n treeSitter: number;\n /** Includes anchors stamped before resolvers were named. */\n regex: number;\n};\n\nexport type KbDoctorOptions = {\n /** How far ahead `expiring` looks. */\n expiringDays?: number;\n /** How old an unconfirmed record must be before `unverified` reports it. */\n unverifiedDays?: number;\n /** How long `open` or `proposed` may stand before `aging` reports it. */\n agingDays?: number;\n now?: Date;\n /**\n * Anchor drift, precomputed by the caller. `doctor` stays pure and sync for\n * the same reason `adjudicate` does — the filesystem work of re-resolving\n * anchors belongs to `detectAnchorDrift`, and a sweep with no map simply\n * reports the `drifted` check as clean rather than half-running it.\n */\n anchorDrift?: Map<string, KbAnchorDriftEntry[]>;\n};\n\nconst DAY_MS = 86_400_000;\n\n/** A whole-file anchor names no resolver, so only symbol anchors are counted. */\nfunction anchorResolverCounts(bundle: KbRecord[]): KbAnchorResolverCounts {\n let treeSitter = 0;\n let regex = 0;\n for (const record of bundle) {\n for (const anchor of record.frontmatter.strauss_anchors ?? []) {\n if (!anchor.hash || !anchor.symbol) continue;\n if (anchor.resolver === \"tree-sitter\") treeSitter += 1;\n else regex += 1;\n }\n }\n return { total: treeSitter + regex, treeSitter, regex };\n}\n\nexport function doctor(\n bundle: KbRecord[],\n options: KbDoctorOptions = {},\n): KbDoctorReport {\n const thresholds: KbDoctorThresholds = {\n expiringDays: options.expiringDays ?? DEFAULT_EXPIRING_DAYS,\n unverifiedDays: options.unverifiedDays ?? DEFAULT_UNVERIFIED_DAYS,\n agingDays: options.agingDays ?? DEFAULT_AGING_DAYS,\n };\n const now = options.now ?? new Date();\n\n const adjudicated = adjudicate(bundle, bundle, now, options.anchorDrift);\n const standings = new Map<string, KbStanding>(\n adjudicated.map((hit) => [hit.record.conceptId, hit.standing]),\n );\n // Superseded and rejected records are already out of force: a replaced\n // record whose date has passed needs no repair, and reporting one would\n // bury the records that do.\n const inForce = adjudicated.filter(\n (hit) => hit.standing !== \"superseded\" && hit.standing !== \"rejected\",\n );\n\n const groups: KbDoctorGroup[] = [\n group(\"expired\", expired(inForce, now)),\n group(\"expiring\", expiring(inForce, now, thresholds.expiringDays)),\n group(\"unverified\", unverified(inForce, now, thresholds.unverifiedDays)),\n group(\"aging\", aging(inForce, now, thresholds.agingDays)),\n group(\"orphaned\", orphaned(bundle)),\n group(\"broken-supersession\", brokenSupersession(bundle, adjudicated)),\n group(\"superseded-but-cited\", supersededButCited(bundle, standings)),\n group(\"drifted\", drifted(inForce)),\n group(\"unchecked\", unchecked(inForce)),\n ];\n\n const counts = Object.fromEntries(\n groups.map((entry) => [entry.check, entry.count]),\n ) as Record<KbDoctorCheck, number>;\n const findingCount = groups.reduce((total, entry) => total + entry.count, 0);\n\n return {\n recordCount: bundle.length,\n thresholds,\n counts,\n groups,\n findingCount,\n anchorResolvers: anchorResolverCounts(bundle),\n healthy: findingCount === 0,\n };\n}\n\nfunction group(\n check: KbDoctorCheck,\n findings: KbDoctorFinding[],\n): KbDoctorGroup {\n return {\n check,\n headline: CHECK_HEADLINES[check],\n count: findings.length,\n findings,\n };\n}\n\n/**\n * An unreadable `stale_after` counts as expired rather than being skipped.\n * A date nobody can parse is a date nobody can trust, and treating it as\n * absent would silently exempt the record from the only check that ages it.\n *\n * `stale_after` is written date-only, which `Date.parse` reads as UTC\n * midnight — so a record goes stale at the start of its date, and a sweep run\n * at 00:00:00Z on that very date still counts it as expiring rather than\n * expired. That is `adjudicate`'s comparison, not a second one: two readings\n * of the same field disagreeing about the day would be worse than either.\n */\nfunction expired(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const raw = hit.record.frontmatter.stale_after;\n if (!raw) continue;\n const at = Date.parse(raw);\n if (Number.isNaN(at)) {\n findings.push(\n finding(hit.record, `stale_after \"${raw}\" is not a readable date`),\n );\n continue;\n }\n if (at < now.getTime()) {\n findings.push(\n finding(\n hit.record,\n `stale since ${raw} (${daysBetween(at, now.getTime())} days ago)`,\n ),\n );\n }\n }\n return findings;\n}\n\nfunction expiring(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n withinDays: number,\n): KbDoctorFinding[] {\n const horizon = now.getTime() + withinDays * DAY_MS;\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const raw = hit.record.frontmatter.stale_after;\n if (!raw) continue;\n const at = Date.parse(raw);\n if (Number.isNaN(at) || at < now.getTime() || at > horizon) continue;\n findings.push(\n finding(\n hit.record,\n `goes stale ${raw} (in ${daysBetween(now.getTime(), at)} days)`,\n ),\n );\n }\n return findings;\n}\n\n/**\n * Age is read from `generated.at`, so a record carrying no timestamp is not\n * reported: this check is about how long something has gone unconfirmed, and\n * without a start there is no duration. `kb_query` still warns `unverified` on\n * every such record at read time, which is where the timeless case belongs.\n */\nfunction unverified(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n olderThanDays: number,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n if (hit.record.frontmatter.verified?.length) continue;\n const age = ageInDays(hit.record, now);\n if (age === null || age <= olderThanDays) continue;\n findings.push(\n finding(hit.record, `never verified, written ${age} days ago`),\n );\n }\n return findings;\n}\n\n/**\n * One group for both spellings of the same decay. An `open` question and a\n * `proposed` decision are the same debt — something was raised and never\n * settled — and splitting them would make the reader check two places for one\n * repair.\n */\nfunction aging(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n olderThanDays: number,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const status = hit.record.frontmatter.strauss_status;\n if (status !== \"open\" && status !== \"proposed\") continue;\n const age = ageInDays(hit.record, now);\n if (age === null || age <= olderThanDays) continue;\n findings.push(\n finding(\n hit.record,\n status === \"open\"\n ? `open for ${age} days`\n : `proposed ${age} days ago and still unsettled`,\n ),\n );\n }\n return findings.sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n}\n\n/**\n * Incoming edges only, and over every record whatever its standing.\n *\n * \"Links to\" is directional: a record that cites five others and is cited by\n * none is precisely the island this names — reachable if you already know it\n * exists, which is the thing nobody does. Standing is not a filter here\n * because the question is about the graph, not about force: a rejected record\n * nothing points at is as lost as a current one.\n *\n * Supersession is read in one direction only — the replacement references what\n * it replaced, never the other way. `kb-edges` deliberately reports the pair\n * symmetrically, which is right for a walk and wrong here: taken symmetrically,\n * a dead record vouches for its own replacement, so an old→new pair nothing\n * else touches would rescue itself and never report. Read one way, the\n * replaced record stays reachable through its history and the replacement has\n * to earn its own inbound link.\n */\nfunction orphaned(bundle: KbRecord[]): KbDoctorFinding[] {\n const present = new Set(bundle.map((record) => record.conceptId));\n const referenced = new Set<string>();\n for (const record of bundle) {\n for (const neighbour of edgeNeighbours(record, bundle, \"body-link\")) {\n referenced.add(neighbour.conceptId);\n }\n // Both spellings of one statement — \"X replaced R\" — whichever side of the\n // pair stores it. Either way it is X that references R.\n for (const replaced of record.frontmatter.strauss_supersedes ?? []) {\n referenced.add(replaced);\n }\n const replacement = record.frontmatter.strauss_superseded_by;\n if (replacement && present.has(replacement)) {\n referenced.add(record.conceptId);\n }\n }\n return bundle\n .filter((record) => !referenced.has(record.conceptId))\n .map((record) => finding(record, \"no other record links to it\"));\n}\n\n/**\n * The cross-record supersession checks `validate` already owns, plus the two\n * shapes only a chain walk can see: a cycle, and a fork where two records both\n * claim to replace one. Re-deriving the first set here would give the two\n * commands room to disagree about what a broken chain is.\n *\n * \"Superseded with nothing surviving\" is not a third clause: a chain ends\n * empty only when a pointer is absent, missing, or cyclic, and all three are\n * already reported above — a second phrasing of the same defect would read as\n * two problems to repair.\n */\nconst SUPERSESSION_CHECKS = new Set([\n \"superseded_by\",\n \"supersedes\",\n \"backlink\",\n]);\n\nfunction brokenSupersession(\n bundle: KbRecord[],\n adjudicated: ReturnType<typeof adjudicate>,\n): KbDoctorFinding[] {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const findings: KbDoctorFinding[] = [];\n const seen = new Set<string>();\n const add = (record: KbRecord, note: string) => {\n const key = `${record.conceptId}\\u0000${note}`;\n if (seen.has(key)) return;\n seen.add(key);\n findings.push(finding(record, note));\n };\n\n for (const problem of validateBundle(bundle)) {\n if (!SUPERSESSION_CHECKS.has(problem.check)) continue;\n const record = byId.get(problem.conceptId);\n if (record) add(record, problem.note);\n }\n\n // Both `validate` and the chain walk below reach a `strauss_superseded_by`\n // only through a record whose status is already `superseded` — so a record\n // left `accepted` while pointing at a replacement is invisible to both, and\n // adjudication reads it as current no matter what the pointer says. That is\n // precisely the hand-edit this check exists for: the store writes the status\n // and the pointer in one mutation, so the two can only disagree off-tool.\n for (const record of bundle) {\n const replacement = record.frontmatter.strauss_superseded_by;\n if (!replacement) continue;\n if (!byId.has(replacement)) {\n add(record, `replacement ${replacement} is missing`);\n } else if (record.frontmatter.strauss_status !== \"superseded\") {\n add(\n record,\n `names ${replacement} as its replacement but is not marked superseded`,\n );\n }\n }\n\n for (const hit of adjudicated) {\n for (const warning of hit.warnings) {\n if (warning.kind === \"broken-chain\") {\n add(hit.record, `replacement ${warning.missing} is missing`);\n } else if (warning.kind === \"chain-cycle\") {\n add(\n hit.record,\n `supersession chain cycles through ${warning.through.join(\" → \")}`,\n );\n } else if (warning.kind === \"forked-chain\") {\n add(\n hit.record,\n `two records claim to replace it: ${warning.heads.join(\", \")}`,\n );\n }\n }\n }\n\n return findings.sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n}\n\n/**\n * A live record whose body points at a record that no longer holds.\n *\n * The most quietly wrong state in a base: the citing record is current, so a\n * reader trusts it, and the link reads as support for a claim its target has\n * already stopped making. One finding per pair, because each is its own edit.\n *\n * Rejected targets count as well as superseded ones. The check's name is for\n * the common case, but the failure is \"cites something that no longer holds\",\n * and a live record citing a rejected one is the worse half — a superseded\n * record at least names its replacement, while a rejected one is a well-formed\n * assertion of what someone decided *not* to do.\n *\n * A record citing the very record it replaced is exempt. That link is the\n * history working as designed — `relatedConceptIds` on a superseding write\n * renders as exactly this edge — and reporting it would put a finding on every\n * correctly performed supersession.\n */\nfunction supersededButCited(\n bundle: KbRecord[],\n standings: Map<string, KbStanding>,\n): KbDoctorFinding[] {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const findings: KbDoctorFinding[] = [];\n for (const record of bundle) {\n const standing = standings.get(record.conceptId);\n if (standing === \"superseded\" || standing === \"rejected\") continue;\n for (const target of edgeNeighbours(record, bundle, \"body-link\")) {\n const targetStanding = standings.get(target.conceptId);\n if (targetStanding !== \"superseded\" && targetStanding !== \"rejected\") {\n continue;\n }\n if (replaces(record, target)) continue;\n const replacement = target.frontmatter.strauss_superseded_by;\n findings.push(\n finding(\n record,\n `cites ${targetStanding} ${target.conceptId}${\n targetStanding === \"superseded\" &&\n replacement &&\n byId.has(replacement)\n ? ` — replaced by ${replacement}`\n : \"\"\n }`,\n ),\n );\n }\n }\n return findings;\n}\n\n/**\n * Records whose anchors no longer resolve to the code they were hashed\n * against — read off the `drifted` warning `adjudicate` already attaches, so\n * the sweep and every read path agree about what drift is. Recomputing the\n * comparison here would give the two room to disagree.\n *\n * In-force records only. A superseded record anchoring code that has since\n * moved is the expected outcome of it being replaced, not a repair.\n *\n * Unresolvable anchors ride in this group rather than a check of their own:\n * the repair is the same edit, and the note says which happened.\n */\nfunction drifted(hits: ReturnType<typeof adjudicate>): KbDoctorFinding[] {\n return anchorFindings(hits, \"drifted\", (count) =>\n count === 1 ? \"anchor no longer matches\" : \"anchors no longer match\",\n );\n}\n\n/**\n * Anchors in another repository that nothing could read — unreachable, refused,\n * or offline. Its own group because the repair is not an edit to the record:\n * a reader who cannot tell \"unchecked\" from \"clean\" trusts a base nobody\n * checked.\n */\nfunction unchecked(hits: ReturnType<typeof adjudicate>): KbDoctorFinding[] {\n return anchorFindings(hits, \"unchecked\", (count) =>\n count === 1 ? \"anchor was not checked\" : \"anchors were not checked\",\n );\n}\n\n/** Anchor findings grouped by repository, so one unreachable remote reads as one cause. */\nfunction anchorFindings(\n hits: ReturnType<typeof adjudicate>,\n kind: \"drifted\" | \"unchecked\",\n headline: (count: number) => string,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const warning = hit.warnings.find(\n (entry): entry is Extract<KbWarning, { anchors: KbWarningAnchor[] }> =>\n entry.kind === kind,\n );\n if (!warning) continue;\n const byRepo = new Map<string, string[]>();\n for (const anchor of warning.anchors) {\n const repo = anchor.repo ?? \"\";\n byRepo.set(repo, [...(byRepo.get(repo) ?? []), describeAnchor(anchor)]);\n }\n const detail = [...byRepo.entries()].map(([repo, entries]) =>\n repo ? `${repo}: ${entries.join(\", \")}` : entries.join(\", \"),\n );\n findings.push(\n finding(\n hit.record,\n `${warning.anchors.length} ${headline(warning.anchors.length)}: ${detail.join(\"; \")}`,\n ),\n );\n }\n return findings.sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n}\n\nfunction describeAnchor(anchor: KbWarningAnchor): string {\n const at = anchor.symbol ? `${anchor.file}:${anchor.symbol}` : anchor.file;\n if (anchor.class === \"gone\") {\n return `${at} gone${anchor.reason ? ` (${anchor.reason})` : \"\"}`;\n }\n if (anchor.reason) return `${at} (${anchor.reason})`;\n if (anchor.remoteState === \"drifted-on-default\") {\n return `${at} (matches ref, moved on the default branch)`;\n }\n if (anchor.diffSize === null) return `${at} (changed, size unrecorded)`;\n // A same-size rewrite is the drift most worth naming plainly:\n // \"0 lines apart\" reads as \"nothing happened\".\n return anchor.diffSize === 0\n ? `${at} (content changed, same line count)`\n : `${at} (${anchor.diffSize} line${anchor.diffSize === 1 ? \"\" : \"s\"} apart)`;\n}\n\n/** Either pointer saying `later` is what stands in `earlier`'s place. */\nfunction replaces(later: KbRecord, earlier: KbRecord): boolean {\n return (\n (later.frontmatter.strauss_supersedes ?? []).includes(earlier.conceptId) ||\n earlier.frontmatter.strauss_superseded_by === later.conceptId\n );\n}\n\nfunction finding(record: KbRecord, note: string): KbDoctorFinding {\n return {\n conceptId: record.conceptId,\n title: record.frontmatter.title ?? null,\n status: record.frontmatter.strauss_status,\n note,\n };\n}\n\n/** Whole days between two instants, never negative. */\nfunction daysBetween(from: number, to: number): number {\n return Math.max(0, Math.floor((to - from) / DAY_MS));\n}\n\nfunction ageInDays(record: KbRecord, now: Date): number | null {\n const at = record.frontmatter.generated?.at;\n if (!at) return null;\n const written = Date.parse(at);\n if (Number.isNaN(written)) return null;\n return daysBetween(written, now.getTime());\n}\n","import { z } from \"zod\";\nimport { adjudicate } from \"../adjudicate.js\";\nimport { reassessPacket, type KbReassessPacket } from \"../drift/index.js\";\nimport { KbRecordNotFoundError } from \"../kb-errors.js\";\nimport { assertBaseNotFrozen, KbBaseFrozenError } from \"../kb-pins/index.js\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport { argvFlag, bundlePath, conceptId, define, REPO_ROOT } from \"./model.js\";\n\n/** One anchor whose code turned up unchanged elsewhere, and where. */\nexport type KbRebaselinedAnchor = {\n file: string;\n symbol?: string;\n toFile: string;\n toSymbol?: string;\n};\n\nexport type KbReassessResult = {\n conceptId: string;\n /** `null` when nothing survived classification — the record needs no reading. */\n packet: KbReassessPacket | null;\n rebaselined: KbRebaselinedAnchor[];\n /** Anchors whose only change was formatting. Reported, never read. */\n cosmetic: number;\n frozen?: true;\n note?: string;\n};\n\nexport const reassessCommand = define({\n name: \"reassess\",\n tool: \"kb_reassess\",\n usage: \"reassess <concept-id> [--repo-root <path>] [--with-diff]\",\n description:\n \"One drifted record, as something to judge: its claim, each anchor's drift class, the old-vs-new span diff, and the records that depend on it. Formatting-only drift is dropped. Empty when there is nothing to reassess. Writes: relocates moved anchors, keeping their hash; never verifies, supersedes, or changes standing.\",\n input: z.object({\n bundlePath,\n conceptId,\n repoRoot: REPO_ROOT,\n withDiff: z\n .boolean()\n .optional()\n .describe(\n \"Recover each anchor's committed span and render the diff. Reads git history.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const repoRoot = argvFlag(argv, \"--repo-root\");\n return {\n bundlePath: path,\n conceptId: argv[1],\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n ...(argv.includes(\"--with-diff\") ? { withDiff: true } : {}),\n };\n },\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, repoRoot, withDiff },\n ): Promise<KbReassessResult> => {\n const root = repoRoot ?? process.cwd();\n const bundle = await store.list(path);\n const record = bundle.find((entry) => entry.conceptId === id);\n if (!record) throw new KbRecordNotFoundError(id);\n\n const drift = await store.detectDrift([record], repoRoot);\n const entries = drift?.get(id) ?? [];\n if (!entries.some((entry) => entry.state !== \"match\")) {\n return { conceptId: id, packet: null, rebaselined: [], cosmetic: 0 };\n }\n\n const standing = adjudicate(bundle, bundle).find(\n (hit) => hit.record.conceptId === id,\n )?.standing;\n // Only asked for once there is drift: the dependants of a record that\n // still holds are not part of this question.\n const impact = await store.impact(path, id);\n\n const { packet, classified } = await reassessPacket(root, record, entries, {\n ...(withDiff ? { withDiff: true } : {}),\n impact,\n ...(standing ? { standing } : {}),\n });\n\n // `moved` is the one class this command settles rather than reports: the\n // bytes are identical, so the record still describes them and only the\n // address was wrong. The hash is kept exactly as it was — nothing here\n // re-baselines *content*, which would be accepting an edit nobody read.\n const moves = classified.filter((found) => found.class === \"moved\");\n let frozen = false;\n const rebaselined: KbRebaselinedAnchor[] = [];\n if (moves.length) {\n const relocated = new Map<KbAnchor, KbAnchor>();\n for (const found of moves) {\n const to = found.entry.movedTo;\n if (!to) continue;\n relocated.set(found.anchor, {\n ...found.anchor,\n file: to.file,\n ...(to.symbol ? { symbol: to.symbol } : {}),\n });\n rebaselined.push({\n file: found.anchor.file,\n ...(found.anchor.symbol ? { symbol: found.anchor.symbol } : {}),\n toFile: to.file,\n ...(to.symbol ? { toSymbol: to.symbol } : {}),\n });\n }\n try {\n await assertBaseNotFrozen(process.cwd(), path);\n } catch (error) {\n if (!(error instanceof KbBaseFrozenError)) throw error;\n frozen = true;\n }\n if (!frozen) {\n await store.updateAnchors(\n path,\n id,\n (record.frontmatter.strauss_anchors ?? []).map(\n (anchor) => relocated.get(anchor) ?? anchor,\n ),\n actor,\n );\n }\n }\n\n return {\n conceptId: id,\n packet,\n rebaselined: frozen ? [] : rebaselined,\n cosmetic: classified.filter((found) => found.class === \"cosmetic\").length,\n ...(frozen\n ? {\n frozen: true as const,\n note: \"base is frozen: nothing was rebaselined\",\n }\n : {}),\n };\n },\n render: (result) => renderReassess(result as KbReassessResult),\n});\n\n/**\n * The packet as prose, because it is read rather than parsed. `--json` is the\n * machine shape; everything below exists so a reader can answer without\n * opening the repository.\n */\nexport function renderReassess(result: KbReassessResult): string {\n const lines: string[] = [];\n for (const move of result.rebaselined) {\n lines.push(\n `rebaselined: ${at(move.file, move.symbol)} → ${at(move.toFile, move.toSymbol)} (same code, new address)`,\n );\n }\n if (result.cosmetic) {\n lines.push(\n `${result.cosmetic} anchor${result.cosmetic === 1 ? \"\" : \"s\"} changed formatting only.`,\n );\n }\n if (result.note) lines.push(result.note);\n\n const packet = result.packet;\n if (!packet) {\n lines.push(`${result.conceptId}: nothing to reassess.`);\n return lines.join(\"\\n\");\n }\n\n lines.push(\n \"\",\n `# ${packet.conceptId}${packet.title ? ` — ${packet.title}` : \"\"}`,\n `type: ${packet.type} standing: ${packet.standing}`,\n ...(packet.why ? [`why: ${packet.why}`] : []),\n ...(packet.claim\n ? [\"\", `## ${packet.claim.section}`, packet.claim.text]\n : []),\n \"\",\n `## Anchors (${packet.anchors.length})`,\n );\n\n for (const anchor of packet.anchors) {\n lines.push(\n `- ${at(anchor.file, anchor.symbol)} — ${anchor.class}${anchor.reason ? ` (${anchor.reason})` : \"\"}`,\n );\n if (!anchor.diff) continue;\n if (anchor.diff.status === \"unrecoverable\") {\n lines.push(\n \" diff: unrecoverable — no committed span to compare against\",\n );\n continue;\n }\n lines.push(\n ` diff vs ${anchor.diff.ref} (${anchor.diff.source}): +${anchor.diff.added} −${anchor.diff.removed}`,\n ...anchor.diff.unified.split(\"\\n\").map((line) => ` ${line}`),\n );\n }\n\n if (packet.impact.length) {\n lines.push(\"\", `## Impact (${packet.impact.length})`);\n for (const entry of packet.impact) {\n lines.push(\n `- ${entry.conceptId} [${entry.standing}]${entry.title ? ` — ${entry.title}` : \"\"}`,\n );\n }\n if (packet.impactTruncated) lines.push(\"- … walk truncated\");\n }\n\n lines.push(\"\", `Default: ${packet.default} — ${packet.defaultNote}.`);\n return lines.join(\"\\n\");\n}\n\nfunction at(file: string, symbol?: string): string {\n return symbol ? `${file}:${symbol}` : file;\n}\n","import { z } from \"zod\";\nimport { KB_CAUSAL_LINK_RELS } from \"../record-types.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\nexport const impactCommand = define({\n name: \"impact\",\n tool: \"kb_impact\",\n usage: \"impact <concept-id> [--depth N] [--rels a,b]\",\n description:\n \"What breaks if this record changes: its transitive set of dependants, each with its standing. Each rel declares which of its ends depends on the other, and the walk follows each rel in its own direction. Naming `related_to` or an unknown rel in `rels` is an error. kb_backlinks gives one flat hop.\",\n input: z.object({\n bundlePath,\n conceptId,\n depth: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Hops out from the record. Unbounded when omitted; a walk this cuts reports truncated: true.\",\n ),\n rels: z\n .array(z.enum(KB_CAUSAL_LINK_RELS))\n .optional()\n .describe(\n \"Narrow which rels the walk follows. Defaults to every rel that carries a dependence — all but related_to.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const depth = argvFlag(argv, \"--depth\");\n const rels = argvFlag(argv, \"--rels\");\n return {\n bundlePath: path,\n conceptId: argv[1],\n ...(depth ? { depth: Number(depth) } : {}),\n ...(rels ? { rels: rels.split(\",\").filter(Boolean) } : {}),\n };\n },\n run: async ({ store }, { bundlePath: path, conceptId: id, depth, rels }) =>\n store.impact(path, id, {\n ...(depth !== undefined ? { depth } : {}),\n ...(rels?.length ? { rels } : {}),\n }),\n});\n","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const listCommand = define({\n name: \"list\",\n tool: \"kb_list\",\n usage: \"list [type]\",\n description:\n \"Every record, optionally one type. For enumerating; use kb_query for a question.\",\n input: z.object({ bundlePath, type: z.enum(KB_RECORD_TYPES).optional() }),\n fromArgv: (argv, path) => ({ bundlePath: path, type: argv[1] }),\n run: async ({ store }, { bundlePath: path, type }) =>\n (await store.list(path, type)).map((record) => ({\n conceptId: record.conceptId,\n title: record.frontmatter.title ?? null,\n description: record.frontmatter.description ?? null,\n status: record.frontmatter.strauss_status,\n anchors: record.frontmatter.strauss_anchors ?? [],\n })),\n});\n","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport { argvFlag, bundlePath, define, REPO_ROOT } from \"./model.js\";\n\nexport const loadCommand = define({\n name: \"load\",\n tool: \"kb_load\",\n usage: \"load [type] [--budget N | --all] [--repo-root PATH]\",\n description:\n \"Load the whole base, each record with its standing — call it first, at the point of use, since compaction drops it. Superseded records arrive as stubs; kb_trace has the history. Over budget it refuses: kb_catalog, then kb_pack, or narrow with `type`; `all` bypasses. Never read record files directly — only kb_* tools resolve supersession. `digest` stamps the base's content, so hooks know when to reload.\",\n input: z\n .object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES).optional(),\n budgetTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Approximate token ceiling. Defaults to 25000.\"),\n all: z\n .boolean()\n .optional()\n .describe(\n \"Loads the entire base regardless of size, bypassing the token budget; mutually exclusive with budgetTokens.\",\n ),\n repoRoot: REPO_ROOT,\n })\n .refine((value) => !(value.all && value.budgetTokens !== undefined), {\n message:\n \"all is mutually exclusive with budgetTokens: pass a ceiling or none, not both.\",\n }),\n fromArgv: (argv, path) => {\n const budget = argvFlag(argv, \"--budget\");\n const repoRoot = argvFlag(argv, \"--repo-root\");\n return {\n bundlePath: path,\n ...(argv[1] && !argv[1].startsWith(\"--\") ? { type: argv[1] } : {}),\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(argv.includes(\"--all\") ? { all: true } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n };\n },\n run: async (\n { store },\n { bundlePath: path, type, budgetTokens, all, repoRoot },\n ) => {\n const result = await store.load(path, {\n ...(type ? { type } : {}),\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(all ? { all } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n });\n if (!result.loaded) return result;\n return {\n ...result,\n records: result.records.map((hit) => ({\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n warnings: hit.warnings,\n anchors: hit.record.frontmatter.strauss_anchors ?? [],\n body: hit.record.body,\n })),\n };\n },\n});\n","import { z } from \"zod\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const logCommand = define({\n name: \"log\",\n tool: \"kb_log\",\n usage: \"log\",\n description:\n \"Who touched what, and when. Append-only; malformed lines are reported, never repaired.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: ({ store }, { bundlePath: path }) => store.readLog(path),\n});\n","import { z } from \"zod\";\nimport { composeNoDecisionRecord } from \"../decision-record.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const noDecisionCommand = define({\n name: \"no-decision\",\n tool: \"kb_no_decision\",\n usage: \"no-decision <reason...>\",\n description:\n \"Record in one sentence that a piece of work had nothing to decide. Idempotent.\",\n input: z.object({ bundlePath, reason: z.string().min(1) }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n reason: argv.slice(1).join(\" \").trim(),\n }),\n run: async ({ store, actor, now }, { bundlePath: path, reason }) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.write(\n path,\n { ...composeNoDecisionRecord(reason, actor, now()), overwrite: true },\n actor,\n );\n return { conceptId: record.conceptId };\n },\n});\n","import { z } from \"zod\";\nimport type { KbWarning } from \"../adjudicate.js\";\nimport type { KbPackResult } from \"../pack.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\nexport const packCommand = define({\n name: \"pack\",\n tool: \"kb_pack\",\n usage: \"pack <conceptId> [--hops N] [--max-nodes N] [--budget N]\",\n description:\n \"Bounded neighbourhood around one record: within `hops`, ranked, cut to `maxNodes`, with every cut record named under Excluded. Use when the base is over kb_load's budget and the work centres on a record you can name. Refuses over budget rather than truncating. Everything below the header is byte-stable across runs. Resolves supersession like kb_load.\",\n input: z.object({\n bundlePath,\n conceptId,\n hops: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"How far from the root the walk may reach. Defaults to 2.\"),\n maxNodes: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"How many records the pack may hold, root included. Defaults to 20.\",\n ),\n budgetTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Approximate token ceiling over what is actually emitted. Defaults to 25000.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const hops = argvFlag(argv, \"--hops\");\n const maxNodes = argvFlag(argv, \"--max-nodes\");\n const budget = argvFlag(argv, \"--budget\");\n return {\n bundlePath: path,\n conceptId: argv[1],\n ...(hops ? { hops: Number(hops) } : {}),\n ...(maxNodes ? { maxNodes: Number(maxNodes) } : {}),\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n };\n },\n run: async (\n { store, now },\n { bundlePath: path, conceptId: root, hops, maxNodes, budgetTokens },\n ) => {\n const result = await store.pack(path, root, {\n ...(hops !== undefined ? { hops } : {}),\n ...(maxNodes !== undefined ? { maxNodes } : {}),\n ...(budgetTokens !== undefined ? { budgetTokens } : {}),\n });\n return render(result, path, now());\n },\n});\n\n/**\n * The timestamp is the header's last line and appears nowhere else, so a\n * caller can drop everything through that line and diff two packs of the same\n * base byte for byte.\n */\nfunction render(result: KbPackResult, bundle: string, at: string): string {\n const lines = [\n `# KB Pack — ${result.root}`,\n `bundle: ${bundle}`,\n `budget: ~${result.tokensLoaded} of ${result.budgetTokens} tokens, ${result.recordCount} records`,\n `packed: ${at}`,\n \"\",\n `## Records (${result.records.length})`,\n ];\n\n for (const record of result.records) {\n lines.push(\n \"\",\n `### ${record.conceptId}${record.title ? ` — ${record.title}` : \"\"} [${record.standing}]`,\n );\n if (record.warnings.length) {\n lines.push(`warnings: ${record.warnings.map(warningLabel).join(\"; \")}`);\n }\n if (record.anchors.length) {\n lines.push(\n `anchors: ${record.anchors\n .map((anchor) =>\n anchor.symbol ? `${anchor.file}#${anchor.symbol}` : anchor.file,\n )\n .join(\", \")}`,\n );\n }\n lines.push(\"\", record.body.trimEnd());\n }\n\n if (result.superseded.length) {\n lines.push(\"\", `## Superseded (${result.superseded.length})`);\n for (const entry of result.superseded) {\n lines.push(\n `- ${entry.conceptId} → ${\n entry.supersededBy.join(\", \") || \"(no surviving head)\"\n }${entry.at ? ` (${entry.at})` : \"\"}`,\n );\n }\n }\n\n if (result.excluded.length) {\n lines.push(\"\", `## Excluded (${result.excluded.length})`);\n for (const cut of result.excluded) lines.push(`- ${cut}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction warningLabel(warning: KbWarning): string {\n switch (warning.kind) {\n case \"superseded\":\n return `superseded by ${warning.by.join(\", \")}`;\n case \"unsettled\":\n return `unsettled (${warning.status})`;\n case \"broken-chain\":\n return `broken chain — ${warning.missing} is not in the bundle`;\n case \"chain-cycle\":\n return `chain cycle through ${warning.through.join(\" → \")}`;\n case \"forked-chain\":\n return `forked chain — heads ${warning.heads.join(\", \")}`;\n case \"stale\":\n return `stale since ${warning.staleAfter}`;\n case \"unresolved-question\":\n return \"unresolved question\";\n default:\n return warning.kind;\n }\n}\n","import { z } from \"zod\";\nimport { pinBase } from \"../kb-pins/index.js\";\nimport { argvFlag, bundlePath, define } from \"./model.js\";\n\nexport const pinCommand = define({\n name: \"pin\",\n tool: \"kb_pin\",\n usage:\n \"pin [bundle-path] [--mode full|index] [--profiles a,b] [--local|--user] [--frozen|--unfreeze]\",\n description:\n \"Pin a base into a workspace manifest so kb_context surfaces it. Layers, nearest wins: project `.strauss/kb-pins.json` (default), `--local` (personal, gitignored), `--user` (`~/.strauss`). Idempotent; `--mode full|index`, `--profiles`, `--frozen`/`--unfreeze` update only those fields. A path with no records pins with a warning. Never touches the base itself.\",\n input: z.object({\n bundlePath,\n mode: z\n .enum([\"full\", \"index\"])\n .optional()\n .describe(\n \"full: always emit this base's records whole (still under the block budget); index: never upgrade. Absent: the profile's full-under threshold decides.\",\n ),\n profiles: z\n .array(z.string())\n .optional()\n .describe(\"Context profiles this pin surfaces in. Absent: all of them.\"),\n layer: z\n .enum([\"project\", \"local\", \"user\"])\n .optional()\n .describe(\n \"Which manifest to write: project (committed, default), local (personal, gitignored), user (~/.strauss, every workspace).\",\n ),\n frozen: z\n .boolean()\n .optional()\n .describe(\n \"true: the base is concluded — writes against it refuse while pinned. false: lift a freeze.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const positional = argv[1] && !argv[1].startsWith(\"--\") ? argv[1] : path;\n const mode = argvFlag(argv, \"--mode\");\n const profiles = argvFlag(argv, \"--profiles\");\n const layer = argv.includes(\"--user\")\n ? \"user\"\n : argv.includes(\"--local\")\n ? \"local\"\n : undefined;\n const frozen = argv.includes(\"--frozen\")\n ? true\n : argv.includes(\"--unfreeze\")\n ? false\n : undefined;\n return {\n bundlePath: positional,\n ...(mode ? { mode } : {}),\n ...(profiles\n ? {\n profiles: profiles\n .split(\",\")\n .map((p) => p.trim())\n .filter(Boolean),\n }\n : {}),\n ...(layer ? { layer } : {}),\n ...(frozen !== undefined ? { frozen } : {}),\n };\n },\n run: ({ store, now }, { bundlePath: path, mode, profiles, layer, frozen }) =>\n pinBase(store, process.cwd(), path, now(), {\n ...(mode ? { mode } : {}),\n ...(profiles ? { profiles } : {}),\n ...(layer ? { layer } : {}),\n ...(frozen !== undefined ? { frozen } : {}),\n }),\n});\n","import { z } from \"zod\";\nimport { listPins } from \"../kb-pins/index.js\";\nimport { define } from \"./model.js\";\n\nexport const pinsCommand = define({\n name: \"pins\",\n tool: \"kb_pins\",\n usage: \"pins\",\n description:\n \"Every pinned base across the manifest layers, with its layer and whether it resolves to records. Takes no bundlePath.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: ({ store }) => listPins(store, process.cwd()),\n});\n","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport { argvFlag, bundlePath, define, REPO_ROOT } from \"./model.js\";\n\nexport const queryCommand = define({\n name: \"query\",\n tool: \"kb_query\",\n usage: \"query <text...> [--repo-root PATH]\",\n description:\n \"Search; every hit carries its standing. Flagged, never filtered: a superseded hit returns with its replacement, a rejected one is marked. Prefer kb_load when the base fits its budget — a full read beats search. Results are volatile: place them at the tail, not the cached prefix. Never read record files directly.\",\n input: z.object({\n bundlePath,\n text: z.string().optional(),\n type: z.enum(KB_RECORD_TYPES).optional(),\n includeNonCurrent: z.boolean().optional(),\n repoRoot: REPO_ROOT,\n }),\n // `--repo-root` is a flag, so its value must not fall into the search text.\n fromArgv: (argv, path) => {\n const repoRoot = argvFlag(argv, \"--repo-root\");\n const words = argv.slice(1);\n const flag = words.indexOf(\"--repo-root\");\n if (flag !== -1) words.splice(flag, 2);\n return {\n bundlePath: path,\n text: words.join(\" \").trim(),\n includeNonCurrent: true,\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n };\n },\n run: async (\n { store },\n { bundlePath: path, text, type, includeNonCurrent, repoRoot },\n ) =>\n (\n await store.query(path, text ?? \"\", {\n ...(type ? { type } : {}),\n includeNonCurrent: includeNonCurrent === true,\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n })\n ).map((hit) => ({\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n description: hit.record.frontmatter.description ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n warnings: hit.warnings,\n body: hit.record.body,\n })),\n});\n","import { z } from \"zod\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const readIndexCommand = define({\n name: \"index\",\n tool: \"kb_index\",\n usage: \"index\",\n description:\n \"The index — title, type, status, description per record — rebuilt if stale. Cheapest re-orientation after compaction: call it (or kb_context) first, then kb_load or fetch by id.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: ({ store }, { bundlePath: path }) => store.readIndex(path),\n});\n","import { z } from \"zod\";\nimport { kbJsonSchemas } from \"../json-schema.js\";\nimport { define } from \"./model.js\";\n\nexport const schemaCommand = define({\n name: \"schema\",\n tool: \"kb_schema\",\n usage: \"schema\",\n description:\n \"JSON Schema for frontmatter, write input, and log entries, generated from the enforcing code.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: () => Promise.resolve(kbJsonSchemas()),\n});\n","import { z } from \"zod\";\nimport { composeInputSchema } from \"./compose.js\";\nimport { kbLogEntrySchema } from \"./kb-log.js\";\nimport { kbRecordFrontmatterSchema } from \"./kb-record.schema.js\";\n\n/**\n * The frontmatter contract, emitted rather than restated.\n *\n * Prose describing a schema drifts from the code that enforces it; a generated\n * artifact cannot. Documentation points at this, a YAML language server\n * validates hand-edited records against it, and a consumer that is not\n * TypeScript has something to check.\n *\n * `io: 'input'` on purpose. `strauss_status` carries a default, so the output\n * type marks it required while the *document* may legitimately omit it — and\n * the document is what this schema is used to validate.\n */\nexport function kbJsonSchemas(): Record<string, unknown> {\n return {\n recordFrontmatter: z.toJSONSchema(kbRecordFrontmatterSchema, {\n io: \"input\",\n }),\n composeInput: z.toJSONSchema(composeInputSchema, { io: \"input\" }),\n logEntry: z.toJSONSchema(kbLogEntrySchema, { io: \"input\" }),\n };\n}\n","import { z } from \"zod\";\n\nexport const LOG_FILE = \"log.jsonl\";\n\nexport const kbLogEntrySchema = z\n .object({\n // Validated, not just `min(1)`: `at` is a sort key (see `parseLog`\n // below), and a value that isn't actually chronological — a Unix\n // timestamp, a human-typed date, garbage — would sort wrong without\n // ever failing to parse. `z.iso.datetime()` accepts exactly what\n // `record()` writes (`Date#toISOString()`: full precision, `Z` offset)\n // and rejects everything else, including a non-`Z` offset — so a\n // malformed `at` is reported the same way a malformed line already is,\n // rather than silently sorting into the wrong place.\n at: z.iso.datetime(),\n by: z.string().min(1),\n operation: z.string().min(1),\n conceptId: z.string().min(1),\n /** Second concept id, where the operation relates two — supersession. */\n target: z.string().min(1).optional(),\n })\n .strict();\n\nexport type KbLogEntry = z.infer<typeof kbLogEntrySchema>;\n\n/**\n * The log is the bundle's only primary artifact, and the reason it is handled\n * unlike `INDEX.md`.\n *\n * The index is derived: lose it and the records rebuild it. The log records\n * events — which agent wrote what, and when — that leave no trace in the record\n * set, so it cannot be regenerated from anything. Repair therefore means detect\n * and report, never rewrite: rewriting an append-only log destroys the only\n * copy of what it holds.\n *\n * JSONL rather than a markdown list. An earlier version rendered entries as\n * `- <at> · <by> · <op> · <id>` and parsed them by splitting on the separator —\n * a hand-written parser for a format invented here, which fails the first time\n * a value contains the separator. JSON needs no parser and the schema below\n * needs no separator to be unambiguous. Humans read the log through\n * `strauss-kb log`, as they read everything else.\n *\n * One line per entry, appended with `O_APPEND`: POSIX makes the offset update\n * atomic, and writes this size do not interleave on a local filesystem.\n */\nexport function renderLogEntry(entry: KbLogEntry): string {\n return `${JSON.stringify(kbLogEntrySchema.parse(entry))}\\n`;\n}\n\nexport type KbLogReadResult = {\n entries: KbLogEntry[];\n /** Lines that did not parse, with their 1-based position. Never rewritten. */\n malformed: { line: number; text: string }[];\n};\n\nexport function parseLog(raw: string): KbLogReadResult {\n const entries: KbLogEntry[] = [];\n const malformed: { line: number; text: string }[] = [];\n const seen = new Set<string>();\n\n raw.split(\"\\n\").forEach((text, index) => {\n if (!text.trim()) return;\n let value: unknown;\n try {\n value = JSON.parse(text) as unknown;\n } catch {\n malformed.push({ line: index + 1, text });\n return;\n }\n const parsed = kbLogEntrySchema.safeParse(value);\n if (!parsed.success) {\n malformed.push({ line: index + 1, text });\n return;\n }\n\n // A union merge keeps both sides' lines even when a line appears on\n // both — a cherry-pick or rebase that carried one worktree's entry into\n // the other's history before the merge produces two byte-identical\n // lines for what was genuinely one event. Dropping the repeat is the\n // right read here: two writers independently logging the *same*\n // `at`/`by`/`operation`/`conceptId`/`target` is not a real scenario\n // `record()` can produce (each call mints its own `at`), so an exact\n // duplicate is merge residue, not two events that happen to coincide.\n // A near-duplicate (same fields but a different `at`) is left alone —\n // that is two genuine events and both stay.\n const key = JSON.stringify(parsed.data);\n if (seen.has(key)) return;\n seen.add(key);\n\n entries.push(parsed.data);\n });\n\n // A union merge (see `kb-gitattributes.ts`) interleaves two worktrees'\n // appends by whatever order git's merge happened to visit them in, not by\n // when each entry was actually written. Sorting on `at` here means line\n // order in the file is never load-bearing — only the timestamp is. `at` is\n // `Date#toISOString`, so lexicographic order is chronological order; the\n // sort is stable, so entries that share a timestamp keep their file order.\n entries.sort((left, right) =>\n left.at < right.at ? -1 : left.at > right.at ? 1 : 0,\n );\n\n return { entries, malformed };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport {\n KbStampBaselineError,\n KbStampDigestBaselineError,\n} from \"../kb-errors.js\";\nimport { readMergedPins } from \"../kb-pins/index.js\";\nimport type { KbStampResult } from \"../kb-store.js\";\nimport { argvFlag, define } from \"./model.js\";\n\n/** One base's stamp, plus which records moved when a baseline was given. */\ntype KbStampReport = KbStampResult & {\n /** Changed, added or removed ids; null when the baseline was a digest. */\n changed: string[] | null;\n};\n\nconst DIGEST = /^[0-9a-f]{64}$/;\n\nexport const stampCommand = define({\n name: \"stamp\",\n tool: \"kb_stamp\",\n usage: \"stamp [--bundle PATH] [--since DIGEST|FILE]\",\n description:\n \"Content stamp of a base — `load`'s digest, record counts, per-record digests, how many records have drifted anchors — without any bodies. Takes no bundlePath to stamp every pinned base. With `since`, reports only the bases that moved, naming the changed ids. Reads, never writes.\",\n input: z.object({\n bundlePath: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Absolute path to one knowledge base. Omit to stamp every pinned base.\",\n ),\n since: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Prior digest, or path to a prior `stamp --json`; only moved bases return, with changed ids when the baseline is a file.\",\n ),\n }),\n fromArgv: (argv, path, _stdin, bundleExplicit) => {\n const since = argvFlag(argv, \"--since\");\n return {\n ...(bundleExplicit ? { bundlePath: path } : {}),\n ...(since !== undefined ? { since } : {}),\n };\n },\n run: async ({ store }, { bundlePath, since }) => {\n const targets = bundlePath\n ? [bundlePath]\n : (await readMergedPins(process.cwd())).pins.map(\n (pin) => pin.absolutePath,\n );\n\n // A digest baseline only answers equality, and equality against which\n // base is ambiguous once more than one is in play — a file baseline\n // carries a digest per base and has no such limit.\n if (since !== undefined && DIGEST.test(since) && targets.length > 1) {\n throw new KbStampDigestBaselineError(since);\n }\n\n const stamps = await Promise.all(\n targets.map((target) => store.stamp(target)),\n );\n if (since === undefined) {\n return stamps.map((stamp) => ({ ...stamp, changed: null }));\n }\n\n const baseline = await readBaseline(since);\n const reports: KbStampReport[] = [];\n for (const stamp of stamps) {\n const before = baseline.byPath.get(stamp.path);\n if (baseline.digest !== null) {\n if (baseline.digest === stamp.digest) continue;\n reports.push({ ...stamp, changed: null });\n continue;\n }\n // A base absent from the baseline was never injected — reported whole,\n // the same as a base whose every record is new.\n if (before && before.digest === stamp.digest) continue;\n reports.push({ ...stamp, changed: changedIds(before?.records, stamp) });\n }\n return reports;\n },\n render: (result) =>\n (result as KbStampReport[])\n .map((report) => {\n const counts = `${report.recordCount} record(s), ${report.superseded} superseded${\n report.drifted ? `, ${report.drifted} drifted` : \"\"\n }`;\n const head = `${report.path} ${report.digest} ${counts}${\n report.newestAt ? ` newest ${report.newestAt}` : \"\"\n }`;\n return report.changed?.length\n ? `${head}\\n changed: ${report.changed.join(\", \")}`\n : head;\n })\n .join(\"\\n\"),\n});\n\nfunction changedIds(\n before: Map<string, string> | undefined,\n stamp: KbStampResult,\n): string[] {\n const now = new Map(\n stamp.records.map((record) => [record.conceptId, record.digest]),\n );\n const ids = new Set<string>();\n for (const [conceptId, digest] of now) {\n if (before?.get(conceptId) !== digest) ids.add(conceptId);\n }\n for (const conceptId of before?.keys() ?? []) {\n if (!now.has(conceptId)) ids.add(conceptId);\n }\n return [...ids].sort();\n}\n\n/**\n * `--since` is either a digest — an equality answer, no ids to name — or a\n * path to a prior `stamp --json` (equally, a hook's session state file), which\n * carries the per-record digests a changed-id list needs.\n */\nasync function readBaseline(since: string): Promise<{\n digest: string | null;\n byPath: Map<string, { digest: string; records: Map<string, string> }>;\n}> {\n if (DIGEST.test(since)) return { digest: since, byPath: new Map() };\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(await readFile(since, \"utf8\"));\n } catch {\n throw new KbStampBaselineError(since);\n }\n\n // Either a `stamp --json` array, or a hook's session state file, which\n // carries the same entries under `stamps` beside the git head it saw.\n const entries = Array.isArray(parsed)\n ? parsed\n : ((parsed as { stamps?: unknown[] })?.stamps ?? []);\n const byPath = new Map<\n string,\n { digest: string; records: Map<string, string> }\n >();\n for (const entry of entries as {\n path?: string;\n digest?: string;\n records?: { conceptId: string; digest: string }[];\n }[]) {\n if (typeof entry?.path !== \"string\" || typeof entry?.digest !== \"string\") {\n continue;\n }\n byPath.set(entry.path, {\n digest: entry.digest,\n records: new Map(\n (entry.records ?? []).map((record) => [\n record.conceptId,\n record.digest,\n ]),\n ),\n });\n }\n return { digest: null, byPath };\n}\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { KB_RECORD_STATUSES } from \"../kb-record.schema.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const statusCommand = define({\n name: \"status\",\n tool: \"kb_status\",\n usage: \"status <concept-id> <status>\",\n description:\n \"Move a record's status. Compare-and-swap: a concurrent change fails instead of being overwritten.\",\n input: z.object({\n bundlePath,\n conceptId,\n status: z.enum(KB_RECORD_STATUSES),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n status: argv[2],\n }),\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, status },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.setStatus(path, id, status, actor);\n return { conceptId: record.conceptId, status };\n },\n});\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const supersedeCommand = define({\n name: \"supersede\",\n tool: \"kb_supersede\",\n usage: \"supersede <concept-id> <replacement-id>\",\n description:\n \"Mark a record superseded by another, linked in both directions. Use instead of editing a record whose meaning changed.\",\n input: z.object({ bundlePath, conceptId, replacementId: conceptId }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n replacementId: argv[2],\n }),\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, replacementId },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n await store.supersede(path, id, replacementId, actor);\n return { superseded: id, replacedBy: replacementId };\n },\n});\n","import { z } from \"zod\";\nimport { buildContext, syncInstructions } from \"../kb-context.js\";\nimport { argvFlag, define } from \"./model.js\";\n\nexport const syncInstructionsCommand = define({\n name: \"sync-instructions\",\n usage:\n \"sync-instructions <file> [--profile NAME] [--budget N] [--full-under N]\",\n description:\n \"CLI-only: plant the kb_context block between sentinel comments in AGENTS.md or CLAUDE.md, idempotently.\",\n input: z.object({\n file: z.string().min(1).describe(\"The instruction file to edit in place.\"),\n budgetTokens: z.number().int().positive().optional(),\n fullUnderTokens: z.number().int().positive().optional(),\n profile: z.string().optional(),\n }),\n fromArgv: (argv) => {\n const budget = argvFlag(argv, \"--budget\");\n const fullUnder = argvFlag(argv, \"--full-under\");\n const profile = argvFlag(argv, \"--profile\");\n return {\n file: argv[1],\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(fullUnder ? { fullUnderTokens: Number(fullUnder) } : {}),\n ...(profile ? { profile } : {}),\n };\n },\n run: async ({ store }, { file, budgetTokens, fullUnderTokens, profile }) => {\n const result = await buildContext(store, process.cwd(), {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens ? { fullUnderTokens } : {}),\n ...(profile ? { profile } : {}),\n warn: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n });\n return syncInstructions(file, result.block);\n },\n});\n","import { z } from \"zod\";\nimport { TRACE_EDGES } from \"../trace.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const traceCommand = define({\n name: \"trace\",\n tool: \"kb_trace\",\n usage: \"trace <concept-id> [edges...]\",\n description:\n 'Timeline of how a position was reached, ordered by write time, following supersession, shared anchors and shared sources. Includes rejected, draft and superseded records — in a history they are the content. For \"why is it like this\"; kb_load answers \"what holds now\".',\n input: z.object({\n bundlePath,\n conceptId,\n edges: z.array(z.enum(TRACE_EDGES)).optional(),\n depth: z.number().int().positive().optional(),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n edges: argv\n .slice(2)\n .filter((edge) => (TRACE_EDGES as readonly string[]).includes(edge)),\n }),\n run: async ({ store }, { bundlePath: path, conceptId: id, edges, depth }) =>\n (\n await store.trace(path, id, {\n ...(edges?.length ? { edges } : {}),\n ...(depth ? { depth } : {}),\n })\n ).map((step) => ({\n conceptId: step.record.conceptId,\n at: step.record.frontmatter.generated?.at ?? null,\n status: step.record.frontmatter.strauss_status,\n title: step.record.frontmatter.title ?? null,\n depth: step.depth,\n via: step.via,\n body: step.record.body,\n })),\n});\n","import { edgeNeighbours } from \"./kb-edges.js\";\nimport type { KbRecord } from \"./kb-record.schema.js\";\nimport { KB_CAUSAL_LINK_RELS } from \"./record-types.js\";\n\n/**\n * Edges a trace may follow — the shared kb-edges.ts definitions, minus\n * `body-link`: body links can reach most of a bundle from anywhere, which\n * suits a bounded pack but floods a timeline. Also absent by design:\n * `strauss_answered` carries no target id, so a question's resolution lives\n * in its own body rather than in another record.\n *\n * `typed-link` is in, where `body-link` is out, because the two differ in how\n * cheaply they are made. A body link is any markdown a writer happened to\n * type; a `strauss_links` entry is a deliberate claim from a closed vocabulary\n * about what this record depends on. That is exactly the kind of edge a\n * timeline should follow — \"we chose this because of that\" is the history.\n *\n * Only the causal rels, though. `related_to` asserts no dependence and reaches\n * whatever a writer thought worth mentioning, which is the same flooding\n * `body-link` is excluded for; a bibliography is a neighbourhood's business\n * (`pack`), not a history's.\n */\nexport const TRACE_EDGES = [\n \"typed-link\",\n \"supersession\",\n \"anchor\",\n \"source\",\n] as const;\nexport type KbTraceEdge = (typeof TRACE_EDGES)[number];\n\nexport type KbTraceStep = {\n record: KbRecord;\n /** Hops from the seed. 0 is the seed itself. */\n depth: number;\n /** Why this record was reached. Empty for the seed. */\n via: KbTraceEdge[];\n};\n\nexport type KbTraceOptions = {\n edges?: readonly KbTraceEdge[];\n /** Body links alone can reach the whole bundle, so a trace is always bounded. */\n depth?: number;\n};\n\n/**\n * How a position was arrived at, as a timeline.\n *\n * The inverse of a point query, and the reason the two cannot be one call with\n * a flag: there, a `rejected` record is the most dangerous thing retrievable —\n * here it is the content. A trace that drops the rejected alternatives and the\n * superseded earlier understanding has removed the answer and kept the\n * conclusion, which is what reading a diff already gives you.\n *\n * Ordered by `generated.at` rather than by relevance. Ranking a history is\n * meaningless when the sequence is the point.\n */\nexport function trace(\n seedId: string,\n bundle: KbRecord[],\n options: KbTraceOptions = {},\n): KbTraceStep[] {\n const edges = options.edges?.length ? options.edges : TRACE_EDGES;\n const maxDepth = options.depth ?? 3;\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const seed = byId.get(seedId);\n if (!seed) return [];\n\n const reached = new Map<string, KbTraceStep>([\n [seedId, { record: seed, depth: 0, via: [] }],\n ]);\n let frontier: KbRecord[] = [seed];\n\n for (let depth = 1; depth <= maxDepth && frontier.length; depth += 1) {\n const next: KbRecord[] = [];\n for (const from of frontier) {\n for (const edge of edges) {\n for (const record of edgeNeighbours(\n from,\n bundle,\n edge,\n KB_CAUSAL_LINK_RELS,\n )) {\n const existing = reached.get(record.conceptId);\n if (existing) {\n // Reached twice by different edges: keep the shorter path, but\n // record both reasons — \"shares an anchor and replaces it\" is more\n // informative than either alone. The seed keeps an empty `via`,\n // since it was not reached by anything.\n if (existing.depth > 0 && !existing.via.includes(edge)) {\n existing.via.push(edge);\n }\n continue;\n }\n reached.set(record.conceptId, { record, depth, via: [edge] });\n next.push(record);\n }\n }\n }\n frontier = next;\n }\n\n return [...reached.values()].sort(byGeneratedAt);\n}\n\nfunction byGeneratedAt(left: KbTraceStep, right: KbTraceStep): number {\n const at = (step: KbTraceStep) => step.record.frontmatter.generated?.at ?? \"\";\n return at(left).localeCompare(at(right)) || left.depth - right.depth;\n}\n","import { z } from \"zod\";\nimport { RECORD_TYPES } from \"../record-types.js\";\nimport { define } from \"./model.js\";\n\nexport const typesCommand = define({\n name: \"types\",\n tool: \"kb_types\",\n usage: \"types\",\n description:\n \"The twelve record types with their purpose, body sections, and starting status. Read this before writing rather than guessing headings — a section the type does not define is rejected.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: () => Promise.resolve(RECORD_TYPES),\n});\n","import { z } from \"zod\";\nimport { unpinBase } from \"../kb-pins/index.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const unpinCommand = define({\n name: \"unpin\",\n tool: \"kb_unpin\",\n usage: \"unpin [bundle-path]\",\n description:\n \"Remove a base from every manifest layer that holds it. Reports the layers touched.\",\n input: z.object({ bundlePath }),\n fromArgv: (argv, path) => ({ bundlePath: argv[1] ?? path }),\n run: (_ctx, { bundlePath: path }) => unpinBase(process.cwd(), path),\n});\n","import { z } from \"zod\";\nimport { validateBundle, type KbValidationProblem } from \"../validate.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const validateCommand = define({\n name: \"validate\",\n tool: \"kb_validate\",\n usage: \"validate\",\n description:\n \"Check pointers no single record can see: supersession links that disagree between the two records, typed causal links, and assumptions that cite sources. Each finding carries a severity: errors fail the exit code, warnings do not.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: async ({ store }, { bundlePath: path }) =>\n validateBundle(await store.list(path)),\n // Warnings never fail the exit code; every other severity does.\n failsWhen: (result) =>\n Array.isArray(result) &&\n (result as KbValidationProblem[]).some(\n (problem) => problem.severity !== \"warning\",\n ),\n});\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\nexport const verifyCommand = define({\n name: \"verify\",\n tool: \"kb_verify\",\n usage: \"verify <concept-id> --note <text>\",\n description:\n \"Append a verified[] event: who checked, when, and what was found. Append-only. A record's own generator is refused unless the actor is `human:`-prefixed.\",\n input: z.object({\n bundlePath,\n conceptId,\n note: z.string().refine((s) => s.trim().length > 0, {\n message: \"note must say what the check found\",\n }),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n note: argvFlag(argv, \"--note\"),\n }),\n run: async (\n { store, actor, now },\n { bundlePath: path, conceptId: id, note },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.verify(path, id, note, actor, now());\n return {\n conceptId: record.conceptId,\n verified: record.frontmatter.verified?.length ?? 0,\n };\n },\n});\n","import { z } from \"zod\";\nimport { composeInputSchema, composeRecord } from \"../compose.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { KB_RECORD_TYPES, type KbRecordType } from \"../kb-record.schema.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const writeCommand = define({\n name: \"write\",\n tool: \"kb_write\",\n usage: \"write <type> < record.json\",\n description:\n \"Write one record. Search first — a duplicate concept id is rejected, not overwritten; kb_types lists each type's sections. An unsourced claim is an `assumption` with assumption: true, never a vague `fact`. Conflicting records get a `risk`, `open-question`, or superseding `decision`. Prefer a new short record over overloading one. Never delete; supersede.\",\n input: z.object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES),\n input: composeInputSchema,\n }),\n fromArgv: async (argv, path, stdin) => ({\n bundlePath: path,\n type: argv[1],\n input: JSON.parse(await stdin()) as unknown,\n }),\n run: async ({ store, actor, now }, { bundlePath: path, type, input }) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.write(\n path,\n composeRecord(type as KbRecordType, input, actor, now()),\n actor,\n );\n return {\n conceptId: record.conceptId,\n action: record.action,\n supersededIds: record.supersededIds,\n };\n },\n});\n","import { z } from \"zod\";\nimport {\n composeDecisionRecord,\n decisionInputSchema,\n} from \"../decision-record.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const writeDecisionCommand = define({\n name: \"write-decision\",\n tool: \"kb_write_decision\",\n usage: \"write-decision < decision.json\",\n description:\n \"Write a decision, with `alternative` (what was rejected and why) and `impact` as fields. Record one when a later reader would otherwise simplify the constraint away; skip when the diff already answers it. `sources` for material read, `anchors` for code, `relatedConceptIds` for records.\",\n input: z.object({ bundlePath, input: decisionInputSchema }),\n fromArgv: async (_argv, path, stdin) => ({\n bundlePath: path,\n input: JSON.parse(await stdin()) as unknown,\n }),\n run: async ({ store, actor, now }, { bundlePath: path, input }) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.write(\n path,\n composeDecisionRecord(input, actor, now()),\n actor,\n );\n return {\n conceptId: record.conceptId,\n action: record.action,\n supersededIds: record.supersededIds,\n };\n },\n});\n","/**\n * The command table, assembled from one file per command.\n *\n * Order is the CLI usage listing's order: the write path, the read path,\n * base housekeeping, the format, and the workspace pin verbs.\n */\nimport { DECISION_TYPE } from \"../decision-record.js\";\nimport { anchorResolveCommand } from \"./anchor-resolve.js\";\nimport { answerCommand } from \"./answer.js\";\nimport { backlinksCommand } from \"./backlinks.js\";\nimport { catalogCommand } from \"./catalog.js\";\nimport { contextCommand } from \"./context.js\";\nimport { doctorCommand } from \"./doctor.js\";\nimport { impactCommand } from \"./impact.js\";\nimport { listCommand } from \"./list.js\";\nimport { loadCommand } from \"./load.js\";\nimport { logCommand } from \"./log.js\";\nimport { noDecisionCommand } from \"./no-decision.js\";\nimport { packCommand } from \"./pack.js\";\nimport { pinCommand } from \"./pin.js\";\nimport { pinsCommand } from \"./pins.js\";\nimport { queryCommand } from \"./query.js\";\nimport { readIndexCommand } from \"./read-index.js\";\nimport { reassessCommand } from \"./reassess.js\";\nimport { schemaCommand } from \"./schema.js\";\nimport { stampCommand } from \"./stamp.js\";\nimport { statusCommand } from \"./status.js\";\nimport { supersedeCommand } from \"./supersede.js\";\nimport { syncInstructionsCommand } from \"./sync-instructions.js\";\nimport { traceCommand } from \"./trace.js\";\nimport { typesCommand } from \"./types.js\";\nimport { unpinCommand } from \"./unpin.js\";\nimport { validateCommand } from \"./validate.js\";\nimport { verifyCommand } from \"./verify.js\";\nimport { writeCommand } from \"./write.js\";\nimport { writeDecisionCommand } from \"./write-decision.js\";\nimport type { KbCommand } from \"./model.js\";\n\nexport const KB_COMMANDS: KbCommand[] = [\n writeCommand,\n writeDecisionCommand,\n noDecisionCommand,\n statusCommand,\n supersedeCommand,\n answerCommand,\n verifyCommand,\n anchorResolveCommand,\n reassessCommand,\n loadCommand,\n catalogCommand,\n packCommand,\n queryCommand,\n traceCommand,\n impactCommand,\n backlinksCommand,\n listCommand,\n readIndexCommand,\n logCommand,\n stampCommand,\n validateCommand,\n doctorCommand,\n schemaCommand,\n pinCommand,\n unpinCommand,\n pinsCommand,\n contextCommand,\n syncInstructionsCommand,\n typesCommand,\n];\n\nexport const KB_COMMANDS_BY_NAME = new Map(\n KB_COMMANDS.map((command) => [command.name, command]),\n);\n\nexport { DECISION_TYPE };\nexport type { KbCommand, KbCommandContext } from \"./model.js\";\n","import {\n appendFile,\n link,\n mkdir,\n readdir,\n readFile,\n rename,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { join, resolve, sep } from \"node:path\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"./concurrency.js\";\nimport {\n parseMarkdownWithFrontmatter,\n stringifyMarkdownWithFrontmatter,\n} from \"./markdown.js\";\nimport {\n kbRecordFrontmatterSchema,\n kbVerifiedEventSchema,\n KB_SLUG_PATTERN,\n type KbAnchor,\n type KbRecord,\n type KbRecordFrontmatter,\n type KbRecordStatus,\n} from \"./kb-record.schema.js\";\nimport {\n KbInvalidConceptIdError,\n KbRecordAlreadyExistsError,\n KbRecordNotFoundError,\n KbSelfVerificationError,\n KbWriteConflictError,\n} from \"./kb-errors.js\";\nimport { INDEX_FILE, indexIsStale, renderIndex } from \"./kb-index.js\";\nimport { adjudicate, type KbAdjudicated } from \"./adjudicate.js\";\nimport {\n bundleDigest,\n bundleStamp,\n sha256 as digest,\n type KbRecordStamp,\n} from \"./kb-stamp.js\";\nimport {\n detectAnchorDrift,\n looksLikeWrongRepoRoot,\n type KbAnchorDriftEntry,\n} from \"./anchor-resolver/index.js\";\nimport { isUncheckedReason } from \"./remote-repo/index.js\";\nimport { resolveHits, searchBase, SEARCH_INDEX_FILE } from \"./search-index.js\";\nimport { trace, type KbTraceOptions, type KbTraceStep } from \"./trace.js\";\nimport { pack, type KbPackOptions, type KbPackResult } from \"./pack.js\";\nimport { catalog, type KbCatalogResult } from \"./catalog.js\";\nimport {\n backlinks,\n impact,\n type KbBacklinksResult,\n type KbImpactOptions,\n type KbImpactResult,\n} from \"./kb-links/index.js\";\nimport {\n LOG_FILE,\n parseLog,\n renderLogEntry,\n type KbLogEntry,\n} from \"./kb-log.js\";\nimport {\n appendUnionMergeLine,\n GITATTRIBUTES_FILE,\n hasMergeDeclaration,\n} from \"./kb-gitattributes.js\";\n\n/**\n * Default bundle, relative to the working directory. A scratch base lives here\n * and is meant to be gitignored; a base worth keeping is written to a committed\n * path instead, passed explicitly. Nothing promotes one to the other.\n */\nexport const KB_DIR = join(\".strauss\", \"kb\");\n\nconst STORE_OWNED = new Set([INDEX_FILE, LOG_FILE, SEARCH_INDEX_FILE]);\n\nexport type KbLogger = {\n info?(entry: Record<string, unknown>): void;\n warn?(entry: Record<string, unknown>): void;\n};\n\n/** Roughly an eighth of a large context window — generous, and overridable. */\nexport const DEFAULT_LOAD_BUDGET = 25_000;\n\n/**\n * A superseded record, named but not spelled out.\n *\n * Standing is a qualifier on a body, and over a long session the body outlives\n * the qualifier — the reader keeps what the record said and loses that it no\n * longer holds. A stub has nothing left to act on, so the failure cannot occur,\n * and `trace` still reaches the content through the id.\n */\nexport type KbSupersededStub = {\n conceptId: string;\n title: string | null;\n supersededBy: string[];\n at: string | null;\n};\n\nexport type KbLoadResult =\n | {\n loaded: true;\n records: KbAdjudicated[];\n /** Named only. Their bodies are reachable through `trace`. */\n superseded: KbSupersededStub[];\n recordCount: number;\n tokensLoaded: number;\n /** `null` when loaded via `all`: no ceiling was applied. */\n budgetTokens: number | null;\n /**\n * Sha256 over every record's content and standing, sorted by concept\n * id. Flips when a body, frontmatter, or standing changes; it's the\n * base's content stamp, compared by hooks and `kb_stamp` (SAA-719).\n */\n digest: string;\n }\n | {\n loaded: false;\n recordCount: number;\n approxTokens: number;\n budgetTokens: number;\n /** The refusal in words, naming the budget and what to call next. */\n message: string;\n /**\n * Same digest a successful load would carry, computed over what would\n * have been handed back. Cheap here — adjudication already ran before\n * the refusal — and it lets a caller notice a refused bundle's content\n * changed (say, after a narrower `type` filter) without loading it.\n */\n digest: string;\n };\n\n/** What `stamp` reports for one base. See `kb-stamp.ts`. */\nexport type KbStampResult = {\n path: string;\n digest: string;\n recordCount: number;\n superseded: number;\n /** Newest `generated.at` across the base, or null when none carries one. */\n newestAt: string | null;\n records: KbRecordStamp[];\n /**\n * Records with at least one anchor whose code no longer matches its hash.\n *\n * Outside the digest, and deliberately: drift is a fact about the working\n * tree, not about the base's content, and folding it in would make a stamp\n * change every time someone checked out a branch. `null` when the drift pass\n * could not run — an unknown count, which is not zero.\n */\n drifted: number | null;\n};\n\nexport type KbWriteInput = {\n type: string;\n slug: string;\n frontmatter: Omit<KbRecordFrontmatter, \"type\">;\n body: string;\n /** Replace an existing record rather than failing on the collision. */\n overwrite?: boolean;\n};\n\nexport type KbWriteResult = KbRecord & {\n /** Whether this write also marked prior records superseded. */\n action: \"created\" | \"superseded-prior\";\n /** `frontmatter.strauss_supersedes` ids that were actually marked. */\n supersededIds: string[];\n};\n\n/**\n * Reads and writes a knowledge bundle.\n *\n * One record per file, deliberately. Several agents run in parallel against the\n * same bundle, and a shared file would need merging — a file-per-record store\n * has no write conflict to resolve, only distinct filenames to choose.\n *\n * The bundle is addressed by path rather than fixed to one directory. A base\n * belongs to whatever prompted it — a worktree, an investigation, a document —\n * and one hardcoded location cannot be all of those.\n *\n * Framework-free on purpose. The consumers are a library caller, a CLI an agent\n * shells out to, and an MCP server; the store takes a logger rather than\n * reaching for one, because only some of those have anything to reach into.\n */\nexport class KbStore {\n constructor(private readonly logger: KbLogger = {}) {}\n\n /**\n * Writes one record. `type` and `slug` compose both the filename and the\n * concept id, so a caller cannot produce a file whose identity disagrees with\n * its contents.\n */\n async write(\n bundlePath: string,\n input: KbWriteInput,\n actor = \"unknown\",\n ): Promise<KbWriteResult> {\n if (!KB_SLUG_PATTERN.test(input.slug)) {\n throw new KbInvalidConceptIdError(\"slug must be kebab-case\", {\n slug: input.slug,\n });\n }\n if (!KB_SLUG_PATTERN.test(input.type)) {\n throw new KbInvalidConceptIdError(\"type must be kebab-case\", {\n type: input.type,\n });\n }\n\n const frontmatter = kbRecordFrontmatterSchema.parse({\n ...input.frontmatter,\n type: input.type,\n });\n const conceptId = `${input.type}.${input.slug}`;\n const root = this.root(bundlePath);\n const target = this.recordPath(bundlePath, conceptId);\n\n await mkdir(root, { recursive: true });\n await this.publish(\n target,\n stringifyMarkdownWithFrontmatter(input.body, frontmatter),\n input.overwrite ?? false,\n conceptId,\n );\n\n await this.record(root, {\n operation: input.overwrite ? \"overwrite\" : \"write\",\n conceptId,\n by: actor,\n });\n\n // The new record is published and logged first, then each prior record it\n // supersedes is marked. A crash between the two leaves an old\n // record with no backlink — exactly what kb_validate already reports as\n // \"<old> is not marked superseded\", never a silent drift.\n //\n // Naming itself is a no-op, not an error — the record is already itself.\n // Duplicates collapse through the Set, so a repeated id marks once.\n const targets = new Set(frontmatter.strauss_supersedes ?? []);\n targets.delete(conceptId);\n\n // Targets are marked sequentially, in order: targets are 1-3 in practice,\n // and marking them concurrently made log.jsonl entry order depend on\n // which retry finished first rather than on strauss_supersedes order.\n const supersededIds: string[] = [];\n for (const old of targets) {\n if (\n await this.markSupersededRetrying(bundlePath, old, conceptId, actor)\n ) {\n supersededIds.push(old);\n }\n }\n\n this.logger.info?.({\n operation: \"kb.write\",\n bundlePath: root,\n conceptId,\n anchors: frontmatter.strauss_anchors?.length ?? 0,\n });\n\n return {\n conceptId,\n frontmatter,\n body: input.body,\n action: supersededIds.length ? \"superseded-prior\" : \"created\",\n supersededIds,\n };\n }\n\n /** One record by concept id, or null when it does not exist. */\n async read(bundlePath: string, conceptId: string): Promise<KbRecord | null> {\n // Resolved outside the try: the `catch` exists to turn a missing file into\n // `null`, and must not also swallow the concept-id validation below it.\n const target = this.recordPath(bundlePath, conceptId);\n let raw: string;\n try {\n raw = await readFile(target, \"utf8\");\n } catch {\n return null;\n }\n return this.parse(conceptId, raw);\n }\n\n /**\n * Every record in the bundle, optionally narrowed to one type.\n *\n * A file that fails to parse is skipped and logged rather than thrown: one\n * malformed record — hand-edited, or written by a producer we don't know —\n * must not make the whole bundle unreadable.\n */\n async list(bundlePath: string, type?: string): Promise<KbRecord[]> {\n const root = this.root(bundlePath);\n let names: string[];\n try {\n names = await readdir(root);\n } catch {\n return [];\n }\n\n // The type filter runs on the filename, so a narrowed list never opens a\n // record it is going to discard. What remains is read concurrently: the\n // cost here is per-file syscall latency, not CPU.\n const wanted = names\n .sort()\n // Both store-owned files are markdown and neither is a record; without\n // this they parse to null and are dropped, but not before logging a\n // warning that says the bundle contains a malformed record.\n .filter((name) => name.endsWith(\".md\") && !STORE_OWNED.has(name))\n .map((name) => ({ name, conceptId: name.slice(0, -\".md\".length) }))\n .filter(({ conceptId }) => !type || conceptId.startsWith(`${type}.`));\n\n const records = await mapLimit(\n wanted,\n DEFAULT_IO_CONCURRENCY,\n async ({ name, conceptId }) =>\n this.parse(conceptId, await readFile(join(root, name), \"utf8\")),\n );\n return records.filter((record): record is KbRecord => record !== null);\n }\n\n /**\n * Moves a record's status, preserving everything else.\n *\n * Read-modify-write on one file is the one place two agents genuinely race,\n * and the fix is a compare-and-swap rather than a lock: hash on read, verify\n * the file is unchanged immediately before writing, fail if it moved. A lock\n * would buy the same guarantee and add a stale-lock failure mode — a writer\n * killed mid-hold blocks every later one until someone reasons about\n * timeouts.\n */\n async setStatus(\n bundlePath: string,\n conceptId: string,\n status: KbRecordStatus,\n actor = \"unknown\",\n ): Promise<KbRecord> {\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({ ...frontmatter, strauss_status: status }),\n { operation: `status:${status}`, by: actor },\n );\n }\n\n /**\n * Replaces a record's anchors wholesale, preserving everything else.\n *\n * Wholesale rather than merged: the caller just resolved the anchors it is\n * writing, so it holds the complete current set, and a merge would keep\n * stale entries the resolution pass deliberately dropped.\n */\n async updateAnchors(\n bundlePath: string,\n conceptId: string,\n anchors: KbAnchor[],\n actor = \"unknown\",\n ): Promise<KbRecord> {\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({ ...frontmatter, strauss_anchors: anchors }),\n { operation: \"anchor-resolve\", by: actor },\n );\n }\n\n /**\n * Appends one `verified[]` event: who checked the record, when, and what the\n * check found. Append-only — prior events are history, and are spread into\n * the new array untouched rather than reshaped through the write schema.\n *\n * A record's generator cannot verify its own record unless the actor is\n * human: the generator re-reading its own output is not an independent\n * check. The rule runs before the mutation so a refusal never publishes,\n * and the refusal is logged under its own operation name — `mutate` only\n * logs what it publishes.\n */\n async verify(\n bundlePath: string,\n conceptId: string,\n note: string,\n actor = \"unknown\",\n at = new Date().toISOString(),\n ): Promise<KbRecord> {\n const event = kbVerifiedEventSchema.parse({ by: actor, at, note });\n\n const existing = await this.read(bundlePath, conceptId);\n if (!existing) throw new KbRecordNotFoundError(conceptId);\n\n // The equality test compares whole actors case-insensitively: case drift\n // (`agent:Claude` vs `agent:claude`) must not mint a distinct verifier\n // identity. Only the `human:` exemption keeps the prefix-only\n // normalization.\n const generatedBy = existing.frontmatter.generated?.by;\n if (\n generatedBy !== undefined &&\n actor.toLowerCase() === generatedBy.toLowerCase() &&\n !normalizeActor(actor).startsWith(\"human:\")\n ) {\n await this.record(this.root(bundlePath), {\n operation: \"verify:refused\",\n conceptId,\n by: actor,\n });\n throw new KbSelfVerificationError(conceptId, actor, generatedBy);\n }\n\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({\n ...frontmatter,\n verified: [...(frontmatter.verified ?? []), event],\n }),\n { operation: \"verify\", by: actor },\n );\n }\n\n /**\n * Marks `conceptId` superseded by `replacementId`, and links both directions.\n *\n * Writing one side and letting a validator notice the other is missing was\n * the previous arrangement; doing both here means the backlink cannot drift\n * in normal use, and validation drops to catching hand-edits.\n */\n async supersede(\n bundlePath: string,\n conceptId: string,\n replacementId: string,\n actor = \"unknown\",\n ): Promise<KbRecord> {\n const replacement = await this.read(bundlePath, replacementId);\n if (!replacement) throw new KbRecordNotFoundError(replacementId);\n\n const superseded = await this.markSuperseded(\n bundlePath,\n conceptId,\n replacementId,\n actor,\n );\n\n await this.mutate(\n bundlePath,\n replacementId,\n (frontmatter) => ({\n ...frontmatter,\n strauss_supersedes: [\n ...new Set([...(frontmatter.strauss_supersedes ?? []), conceptId]),\n ],\n }),\n { operation: \"supersedes\", by: actor, target: conceptId },\n );\n\n return superseded;\n }\n\n /** Resolves an open question, stamping who answered and when. */\n async answer(\n bundlePath: string,\n conceptId: string,\n answer: string,\n actor = \"unknown\",\n at = new Date().toISOString(),\n ): Promise<KbRecord> {\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({\n ...frontmatter,\n strauss_status: \"resolved\" as const,\n strauss_answered: { by: actor, at },\n }),\n { operation: \"answer\", by: actor },\n (body) => `${body.trimEnd()}\\n\\n## Answer\\n\\n${answer}\\n`,\n );\n }\n\n /**\n * Records matching a text query, each carrying its standing.\n *\n * Relevance comes from qmd's BM25 where an index is available and from a\n * substring scan where it is not. What never moves to the ranker is the\n * adjudication below it: a ranker answers relevance, and relevance is not\n * standing — a superseded record is the older, longer, more general one, so\n * ranking alone prefers what is no longer true.\n *\n * The fallback is deliberate. A search index is an optimisation, so losing it\n * degrades recall and must never change the answer's shape or fail the call.\n */\n async query(\n bundlePath: string,\n text: string,\n options: {\n type?: string;\n includeNonCurrent?: boolean;\n repoRoot?: string;\n } = {},\n ): Promise<KbAdjudicated[]> {\n const bundle = await this.list(bundlePath);\n const needle = text.trim();\n const hits = needle ? await this.rank(bundlePath, needle, bundle) : bundle;\n const narrowed = options.type\n ? hits.filter((r) => r.frontmatter.type === options.type)\n : hits;\n const adjudicated = adjudicate(\n narrowed,\n bundle,\n new Date(),\n await this.detectDrift(narrowed, options.repoRoot),\n );\n\n if (options.includeNonCurrent) return adjudicated;\n // Superseded records are dropped only once their replacement is in the\n // result too — otherwise the caller loses the thread entirely rather than\n // being handed a newer version of it.\n const present = new Set(adjudicated.map((hit) => hit.record.conceptId));\n return adjudicated.filter(\n (hit) =>\n hit.standing !== \"superseded\" ||\n !hit.heads.some((head) => present.has(head.conceptId)),\n );\n }\n\n private async rank(\n bundlePath: string,\n needle: string,\n bundle: KbRecord[],\n ): Promise<KbRecord[]> {\n const ranked = await searchBase(this.root(bundlePath), needle, {\n logger: this.logger,\n });\n if (ranked) {\n const found = resolveHits(ranked, bundle);\n if (found.length) return found;\n }\n const lowered = needle.toLowerCase();\n return bundle.filter((record) => matches(record, lowered));\n }\n\n /**\n * Anchor drift over the records about to be handed back. Like the search\n * index, this is an enrichment: a filesystem failure degrades to \"no drift\n * reported\" rather than failing the read. Anchors without a stored hash are\n * skipped inside `detectAnchorDrift`, so a base nobody has stamped pays no\n * fs cost here. `repoRoot` defaults to the working directory — the CLI runs\n * at the repo root, and the MCP server's cwd is the workspace.\n *\n * Public because `doctor` needs the same map with the same degradation: a\n * sweep that failed to read the tree should report no drift, not fail — and\n * `offline: false` there, because a sweep is worth a fetch.\n *\n * When no root was given and not one anchored file was found, the finding is\n * discarded. A base read from somewhere other than the tree it describes\n * misses every file at once, and that shape is far likelier to be a wrong\n * default root than a repository where every anchored file was deleted on\n * the same day. Reporting it would put a drift warning on every record in\n * the base, which teaches a reader to ignore the warning — the one outcome\n * worse than not having it. One file found anywhere makes the root\n * plausible, and the misses become findings again; an explicit `repoRoot` is\n * taken at its word either way.\n */\n async detectDrift(\n records: KbRecord[],\n repoRoot?: string,\n options: { offline?: boolean } = {},\n ): Promise<Map<string, KbAnchorDriftEntry[]> | undefined> {\n try {\n const drift = await detectAnchorDrift(records, {\n repoRoot: repoRoot ?? process.cwd(),\n // Offline by default: a read path must never spend a network fetch per\n // call. `doctor` and `anchor-resolve` are the verbs that go get it.\n remote: { offline: options.offline !== false },\n });\n if (repoRoot === undefined && looksLikeWrongRepoRoot(drift)) {\n this.logger.warn?.({\n operation: \"kb.anchor-drift\",\n outcome: \"skipped\",\n reason: \"no anchored file found under the default repo root\",\n });\n return undefined;\n }\n return drift;\n } catch (error) {\n this.logger.warn?.({\n operation: \"kb.anchor-drift\",\n outcome: \"skipped\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n return undefined;\n }\n }\n\n /**\n * The whole base, adjudicated, when it is small enough to hand over.\n *\n * At the sizes these reach — twenty records is about three thousand tokens —\n * loading everything beats searching it, and measurably: on nine questions\n * whose wording appears in no record, a reader holding the base answered\n * eight against an embedding search's four. Two of those differences are\n * structural. A reader can say no record answers the question; vector search\n * returns its nearest neighbour whatever the distance. And a reader picks the\n * record that answers the question rather than the one nearest the topic.\n * See the README's retrieval section for the measurements.\n *\n * Load it for a question, not for a session — a base read into a long\n * conversation is summarised away by the end of it.\n *\n * Refuses rather than truncates when the base is too large. A truncated base\n * is indistinguishable from a complete one, so a caller would answer \"that\n * was never decided\" from a slice it did not know was a slice.\n *\n * A token budget decides that, measured over what is actually handed back.\n * The refusal names the estimate and the budget, because a caller told only\n * \"too big\" cannot tell whether to narrow the type filter, raise the budget,\n * or stop loading the base whole altogether. Past the budget the answer is\n * the catalog and then a pack, which is what the refusal says.\n *\n * That refusal is the default guardrail. `all` bypasses the budget outright\n * and always hands back the whole bundle: an explicit, never-accidental\n * escape hatch for an operator who has the budget to spend, not a wider\n * default.\n */\n async load(\n bundlePath: string,\n options: {\n budgetTokens?: number;\n type?: string;\n all?: boolean;\n repoRoot?: string;\n } = {},\n ): Promise<KbLoadResult> {\n const budgetTokens = options.budgetTokens ?? DEFAULT_LOAD_BUDGET;\n const bundle = await this.list(bundlePath);\n const wanted = options.type\n ? bundle.filter((record) => record.frontmatter.type === options.type)\n : bundle;\n\n // Adjudicated against the whole base, not the filtered slice: a record's\n // replacement may be of another type.\n const adjudicated = adjudicate(\n wanted,\n bundle,\n new Date(),\n await this.detectDrift(wanted, options.repoRoot),\n );\n const records = adjudicated.filter((hit) => hit.standing !== \"superseded\");\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(stub);\n\n // Measured over what is actually handed back. Costing the full bodies would\n // refuse bases that fit comfortably once the superseded ones are stubs.\n const approxTokens =\n records.reduce((total, hit) => total + estimateTokens(hit.record), 0) +\n superseded.reduce((total, entry) => total + estimateStubTokens(entry), 0);\n\n // Adjudication has already run either way, so this costs nothing extra —\n // computed once and carried on whichever branch returns.\n const bundleDigestValue = bundleDigest(records, superseded);\n\n if (!options.all && approxTokens > budgetTokens) {\n return {\n loaded: false,\n recordCount: wanted.length,\n approxTokens,\n budgetTokens,\n message: refusalMessage({\n approxTokens,\n budgetTokens,\n type: options.type,\n }),\n digest: bundleDigestValue,\n };\n }\n\n return {\n loaded: true,\n recordCount: wanted.length,\n tokensLoaded: approxTokens,\n budgetTokens: options.all ? null : budgetTokens,\n records,\n superseded,\n digest: bundleDigestValue,\n };\n }\n\n /**\n * `load`'s digest without `load`'s bodies — the same records, adjudicated\n * the same way, handed back as a stamp.\n *\n * Drift is counted but kept out of the digest, which is what lets the reload\n * hook ask one question and get two answers: whether the base moved, and\n * whether the code under it did. A `load` and a `stamp` of the same base\n * still agree on the digest, because no warning has ever reached it.\n */\n async stamp(\n bundlePath: string,\n options: { repoRoot?: string } = {},\n ): Promise<KbStampResult> {\n const bundle = await this.list(bundlePath);\n const adjudicated = adjudicate(bundle, bundle, new Date());\n const current = adjudicated.filter((hit) => hit.standing !== \"superseded\");\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(stub);\n\n const stamped = bundleStamp(current, superseded);\n const dates = bundle\n .map((record) => record.frontmatter.generated?.at ?? null)\n .filter((at): at is string => typeof at === \"string\")\n .sort();\n\n // Counted after the digest, so a failed or suppressed drift pass can only\n // cost the count, never the stamp.\n //\n // Deliberately the shallow pass: `detectAnchorDrift` compares hashes and\n // stops, so this reads each anchored file once and never lists or parses\n // the repository. `moved` and `cosmetic` would need both, and a count does\n // not want them — a reload hook runs this after ordinary git commands, and\n // it asks how many records need a look, not which of them are relocatable.\n // That question belongs to `reassess` and `doctor --drifted`. Anchors\n // naming another repository are read from the local cache only — never\n // fetched — and an unchecked one is never counted.\n const drift = await this.detectDrift(bundle, options.repoRoot);\n const drifted =\n drift === undefined\n ? null\n : [...drift.values()].filter((entries) =>\n entries.some(\n (entry) =>\n entry.state !== \"match\" && !isUncheckedReason(entry.reason),\n ),\n ).length;\n\n return {\n path: bundlePath,\n digest: stamped.digest,\n recordCount: bundle.length,\n superseded: superseded.length,\n newestAt: dates.at(-1) ?? null,\n records: stamped.records,\n drifted,\n };\n }\n\n /** How a position was arrived at, as a timeline. See `trace.ts`. */\n async trace(\n bundlePath: string,\n seedId: string,\n options: KbTraceOptions = {},\n ): Promise<KbTraceStep[]> {\n return trace(seedId, await this.list(bundlePath), options);\n }\n\n /** Every record named in one line each. See `catalog.ts`. */\n async catalog(\n bundlePath: string,\n options: { type?: string; now?: Date } = {},\n ): Promise<KbCatalogResult> {\n return catalog(await this.list(bundlePath), options);\n }\n\n /** A bounded neighbourhood around one record. See `pack.ts`. */\n async pack(\n bundlePath: string,\n rootId: string,\n options: KbPackOptions = {},\n ): Promise<KbPackResult> {\n return pack(await this.list(bundlePath), rootId, options);\n }\n\n /** What breaks if this record changes. See `kb-links/impact.ts`. */\n async impact(\n bundlePath: string,\n targetId: string,\n options: KbImpactOptions = {},\n ): Promise<KbImpactResult> {\n return impact(targetId, await this.list(bundlePath), options);\n }\n\n /** Who points at this record, one hop. See `kb-links/backlinks.ts`. */\n async backlinks(\n bundlePath: string,\n targetId: string,\n ): Promise<KbBacklinksResult> {\n return backlinks(targetId, await this.list(bundlePath));\n }\n\n /**\n * The stored index, rebuilt if it disagrees with the records.\n *\n * Repair on read is what makes the lock-free write path safe: a writer whose\n * scan predated another writer's record publishes a momentarily stale index,\n * and the next reader through here settles it.\n */\n async readIndex(bundlePath: string): Promise<string> {\n const root = this.root(bundlePath);\n const expected = renderIndex(await this.list(bundlePath));\n const stored = await readFile(join(root, INDEX_FILE), \"utf8\").catch(\n () => null,\n );\n\n if (indexIsStale(stored, expected)) {\n await this.publish(join(root, INDEX_FILE), expected, true, INDEX_FILE);\n this.logger.info?.({\n operation: \"kb.index.repair\",\n bundlePath: root,\n reason: stored === null ? \"missing\" : \"stale\",\n });\n }\n return expected;\n }\n\n /**\n * The log, with unparseable lines reported rather than repaired.\n *\n * The log is the bundle's only artifact that cannot be reconstructed — the\n * records rebuild the index, and the code outlives both, but nothing else\n * knows which agent touched what. So a bad line is surfaced and left alone.\n */\n async readLog(bundlePath: string): Promise<ReturnType<typeof parseLog>> {\n const raw = await readFile(\n join(this.root(bundlePath), LOG_FILE),\n \"utf8\",\n ).catch(() => \"\");\n const result = parseLog(raw);\n for (const bad of result.malformed) {\n this.logger.warn?.({\n operation: \"kb.log.parse\",\n line: bad.line,\n outcome: \"skipped\",\n });\n }\n return result;\n }\n\n /**\n * `markSuperseded`, tolerant of the two ways it legitimately doesn't land:\n * a missing target (a broken link, legal per compose.ts) or a CAS conflict\n * from a concurrent writer touching the same target. A conflict is retried\n * a bounded number of times — each attempt re-reads the target fresh — and\n * on the last, `false` reports \"not marked\" rather than throwing: the\n * caller's own record is already published, so failing here would leave\n * that publish unreported instead of undone. kb_validate's existing\n * \"not marked superseded\" check is what surfaces the residue.\n */\n private async markSupersededRetrying(\n bundlePath: string,\n conceptId: string,\n replacementId: string,\n actor: string,\n retries = 3,\n ): Promise<boolean> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n await this.markSuperseded(bundlePath, conceptId, replacementId, actor);\n return true;\n } catch (error) {\n if (error instanceof KbRecordNotFoundError) return false;\n if (!(error instanceof KbWriteConflictError)) throw error;\n if (attempt === retries) return false;\n }\n }\n return false;\n }\n\n /** The one-directional half of `supersede`: marks `conceptId` superseded. */\n private async markSuperseded(\n bundlePath: string,\n conceptId: string,\n replacementId: string,\n actor: string,\n ): Promise<KbRecord> {\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({\n ...frontmatter,\n strauss_status: \"superseded\" as const,\n strauss_superseded_by: replacementId,\n }),\n { operation: \"supersede\", by: actor, target: replacementId },\n );\n }\n\n private async mutate(\n bundlePath: string,\n conceptId: string,\n change: (frontmatter: KbRecordFrontmatter) => KbRecordFrontmatter,\n entry: Omit<KbLogEntry, \"at\" | \"conceptId\"> & { target?: string },\n changeBody: (body: string) => string = (body) => body,\n ): Promise<KbRecord> {\n const target = this.recordPath(bundlePath, conceptId);\n const before = await readFile(target, \"utf8\").catch(() => null);\n if (before === null) throw new KbRecordNotFoundError(conceptId);\n\n const parsed = this.parse(conceptId, before);\n if (!parsed) throw new KbRecordNotFoundError(conceptId);\n\n const frontmatter = change(parsed.frontmatter);\n const body = changeBody(parsed.body);\n const contents = stringifyMarkdownWithFrontmatter(body, frontmatter);\n\n // Optimistic check, not a hard guarantee: a writer landing between this\n // read and the publish below still wins silently. It narrows the window\n // from \"the whole compose\" to two adjacent syscalls, which is as far as a\n // filesystem goes without a lock — and a lock's stale-hold failure mode is\n // worse than the residue.\n const witness = await readFile(target, \"utf8\").catch(() => null);\n if (witness === null || digest(witness) !== digest(before)) {\n throw new KbWriteConflictError(conceptId);\n }\n await this.publish(target, contents, true, conceptId);\n await this.record(this.root(bundlePath), { ...entry, conceptId });\n\n return { conceptId, frontmatter, body };\n }\n\n /**\n * Two guarantees, both about writers running in parallel.\n *\n * The record is written to a staging file and only then published, so a\n * concurrent reader sees the whole record or no record — never half of one. A\n * plain write is not atomic, and `list()` skips what it cannot parse, so a\n * torn read would be silently reported as a malformed record.\n *\n * Publishing uses `link` rather than `rename` unless the caller asked to\n * overwrite: `link` fails with EEXIST instead of replacing, which turns \"two\n * writers chose the same concept id\" from silent data loss into a collision\n * the caller has to answer. Both are atomic; only `rename` clobbers.\n *\n * The staging name deliberately does not end in `.md` — `list()` would\n * otherwise try to read it mid-write.\n */\n private async publish(\n target: string,\n contents: string,\n overwrite: boolean,\n conceptId: string,\n ): Promise<void> {\n const staging = `${target}.${process.pid}.tmp`;\n await writeFile(staging, contents, \"utf8\");\n\n try {\n if (overwrite) {\n await rename(staging, target);\n return;\n }\n await link(staging, target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new KbRecordAlreadyExistsError(conceptId);\n }\n throw error;\n } finally {\n // `rename` consumed the staging file; `link` left it behind.\n await unlink(staging).catch(() => undefined);\n }\n }\n\n /**\n * Declares union merge for the log, so two worktrees writing the same\n * bundle interleave their `log.jsonl` lines on merge rather than one\n * side's appends silently losing to git's ordinary line-level merge.\n *\n * Called from `record` — every path that appends a log line, not just\n * `write` — so a bundle only ever mutated through `setStatus`/`verify`/\n * `supersede` still gets it. There is no cheaper reliable signal for\n * \"first write\" than checking the file itself, and after the first call\n * the check is a no-op `readFile`.\n *\n * A missing `.gitattributes` is created outright, with `wx` (exclusive\n * create) rather than a plain write: if another process's `write()` won a\n * race and created the file between the `readFile` below and this call,\n * `wx` fails instead of truncating what that writer just wrote, and the\n * failure is swallowed by the catch below same as any other best-effort\n * miss. A file that exists but declares no merge strategy for the log\n * gets the line appended, never a wholesale rewrite; one that already\n * declares any merge strategy — this one or a user's own — is left alone\n * entirely (see `hasMergeDeclaration`).\n *\n * `readFile` failing is `existing === null` only for `ENOENT` — genuinely\n * missing. Any other error (a permission problem, a transient `EMFILE`,\n * the path being a directory) is *not* \"missing\" and must not fall into\n * the create branch, which would truncate whatever is actually there with\n * just the union-merge line: that is the file-destroying bug this\n * function exists to avoid, not commit. An unreadable existing file is\n * therefore left untouched and reported as a failure like any other.\n *\n * Two processes racing the append branch — both read a file without the\n * line, both append it — is possible and left unguarded: `appendFile` is\n * `O_APPEND`, so the result is two copies of the same line rather than a\n * torn write, and `hasMergeDeclaration` sees a duplicate declaration as\n * \"already declared\" on the next call. A cheap-to-detect, harmless-to-\n * leave residue, not a reason to add a cross-process lock (see\n * `ARCHITECTURE.md`'s rejection of one for the same trade on records).\n *\n * Best-effort, like the log append it precedes: failing to write this\n * file must not fail the mutation it guards.\n */\n private async ensureGitattributes(root: string): Promise<void> {\n const target = join(root, GITATTRIBUTES_FILE);\n try {\n let existing: string | null;\n try {\n existing = await readFile(target, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n existing = null;\n }\n\n if (existing === null) {\n try {\n await writeFile(target, appendUnionMergeLine(\"\"), {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n } catch (error) {\n // Another writer created the same file with the same content\n // between our read and our write — a win for them counts as a win\n // for us, not a failure.\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n this.logger.info?.({\n operation: \"kb.gitattributes.ensure\",\n bundlePath: root,\n outcome: \"exists\",\n });\n return;\n }\n this.logger.info?.({\n operation: \"kb.gitattributes.ensure\",\n bundlePath: root,\n outcome: \"created\",\n });\n return;\n }\n if (!hasMergeDeclaration(existing)) {\n await appendFile(target, appendUnionMergeLine(existing), \"utf8\");\n this.logger.info?.({\n operation: \"kb.gitattributes.ensure\",\n bundlePath: root,\n outcome: \"appended\",\n });\n }\n } catch (error) {\n this.logger.warn?.({\n operation: \"kb.gitattributes.ensure\",\n outcome: \"failed\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n }\n }\n\n /** Appends one log line. Failing to log must not fail the mutation. */\n private async record(\n root: string,\n entry: Omit<KbLogEntry, \"at\"> & { at?: string },\n ): Promise<void> {\n await this.ensureGitattributes(root);\n const line = renderLogEntry({ at: new Date().toISOString(), ...entry });\n await appendFile(join(root, LOG_FILE), line, \"utf8\").catch((error) => {\n this.logger.warn?.({\n operation: \"kb.log.append\",\n outcome: \"failed\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n });\n }\n\n private parse(conceptId: string, raw: string): KbRecord | null {\n const parsed = parseMarkdownWithFrontmatter(raw, kbRecordFrontmatterSchema);\n if (!parsed.frontmatter.success) {\n this.logger.warn?.({\n operation: \"kb.parse\",\n conceptId,\n outcome: \"skipped\",\n error: parsed.frontmatter.error.issues[0]?.message ?? \"invalid\",\n });\n return null;\n }\n return {\n conceptId,\n frontmatter: parsed.frontmatter.data,\n body: parsed.content,\n };\n }\n\n private root(bundlePath: string): string {\n return resolve(bundlePath);\n }\n\n // Concept ids are `<type>.<slug>` and map to a single file directly under the\n // bundle root; anything carrying a separator would escape it.\n private recordPath(bundlePath: string, conceptId: string): string {\n if (conceptId.includes(sep) || conceptId.includes(\"/\")) {\n throw new KbInvalidConceptIdError(\n \"concept id must not contain a path separator\",\n { conceptId },\n );\n }\n return join(this.root(bundlePath), `${conceptId}.md`);\n }\n}\n\n/**\n * Deliberately crude, and labelled `approx` everywhere it surfaces. A real\n * tokeniser would be a dependency carried to decide whether to avoid carrying\n * dependencies, and four characters per token is close enough to choose\n * between \"hand it over\" and \"do not\".\n *\n * Exported (with `estimateStubTokens` and `stub`) so `pack` costs and stubs\n * records exactly as `load` does — two accountings would drift.\n */\nexport function estimateTokens(record: KbRecord): number {\n return Math.ceil(\n (record.body.length + JSON.stringify(record.frontmatter).length) / 4,\n );\n}\n\nexport function estimateStubTokens(entry: KbSupersededStub): number {\n return Math.ceil(JSON.stringify(entry).length / 4);\n}\n\n/** What a refused load says: what tripped the budget, and what to call next. */\nfunction refusalMessage(refusal: {\n approxTokens: number;\n budgetTokens: number;\n type?: string;\n}): string {\n const scope = refusal.type ? ` of type ${refusal.type}` : \"\";\n\n return [\n `Refusing to load this base whole: ~${refusal.approxTokens} tokens is past the ${refusal.budgetTokens}-token budget.`,\n `Call kb_catalog for one line per record${scope} (id, type, title, standing), then kb_pack on the record that matters; kb_query works for a lookup by wording.`,\n `To load anyway: raise budgetTokens (currently ${refusal.budgetTokens}), or all=true to bypass the budget.`,\n ].join(\" \");\n}\n\n/**\n * `heads` is where the supersession chain ends, which is what a reader needs:\n * pointing at an intermediate record that is itself superseded would answer\n * \"what replaced this\" with something else that no longer holds. A broken or\n * forked chain resolves to no head, and the warning that says so travels with\n * the head record rather than here.\n */\nexport function stub(hit: KbAdjudicated): KbSupersededStub {\n return {\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n supersededBy: hit.heads.map((head) => head.conceptId),\n at: hit.record.frontmatter.generated?.at ?? null,\n };\n}\n\nfunction matches(record: KbRecord, needle: string): boolean {\n const { title, description } = record.frontmatter;\n // The concept id is searched too: a slug is chosen to describe the record, so\n // a base where `decision.cursor-v2` does not answer \"cursor\" is surprising in\n // a way no caller would think to work around.\n return [record.conceptId, title, description, record.body].some((field) =>\n field?.toLowerCase().includes(needle),\n );\n}\n\n/**\n * Case-normalizes only the kind prefix — the segment up to and including the\n * first `:` — so `Human:alice` and `human:alice` name the same kind of actor\n * while the identity after the colon keeps its case. An id with no colon is\n * all prefix, and is lowercased whole.\n */\nfunction normalizeActor(id: string): string {\n const colon = id.indexOf(\":\");\n if (colon === -1) return id.toLowerCase();\n return id.slice(0, colon + 1).toLowerCase() + id.slice(colon + 1);\n}\n","import matter from \"gray-matter\";\nimport type { z } from \"zod\";\n\n/**\n * Frontmatter round-tripping, thin over gray-matter.\n *\n * Thin on purpose. A record is a YAML block and a markdown body, and every\n * hand-rolled reader of that shape eventually meets a nested map — an OKF\n * `generated`, a `sources[]`, a `verified[]` — and misreads it. The parser is\n * therefore borrowed and the only thing added is the schema gate below.\n */\nexport function stringifyMarkdownWithFrontmatter(\n content: string,\n frontmatter: Record<string, unknown>,\n): string {\n return matter.stringify(content, frontmatter);\n}\n\nexport function splitMarkdownFrontmatter(text: string): {\n content: string;\n prefix: string;\n raw: Record<string, unknown>;\n} {\n const file = matter(text);\n\n return {\n content: file.content,\n // Everything gray-matter consumed: the fences, the YAML, and the blank line\n // after them. Kept so a caller can rewrite a body without touching the head.\n prefix: text.slice(0, text.length - file.content.length),\n raw: file.data as Record<string, unknown>,\n };\n}\n\n/**\n * Splits, then validates the frontmatter against a schema.\n *\n * The result is a `safeParse` outcome rather than a throw: one malformed record\n * must not make a whole directory unreadable, so the caller decides whether to\n * skip it or fail.\n */\nexport function parseMarkdownWithFrontmatter<S extends z.ZodType>(\n text: string,\n schema: S,\n): {\n content: string;\n prefix: string;\n raw: Record<string, unknown>;\n frontmatter: ReturnType<S[\"safeParse\"]>;\n} {\n const { content, prefix, raw } = splitMarkdownFrontmatter(text);\n\n return {\n content,\n prefix,\n raw,\n frontmatter: schema.safeParse(raw) as ReturnType<S[\"safeParse\"]>,\n };\n}\n","/**\n * A base's content stamp: `load`'s digest, and the per-record digests it is\n * built from.\n *\n * The aggregate answers \"did anything change\"; the per-record entries answer\n * \"which records\", which is what a reload notice has to name. One pass\n * produces both, so `load` and `stamp` cannot disagree.\n */\nimport { createHash } from \"node:crypto\";\nimport { stringifyMarkdownWithFrontmatter } from \"./markdown.js\";\nimport type { KbAdjudicated } from \"./adjudicate.js\";\nimport type { KbSupersededStub } from \"./kb-store.js\";\n\nexport type KbRecordStamp = { conceptId: string; digest: string };\n\nexport type KbBundleStamp = { digest: string; records: KbRecordStamp[] };\n\nexport function sha256(contents: string): string {\n return createHash(\"sha256\").update(contents).digest(\"hex\");\n}\n\n/**\n * Entries are sorted by concept id, so the digest never depends on listing\n * order; each is hashed over its record's canonical recomposed form, not the\n * on-disk bytes; superseded stubs are included, so a standing flip changes the\n * digest even when the body did not.\n */\nexport function bundleStamp(\n records: KbAdjudicated[],\n superseded: KbSupersededStub[],\n): KbBundleStamp {\n const entries: KbRecordStamp[] = [\n ...records.map((hit) => ({\n conceptId: hit.record.conceptId,\n digest: `current:${sha256(\n stringifyMarkdownWithFrontmatter(\n hit.record.body,\n hit.record.frontmatter,\n ),\n )}`,\n })),\n ...superseded.map((entry) => ({\n conceptId: entry.conceptId,\n digest: `superseded:${sha256(JSON.stringify(entry))}`,\n })),\n ].sort((a, b) => (a.conceptId < b.conceptId ? -1 : 1));\n\n return {\n digest: sha256(\n entries.map((entry) => `${entry.conceptId}:${entry.digest}`).join(\"\\n\"),\n ),\n records: entries,\n };\n}\n\nexport function bundleDigest(\n records: KbAdjudicated[],\n superseded: KbSupersededStub[],\n): string {\n return bundleStamp(records, superseded).digest;\n}\n","import { stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"./concurrency.js\";\nimport { INDEX_FILE } from \"./kb-index.js\";\nimport { LOG_FILE } from \"./kb-log.js\";\n\nexport const SEARCH_INDEX_FILE = \".index.sqlite\";\n\nconst COLLECTION = \"kb\";\n\n/**\n * BM25 over one knowledge base, via qmd's SDK.\n *\n * Reached only when a base is too large to hand over whole — see `load()`,\n * which is the first thing a reader should try.\n *\n * Lexical only. `searchLex` is BM25 and needs no model. Measured against the\n * substring scan it replaces it wins on word forms and little else: `pages`\n * finds a record saying only `page`, and eight of nine probe queries returned\n * exactly what substring returned.\n *\n * The vector tier does close the semantic gap — \"why not just use a mutex\"\n * finds the record about compare-and-swap, which no lexical match can. It stays\n * off because its scores do not separate right from wrong: a wrong hit scored\n * 0.318 against a correct one at 0.295, and a query about a subject absent from\n * the base still returns its nearest record rather than nothing.\n *\n * The index is derived and disposable — one file per base, gitignored, deleted\n * and rebuilt at will. That is only true because a base is self-contained: an\n * index covering exactly one directory can always be rebuilt from it.\n *\n * qmd is used as a **library**, and is an optional peer dependency: with it\n * absent every path here still answers, `searchBase` returns null, and the\n * store falls back to a substring scan. Its own MCP server would let an agent\n * reach a base without passing the store, and its default markdown glob would\n * return `INDEX.md` as a search hit — the case `list()` already excludes,\n * reintroduced by a reader this package does not control. Hence the explicit\n * `ignore` below.\n */\n/**\n * A hit as qmd reports it — by its own normalised path, not by our identity.\n *\n * qmd rewrites `decision.cursor-keyset.md` to `decision-cursor-keyset.md`,\n * which destroys the separator between a record's type and its slug and cannot\n * be undone from the string alone: `decision-cursor-keyset` could be the type\n * `decision` or a type `decision-cursor`. The caller maps these back through\n * the records it already holds rather than parsing them.\n */\nexport type SearchHit = { displayPath: string; score: number };\n\ntype QmdStore = {\n searchLex(\n query: string,\n options?: { limit?: number; collection?: string },\n ): Promise<{ displayPath?: string; filepath?: string; score?: number }[]>;\n addCollection(\n name: string,\n opts: { path: string; pattern?: string; ignore?: string[] },\n ): Promise<void>;\n listCollections(): Promise<unknown[]>;\n update(options?: { collections?: string[] }): Promise<unknown>;\n close(): Promise<void>;\n};\n\nexport type KbSearchLogger = {\n warn?(entry: Record<string, unknown>): void;\n};\n\n/** What this module needs of qmd, which is all it is allowed to assume. */\nexport type QmdModule = { createStore(options: unknown): Promise<unknown> };\n\nexport type SearchOptions = {\n limit?: number;\n logger?: KbSearchLogger;\n /**\n * The backend, supplied rather than imported. Production passes nothing and\n * gets the dynamic import below; a caller that already holds qmd — or a test\n * covering the present-backend branch on a machine where the optional peer is\n * not installed — passes it here.\n */\n qmd?: QmdModule;\n};\n\n/**\n * Opens (or creates) the base's index and answers a query against it.\n *\n * Re-indexes when the index is older than the newest record rather than on a\n * schedule or a write hook: the same repair-on-read rule `INDEX.md` follows,\n * and for the same reason — a derived artifact that can rebuild itself does not\n * need anyone to remember to rebuild it.\n */\nexport async function searchBase(\n bundlePath: string,\n query: string,\n options: SearchOptions = {},\n): Promise<SearchHit[] | null> {\n const qmd = options.qmd ?? (await loadQmd(options.logger));\n if (!qmd) return null;\n\n let store: QmdStore | null = null;\n try {\n store = (await qmd.createStore({\n dbPath: join(bundlePath, SEARCH_INDEX_FILE),\n config: {\n collections: {\n [COLLECTION]: {\n path: bundlePath,\n pattern: \"**/*.md\",\n // Both store-owned files are markdown and neither is a record.\n ignore: [INDEX_FILE, LOG_FILE],\n },\n },\n },\n })) as QmdStore;\n\n if (await isStale(bundlePath)) {\n await store.update({ collections: [COLLECTION] });\n }\n\n const hits = await store.searchLex(query, {\n collection: COLLECTION,\n ...(options.limit ? { limit: options.limit } : {}),\n });\n return hits\n .map((hit) => ({\n displayPath: hit.displayPath ?? hit.filepath ?? \"\",\n score: hit.score ?? 0,\n }))\n .filter((hit) => hit.displayPath.length > 0);\n } catch (error) {\n // A search index is an optimisation. Losing it must degrade recall, never\n // the answer — `query()` falls back to substring rather than failing.\n options.logger?.warn?.({\n operation: \"kb.search\",\n outcome: \"unavailable\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n return null;\n } finally {\n await store?.close().catch(() => undefined);\n }\n}\n\n/**\n * Whether any record is newer than the index.\n *\n * Stats run through a bounded pool rather than one at a time; once one record\n * has answered \"newer\", the workers still queued skip their `stat` entirely.\n */\nasync function isStale(bundlePath: string): Promise<boolean> {\n const indexAt = await stat(join(bundlePath, SEARCH_INDEX_FILE))\n .then((s) => s.mtimeMs)\n .catch(() => 0);\n if (!indexAt) return true;\n\n const { readdir } = await import(\"node:fs/promises\");\n const names = (await readdir(bundlePath).catch(() => [] as string[])).filter(\n (name) => name.endsWith(\".md\") && name !== INDEX_FILE,\n );\n\n let stale = false;\n await mapLimit(names, DEFAULT_IO_CONCURRENCY, async (name) => {\n if (stale) return;\n const at = await stat(join(bundlePath, name))\n .then((s) => s.mtimeMs)\n .catch(() => 0);\n if (at > indexAt) stale = true;\n });\n return stale;\n}\n\n/**\n * Maps qmd's normalised paths back onto real records.\n *\n * Comparing on the same normalisation rather than trying to invert it: a dot in\n * a concept id and a dash in a slug are indistinguishable once qmd has rewritten\n * the name, so the only reliable direction is forwards, from ids we hold.\n */\nexport function resolveHits<T extends { conceptId: string }>(\n hits: SearchHit[],\n records: T[],\n): T[] {\n const byName = new Map<string, T>();\n for (const record of records) {\n const name = flatten(record.conceptId);\n // A collision would make the mapping a guess; drop both rather than pick.\n if (byName.has(name)) byName.delete(name);\n else byName.set(name, record);\n }\n\n const resolved: T[] = [];\n for (const hit of hits) {\n const file = hit.displayPath.split(\"/\").pop() ?? \"\";\n const name = file.endsWith(\".md\") ? file.slice(0, -\".md\".length) : file;\n const record = byName.get(flatten(name));\n if (record) resolved.push(record);\n }\n return resolved;\n}\n\nfunction flatten(value: string): string {\n return value.replace(/[.]/g, \"-\").toLowerCase();\n}\n\n/**\n * Held in a variable rather than written inline. qmd is not a dependency of\n * this package, so a literal specifier sends the compiler looking for types\n * that are not installed; the indirection keeps the import dynamic at runtime\n * and invisible at build time, which is what an optional engine needs.\n */\nconst QMD_MODULE = \"@tobilu/qmd\";\n\n/**\n * Loaded on demand so a caller that never searches pays nothing for a\n * dependency that pulls in native SQLite bindings and a llama runtime — and\n * returns null rather than throwing when it is not installed at all, which is\n * the normal case for an optional peer.\n */\nexport async function loadQmd(\n logger?: KbSearchLogger,\n): Promise<QmdModule | null> {\n try {\n return (await import(QMD_MODULE)) as unknown as QmdModule;\n } catch {\n logger?.warn?.({ operation: \"kb.search\", outcome: \"qmd-unavailable\" });\n return null;\n }\n}\n","import { adjudicate, type KbStanding, type KbWarning } from \"./adjudicate.js\";\nimport { neighbours } from \"./kb-edges.js\";\nimport {\n KbPackBudgetExceededError,\n KbRecordNotFoundError,\n} from \"./kb-errors.js\";\nimport {\n KB_RECORD_TYPES,\n type KbAnchor,\n type KbRecord,\n} from \"./kb-record.schema.js\";\nimport {\n DEFAULT_LOAD_BUDGET,\n estimateStubTokens,\n estimateTokens,\n stub,\n type KbSupersededStub,\n} from \"./kb-store.js\";\n\nexport const DEFAULT_PACK_HOPS = 2;\nexport const DEFAULT_PACK_MAX_NODES = 20;\n\nexport type KbPackOptions = {\n /** How far from the root the walk may reach. */\n hops?: number;\n /** How many records the pack may hold, root included. */\n maxNodes?: number;\n /** Approximate token ceiling over what is actually emitted. */\n budgetTokens?: number;\n};\n\n/** One record as the pack emits it — the same mapping `kb_load` hands back. */\nexport type KbPackedRecord = {\n conceptId: string;\n title: string | null;\n standing: KbStanding;\n supersededBy: string[];\n warnings: KbWarning[];\n anchors: KbAnchor[];\n body: string;\n};\n\n/**\n * Deliberately timestamp-free: the same bundle and root must produce the same\n * bytes on every run, so a caller can diff two packs and trust that a changed\n * byte means changed knowledge.\n */\nexport type KbPackResult = {\n root: string;\n records: KbPackedRecord[];\n /** Named only, exactly as `load` stubs them. Bodies reachable via trace. */\n superseded: KbSupersededStub[];\n /** Every reachable record the hop and node limits cut, never summarized. */\n excluded: string[];\n recordCount: number;\n tokensLoaded: number;\n budgetTokens: number;\n};\n\n// What a reader wants first when the walk has to cut: what was settled\n// (decision), then what binds (constraint, requirement), then the rest in\n// their declared order.\nconst TYPE_PRIORITY: readonly string[] = [\n \"decision\",\n \"constraint\",\n \"requirement\",\n ...KB_RECORD_TYPES.filter(\n (type) => ![\"decision\", \"constraint\", \"requirement\"].includes(type),\n ),\n];\n\ntype Reached = { record: KbRecord; depth: number };\n\n/**\n * A bounded, progressively disclosed neighbourhood around one record.\n *\n * Where `load` hands over a whole base and `trace` a timeline, a pack is the\n * subgraph a reader needs to act near one record: everything within `hops`\n * of the root, cut to `maxNodes` by ranking, with every cut id listed —\n * a named gap is knowable, a silent one is not.\n *\n * Adjudication runs against the whole bundle, not the reached slice, so a\n * record's standing cannot depend on whether its replacement happened to be\n * within reach. Superseded records become the same stubs `load` emits, costed\n * as stubs, and the budget is a refusal rather than a truncation: a partial\n * pack looks complete to its reader.\n */\nexport function pack(\n bundle: KbRecord[],\n rootId: string,\n options: KbPackOptions = {},\n): KbPackResult {\n const hops = options.hops ?? DEFAULT_PACK_HOPS;\n const maxNodes = options.maxNodes ?? DEFAULT_PACK_MAX_NODES;\n const budgetTokens = options.budgetTokens ?? DEFAULT_LOAD_BUDGET;\n\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const root = byId.get(rootId);\n if (!root) throw new KbRecordNotFoundError(rootId);\n\n // The whole reachable component is walked, not just the first `hops` rings:\n // the bundle is already in memory, and knowing what lies past the bound is\n // what lets the excluded list name records instead of waving at them.\n const reached: Reached[] = [{ record: root, depth: 0 }];\n const seen = new Set([rootId]);\n let frontier: KbRecord[] = [root];\n for (let depth = 1; frontier.length; depth += 1) {\n const next: KbRecord[] = [];\n for (const from of frontier) {\n for (const { record } of neighbours(from, bundle)) {\n if (seen.has(record.conceptId)) continue;\n seen.add(record.conceptId);\n reached.push({ record, depth });\n next.push(record);\n }\n }\n frontier = next;\n }\n\n reached.sort(byRank);\n const within = reached.filter((entry) => entry.depth <= hops);\n const kept = within.slice(0, maxNodes);\n const excluded = [\n ...within.slice(maxNodes),\n ...reached.filter((entry) => entry.depth > hops),\n ]\n .map((entry) => entry.record.conceptId)\n .sort();\n\n const adjudicated = adjudicate(\n kept.map((entry) => entry.record),\n bundle,\n );\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(stub);\n const whole = adjudicated.filter((hit) => hit.standing !== \"superseded\");\n\n const tokensLoaded =\n whole.reduce((total, hit) => total + estimateTokens(hit.record), 0) +\n superseded.reduce((total, entry) => total + estimateStubTokens(entry), 0);\n const recordCount = adjudicated.length;\n\n if (tokensLoaded > budgetTokens) {\n throw new KbPackBudgetExceededError(\n recordCount,\n tokensLoaded,\n budgetTokens,\n excluded,\n );\n }\n\n return {\n root: rootId,\n records: whole.map((hit) => ({\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n warnings: hit.warnings,\n anchors: hit.record.frontmatter.strauss_anchors ?? [],\n body: hit.record.body,\n })),\n superseded,\n excluded,\n recordCount,\n tokensLoaded,\n budgetTokens,\n };\n}\n\nfunction byRank(left: Reached, right: Reached): number {\n return (\n left.depth - right.depth ||\n typeRank(left.record) - typeRank(right.record) ||\n (left.record.frontmatter.title ?? \"\").localeCompare(\n right.record.frontmatter.title ?? \"\",\n ) ||\n left.record.conceptId.localeCompare(right.record.conceptId)\n );\n}\n\n// A foreign type — legal under OKF — ranks after every known one.\nfunction typeRank(record: KbRecord): number {\n const index = TYPE_PRIORITY.indexOf(record.frontmatter.type);\n return index === -1 ? TYPE_PRIORITY.length : index;\n}\n","import type { KbRecord } from \"../kb-record.schema.js\";\nimport type { KbInboundEdge } from \"./model.js\";\n\n/**\n * The whole bundle's typed edges, indexed by target — built once per call, so a\n * walk stays linear in the bundle rather than quadratic. Order is `list()`'s\n * own, then each record's declared link order, so repeated runs agree.\n */\nexport function inboundIndex(bundle: KbRecord[]): Map<string, KbInboundEdge[]> {\n const byTarget = new Map<string, KbInboundEdge[]>();\n\n for (const record of bundle) {\n for (const link of record.frontmatter.strauss_links ?? []) {\n // A record naming itself is a no-op, not an error, for the same reason\n // `supersedes` treats it that way: the claim is already true.\n if (link.target === record.conceptId) continue;\n\n const edges = byTarget.get(link.target) ?? [];\n // The same pair stated twice says nothing twice.\n if (\n edges.some(\n (edge) => edge.from === record.conceptId && edge.rel === link.rel,\n )\n ) {\n continue;\n }\n edges.push({ from: record.conceptId, rel: link.rel });\n byTarget.set(link.target, edges);\n }\n }\n\n return byTarget;\n}\n","import { adjudicate } from \"../adjudicate.js\";\nimport { KbRecordNotFoundError } from \"../kb-errors.js\";\nimport type { KbRecord } from \"../kb-record.schema.js\";\nimport { inboundIndex } from \"./inbound.js\";\nimport type { KbBacklink, KbBacklinksResult } from \"./model.js\";\n\n/**\n * Every edge the bundle holds against this id: one hop, every rel including\n * `related_to`, each row carrying the standing of the record that made it.\n * Flat and factual, where `impact` answers the causal, transitive question.\n */\nexport function backlinks(\n targetId: string,\n bundle: KbRecord[],\n): KbBacklinksResult {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n if (!byId.has(targetId)) throw new KbRecordNotFoundError(targetId);\n\n const standingOf = new Map(\n adjudicate(bundle, bundle).map((hit) => [hit.record.conceptId, hit]),\n );\n\n const rows: KbBacklink[] = [];\n for (const edge of inboundIndex(bundle).get(targetId) ?? []) {\n const record = byId.get(edge.from);\n if (!record) continue;\n const hit = standingOf.get(edge.from);\n rows.push({\n ...edge,\n title: record.frontmatter.title ?? null,\n standing: hit?.standing ?? \"unsettled\",\n warnings: hit?.warnings ?? [],\n });\n }\n\n return {\n target: targetId,\n backlinks: rows.sort(\n (left, right) =>\n left.from.localeCompare(right.from) ||\n left.rel.localeCompare(right.rel),\n ),\n };\n}\n","import { adjudicate, type KbAdjudicated } from \"../adjudicate.js\";\nimport { KbRecordNotFoundError, KbUnknownLinkRelError } from \"../kb-errors.js\";\nimport type { KbRecord } from \"../kb-record.schema.js\";\nimport {\n isKbLinkRel,\n KB_CAUSAL_LINK_RELS,\n LINK_RELS,\n} from \"../record-types.js\";\nimport { inboundIndex } from \"./inbound.js\";\nimport type {\n KbImpactOptions,\n KbImpactResult,\n KbImpactedRecord,\n KbLinkEdge,\n} from \"./model.js\";\n\n/**\n * The transitive set of *dependants*, not the set of inbound edges: each rel is\n * followed in its own direction of dependence. `related_to` and unknown rels\n * propagate nothing. A superseded or rejected record is reported, then not\n * walked through. A record expands once, so cycles terminate.\n */\nexport function impact(\n targetId: string,\n bundle: KbRecord[],\n options: KbImpactOptions = {},\n): KbImpactResult {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n if (!byId.has(targetId)) throw new KbRecordNotFoundError(targetId);\n\n const rels = resolveRels(options.rels);\n const maxDepth = options.depth ?? Number.POSITIVE_INFINITY;\n const inbound = inboundIndex(bundle);\n\n // Adjudicated once over the whole bundle: standing must not depend on\n // whether a record's replacement happened to be within the walk.\n const standingOf = new Map<string, KbAdjudicated>(\n adjudicate(bundle, bundle).map((hit) => [hit.record.conceptId, hit]),\n );\n\n const reached = new Map<string, KbImpactedRecord>();\n const stopped: string[] = [];\n let frontier = [targetId];\n let depth = 0;\n\n while (frontier.length && depth < maxDepth) {\n depth += 1;\n const next: string[] = [];\n\n const consider = (dependantId: string, edge: KbLinkEdge) => {\n // The root is the question, not an answer to it.\n if (dependantId === targetId) return;\n\n const existing = reached.get(dependantId);\n if (existing) {\n if (!hasEdge(existing.via, edge)) existing.via.push(edge);\n return;\n }\n\n const record = byId.get(dependantId);\n // An edge naming a record that is not in the bundle is routine — records\n // are written before the ones they point at — and `kb_validate` is what\n // reports it. Nothing to report as impacted, so nothing is invented.\n if (!record) return;\n\n const hit = standingOf.get(dependantId);\n const entry: KbImpactedRecord = {\n conceptId: dependantId,\n title: record.frontmatter.title ?? null,\n standing: hit?.standing ?? \"unsettled\",\n warnings: hit?.warnings ?? [],\n depth,\n via: [edge],\n };\n reached.set(dependantId, entry);\n\n if (entry.standing === \"superseded\" || entry.standing === \"rejected\") {\n stopped.push(dependantId);\n return;\n }\n next.push(dependantId);\n };\n\n for (const id of frontier) {\n // Inbound: someone points at me with a rel whose dependant is the source.\n for (const edge of inbound.get(id) ?? []) {\n if (!rels.has(edge.rel)) continue;\n if (dependantEnd(edge.rel) !== \"source\") continue;\n consider(edge.from, { source: edge.from, target: id, rel: edge.rel });\n }\n\n // Outbound: I point at someone with a rel whose dependant is the target.\n for (const link of byId.get(id)?.frontmatter.strauss_links ?? []) {\n if (!rels.has(link.rel)) continue;\n if (dependantEnd(link.rel) !== \"target\") continue;\n if (link.target === id) continue;\n consider(link.target, {\n source: id,\n target: link.target,\n rel: link.rel,\n });\n }\n }\n\n frontier = next;\n }\n\n return {\n root: targetId,\n impacted: [...reached.values()].sort(\n (left, right) =>\n left.depth - right.depth ||\n left.conceptId.localeCompare(right.conceptId),\n ),\n stopped: stopped.sort(),\n truncated: frontier.length > 0,\n unexpanded: [...frontier].sort(),\n };\n}\n\n/**\n * The caller's `rels`, checked at the library boundary.\n *\n * A rel the walk cannot follow is an error, not an empty result: the two are\n * indistinguishable to a caller, and \"nothing breaks\" is the most dangerous\n * answer this function can return.\n */\nfunction resolveRels(rels: readonly string[] | undefined): Set<string> {\n if (!rels?.length) return new Set<string>(KB_CAUSAL_LINK_RELS);\n for (const rel of rels) {\n if (!isKbLinkRel(rel) || LINK_RELS[rel].dependant === null) {\n throw new KbUnknownLinkRelError(rel, KB_CAUSAL_LINK_RELS);\n }\n }\n return new Set(rels);\n}\n\n/** Which end of a stored rel depends on the other. `null` for anything inert. */\nfunction dependantEnd(rel: string): \"source\" | \"target\" | null {\n return isKbLinkRel(rel) ? LINK_RELS[rel].dependant : null;\n}\n\nfunction hasEdge(edges: KbLinkEdge[], edge: KbLinkEdge): boolean {\n return edges.some(\n (existing) =>\n existing.source === edge.source &&\n existing.target === edge.target &&\n existing.rel === edge.rel,\n );\n}\n","import { LOG_FILE } from \"./kb-log.js\";\n\nexport const GITATTRIBUTES_FILE = \".gitattributes\";\n\n/**\n * Declares the log's merge driver, plus line endings.\n *\n * `merge=union` interleaves both sides' lines instead of the ordinary\n * line-level merge, which can drop one side's appends outright. The log is\n * append-only JSONL and two worktrees against the same bundle is the normal\n * case, not an edge case — `kb_log`'s reader sorts on `at` and dedupes exact\n * repeats (`kb-log.ts`), so interleaved line order — or a line a union merge\n * happened to keep twice — coming out of a merge is exactly as readable as a\n * single writer's log.\n *\n * `text eol=lf` pins line endings to `\\n` regardless of a checkout's\n * `core.autocrlf`. Without it, Windows with `autocrlf=true` normalizes the\n * file to CRLF on checkout while every append after that (`O_APPEND`, raw\n * `\\n`) keeps writing LF — a file with mixed endings, which is exactly the\n * kind of divergence a merge driver can't paper over.\n */\nexport const UNION_MERGE_LINE = `${LOG_FILE} text eol=lf merge=union`;\n\n/**\n * One parsed `.gitattributes` line: the pattern and its whitespace-separated\n * attributes. `null` for a blank line or a `#` comment — gitattributes\n * ignores both.\n */\nfunction parseLine(line: string): { pattern: string; attrs: string[] } | null {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) return null;\n const [pattern, ...attrs] = trimmed.split(/\\s+/);\n return pattern === undefined ? null : { pattern, attrs };\n}\n\n/**\n * Whether `contents` already assigns *any* `merge` attribute to the log\n * file — our own `merge=union`, a plain `merge` (the default driver), an\n * explicit `-merge` (merging disabled), or a user's own choice such as\n * `merge=ours`.\n *\n * Exact-string matching against `UNION_MERGE_LINE` was the first cut, and it\n * both under- and over-reaches: a line with a tab or doubled space between\n * tokens, or one that also sets an unrelated attribute alongside `merge`,\n * would not match and get a harmless-looking but wrong second line appended\n * — and it can never see a deliberate `merge=ours` as \"already decided\",\n * which is the one case where appending anything at all would be wrong.\n * Whitespace-tokenizing the pattern and attributes separately answers the\n * question this function actually needs answered: does *some* line already\n * give `log.jsonl` a merge strategy, whatever it is — and if so, that\n * strategy is left alone rather than layered under a second, possibly\n * conflicting one. gitattributes itself resolves multiple matching lines by\n * \"last one wins\", so appending a second `merge=` line for the same pattern\n * would silently override a user's `merge=ours` with `merge=union` — the\n * opposite of respecting what they set.\n */\nexport function hasMergeDeclaration(contents: string): boolean {\n return contents.split(\"\\n\").some((line) => {\n const parsed = parseLine(line);\n if (!parsed || parsed.pattern !== LOG_FILE) return false;\n return parsed.attrs.some(\n (attr) =>\n attr === \"merge\" || attr === \"-merge\" || attr.startsWith(\"merge=\"),\n );\n });\n}\n\n/**\n * The bytes to append to a `.gitattributes` that does not yet declare a\n * merge strategy for the log — a newline first, unless `contents` already\n * ends in one, so the line lands on its own rather than tacked onto the\n * file's last line.\n */\nexport function appendUnionMergeLine(contents: string): string {\n const separator =\n contents.length === 0 || contents.endsWith(\"\\n\") ? \"\" : \"\\n\";\n return `${separator}${UNION_MERGE_LINE}\\n`;\n}\n","/**\n * The package version, injected at build time by tsup's `define`.\n *\n * Hardcoding it here would be a second copy of `package.json`'s version, and a\n * copy that only a human comparing two numbers would ever catch: it reaches\n * users as `serverInfo.version`, which is the one thing a client can ask a\n * running server about itself. It sat at 0.1.0 through five releases.\n *\n * `typeof` rather than a bare reference so this also works unbuilt — under\n * Vitest the identifier is never defined, and reading an undeclared name would\n * throw where reading its type does not.\n */\ndeclare const __STRAUSS_KB_VERSION__: string | undefined;\n\nexport const VERSION: string =\n typeof __STRAUSS_KB_VERSION__ === \"string\"\n ? __STRAUSS_KB_VERSION__\n : \"0.0.0-dev\";\n","#!/usr/bin/env node\nimport { runKbMcpServer } from \"./mcp.js\";\n\nrunKbMcpServer().catch((error: unknown) => {\n process.stderr.write(\n `${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,IAAM,mBAAmB,MACvB,OAAO,aAAa,cAChB,IAAI,IAAI,QAAQ,UAAU,EAAE,EAAE,OAC7B,SAAS,iBAAiB,SAAS,cAAc,QAAQ,YAAY,MAAM,WAC1E,SAAS,cAAc,MACvB,IAAI,IAAI,WAAW,SAAS,OAAO,EAAE;AAEtC,IAAM,gBAAgC,iCAAiB;;;ACZ9D,iBAA0B;AAC1B,mBAAqC;;;ACDrC,IAAAA,cAAkB;;;ACAlB,IAAAC,cAAkB;;;ACAlB,iBAAkB;AAqBX,IAAM,iBAAiB,aAC3B,OAAO;AAAA,EACN,IAAI,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,UAAU,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC1B,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAClC,QAAQ,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnC,eAAe,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAC5C,CAAC,EACA,YAAY;AAGR,IAAM,qBAAqB,aAC/B,OAAO;AAAA,EACN,IAAI,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,IAAI,aAAE,OAAO,EAAE,IAAI,CAAC;AACtB,CAAC,EACA,YAAY;AAQR,IAAM,wBAAwB,mBAAmB,OAAO;AAAA,EAC7D,MAAM,aAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG;AAAA,IAClD,SAAS;AAAA,EACX,CAAC;AACH,CAAC;AAsBM,IAAM,iBAAiB,aAC3B,OAAO;AAAA,EACN,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,QAAQ,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUnC,MAAM,aAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQxC,KAAK,aAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACvC,MAAM,aACH,OAAO,EACP,MAAM,yBAAyB;AAAA,IAC9B,SAAS;AAAA,EACX,CAAC,EACA,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQZ,WAAW,aAAE,KAAK,CAAC,OAAO,KAAK,CAAC,EAAE,SAAS;AAAA;AAAA,EAE3C,aAAa,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAExC,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM5C,UAAU,aAAE,KAAK,CAAC,eAAe,OAAO,CAAC,EAAE,SAAS;AACtD,CAAC,EACA,OAAO;AAcH,IAAM,eAAe,aACzB,OAAO;AAAA,EACN,QAAQ,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACxB,KAAK,aAAE,OAAO,EAAE,IAAI,CAAC;AACvB,CAAC,EACA,YAAY;AAER,IAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,kBAAkB;AACxB,IAAM,wBACX;AAOK,IAAM,oBAAoB,aAAE,OAAO,EAAE,MAAM,uBAAuB;AAAA,EACvE,SAAS;AACX,CAAC;AAUM,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF;AACO,IAAM,iBAAiB,CAAC,OAAO,UAAU,MAAM;AAE/C,IAAM,4BAA4B,aACtC,OAAO;AAAA;AAAA;AAAA,EAGN,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAGtB,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAClC,aAAa,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACxC,UAAU,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACrC,MAAM,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA;AAAA,EAGnC,SAAS,aAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAC1C,WAAW,mBAAmB,SAAS;AAAA,EACvC,UAAU,aAAE,MAAM,kBAAkB,EAAE,SAAS;AAAA,EAC/C,aAAa,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAGxC,iBAAiB,aAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAClD,gBAAgB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,EAKpD,eAAe,aAAE,MAAM,YAAY,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO9C,gBAAgB,aAAE,KAAK,kBAAkB,EAAE,QAAQ,OAAO;AAAA,EAC1D,oBAAoB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EACxD,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAClD,kBAAkB,mBAAmB,SAAS;AAAA,EAC9C,qBAAqB,aAAE,KAAK,gBAAgB,EAAE,SAAS;AAAA,EACvD,oBAAoB,aAAE,KAAK,cAAc,EAAE,SAAS;AAAA,EACpD,eAAe,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,EAK1C,oBAAoB,aAAE,QAAQ,EAAE,SAAS;AAC3C,CAAC,EAIA,YAAY;;;AC9NR,IAAM,eAAiE;AAAA,EAC5E,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,UAAU,CAAC,SAAS,YAAY,aAAa;AAAA,IAC7C,eAAe;AAAA,EACjB;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,UAAU,CAAC,SAAS,YAAY,aAAa;AAAA,IAC7C,eAAe;AAAA,EACjB;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,UAAU,CAAC,SAAS,YAAY,aAAa;AAAA,IAC7C,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,UAAU,CAAC,YAAY,aAAa,YAAY,QAAQ;AAAA,IACxD,eAAe;AAAA,EACjB;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,UAAU,CAAC,SAAS,mBAAmB,uBAAuB;AAAA,IAC9D,eAAe;AAAA,EACjB;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,UAAU,CAAC,YAAY,kBAAkB,oBAAoB;AAAA,IAC7D,eAAe;AAAA,EACjB;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,UAAU,CAAC,QAAQ,kBAAkB,cAAc,cAAc;AAAA,IACjE,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,UAAU,CAAC,YAAY,YAAY,YAAY,eAAe;AAAA,IAC9D,eAAe;AAAA,EACjB;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,UAAU,CAAC,QAAQ,WAAW,SAAS,eAAe;AAAA,IACtD,eAAe;AAAA,EACjB;AAAA,EACA,mBAAmB;AAAA,IACjB,SAAS;AAAA,IACT,UAAU,CAAC,UAAU,sBAAsB,cAAc;AAAA,IACzD,eAAe;AAAA,EACjB;AAAA,EACA,mBAAmB;AAAA,IACjB,SAAS;AAAA,IACT,UAAU,CAAC,cAAc,kBAAkB,eAAe;AAAA,IAC1D,eAAe;AAAA,EACjB;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,UAAU,CAAC,QAAQ,oBAAoB;AAAA,IACvC,eAAe;AAAA,EACjB;AACF;AAEO,SAAS,eAAe,OAAsC;AACnE,SAAO,OAAO,UAAU,eAAe,KAAK,cAAc,KAAK;AACjE;AA4BO,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,IAAM,YAAwD;AAAA,EACnE,YAAY;AAAA,IACV,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,YAAY;AAAA,IACV,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,SAAS;AAAA,IACP,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,QAAQ;AAAA,IACN,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,aAAa;AAAA,IACX,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,aAAa;AAAA,IACX,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,WAAW;AAAA,IACT,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AACF;AAWO,IAAM,sBAAsB,aAAa;AAAA,EAC9C,CAAC,QAAQ,UAAU,GAAG,EAAE,cAAc;AACxC;AAEO,SAAS,YAAY,OAAmC;AAC7D,SAAO,OAAO,UAAU,eAAe,KAAK,WAAW,KAAK;AAC9D;;;AF9KO,IAAM,oBAAoB,cAC9B,OAAO;AAAA,EACN,QAAQ;AAAA,EACR,KAAK,cAAE,KAAK,YAAY;AAC1B,CAAC,EACA,OAAO;AAIH,IAAM,qBAAqB,cAC/B,OAAO;AAAA,EACN,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEtB,OAAO,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEvB,KAAK,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAErB,UAAU,cAAE,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EAC3D,SAAS,cAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAC1C,SAAS,cAAE,MAAM,cAAc,EAAE,SAAS;AAAA;AAAA,EAE1C,YAAY,cAAE,QAAQ,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjC,aAAa,cACV,OAAO,EACP,MAAM,uBAAuB;AAAA,IAC5B,SAAS;AAAA,EACX,CAAC,EACA,OAAO,CAAC,SAAS,CAAC,OAAO,MAAM,KAAK,MAAM,IAAI,CAAC,GAAG;AAAA,IACjD,SAAS;AAAA,EACX,CAAC,EACA,SAAS;AAAA,EACZ,QAAQ,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EAC5C,MAAM,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA;AAAA,EAE1C,mBAAmB,cAAE,MAAM,iBAAiB,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQvD,OAAO,cACJ,MAAM,iBAAiB,EACvB,IAAI,EAAE,EACN,SAAS,EACT;AAAA,IACC,4GAAkG,aAAa;AAAA,MAC7G,CAAC,QAAQ,GAAG,GAAG,KAAK,UAAU,GAAG,EAAE,OAAO;AAAA,IAC5C,EAAE,KAAK,IAAI,CAAC;AAAA,EACd;AAAA;AAAA,EAEF,YAAY,cAAE,MAAM,iBAAiB,EAAE,IAAI,EAAE,EAAE,SAAS;AAAA,EACxD,aAAa,cAAE,KAAK,gBAAgB,EAAE,SAAS;AAAA,EAC/C,YAAY,cAAE,KAAK,cAAc,EAAE,SAAS;AAAA,EAC5C,OAAO,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACpC,CAAC,EACA,OAAO;AAoBH,SAAS,cACd,MACA,OACA,WACA,WACgB;AAIhB,QAAM,SAAS,mBAAmB,MAAM,KAAK;AAC7C,QAAM,OAAO,aAAa,IAAI;AAC9B,QAAM,WAAW,OAAO,YAAY,CAAC;AAErC,QAAM,UAAU,OAAO,KAAK,QAAQ,EAAE;AAAA,IACpC,CAAC,YAAY,CAAC,KAAK,SAAS,SAAS,OAAO;AAAA,EAC9C;AACA,MAAI,QAAQ,QAAQ;AAClB,UAAM,IAAI;AAAA,MACR,OAAO,IAAI,mBAAmB,QAAQ,KAAK,IAAI,CAAC,2BAAsB,KAAK,SAAS,KAAK,IAAI,CAAC;AAAA,IAChG;AAAA,EACF;AAEA,QAAM,cAAiD;AAAA,IACrD,OAAO,OAAO;AAAA,IACd,aAAa,OAAO;AAAA,IACpB,WAAW,EAAE,IAAI,WAAW,IAAI,UAAU;AAAA;AAAA;AAAA;AAAA,IAI1C,UAAU,CAAC;AAAA,IACX,gBAAgB,KAAK;AAAA,EACvB;AACA,MAAI,OAAO,YAAa,aAAY,cAAc,OAAO;AACzD,MAAI,OAAO,SAAS,OAAQ,aAAY,kBAAkB,OAAO;AACjE,MAAI,OAAO,QAAQ,OAAQ,aAAY,iBAAiB,OAAO;AAC/D,MAAI,OAAO,MAAM,OAAQ,aAAY,OAAO,OAAO;AACnD,MAAI,OAAO,SAAS,OAAQ,aAAY,UAAU,OAAO;AACzD,MAAI,OAAO,WAAY,aAAY,qBAAqB;AACxD,MAAI,OAAO,YAAa,aAAY,sBAAsB,OAAO;AACjE,MAAI,OAAO,WAAY,aAAY,qBAAqB,OAAO;AAC/D,MAAI,OAAO,MAAO,aAAY,gBAAgB,OAAO;AACrD,MAAI,OAAO,YAAY;AACrB,gBAAY,qBAAqB,OAAO;AAK1C,QAAM,WAAW,OAAO,OAAO;AAAA,IAC7B,CAACC,UAASA,MAAK,WAAW,GAAG,IAAI,IAAI,OAAO,IAAI;AAAA,EAClD;AACA,MAAI,UAAU;AACZ,UAAM,IAAI;AAAA,MACR,OAAO,IAAI,IAAI,OAAO,IAAI,WAAW,SAAS,GAAG;AAAA,IACnD;AAAA,EACF;AACA,MAAI,OAAO,OAAO,OAAQ,aAAY,gBAAgB,OAAO;AAE7D,QAAM,SAAmB,CAAC;AAC1B,aAAW,WAAW,KAAK,UAAU;AACnC,UAAM,OAAO,SAAS,OAAO;AAG7B,QAAI,KAAM,QAAO,KAAK,MAAM,OAAO;AAAA;AAAA,EAAO,IAAI,EAAE;AAAA,EAClD;AACA,MAAI,CAAC,OAAO,OAAQ,QAAO,KAAK,OAAO,GAAG;AAE1C,aAAW,WAAW,OAAO,qBAAqB,CAAC,GAAG;AACpD,WAAO,KAAK,eAAe,OAAO,KAAK,OAAO,OAAO;AAAA,EACvD;AAOA,aAAWA,SAAQ,OAAO,SAAS,CAAC,GAAG;AACrC,WAAO;AAAA,MACL,GAAG,UAAUA,MAAK,GAAG,EAAE,MAAM,KAAKA,MAAK,MAAM,KAAKA,MAAK,MAAM;AAAA,IAC/D;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,QAAQ;AAC1B,WAAO;AAAA,MACL,OAAO,QACJ,IAAI,CAAC,WAAW,KAAK,OAAO,EAAE,MAAM,OAAO,SAAS,OAAO,QAAQ,EAAE,EACrE,KAAK,IAAI;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,OAAO;AAAA,IACb;AAAA,IACA,MAAM,GAAG,OAAO,KAAK,MAAM,CAAC;AAAA;AAAA,EAC9B;AACF;;;ADnLO,IAAM,gBAAgB;AAWtB,IAAM,mBAAmB;AAQzB,IAAM,sBAAsB,mBAChC,KAAK,EAAE,UAAU,KAAK,CAAC,EACvB,OAAO;AAAA,EACN,aAAa,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACxC,QAAQ,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACrC,CAAC,EACA,OAAO;AAIH,SAAS,sBACd,OACA,WACA,WACgB;AAChB,QAAM,EAAE,aAAa,QAAAC,SAAQ,GAAG,KAAK,IAAI;AACzC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,UAAU;AAAA,QACR,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,QACjB,GAAI,cAAc,EAAE,UAAU,YAAY,IAAI,CAAC;AAAA,QAC/C,GAAIA,UAAS,EAAE,QAAQA,QAAO,IAAI,CAAC;AAAA,MACrC;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGO,SAAS,wBACd,QACA,WACA,WACgB;AAChB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,UAAU,EAAE,UAAU,OAAO;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AItFA,IAAAC,cAAkB;;;ACQX,IAAM,yBAAyB;AAQtC,eAAsB,SACpB,OACA,OACA,IACc;AACd,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACzC,UAAM,IAAI;AAAA,MACR,qDAAqD,KAAK;AAAA,IAC5D;AAAA,EACF;AACA,QAAM,MAAM,IAAI,MAAS,MAAM,MAAM;AACrC,MAAI,OAAO;AACX,MAAI,SAAS;AACb,QAAM,UAAU,MAAM;AAAA,IACpB,EAAE,QAAQ,KAAK,IAAI,OAAO,MAAM,MAAM,EAAE;AAAA,IACxC,YAAY;AACV,aAAO,CAAC,UAAU,OAAO,MAAM,QAAQ;AACrC,cAAMC,MAAK;AACX,YAAI;AACF,cAAIA,GAAE,IAAI,MAAM,GAAG,MAAMA,GAAE,GAAQA,GAAE;AAAA,QACvC,SAAS,OAAO;AACd,mBAAS;AACT,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,QAAM,QAAQ,IAAI,OAAO;AACzB,SAAO;AACT;;;AC7CA,qBAAwB;AACxB,uBAAqB;;;ACDrB,gCAAyB;AACzB,uBAA0B;AAG1B,IAAM,oBAAgB,4BAAU,kCAAQ;AAajC,SAAS,iBAAiB,OAAuB;AACtD,MAAI,MAAM,MAAM,KAAK,EAAE,QAAQ,UAAU,EAAE;AAE3C,QAAM,MAAM,2BAA2B,KAAK,GAAG;AAC/C,MAAI,IAAK,OAAM,WAAW,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AAC1C,QAAM,IAAI,QAAQ,yBAAyB,UAAU;AAIrD,QAAM,oBAAoB,GAAG;AAC7B,MAAI,IAAI,SAAS,MAAM,EAAG,OAAM,IAAI,MAAM,GAAG,EAAE;AAC/C,SAAO,oBAAoB,GAAG,EAAE,YAAY;AAC9C;AAEA,SAAS,oBAAoB,OAAuB;AAClD,MAAI,MAAM,MAAM;AAChB,SAAO,MAAM,KAAK,MAAM,MAAM,CAAC,MAAM,IAAK,QAAO;AACjD,SAAO,MAAM,MAAM,GAAG,GAAG;AAC3B;AAQO,SAAS,mBAAmB,OAAwB;AACzD,SAAO,qBAAqB,KAAK,iBAAiB,KAAK,CAAC;AAC1D;AAGA,SAAS,SAAS,YAA4B;AAC5C,QAAM,gBAAgB,WAAW,QAAQ,sBAAsB,EAAE;AACjE,QAAM,WAAW,cAAc,MAAM,GAAG,EAAE,OAAO,OAAO;AACxD,SAAO,SAAS,SAAS,IAAI,SAAS,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI;AAC7D;AAWO,SAAS,eACd,UACA,WACS;AACT,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,SAAS,iBAAiB,SAAS;AACzC,QAAM,OAAO,iBAAiB,QAAQ;AACtC,MAAI,CAAC,QAAQ,CAAC,OAAQ,QAAO;AAC7B,MAAI,SAAS,OAAQ,QAAO;AAE5B,QAAM,OAAO,SAAS,MAAM;AAC5B,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,SAAS,QAAQ,UAAU,KAAK,MAAM,GAAG,EAAE,IAAI,KAAK;AAC7D;AAWA,eAAsB,cAAc,UAA0C;AAC5E,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB;AAAA,MACA,CAAC,MAAM,UAAU,UAAU,SAAS,mBAAmB;AAAA,MACvD,EAAE,SAAS,IAAM;AAAA,IACnB;AACA,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,IAAM,aAAN,MAAiB;AAAA,EAItB,YAA6B,UAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA,EAHrB,MAAqB;AAAA,EACrB,QAAQ;AAAA;AAAA,EAKhB,MAAM,QAAuB;AAC3B,QAAI,KAAK,MAAO;AAChB,SAAK,MAAM,MAAM,cAAc,KAAK,QAAQ;AAC5C,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA,EAGA,UAAU,QAA2B;AACnC,QAAI,CAAC,OAAO,KAAM,QAAO;AACzB,WAAO,CAAC,eAAe,OAAO,MAAM,KAAK,GAAG;AAAA,EAC9C;AAAA,EAEA,MAAM,QAAQ,QAAoC;AAChD,QAAI,CAAC,OAAO,KAAM,QAAO;AACzB,UAAM,KAAK,MAAM;AACjB,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B;AACF;;;AD3HO,SAAS,aAAa,UAA2B;AACtD,SACE,YACA,QAAQ,IAAI,uBAAuB,SACnC,2BAAK,wBAAQ,GAAG,YAAY,YAAY;AAE5C;AAGO,IAAM,2BAA2B;AAEjC,SAAS,eAAe,UAA2B;AACxD,MAAI,aAAa,OAAW,QAAO;AACnC,QAAM,UAAU,OAAO,QAAQ,IAAI,6BAA6B,CAAC;AACjE,SAAO,OAAO,SAAS,OAAO,KAAK,UAAU,IACzC,UACA;AACN;AAQO,SAAS,aAAa,MAAc,UAAiC;AAC1E,QAAM,aAAa,iBAAiB,IAAI;AACxC,QAAM,SAAS,qBAAqB,KAAK,UAAU;AACnD,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,WAAW,WACd,MAAM,OAAO,CAAC,EAAE,MAAM,EACtB,MAAM,GAAG,EACT,OAAO,OAAO,EACd,IAAI,CAAC,YAAoB,YAAY,OAAO,CAAC;AAChD,MAAI,SAAS,SAAS,KAAK,SAAS,KAAK,CAAC,YAAY,YAAY,IAAI,GAAG;AACvE,WAAO;AAAA,EACT;AACA,QAAM,OAAO;AACb,aAAO,uBAAK,UAAU,GAAG,KAAK,MAAM,GAAG,EAAE,GAAG,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,MAAM;AAC5E;AAQA,SAAS,YAAY,OAA8B;AACjD,SAAO,UAAU,OAAO,UAAU,QAAQ,MAAM,SAAS,IAAI,IACzD,OACA,MAAM,QAAQ,WAAW,GAAG;AAClC;AAMO,SAAS,OAAO,KAAqB;AAE1C,QAAM,OAAO,IAAI,QAAQ,mBAAmB,GAAG,EAAE,MAAM,GAAG,EAAE;AAC5D,MAAI,OAAO;AACX,WAASC,MAAK,GAAGA,MAAK,IAAI,QAAQA,OAAM;AACtC,YAAS,OAAO,KAAM,IAAI,WAAWA,GAAE,OAAO;AAAA,EAChD;AACA,SAAO,gBAAgB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;AAClD;;;AE9CO,IAAM,oBAAuD;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,kBACd,QACS;AACT,SACE,WAAW,UACX,kBAAkB,SAAS,MAAgC;AAE/D;AAGO,SAAS,QACd,MACA,KACA,MACQ;AACR,SAAO,GAAG,IAAI,KAAS,OAAO,EAAE,KAAS,IAAI;AAC/C;;;AC9CA,sBAAsB;;;ACAtB,IAAAC,6BAAyB;AACzB,IAAAC,oBAA0B;;;ACkGnB,IAAM,wBAAwB;;;AD5FrC,IAAMC,qBAAgB,6BAAU,mCAAQ;AAmBxC,SAAS,WAA8B;AACrC,QAAM,MAAyB,EAAE,GAAG,QAAQ,KAAK,qBAAqB,IAAI;AAC1E,aAAW,QAAQ,CAAC,WAAW,iBAAiB,gBAAgB,GAAG;AACjE,WAAO,IAAI,IAAI;AAAA,EACjB;AACA,SAAO;AACT;AAMA,eAAsB,IACpB,MACA,UAAmE,CAAC,GACnD;AACjB,MAAI;AACF,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAMA,eAAc,OAAO,MAAM;AAAA,MAC1D,GAAI,QAAQ,MAAM,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC;AAAA,MAC1C,SAAS,QAAQ,aAAa;AAAA,MAC9B,WAAW,QAAQ,YAAY;AAAA,MAC/B,UAAU;AAAA,MACV,aAAa;AAAA,MACb,KAAK,SAAS;AAAA,IAChB,CAAC;AACD,WAAO,EAAE,IAAI,MAAM,QAAQ,QAAQ,YAAY,MAAM;AAAA,EACvD,SAAS,OAAO;AACd,UAAM,UAAU;AAKhB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ,QAAQ,UAAU;AAAA,MAC1B,QAAQ,QAAQ,UAAU;AAAA,MAC1B,YAAY,QAAQ,SAAS;AAAA,IAC/B;AAAA,EACF;AACF;AAOO,SAAS,gBAAgB,QAAwC;AACtE,QAAM,OAAO,OAAO,YAAY;AAChC,MACE,KAAK,SAAS,uBAAuB,KACrC,KAAK,SAAS,mBAAmB,KACjC,KAAK,SAAS,yBAAyB,KACvC,KAAK,SAAS,eAAe,KAC7B,KAAK,SAAS,eAAe,GAC7B;AACA,WAAO;AAAA,EACT;AACA,MACE,KAAK,SAAS,0BAA0B,KACxC,KAAK,SAAS,qBAAqB,KACnC,KAAK,SAAS,aAAa,GAC3B;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;AE9EA,IAAM,iBAAiB;AAOvB,IAAM,YAAY;AAGX,SAAS,eAAe,KAAsB;AACnD,MAAI,CAAC,OAAO,IAAI,SAAS,eAAgB,QAAO;AAEhD,MAAI,IAAI,SAAS,IAAI,EAAG,QAAO;AAC/B,SAAO,UAAU,KAAK,GAAG;AAC3B;AAMA,eAAsB,gBAAgB,KAA+B;AACnE,MAAI,CAAC,eAAe,GAAG,EAAG,QAAO;AACjC,QAAM,UAAU,MAAM,IAAI,CAAC,oBAAoB,oBAAoB,GAAG,CAAC;AACvE,SAAO,QAAQ;AACjB;AAMO,SAAS,eAAe,MAAuB;AACpD,QAAM,OAAO,KAAK,QAAQ,SAAS,EAAE;AACrC,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,IAAI,EAAG,QAAO;AACjE,SAAO,CAAC,KAAK,MAAM,GAAG,EAAE,SAAS,IAAI;AACvC;AAGA,IAAM,oBAAoB,CAAC,SAAS,OAAO,KAAK;AAOzC,SAAS,mBAA6B;AAC3C,QAAM,MAAM,QAAQ,IAAI,2BAA2B;AACnD,MAAI,QAAQ,OAAW,QAAO,CAAC,GAAG,iBAAiB;AACnD,QAAM,SAAS,IACZ,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,EAAE,YAAY,CAAC,EACzC,OAAO,OAAO;AACjB,SAAO,OAAO,SAAS,SAAS,CAAC,GAAG,iBAAiB;AACvD;AAOO,SAAS,gBAAgB,MAAuB;AACrD,SAAO,0CAA0C,KAAK,KAAK,KAAK,CAAC;AACnE;AAGA,IAAM,WAAW;AAEjB,IAAM,aAAa;AAGnB,IAAM,gBAAgB;AAGf,SAAS,cAAc,MAAuB;AACnD,QAAM,MAAM,KAAK,KAAK;AACtB,MAAI,CAAC,OAAO,IAAI,WAAW,GAAG,KAAK,cAAc,KAAK,GAAG,EAAG,QAAO;AAEnE,QAAM,UAAU,iBAAiB;AACjC,MAAI,SAAS,KAAK,GAAG,EAAG,QAAO,QAAQ,SAAS,KAAK;AAErD,QAAM,SAAS,WAAW,KAAK,GAAG;AAElC,MAAI,CAAC,SAAS,CAAC,EAAG,QAAO;AACzB,MAAI,CAAC,QAAQ,SAAS,OAAO,CAAC,EAAE,YAAY,CAAC,EAAG,QAAO;AAIvD,QAAM,YAAY,IAAI,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK;AAC/D,QAAMC,MAAK,UAAU,YAAY,GAAG;AACpC,SAAOA,MAAK,KAAK,CAAC,UAAU,MAAM,GAAGA,GAAE,EAAE,SAAS,GAAG;AACvD;AAMO,SAAS,eAAyB;AACvC,QAAM,UAAU,iBAAiB;AACjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,uBAAuB,QAAQ,SAAS,MAAM,IAAI,SAAS,OAAO;AAAA,EACpE;AACF;;;AH/FA,IAAM,2BAA2B;AAGjC,IAAM,gBAAgB;AAStB,eAAsB,kBACpB,OACA,UAAyB,CAAC,GACQ;AAClC,QAAM,MAAM,oBAAI,IAAwB;AACxC,MAAI,CAAC,MAAM,OAAQ,QAAO;AAE1B,QAAM,WAAW,aAAa,QAAQ,QAAQ;AAC9C,QAAM,YAAY,eAAe,QAAQ,cAAc;AACvD,QAAM,SAAS,oBAAI,IAAkD;AACrE,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,iBAAiB,KAAK,IAAI;AACtC,UAAMC,SAAQ,OAAO,IAAI,GAAG,KAAK,EAAE,KAAK,KAAK,KAAK,KAAK,GAAG,OAAO,CAAC,EAAE;AACpE,IAAAA,OAAM,MAAM,KAAK,IAAI;AACrB,WAAO,IAAI,KAAKA,MAAK;AAAA,EACvB;AAEA,QAAM,SAAS,CAAC,GAAG,OAAO,QAAQ,CAAC;AACnC,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA,KAAK,IAAI,GAAG,QAAQ,eAAe,wBAAwB;AAAA,IAC3D,CAAC,CAAC,MAAMA,MAAK,MACX,YAAY,MAAMA,OAAM,KAAKA,OAAM,OAAO;AAAA,MACxC;AAAA,MACA;AAAA,MACA,SAAS,QAAQ,YAAY;AAAA,IAC/B,CAAC;AAAA,EACL;AACA,aAAW,UAAU,SAAS;AAC5B,eAAW,CAAC,KAAK,IAAI,KAAK,OAAQ,KAAI,IAAI,KAAK,IAAI;AAAA,EACrD;AACA,SAAO;AACT;AAIA,eAAe,YACb,MACA,KACA,UACA,SACkC;AAClC,MAAI,QAA+B;AACnC,QAAM,MAAM,CAAC,SACX,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,MAAM,KAAK,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;AAIzE,MAAI,gBAAgB,GAAG,GAAG;AACxB,WAAO,IAAI,EAAE,IAAI,OAAO,QAAQ,qBAAqB,CAAC;AAAA,EACxD;AAGA,MAAI,CAAC,cAAc,GAAG,EAAG,QAAO,IAAI,EAAE,IAAI,OAAO,QAAQ,eAAe,CAAC;AAEzE,QAAM,QAAQ,aAAa,MAAM,QAAQ,QAAQ;AACjD,MAAI,CAAC,MAAO,QAAO,IAAI,EAAE,IAAI,OAAO,QAAQ,qBAAqB,CAAC;AAIlE,QAAMC,YAAW,oBAAI,IAAwB;AAC7C,QAAM,SAAuB,CAAC;AAC9B,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,WAAW,IAAI;AAC9B,QAAI;AACF,MAAAA,UAAS,IAAI,QAAQ,MAAM,KAAK,KAAK,KAAK,IAAI,GAAG,EAAE,IAAI,OAAO,OAAO,CAAC;AAAA,QACnE,QAAO,KAAK,IAAI;AAAA,EACvB;AACA,MAAI,CAAC,OAAO,OAAQ,QAAOA;AAC3B,UAAQ;AAER,QAAM,SAAS,MAAM,UAAU,OAAO,KAAK,OAAO;AAClD,MAAI,OAAQ,QAAO,IAAI,IAAI,CAAC,GAAGA,WAAU,GAAG,IAAI,MAAM,CAAC,CAAC;AAExD,QAAM,eAAe,MAAM,KAAK,CAAC,SAAS,KAAK,QAAQ,MAAS;AAChE,QAAM,SAAiB,eACnB,MAAM,cAAc,OAAO,OAAO,IAClC,CAAC;AAIL,QAAM,OAAO,oBAAI,IAAoC;AACrD,aAAW,OAAO,aAAa,OAAO,OAAO,IAAI,GAAG;AAClD,SAAK;AAAA,MACH;AAAA,MACC,MAAM,gBAAgB,GAAG,IACtB,MAAM,UAAU,OAAO,KAAK,OAAO,IACnC,EAAE,IAAI,OAAO,QAAQ,cAAc;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM;AAAA,IAClB;AAAA,IACA;AAAA,IACA,OAAO,SAA8B;AACnC,YAAM,MAAM,KAAK,OAAO,OAAO;AAC/B,UAAI,QAAQ,QAAW;AACrB,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,QAAQ,OAAO,UAAU;AAAA,QAC3B;AAAA,MACF;AACA,YAAM,SAAS,KAAK,IAAI,GAAG;AAC3B,UAAI,OAAQ,QAAO;AACnB,aAAO,SAAS,OAAO,KAAK,KAAK,MAAM,OAAO;AAAA,IAChD;AAAA,EACF;AACA,SAAO,IAAI,IAAI;AAAA,IACb,GAAGA;AAAA,IACH,GAAG,MAAM;AAAA,MACP,CAAC,MAAMC,QACL,CAAC,QAAQ,MAAM,KAAK,KAAK,KAAK,IAAI,GAAG,MAAMA,GAAE,CAAe;AAAA,IAChE;AAAA,EACF,CAAC;AACH;AAQA,SAAS,WAAW,MAAsD;AACxE,MAAI,KAAK,QAAQ,UAAa,CAAC,eAAe,KAAK,GAAG,EAAG,QAAO;AAChE,SAAO,eAAe,KAAK,IAAI,IAAI,SAAY;AACjD;AAEA,SAAS,aACP,OACA,QACU;AACV,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,QAAQ,OAAW,MAAK,IAAI,KAAK,GAAG;AAAA,aACpC,OAAQ,MAAK,IAAI,MAAM;AAAA,EAClC;AACA,SAAO,CAAC,GAAG,IAAI;AACjB;AAGA,eAAe,UACb,OACA,KACA,SACiC;AACjC,MAAI;AACF,cAAM,uBAAM,OAAO,EAAE,WAAW,KAAK,CAAC;AAAA,EACxC,QAAQ;AACN,WAAO,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAAA,EACnD;AACA,QAAM,OAAO,MAAM,IAAI,CAAC,QAAQ,UAAU,WAAW,KAAK,GAAG;AAAA,IAC3D,WAAW,QAAQ;AAAA,EACrB,CAAC;AACD,MAAI,CAAC,KAAK,GAAI,QAAO,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAK/D,QAAM,SAAS,MAAM,IAAI,CAAC,UAAU,qBAAqB,GAAG,GAAG;AAAA,IAC7D,KAAK;AAAA,IACL,WAAW,QAAQ;AAAA,EACrB,CAAC;AACD,SAAO,OAAO,KAAK,SAAY,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAC3E;AAQA,eAAe,cACb,OACA,SACiB;AACjB,MAAI,CAAC,QAAQ,SAAS;AACpB,UAAM,SAAS,MAAM;AAAA,MACnB,CAAC,GAAG,aAAa,GAAG,aAAa,YAAY,UAAU,MAAM;AAAA,MAC7D;AAAA,QACE,KAAK;AAAA,QACL,WAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AACA,UAAM,QAAQ,sCAAsC,KAAK,OAAO,MAAM;AACtE,QAAI,OAAO,MAAM,QAAQ,CAAC,GAAG;AAC3B,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,IAAI,CAAC,UAAU,yBAAyB,IAAI,GAAG,EAAE,KAAK,MAAM,CAAC;AACnE,aAAO,EAAE,KAAK;AAAA,IAChB;AACA,QAAI,CAAC,OAAO,IAAI;AACd,YAAM,SAAS,gBAAgB,OAAO,MAAM;AAC5C,UAAI,WAAW,iBAAiB;AAC9B,cAAMC,UAAS,MAAM,aAAa,KAAK;AACvC,eAAOA,UAAS,EAAE,MAAMA,QAAO,IAAI,EAAE,OAAO;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACA,QAAMA,UAAS,MAAM,aAAa,KAAK;AACvC,MAAIA,QAAQ,QAAO,EAAE,MAAMA,QAAO;AAGlC,SAAO;AAAA,IACL,QAAQ,QAAQ,UAAU,uBAAuB;AAAA,EACnD;AACF;AAEA,eAAe,aAAa,OAA4C;AACtE,QAAM,SAAS,MAAM,IAAI,CAAC,UAAU,SAAS,uBAAuB,GAAG;AAAA,IACrE,KAAK;AAAA,EACP,CAAC;AACD,MAAI,OAAO,MAAM,OAAO,OAAO,KAAK,EAAG,QAAO,OAAO,OAAO,KAAK;AACjE,QAAM,OAAO,MAAM;AAAA,IACjB,CAAC,gBAAgB,WAAW,0BAA0B;AAAA,IACtD;AAAA,MACE,KAAK;AAAA,IACP;AAAA,EACF;AACA,QAAM,OAAO,KAAK,OAAO,KAAK,EAAE,QAAQ,aAAa,EAAE;AACvD,SAAO,KAAK,MAAM,OAAO,OAAO;AAClC;AASA,eAAe,UACb,OACA,KACA,SACiC;AACjC,QAAM,MAAM,OAAO,GAAG;AACtB,QAAM,OAAO,MAAM;AAAA,IACjB,CAAC,aAAa,YAAY,WAAW,GAAG,GAAG,WAAW;AAAA,IACtD;AAAA,MACE,KAAK;AAAA,IACP;AAAA,EACF;AACA,QAAMA,UAAS,KAAK,MAAM,KAAK,OAAO,KAAK,EAAE,SAAS;AACtD,MAAIA,YAAW,QAAQ,WAAW,cAAc,KAAK,GAAG,GAAI,QAAO;AACnE,MAAI,QAAQ,QAAS,QAAO,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAKtE,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,MACE,GAAG,aAAa;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,EAAE,KAAK,OAAO,WAAW,QAAQ,UAAU;AAAA,EAC7C;AACA,MAAI,CAAC,QAAQ,IAAI;AAGf,UAAM,SAAS,gBAAgB,QAAQ,MAAM;AAC7C,QAAIA,WAAU,WAAW,gBAAiB,QAAO;AACjD,WAAO,EAAE,IAAI,OAAO,OAAO;AAAA,EAC7B;AACA,QAAM,OAAO,MAAM,IAAI,CAAC,aAAa,YAAY,GAAG,EAAE,KAAK,MAAM,CAAC;AAClE,QAAM,MAAM,KAAK,OAAO,KAAK;AAC7B,MAAI,CAAC,KAAK,MAAM,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AACvE,QAAM,UAAU,MAAM,IAAI,CAAC,cAAc,KAAK,GAAG,GAAG,EAAE,KAAK,MAAM,CAAC;AAClE,SAAO,QAAQ,KAAK,SAAY,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAC5E;AAGA,eAAe,SACb,OACA,KACA,MACA,SACqB;AACrB,QAAM,OAAO,KAAK,QAAQ,SAAS,EAAE;AACrC,QAAM,OAAO,MAAM;AAAA,IACjB,CAAC,YAAY,QAAQ,oBAAoB,GAAG,OAAO,GAAG,CAAC,IAAI,IAAI,EAAE;AAAA,IACjE;AAAA,MACE,KAAK;AAAA,MACL,WAAW,QAAQ;AAAA,IACrB;AAAA,EACF;AACA,MAAI,KAAK,GAAI,QAAO,EAAE,IAAI,MAAM,QAAQ,KAAK,OAAO;AACpD,MAAI,KAAK,WAAY,QAAO,EAAE,IAAI,OAAO,QAAQ,iBAAiB;AAClE,QAAM,OAAO,KAAK,OAAO,YAAY;AACrC,SAAO,KAAK,SAAS,gBAAgB,KAAK,KAAK,SAAS,oBAAoB,IACxE,EAAE,IAAI,OAAO,QAAQ,eAAe,IACpC,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAC7C;;;AIxUA,IAAAC,mBAAyC;AACzC,IAAAC,oBAAmD;AAkB5C,SAAS,eAAe,UAAkB,MAA6B;AAE5E,QAAM,WAAO,2BAAQ,UAAU,KAAK,QAAQ,SAAS,EAAE,CAAC;AACxD,QAAM,UAAM,gCAAS,2BAAQ,QAAQ,GAAG,IAAI;AAC5C,MACE,QAAQ,MACR,QAAQ,QACR,IAAI,WAAW,KAAK,qBAAG,EAAE,SACzB,8BAAW,GAAG,GACd;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,SAAS,MAAc,MAAuB;AACrD,QAAM,UAAM,4BAAS,MAAM,IAAI;AAC/B,SACE,QAAQ,MACR,QAAQ,QACR,CAAC,IAAI,WAAW,KAAK,qBAAG,EAAE,KAC1B,KAAC,8BAAW,GAAG;AAEnB;AAEA,SAAS,UAAU,OAAoC;AACrD,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,QAC5D,OAAQ,MAA4B,IAAI,IACxC;AACN;AAGO,SAAS,iBAAiB,UAAoC;AACnE,MAAI;AACJ,QAAM,WAAW,MAAuB;AACtC,qBAAa,+BAAS,2BAAQ,QAAQ,CAAC,EAAE,MAAM,CAAC,UAAmB;AAKjE,iBAAW;AACX,YAAM;AAAA,IACR,CAAC;AACD,WAAO;AAAA,EACT;AACA,SAAO,CAAC,SAAS,uBAAuB,UAAU,MAAM,QAAQ;AAClE;AAiBA,eAAe,uBACb,UACA,MACA,UACqB;AACrB,QAAM,UAAU,eAAe,UAAU,IAAI;AAC7C,MAAI,YAAY,KAAM,QAAO,EAAE,IAAI,OAAO,QAAQ,eAAe;AAEjE,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,SAAS;AACtB,WAAO,UAAM,2BAAS,OAAO;AAAA,EAC/B,SAAS,OAAO;AACd,UAAM,OAAO,UAAU,KAAK;AAC5B,QAAI,SAAS,YAAY,SAAS,WAAW;AAC3C,aAAO,EAAE,IAAI,OAAO,QAAQ,eAAe;AAAA,IAC7C;AACA,WAAO,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAAA,EAChD;AACA,MAAI,CAAC,SAAS,MAAM,IAAI,EAAG,QAAO,EAAE,IAAI,OAAO,QAAQ,eAAe;AAEtE,MAAI;AACF,UAAM,QAAQ,UAAM,uBAAK,IAAI;AAC7B,QAAI,CAAC,MAAM,OAAO,EAAG,QAAO,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAGnE,QAAI,MAAM,OAAO,uBAAuB;AACtC,aAAO,EAAE,IAAI,OAAO,QAAQ,iBAAiB;AAAA,IAC/C;AACA,WAAO,EAAE,IAAI,MAAM,QAAQ,UAAM,2BAAS,MAAM,MAAM,EAAE;AAAA,EAC1D,SAAS,OAAO;AACd,UAAM,OAAO,UAAU,KAAK;AAC5B,QAAI,SAAS,YAAY,SAAS,WAAW;AAC3C,aAAO,EAAE,IAAI,OAAO,QAAQ,eAAe;AAAA,IAC7C;AACA,WAAO,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAAA,EAChD;AACF;AAWO,SAAS,uBACd,OACS;AACT,MAAI,UAAU;AACd,aAAW,WAAW,MAAM,OAAO,GAAG;AACpC,eAAW,SAAS,SAAS;AAK3B,UAAI,MAAM,SAAS,OAAW;AAC9B,iBAAW;AACX,UAAI,MAAM,UAAU,gBAAgB,MAAM,WAAW,gBAAgB;AACnE,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO,UAAU;AACnB;AAOA,eAAsB,gBACpB,OACA,MACA,cAAsB,wBACY;AAClC,MAAI,CAAC,OAAO,UAAU,WAAW,KAAK,cAAc,GAAG;AACrD,UAAM,IAAI;AAAA,MACR,yEAAyE,WAAW;AAAA,IACtF;AAAA,EACF;AACA,QAAM,SAAS,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AACjC,QAAM,UAAU,MAAM,SAAS,QAAQ,aAAa,OAAO,SAAS;AAClE,QAAI;AACF,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB,QAAQ;AACN,aAAO,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAAA,IAChD;AAAA,EACF,CAAC;AACD,SAAO,IAAI,IAAI,OAAO,IAAI,CAAC,MAAMC,QAAO,CAAC,MAAM,QAAQA,GAAE,CAAe,CAAC,CAAC;AAC5E;;;AC/KA,IAAAC,sBAA2B;;;ACA3B,IAAAC,oBAAwB;;;ACAxB,IAAAC,mBAAyB;;;ACAzB,yBAAwC;AACxC,IAAAC,mBAAuD;AACvD,IAAAC,kBAAwB;AACxB,IAAAC,oBAA8B;AAIvB,SAAS,kBAAkB,UAA2B;AAC3D,SACE,YACA,QAAQ,IAAI,yBAAyB,SACrC,4BAAK,yBAAQ,GAAG,YAAY,UAAU;AAE1C;AAOO,SAAS,iBACd,MACA,UACAC,SACA,YAA4B,QACpB;AACR,aAAO,wBAAK,MAAM,UAAU,GAAGA,QAAO,MAAM,GAAG,EAAE,CAAC,IAAI,SAAS,EAAE;AACnE;AAEO,SAAS,OAAO,OAA2B;AAChD,aAAO,+BAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAEO,SAAS,QAAQ,OAAmB,OAAwB;AACjE,MAAI,MAAM,UAAU,UAAa,MAAM,eAAe,MAAM;AAC1D,WAAO;AACT,SAAO,OAAO,KAAK,MAAM,MAAM;AACjC;AAOA,eAAsB,aACpB,MACA,OACkB;AAClB,MAAI;AACJ,MAAI;AACF,YAAQ,UAAM,2BAAS,IAAI;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,OAAO,KAAK,EAAG,QAAO;AAClC,YAAM,qBAAG,MAAM,EAAE,OAAO,KAAK,CAAC;AAC9B,SAAO;AACT;AAMA,eAAsB,YACpB,MACA,OACe;AACf,YAAM,4BAAM,2BAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,QAAM,YAAY,GAAG,IAAI,IAAI,QAAQ,GAAG,QAAI,gCAAY,CAAC,EAAE,SAAS,KAAK,CAAC;AAC1E,MAAI;AACF,cAAM,4BAAU,WAAW,KAAK;AAChC,cAAM,yBAAO,WAAW,IAAI;AAAA,EAC9B,SAAS,OAAO;AACd,cAAM,qBAAG,WAAW,EAAE,OAAO,KAAK,CAAC;AACnC,UAAM;AAAA,EACR;AACF;;;ACvEA,IAAM,WAAW;AACjB,IAAM,aAAa;AAOZ,SAAS,WAAW,KAAa,UAA2B;AACjE,QAAMC,QAAO,gBAAgB,QAAQ;AACrC,MAAI,CAACA,MAAM,QAAO;AAClB,MAAI,OAAOA;AACX,SAAO,KAAK,SAAS,GAAG,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE;AAClD,QAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,SAAO,GAAG,IAAI,GAAG,OAAO,QAAQ,GAAG,OAAO,MAAM;AAClD;AAEO,SAAS,gBAAgB,UAAuC;AACrE,SAAO,YAAY,QAAQ,IAAI,yBAAyB;AAC1D;AAWA,eAAsB,aACpB,KACA,MACA,OACA,UAA0B,CAAC,GACR;AACnB,QAAM,MACJ,QAAQ,QAAQ,CAAC,SAAiB,KAAK,QAAQ,OAAO,MAAM,IAAI;AAClE,QAAM,SACJ,MAAM,UAAU,SAAY,KAAK,KAAK,KAAK,MAAM,KAAK,CAAC;AACzD,MAAI,2BAA2B,IAAI,GAAG,MAAM,SAAS,GAAG;AAAA,CAAI;AAE5D,MAAI,QAAQ;AACZ,WAAS,UAAU,GAAG,WAAW,UAAU,WAAW;AACpD,UAAM,UAAU,MAAM,gBAAgB,KAAK,OAAO,QAAQ,cAAc;AACxE,QAAI,WAAW,QAAS,QAAO;AAC/B,YAAQ,QAAQ;AAChB;AAAA,MACE,eAAe,IAAI,YAAY,OAAO,IAAI,QAAQ,YAAY,KAAK;AAAA;AAAA,IACrE;AACA,QAAI,CAAC,QAAQ,MAAO;AACpB,QAAI,UAAU,SAAU,OAAM,MAAM,aAAa,OAAO;AAAA,EAC1D;AACA,MAAI,eAAe,IAAI,oBAAoB,KAAK;AAAA,CAAI;AACpD,SAAO,EAAE,MAAM;AACjB;AAEA,eAAe,gBACb,KACA,OACA,WACoE;AACpE,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ,YAAY,QAAQ,eAAe,SAAS,CAAC;AAAA,IACvD,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO;AAAA,QACL,OAAO,QAAQ,SAAS,MAAM;AAAA,QAC9B,OAAO,SAAS,UAAU,OAAO,SAAS,WAAW;AAAA,MACvD;AAAA,IACF;AACA,UAAM,QAAQ,IAAI,WAAW,MAAM,SAAS,YAAY,CAAC;AACzD,QAAI,CAAC,QAAQ,OAAO,KAAK;AACvB,aAAO,EAAE,OAAO,mBAAmB,OAAO,MAAM;AAClD,WAAO,EAAE,MAAM;AAAA,EACjB,SAAS,OAAO;AACd,UAAM,WACJ,iBAAiB,UAChB,MAAM,SAAS,kBAAkB,MAAM,SAAS;AACnD,WAAO,EAAE,OAAO,WAAW,YAAY,iBAAiB,OAAO,KAAK;AAAA,EACtE;AACF;AAGA,SAAS,KAAK,OAAuB;AACnC,SAAO,SAAS,OAAO,OACnB,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC,QACrC,GAAG,KAAK,MAAM,QAAQ,IAAI,CAAC;AACjC;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAACC,aAAY,WAAWA,UAAS,EAAE,CAAC;AACzD;;;AClGA,qBAAyC;AACzC,IAAAC,oBAA8B;AAC9B,sBAA8B;;;ACF9B,IAAAC,cAAkB;AAElB,IAAMC,UAAS,cAAE,OAAO,EAAE,MAAM,gBAAgB;AAOzC,IAAM,oBAAoB,cAAE,OAAO;AAAA,EACxC,KAAK,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACrB,QAAAA;AAAA,EACA,OAAO,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AACnC,CAAC;AAMM,IAAM,oBAAoB,cAAE,OAAO,EAAE,KAAK,cAAE,OAAO,EAAE,IAAI,CAAC,GAAG,QAAAA,QAAO,CAAC;AAOrE,IAAM,oBAAoB,cAAE,OAAO;AAAA,EACxC,SAAS,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACzB,MAAM;AAAA,EACN,MAAM,cAAE,MAAM,iBAAiB;AAAA,EAC/B,SAAS,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACzB,YAAY,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AAEM,IAAM,wBAAwB,cAAE,OAAO;AAAA;AAAA,EAE5C,eAAe,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC/B,UAAU,cAAE,OAAO,EAAE,KAAK,cAAE,OAAO,EAAE,IAAI,CAAC,GAAG,QAAQ,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,EACxE,OAAO,cAAE,OAAO,cAAE,OAAO,EAAE,IAAI,CAAC,GAAG,iBAAiB;AACtD,CAAC;;;ADlCD,IAAI;AAMG,SAAS,kBAAmC;AACjD,aAAW,sBAAsB;AAAA,IAC/B,KAAK,UAAM,6BAAa,iBAAiB,eAAe,GAAG,MAAM,CAAC;AAAA,EACpE;AACA,SAAO;AACT;AAiBO,SAAS,oBAAoB,UAA4B;AAC9D,MAAI,UAAM,+BAAQ,+BAAc,aAAe,CAAC;AAChD,WAAS,KAAK,GAAG,KAAK,GAAG,MAAM;AAC7B,UAAM,gBAAY,wBAAK,KAAK,UAAU;AACtC,YAAI,+BAAW,wBAAK,WAAW,eAAe,CAAC;AAC7C,iBAAO,wBAAK,WAAW,GAAG,QAAQ;AACpC,cAAM,2BAAQ,GAAG;AAAA,EACnB;AACA,QAAM,IAAI,MAAM,oDAAoD;AACtE;;;AHfA,IAAM,WAAW,oBAAI,IAAqC;AAG1D,IAAM,UAAU,oBAAI,IAAiD;AAGrE,IAAM,eAAe,oBAAI,IAAoB;AAG7C,IAAM,WAAW,oBAAI,IAAoB;AAGlC,SAAS,2BAAoC;AAClD,SAAO,QAAQ,IAAI,qBAAqB,MAAM;AAChD;AAOA,eAAsB,cACpB,UACA,UAA0B,CAAC,GACF;AACzB,QAAMC,QAAO,gBAAgB,EAAE,MAAM,QAAQ;AAC7C,MAAI,CAACA,MAAM,QAAO;AAElB,QAAM,OAAO,kBAAkB,QAAQ,SAAS;AAChD,QAAM,OAAO,iBAAiB,MAAM,UAAUA,MAAK,KAAK,MAAM;AAG9D,QAAM,MAAM,GAAG,IAAI,IAAI,gBAAgB,QAAQ,OAAO,KAAK,EAAE;AAC7D,QAAM,WAAW,SAAS,IAAI,GAAG;AACjC,MAAI,SAAU,QAAO;AAErB,QAAM,WAAW,YAAY;AAC3B,UAAM,UAAU,MAAM;AAAA,MACpB;AAAA,MACA,eAAe,QAAQ;AAAA,MACvBA,MAAK;AAAA,MACL;AAAA,IACF;AACA,QAAI,YAAY;AACd,aAAO,KAAK,UAAU,uBAAuB,QAAQ,IAAI,OAAO;AAElE,UAAM,QAAkB,CAAC;AACzB,UAAM,QAAQA,MAAK,KAAK;AACxB,eAAW,CAACC,KAAI,IAAI,KAAKD,MAAK,KAAK,QAAQ,GAAG;AAC5C,YAAM,OAAO,GAAG,QAAQ,QAAQ,QAAQ,IAAI,SAASC,MAAK,CAAC,IAAI,KAAK,KAAK,EAAE;AAC3E,YAAM,OAAO,iBAAiB,MAAM,UAAU,KAAK,QAAQ,KAAK;AAChE,YAAM,OAAO,MAAM,WAAW,MAAM,MAAM,MAAM,OAAO;AACvD,UAAI,SAAS,KAAM,QAAO,KAAK,UAAU,MAAM,IAAI;AACnD,YAAM,KAAK,KAAK,KAAK,GAAG;AAAA,EAAK,GAAG,UAAM,2BAAS,MAAM,MAAM,CAAC,CAAC,EAAE;AAAA,IACjE;AAEA,YAAQ,OAAO,QAAQ;AACvB,WAAO,EAAE,MAAM,OAAO,QAAQ,MAAM,KAAK,IAAI,IAAI,OAAU;AAAA,EAC7D,GAAG;AACH,WAAS,IAAI,KAAK,OAAO;AACzB,QAAM,SAAS,MAAM;AACrB,MAAI,WAAW,KAAM,UAAS,OAAO,GAAG;AACxC,SAAO;AACT;AAGA,eAAe,WACb,MACA,MACA,OACA,SACoC;AACpC,MAAI,MAAM,aAAa,MAAM,KAAK,EAAG,QAAO;AAC5C,MAAI,QAAQ,YAAY,QAAQ,yBAAyB,EAAG,QAAO,CAAC;AACpE,QAAM,WAAW,MAAM;AAAA,IACrB,WAAW,MAAM,KAAK,QAAQ,OAAO;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,WAAW,SAAU,QAAO,EAAE,OAAO,SAAS,MAAM;AACxD,QAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACxD,SAAO;AACT;AAGA,SAAS,KACP,UACA,SACA,SACM;AACN,UAAQ,IAAI,UAAU,EAAE,SAAS,GAAG,QAAQ,CAAC;AAC7C,SAAO;AACT;AAGA,SAAS,GAAG,MAAsB;AAChC,SAAO,KAAK,QAAQ,SAAS,IAAI;AACnC;AAMO,SAAS,sBAAsB,UAAkB,OAAqB;AAC3E,eAAa,IAAI,UAAU,KAAK;AAClC;AAOO,SAAS,oBAAoB,UAAkB,OAAqB;AACzE,WAAS,IAAI,UAAU,KAAK;AAC9B;AAMO,SAAS,eAAyB;AACvC,QAAM,WAAW,gBAAgB;AACjC,QAAM,QAAQ,SAAS;AACvB,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,CAAC,UAAU,EAAE,SAAS,MAAM,CAAC,KAAK;AAC3C,UAAM;AAAA,MACJ;AAAA,MACA,GAAG,OAAO,cAAc,QAAQ,KAAK,KAAK,MAAM,EAAE;AAAA,IACpD;AACF,aAAW,CAAC,UAAU,KAAK,KAAK;AAC9B,UAAM;AAAA,MACJ;AAAA,MACA,GAAG,MAAM,QAAQ,GAAG,WAAW,eAAe,QAAQ,EAAE,gCAAgC,SAAS,aAAa,GAAG,QAAQ,KAAK,KAAK,KAAK,EAAE,mCAAmC,QAAQ;AAAA,IACvL;AACF,aAAW,CAAC,UAAU,KAAK,KAAK;AAC9B,UAAM;AAAA,MACJ;AAAA,MACA,kBAAkB,QAAQ,6BAA6B,MAAM,QAAQ,GAAG,WAAW,eAAe,QAAQ,EAAE,KAAK,KAAK,mCAAmC,QAAQ;AAAA,IACnK;AACF,SAAO,CAAC,GAAG,KAAK,EACb,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EACrC,IAAI,CAAC,CAAC,EAAE,IAAI,MAAM,IAAI;AAC3B;;;AD/JA,IAAI;AAGJ,SAAS,iBAAyC;AAChD,QAAM,WAAW,gBAAgB;AACjC,MAAI,OAAO,OAAO;AAChB,YAAQ;AAAA,MACN,IAAI;AAAA,MACJ,YAAY,OAAO;AAAA,QACjB,OAAO,QAAQ,SAAS,KAAK,EAAE;AAAA,UAAQ,CAAC,CAAC,UAAUC,KAAI,MACrDA,MAAK,WAAW,IAAI,CAAC,cAAc,CAAC,WAAW,QAAQ,CAAC;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AACF,SAAO,MAAM;AACf;AAGA,SAAS,SAAS,UAA2B;AAC3C,UAAQ,gBAAgB,EAAE,MAAM,QAAQ,GAAG,KAAK,UAAU,KAAK;AACjE;AAOO,SAAS,gBAAgB,MAAkC;AAChE,QAAM,WAAW,eAAe,MAAE,2BAAQ,IAAI,EAAE,YAAY,CAAC;AAC7D,SAAO,YAAY,SAAS,QAAQ,IAAI,WAAW;AACrD;;;AMzCA,IAAAC,sBAA2B;AAC3B,6BAAmD;;;ACQnD,IAAM,aAAa;AAuBZ,SAAS,MAAM,MAAY,OAA0B;AAC1D,QAAM,SAAS,oBAAI,IAAwB;AAE3C,aAAW,SAAS,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAChD,UAAM,WAAW,MAAM,SAAS,KAAK,CAAC,YAAY,QAAQ,SAAS,MAAM;AACzE,UAAM,UAAU,MAAM,SAAS;AAAA,MAC7B,CAAC,YACC,QAAQ,KAAK,WAAW,aAAa,KAAK,QAAQ,SAAS;AAAA,IAC/D;AACA,QAAI,CAAC,YAAY,CAAC,QAAS;AAE3B,UAAM,YAAwB;AAAA,MAC5B,MAAM,QAAQ;AAAA,MACd,MAAM,SAAS,KAAK;AAAA,MACpB,QAAQ,QAAQ,SAAS;AAAA,IAC3B;AACA,UAAM,WAAW,OAAO,IAAI,SAAS,KAAK,EAAE;AAC5C,QAAI,YAAY,MAAM,SAAS,IAAI,KAAK,MAAM,UAAU,IAAI,EAAG;AAC/D,WAAO,IAAI,SAAS,KAAK,IAAI,SAAS;AAAA,EACxC;AAEA,QAAM,cAAc,CAAC,GAAG,OAAO,OAAO,CAAC;AACvC,SAAO;AAAA,IACL;AAAA,IACA,UAAU,IAAI;AAAA,MACZ,YAAY,IAAI,CAAC,eAAe,CAAC,WAAW,KAAK,IAAI,UAAU,CAAC;AAAA,IAClE;AAAA,IACA;AAAA,EACF;AACF;AAOO,SAAS,OACd,QACA,QACc;AACd,QAAMC,WAAU,OAAO,YAAY;AAAA,IACjC,CAAC,eACC,WAAW,UACX,SAAS,QAAQ,YAAY,OAAO,QAAQ,GAAG,MAAM;AAAA,EACzD;AACA,MAAIA,SAAQ,SAAS,EAAG,QAAOA;AAC/B,QAAM,SAASA,SAAQ;AAAA,IACrB,CAAC,eAAe,WAAW,KAAK,kBAAkB,MAAM,MAAM;AAAA,EAChE;AACA,SAAO,OAAO,WAAW,IAAI,SAASA;AACxC;AASO,SAAS,QACd,YACA,UACU;AACV,QAAM,QAAQ,CAAC,WAAW,IAAI;AAE9B,QAAM,WAAW,WAAW,KAAK,kBAAkB,UAAU;AAC7D,QAAM,OAAO,YAAY,WAAW,QAAQ;AAC5C,MAAI,KAAM,OAAM,QAAQ,IAAI;AAE5B,WAAS,OAAO,WAAW,KAAK,QAAQ,MAAM,OAAO,KAAK,QAAQ;AAChE,UAAM,YAAY,SAAS,IAAI,KAAK,EAAE;AACtC,QAAI,aAAa,UAAU,SAAS,WAAW;AAC7C,YAAM,QAAQ,UAAU,IAAI;AAAA,EAChC;AACA,SAAO;AACT;AAGA,SAAS,WAAW,UAAoC;AACtD,QAAM,QAAgB,CAAC,QAAQ;AAC/B,SAAO,MAAM,QAAQ;AACnB,UAAM,OAAO,MAAM,IAAI;AACvB,QAAI,KAAK,SAAS,kBAAmB,QAAO,KAAK;AACjD,aAASC,MAAK,GAAGA,MAAK,KAAK,YAAYA,OAAM;AAC3C,YAAM,QAAQ,KAAK,MAAMA,GAAE;AAC3B,UAAI,MAAO,OAAM,KAAK,KAAK;AAAA,IAC7B;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,SAAS,OAAiB,QAAoC;AACrE,MAAI,OAAO,SAAS,MAAM,OAAQ,QAAO;AACzC,QAAM,SAAS,MAAM,SAAS,OAAO;AACrC,SAAO,OAAO,MAAM,CAAC,SAASA,QAAO,MAAM,SAASA,GAAE,MAAM,OAAO;AACrE;AAEA,SAAS,MAAM,MAAoB;AACjC,SAAO,KAAK,WAAW,KAAK;AAC9B;AAMO,SAAS,OAAO,YAAwB,QAAgC;AAC7E,MAAI,QAAQ,WAAW;AACvB,MAAI,MAAM,WAAW;AAErB,WACM,UAAU,MAAM,iBACpB,SAAS,SAAS,aAClB,UAAU,QAAQ,iBAClB;AACA,YAAQ;AAAA,EACV;AAEA,QAAM,SAAS,IAAI;AACnB,MACE,QAAQ,SAAS,sBACjB,OAAO,kBAAkB,aAAa,GAAG,OAAO,IAAI,IACpD;AACA,YAAQ;AACR,UAAM;AAAA,EACR;AAEA,QAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,QAAM,YAAY,MAAM,cAAc;AAEtC,QAAM,UACJ,IAAI,YAAY,WAAW,KAAK,IAAI,YAAY,MAAM,YAClD,IAAI,YAAY,MAAM,IACtB,IAAI,YAAY;AAEtB,SAAO;AAAA,IACL,MAAM,MAAM,MAAM,WAAW,UAAU,CAAC,EAAE,KAAK,IAAI;AAAA,IACnD,WAAW,YAAY;AAAA,IACvB,SAAS,UAAU;AAAA,EACrB;AACF;;;ACnKO,SAAS,OAAO,MAAsB;AAC3C,QAAM,MAAgB,CAAC;AACvB,QAAM,QAAgB,CAAC,IAAI;AAC3B,SAAO,MAAM,QAAQ;AACnB,UAAM,OAAO,MAAM,IAAI;AACvB,QAAI,KAAK,KAAK,SAAS,SAAS,EAAG;AACnC,QAAI,KAAK,eAAe,GAAG;AACzB,YAAM,OAAO,KAAK,KAAK,KAAK;AAC5B,UAAI,KAAM,KAAI,KAAK,IAAI;AACvB;AAAA,IACF;AACA,aAASC,MAAK,KAAK,aAAa,GAAGA,OAAM,GAAGA,OAAM;AAChD,YAAM,QAAQ,KAAK,MAAMA,GAAE;AAC3B,UAAI,MAAO,OAAM,KAAK,KAAK;AAAA,IAC7B;AAAA,EACF;AACA,SAAO;AACT;;;AFSA,IAAM,mBAAmB;AASlB,IAAM,qBAAN,MAAmD;AAAA,EAC/C,OAAO;AAAA,EAEC;AAAA,EACA,SAAS,oBAAI,IAA2B;AAAA,EACxC,QAAQ,oBAAI,IAAwB;AAAA,EAC7C;AAAA,EACA,cAAc;AAAA;AAAA,EAGb,QAAyB,EAAE,QAAQ,GAAG,WAAW,EAAE;AAAA,EAE5D,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,OAAyC;AACrD,UAAM,SAAS,oBAAI,IAAY;AAC/B,eAAW,QAAQ,OAAO;AACxB,YAAM,WAAW,gBAAgB,IAAI;AACrC,UAAI,YAAY,CAAC,KAAK,OAAO,IAAI,QAAQ,EAAG,QAAO,IAAI,QAAQ;AAAA,IACjE;AACA,QAAI,CAAC,OAAO,KAAM;AAElB,QAAI,CAAC,KAAK,aAAa;AACrB,UAAI;AACF,cAAM,8BAAO,KAAK;AAClB,aAAK,SAAS,IAAI,8BAAO;AACzB,aAAK,cAAc;AAAA,MACrB,QAAQ;AACN,mBAAW,YAAY,OAAQ,MAAK,OAAO,IAAI,UAAU,IAAI;AAC7D;AAAA,MACF;AAAA,IACF;AAIA,UAAM,YAAY,CAAC,GAAG,MAAM;AAC5B,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,KAAK,IAAI,wBAAwB,UAAU,MAAM;AAAA,MACjD,CAAC,aAAa,KAAK,KAAK,QAAQ;AAAA,IAClC;AACA,cAAU;AAAA,MAAQ,CAAC,UAAUC,QAC3B,KAAK,OAAO,IAAI,UAAU,OAAOA,GAAE,KAAK,IAAI;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,KAAK,UAA0C;AAC3D,QAAIC;AACJ,QAAI;AACF,MAAAA,QAAO,MAAM,cAAc,UAAU,KAAK,QAAQ;AAAA,IACpD,QAAQ;AACN,aAAO;AAAA,IACT;AACA,QAAI,CAACA,OAAM,MAAO,QAAO;AAEzB,QAAI;AACJ,QAAI;AACF,gBAAU,MAAM,gCAAS,KAAKA,MAAK,IAAI;AAAA,IACzC,SAAS,OAAO;AACd,0BAAoB,UAAU,IAAI,KAAK,CAAC;AACxC,aAAO;AAAA,IACT;AACA,QAAI;AACF,aAAO,EAAE,UAAU,SAAS,OAAO,IAAI,6BAAM,SAASA,MAAK,KAAK,EAAE;AAAA,IACpE,SAAS,OAAO;AACd,4BAAsB,UAAU,IAAI,KAAK,CAAC;AAC1C,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAQ,QAAgB,QAAgB,MAAgC;AACtE,UAAM,WAAW,OAAO,gBAAgB,IAAI,IAAI;AAChD,QAAI,CAAC,SAAU,QAAO,EAAE,MAAM,UAAU;AACxC,QAAI,CAAC,KAAK,OAAO,IAAI,QAAQ,EAAG,QAAO,EAAE,MAAM,UAAU;AACzD,UAAM,SAAS,KAAK,OAAO,IAAI,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,cAAc,QAAQ,uBAAuB;AAEzE,UAAM,SAAS,KAAK,MAAM,UAAU,QAAQ,MAAM;AAClD,QAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,cAAc,QAAQ,uBAAuB;AAEzE,UAAM,SAAS,OAAO,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/C,QAAI,CAAC,OAAO;AACV,aAAO,EAAE,MAAM,cAAc,QAAQ,mBAAmB;AAE1D,UAAMC,WAAU,OAAO,QAAQ,MAAM;AACrC,QAAI,CAACA,SAAQ;AACX,aAAO,EAAE,MAAM,cAAc,QAAQ,mBAAmB;AAC1D,QAAIA,SAAQ,SAAS;AACnB,aAAO,EAAE,MAAM,cAAc,QAAQ,mBAAmB;AAC1D,WAAO,EAAE,MAAM,YAAY,MAAM,OAAOA,SAAQ,CAAC,GAAiB,MAAM,EAAE;AAAA,EAC5E;AAAA,EAEA,QACE,QACA,QACA,MACuB;AACvB,UAAM,UAAU,KAAK,QAAQ,QAAQ,QAAQ,IAAI;AACjD,WAAO,QAAQ,SAAS,aAAa,QAAQ,OAAO;AAAA,EACtD;AAAA;AAAA,EAGQ,MACN,UACA,QACA,QACmB;AACnB,UAAM,MAAM,GAAG,QAAQ,QAAI,gCAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,CAAC;AAC5E,UAAMC,UAAS,KAAK,MAAM,IAAI,GAAG;AACjC,QAAIA,SAAQ;AACV,WAAK,MAAM,aAAa;AACxB,aAAOA;AAAA,IACT;AAEA,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAQ,QAAO;AACpB,QAAI;AACJ,QAAI;AACF,aAAO,YAAY,OAAO,QAAQ;AAClC,YAAM,OAAO,OAAO,MAAM,MAAM;AAChC,UAAI,CAAC,KAAM,QAAO;AAClB,eAAS,MAAM,MAAM,OAAO,KAAK;AAAA,IACnC,QAAQ;AACN,aAAO;AAAA,IACT;AACA,SAAK,MAAM,UAAU;AAErB,QAAI,KAAK,MAAM,QAAQ,kBAAkB;AACvC,YAAM,SAAS,KAAK,MAAM,KAAK,EAAE,KAAK;AACtC,UAAI,CAAC,OAAO,MAAM;AAChB,aAAK,MAAM,IAAI,OAAO,KAAK,GAAG,KAAK,OAAO;AAC1C,aAAK,MAAM,OAAO,OAAO,KAAK;AAAA,MAChC;AAAA,IACF;AACA,SAAK,MAAM,IAAI,KAAK,MAAM;AAC1B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MACE,QACA,MAC4C;AAC5C,UAAM,WAAW,gBAAgB,IAAI;AACrC,QAAI,CAAC,SAAU,QAAO,CAAC;AACvB,UAAM,SAAS,KAAK,OAAO,IAAI,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,UAAM,SAAS,KAAK,MAAM,UAAU,QAAQ,MAAM;AAClD,QAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,WAAO,OAAO,YACX,OAAO,CAAC,eAAe,WAAW,MAAM,EACxC,IAAI,CAAC,gBAAgB;AAAA,MACpB,QAAQ,QAAQ,YAAY,OAAO,QAAQ,EAAE,KAAK,GAAG;AAAA,MACrD,MAAM,OAAO,YAAY,MAAM;AAAA,IACjC,EAAE;AAAA,EACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,UAAU,MAAc,MAA8B;AACpD,UAAM,WAAW,OAAO,gBAAgB,IAAI,IAAI;AAChD,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,SAAS,KAAK,OAAO,IAAI,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAQ,QAAO;AACpB,QAAI;AACJ,QAAI;AACF,aAAO,YAAY,OAAO,QAAQ;AAClC,aAAO,OAAO,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,aAAO;AAAA,IACT;AACA,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI;AACF,aAAO,OAAO,KAAK,QAAQ,EAAE,KAAK,GAAG;AAAA,IACvC,UAAE;AACA,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA,EAGA,QAAc;AACZ,eAAW,UAAU,KAAK,MAAM,OAAO,EAAG,QAAO,KAAK,OAAO;AAC7D,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,SAAS;AACpB,SAAK,MAAM,YAAY;AAAA,EACzB;AACF;AAGA,SAAS,IAAI,OAAwB;AACnC,QAAM,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAClE,SAAO,QAAQ;AACjB;;;AP7PA,IAAM,qBAAqB;AAQ3B,IAAM,cAAyB,EAAE,cAAc,OAAO,UAAU,MAAM;AAatE,SAAS,UACP,MACA,OACoC;AACpC,MAAI,MAAM;AACV,MAAIC,SAAQ;AACZ,MAAI,EAAE,cAAc,SAAS,IAAI;AAEjC,SAAOA,SAAQ,KAAK,QAAQ;AAC1B,UAAM,OAAO,KAAKA,MAAK;AACvB,UAAM,OAAO,KAAKA,SAAQ,CAAC;AAE3B,QAAI,cAAc;AAChB,UAAI,SAAS,OAAO,SAAS,KAAK;AAChC,uBAAe;AACf,QAAAA,UAAS;AACT;AAAA,MACF;AACA,MAAAA,UAAS;AACT;AAAA,IACF;AAIA,QAAI,UAAU;AACZ,UAAI,SAAS,MAAM;AACjB,QAAAA,UAAS;AACT;AAAA,MACF;AACA,UAAI,SAAS,IAAK,YAAW;AAC7B,MAAAA,UAAS;AACT;AAAA,IACF;AAEA,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,qBAAe;AACf,MAAAA,UAAS;AACT;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,IAAK;AAClC,QAAI,SAAS,KAAK;AAChB,iBAAW;AACX,MAAAA,UAAS;AACT;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,YAAM,QAAQ;AACd,MAAAA,UAAS;AACT,aAAOA,SAAQ,KAAK,QAAQ;AAC1B,YAAI,KAAKA,MAAK,MAAM,MAAM;AACxB,UAAAA,UAAS;AACT;AAAA,QACF;AACA,YAAI,KAAKA,MAAK,MAAM,OAAO;AACzB,UAAAA,UAAS;AACT;AAAA,QACF;AACA,QAAAA,UAAS;AAAA,MACX;AACA;AAAA,IACF;AAEA,WAAO;AACP,IAAAA,UAAS;AAAA,EACX;AAEA,SAAO,EAAE,MAAM,KAAK,OAAO,EAAE,cAAc,SAAS,EAAE;AACxD;AAMA,SAAS,KAAK,OAAiB,MAAc,IAA4B;AACvE,SAAO;AAAA,IACL,MAAM,MAAM,MAAM,MAAM,KAAK,CAAC,EAAE,KAAK,IAAI;AAAA,IACzC,WAAW,OAAO;AAAA,IAClB,SAAS,KAAK;AAAA,EAChB;AACF;AAUA,SAAS,kBACP,OACA,WACuB;AACvB,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,MAAI,QAAQ;AAEZ,WAASA,SAAQ,WAAWA,SAAQ,MAAM,QAAQA,UAAS;AACzD,UAAM,WAAW,UAAU,MAAMA,MAAK,KAAK,IAAI,KAAK;AACpD,YAAQ,SAAS;AAEjB,eAAW,QAAQ,SAAS,MAAM;AAChC,UAAI,SAAS,KAAK;AAChB,iBAAS;AACT,iBAAS;AAAA,MACX,WAAW,SAAS,KAAK;AACvB,gBAAQ,KAAK,IAAI,GAAG,QAAQ,CAAC;AAAA,MAC/B,WAAW,SAAS,OAAO,CAAC,QAAQ;AAClC,eAAO,KAAK,OAAO,WAAWA,MAAK;AAAA,MACrC;AAAA,IACF;AAEA,QAAI,UAAU,UAAU,EAAG,QAAO,KAAK,OAAO,WAAWA,MAAK;AAAA,EAChE;AAEA,SAAO;AACT;AAGA,IAAM,gBAAgB;AAUtB,SAAS,qBACP,OACA,WACuB;AACvB,QAAM,SAAS,MAAM,SAAS,KAAK;AACnC,QAAM,SAAS,OAAO,SAAS,OAAO,UAAU,EAAE;AAElD,MAAI,YAAY;AAChB,WACMA,SAAQ,WACZA,SAAQ,MAAM,UAAUA,UAAS,YAAY,IAC7CA,UACA;AACA,UAAM,OAAO,UAAU,MAAMA,MAAK,KAAK,IAAI,WAAW,EAAE,KAAK,QAAQ;AACrE,QAAI,KAAK,SAAS,GAAG,GAAG;AACtB,kBAAYA;AACZ;AAAA,IACF;AAEA,QAAI,KAAK,SAAS,GAAG,EAAG,QAAO,KAAK,OAAO,WAAWA,MAAK;AAAA,EAC7D;AACA,MAAI,cAAc,GAAI,QAAO;AAE7B,MAAI,MAAM;AACV,WAASA,SAAQ,YAAY,GAAGA,SAAQ,MAAM,QAAQA,UAAS;AAC7D,UAAM,OAAO,MAAMA,MAAK,KAAK;AAC7B,QAAI,KAAK,KAAK,MAAM,GAAI;AACxB,UAAM,aAAa,KAAK,SAAS,KAAK,UAAU,EAAE;AAClD,QAAI,cAAc,OAAQ;AAC1B,UAAMA;AAAA,EACR;AAGA,SAAO,QAAQ,YAAY,OAAO,KAAK,OAAO,WAAW,GAAG;AAC9D;AAYA,IAAM,QAAsC;AAAA,EAC1C,CAAC,SACC,IAAI;AAAA,IACF,+DAA+D,IAAI;AAAA,EACrE;AAAA,EACF,CAAC,SAAS,IAAI,OAAO,MAAM,IAAI,UAAU;AAAA,EACzC,CAAC,SAAS,IAAI,OAAO,MAAM,IAAI,SAAS;AAAA,EACxC,CAAC,SAAS,IAAI,OAAO,MAAM,IAAI,KAAK;AACtC;AAYO,IAAM,gBAAgC;AAAA,EAC3C,MAAM;AAAA,EACN,QAAQ,QAAQ,QAAQ;AACtB,UAAM,WAAW,OAAO,MAAM,GAAG;AACjC,UAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,SACJ,SAAS,SAAS,IAAI,SAAS,SAAS,SAAS,CAAC,IAAI;AAExD,UAAM,UAAU,aAAa,IAAI;AACjC,UAAM,gBAAgB,SAClB,IAAI,OAAO,MAAM,aAAa,MAAM,CAAC,KAAK,IAC1C;AACJ,UAAM,QAAQ,OAAO,MAAM,IAAI;AAE/B,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,OAAO;AAC5B,UAAI,aAAa,MACd,IAAI,CAAC,MAAMA,YAAW,EAAE,MAAM,OAAAA,OAAM,EAAE,EACtC,OAAO,CAAC,UAAU,QAAQ,KAAK,MAAM,IAAI,CAAC,EAC1C,IAAI,CAAC,UAAU,MAAM,KAAK;AAC7B,UAAI,CAAC,WAAW,OAAQ;AAKxB,UAAI,iBAAiB,WAAW,SAAS,GAAG;AAC1C,cAAM,YAAY,WAAW;AAAA,UAAI,CAACA,WAChC,iBAAiB,OAAOA,QAAO,aAAa;AAAA,QAC9C;AACA,cAAM,UAAU,KAAK,IAAI,GAAG,SAAS;AACrC,YAAI,OAAO,SAAS,OAAO,GAAG;AAC5B,uBAAa,WAAW,OAAO,CAAC,GAAGC,QAAO,UAAUA,GAAE,MAAM,OAAO;AAAA,QACrE;AAAA,MACF;AAIA,UAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,YAAM,YAAY,WAAW,CAAC;AAC9B,aAAO,cAAc,KAAK,MAAM,SAAS,KAAK,EAAE,IAC5C,qBAAqB,OAAO,SAAS,IACrC,kBAAkB,OAAO,SAAS;AAAA,IACxC;AAEA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;AAGA,SAAS,iBACP,OACAD,QACA,QACQ;AACR,QAAM,QAAQ,KAAK,IAAI,GAAGA,SAAQ,kBAAkB;AACpD,WAASC,MAAKD,QAAOC,OAAM,OAAOA,OAAM;AACtC,QAAI,OAAO,KAAK,MAAMA,GAAE,KAAK,EAAE,EAAG,QAAOD,SAAQC;AAAA,EACnD;AACA,SAAO,OAAO;AAChB;AAGO,SAAS,eAAe,MAAsB;AACnD,SAAO,cAAU,gCAAW,QAAQ,EACjC,OAAO,KAAK,QAAQ,SAAS,IAAI,CAAC,EAClC,OAAO,KAAK,CAAC;AAClB;AA6BO,SAAS,kBACd,QACA,QACA,YAAuC,CAAC,aAAa,GACnC;AAClB,QAAM,aAAa,OAAO,QAAQ,SAAS,IAAI;AAC/C,MAAI,CAAC,OAAO,QAAQ;AAClB,UAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,QAAI,MAAM,SAAS,KAAK,MAAM,MAAM,SAAS,CAAC,MAAM,GAAI,OAAM,IAAI;AAClE,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,WAAW;AAAA,QACX,SAAS,KAAK,IAAI,GAAG,MAAM,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAEA,aAAW,YAAY,WAAW;AAChC,UAAM,UAAU,SAAS,UACrB,SAAS,QAAQ,YAAY,OAAO,QAAQ,OAAO,IAAI,IACvD,YAAY,UAAU,YAAY,OAAO,QAAQ,OAAO,IAAI;AAChE,QAAI,QAAQ,SAAS,UAAW;AAChC,QAAI,QAAQ,SAAS,cAAc;AACjC,UAAI,QAAQ,WAAW,mBAAoB;AAC3C,aAAO,EAAE,IAAI,OAAO,QAAQ,QAAQ,OAAO;AAAA,IAC7C;AACA,UAAMC,UAAS,SAAS,YAAY,QAAQ,KAAK,MAAM,OAAO,IAAI;AAClE,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM,QAAQ;AAAA,MACd,GAAI,eAAe,SAAS,IAAI,IAAI,EAAE,UAAU,SAAS,KAAK,IAAI,CAAC;AAAA,MACnE,GAAIA,UAAS,EAAE,YAAYA,QAAO,IAAI,CAAC;AAAA,IACzC;AAAA,EACF;AACA,SAAO,EAAE,IAAI,OAAO,QAAQ,mBAAmB;AACjD;AAGA,SAAS,YACP,UACA,QACA,QACA,MACiB;AACjB,QAAMC,QAAO,SAAS,QAAQ,QAAQ,QAAQ,IAAI;AAClD,SAAOA,QACH,EAAE,MAAM,YAAY,MAAAA,MAAK,IACzB,EAAE,MAAM,cAAc,QAAQ,mBAAmB;AACvD;AAEA,SAAS,eAAe,MAA0C;AAChE,SAAO,SAAS,iBAAiB,SAAS;AAC5C;AAGA,eAAsB,iBACpB,WACA,OACe;AACf,aAAW,YAAY,UAAW,OAAM,SAAS,UAAU,KAAK;AAClE;AAQO,SAAS,uBACd,WAA2B,CAAC,GACV;AAClB,SAAO,CAAC,IAAI,mBAAmB,QAAQ,GAAG,aAAa;AACzD;AASO,SAAS,gBACd,QACA,QACA,UACS;AACT,QAAM,WAAW,OAAO,YAAY;AACpC,MAAI,CAAC,YAAY,CAAC,OAAO,UAAU,aAAa,SAAU,QAAO;AACjE,MAAI,aAAa,QAAS,QAAO;AACjC,QAAM,SAAS,cAAc;AAAA,IAC3B,OAAO,QAAQ,SAAS,IAAI;AAAA,IAC5B,OAAO;AAAA,EACT;AACA,SAAO,WAAW,QAAQ,eAAe,OAAO,IAAI,MAAM,OAAO;AACnE;AAWO,SAAS,aACd,QACA,SACwC;AACxC,QAAM,SAAS,OAAO,OAAQ,OAAO,aAAa,QAAS;AAC3D,QAAM,SAAS,WAAW,QAAQ,aAAa,QAAQ;AACvD,SAAO,WAAW,SAAS,QAAQ,aAC/B,EAAE,MAAM,eAAe,QAAQ,UAAU,GAAG,MAAM,MAAM,IACxD,EAAE,MAAM,eAAe,QAAQ,KAAK,IAAI,GAAG,MAAM,MAAM;AAC7D;;;AUhZA,eAAsB,kBACpB,SACA,UAA8B,CAAC,GACa;AAC5C,QAAM,WAAW,QAAQ,YAAY,QAAQ,IAAI;AACjD,QAAM,YACJ,QAAQ,cACP,QAAQ,WACL,CAAC,QAAQ,QAAQ,IACjB,uBAAuB;AAAA,IACrB,SAAS,QAAQ,QAAQ,YAAY;AAAA,EACvC,CAAC;AACP,QAAM,SAAS,IAAI,WAAW,QAAQ;AAEtC,QAAM,UAAU,oBAAI,IAAuB;AAC3C,MAAI,eAAe;AACnB,aAAW,UAAU,SAAS;AAC5B,UAAM,WAAW,OAAO,YAAY,mBAAmB,CAAC,GAAG;AAAA,MACzD,CAAC,WAAW,OAAO;AAAA,IACrB;AACA,QAAI,CAAC,QAAQ,OAAQ;AACrB,QAAI,QAAQ,KAAK,CAAC,WAAW,OAAO,IAAI,EAAG,gBAAe;AAC1D,YAAQ;AAAA,MACN,OAAO;AAAA,MACP,QAAQ,IAAI,CAAC,YAAY,EAAE,QAAQ,SAAS,MAAM,EAAE;AAAA,IACtD;AAAA,EACF;AACA,MAAI,cAAc;AAChB,UAAM,OAAO,MAAM;AACnB,eAAW,WAAW,QAAQ,OAAO,GAAG;AACtC,iBAAW,SAAS;AAClB,cAAM,UAAU,OAAO,UAAU,MAAM,MAAM;AAAA,IACjD;AAAA,EACF;AAEA,QAAM,QAAkB,CAAC;AACzB,QAAM,QAAsB,CAAC;AAC7B,aAAW,WAAW,QAAQ,OAAO,GAAG;AACtC,eAAW,EAAE,QAAQ,QAAQ,KAAK,SAAS;AACzC,UAAI,CAAC,QAAS,OAAM,KAAK,OAAO,IAAI;AAAA,UAC/B,OAAM,KAAK,GAAG,YAAY,MAAM,CAAC;AAAA,IACxC;AAAA,EACF;AAGA,QAAM,CAAC,OAAO,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IACxC;AAAA,MACE;AAAA,MACA,QAAQ,UAAU,iBAAiB,QAAQ;AAAA,MAC3C,QAAQ,eAAe;AAAA,IACzB;AAAA,KACC,QAAQ,cAAc,mBAAmB,OAAO,QAAQ,UAAU,CAAC,CAAC;AAAA,EACvE,CAAC;AACD,QAAM,iBAAiB,WAAW;AAAA,IAChC,GAAG;AAAA,IACH,GAAG,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,EAClC,CAAC;AAED,QAAM,QAAQ,oBAAI,IAAkC;AACpD,aAAW,UAAU,SAAS;AAC5B,UAAM,UAAgC,CAAC;AACvC,eAAW,EAAE,QAAQ,QAAQ,KAAK,QAAQ,IAAI,OAAO,SAAS,KAAK,CAAC,GAAG;AACrE,cAAQ;AAAA,QACN,UACI,YAAY,QAAQ,QAAQ,SAAS,IACrC,WAAW,QAAQ,MAAM,IAAI,OAAO,IAAI,GAAiB,SAAS;AAAA,MACxE;AAAA,IACF;AACA,QAAI,QAAQ,OAAQ,OAAM,IAAI,OAAO,WAAW,OAAO;AAAA,EACzD;AACA,SAAO;AACT;AAMO,SAAS,YAAY,QAAgC;AAC1D,QAAM,OAAO,OAAO;AACpB,QAAM,QAAsB,CAAC,EAAE,MAAM,MAAM,OAAO,KAAK,CAAC;AACxD,MAAI,OAAO,IAAK,OAAM,QAAQ,EAAE,MAAM,KAAK,OAAO,KAAK,MAAM,OAAO,KAAK,CAAC;AAC1E,SAAO;AACT;AAEA,SAAS,KACP,QAC4D;AAC5D,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,IACjD,YAAY,OAAO;AAAA,EACrB;AACF;AAEA,SAAS,WACP,QACA,QACA,MACoB;AACpB,SAAO;AAAA,IACL,GAAG,KAAK,MAAM;AAAA,IACd,OAAO;AAAA,IACP,UAAU;AAAA,IACV,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACvB,GAAG,QAAQ,MAAM;AAAA,EACnB;AACF;AAUO,SAAS,sBACd,OAC0B;AAC1B,MAAI,MAAM,UAAU,cAAc;AAChC,WAAO,MAAM,WAAW,kBACtB,MAAM,WAAW,qBACf,SACA;AAAA,EACN;AACA,SAAO,MAAM,UAAU,YAAY,YAAY;AACjD;AAGA,SAAS,QAAQ,QAEf;AACA,QAAM,UAAU,sBAAsB,EAAE,OAAO,cAAc,OAAO,CAAC;AACrE,SAAO,UAAU,EAAE,OAAO,QAAQ,IAAI,CAAC;AACzC;AAUA,SAAS,OACP,QACA,QACA,WAGsD;AACtD,QAAM,UAAU,kBAAkB,QAAQ,QAAQ,SAAS;AAC3D,MAAI,CAAC,QAAQ,GAAI,QAAO,EAAE,IAAI,OAAO,QAAQ,QAAQ,OAAO;AAC5D,QAAM,EAAE,MAAM,KAAK,IAAI,aAAa,QAAQ,OAAO;AACnD,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA,OAAO,QAAQ,KAAK,UAAU,QAAQ,KAAK,YAAY;AAAA,MACvD,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,IAC3D;AAAA,EACF;AACF;AASA,SAAS,eACP,QACA,QACA,SAC6B;AAC7B,SAAO;AAAA,IACL,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,IACzD,GAAI,QAAQ,SAAS,OAAO,QAC5B,gBAAgB,QAAQ,QAAQ,QAAQ,QAAQ,IAC5C,EAAE,QAAQ,mBAA4B,IACtC,CAAC;AAAA,EACP;AACF;AAEA,SAAS,SACP,QACA,SACA,QAAqC,CAAC,GAClB;AACpB,QAAM,UAAU,QAAQ,SAAS,OAAO;AACxC,SAAO;AAAA,IACL,GAAG,KAAK,MAAM;AAAA,IACd,OAAO,UAAU,UAAU;AAAA,IAC3B,aAAa,QAAQ;AAAA,IACrB,UAAU,QAAQ;AAAA,IAClB,UACE,OAAO,UAAU,SACb,OACA,KAAK,IAAI,QAAQ,QAAQ,OAAO,KAAK;AAAA,IAC3C,GAAI,UAAU,CAAC,IAAI,EAAE,OAAO,UAAmB;AAAA,IAC/C,GAAG;AAAA,EACL;AACF;AAEA,SAAS,WACP,QACA,MACA,WACoB;AACpB,MAAI,CAAC,KAAK,GAAI,QAAO,WAAW,QAAQ,KAAK,MAAM;AACnD,QAAM,QAAQ,OAAO,KAAK,QAAQ,QAAQ,SAAS;AACnD,MAAI,CAAC,MAAM,GAAI,QAAO,WAAW,QAAQ,MAAM,MAAM;AACrD,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,eAAe,KAAK,QAAQ,QAAQ,MAAM,OAAO;AAAA,EACnD;AACF;AAUA,SAAS,YACP,QACA,QACA,WACoB;AACpB,QAAM,OAAO,OAAO;AACpB,QAAM,MAAM,iBAAiB,IAAI;AACjC,QAAM,YAAY,OAAO,IAAI,QAAQ,KAAK,QAAW,OAAO,IAAI,CAAC;AACjE,QAAM,UAAU,OAAO,MACnB,OAAO,IAAI,QAAQ,KAAK,OAAO,KAAK,OAAO,IAAI,CAAC,IAChD;AAEJ,MAAI,CAAC,QAAS,QAAO,WAAW,QAAQ,sBAAsB,IAAI;AAClE,MAAI,CAAC,QAAQ,GAAI,QAAO,WAAW,QAAQ,QAAQ,QAAQ,IAAI;AAE/D,QAAM,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,SAAS;AACtD,MAAI,CAAC,MAAM,GAAI,QAAO,WAAW,QAAQ,MAAM,QAAQ,IAAI;AAC3D,QAAM,UAAU,MAAM;AACtB,QAAM,SAAS,eAAe,QAAQ,QAAQ,QAAQ,OAAO;AAC7D,MAAI,CAAC,OAAO,IAAK,QAAO,SAAS,QAAQ,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;AACrE,MAAI,QAAQ,SAAS,OAAO,MAAM;AAChC,WAAO,SAAS,QAAQ,SAAS;AAAA,MAC/B;AAAA,MACA,GAAG;AAAA,MACH,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,WAAW,KACpB,OAAO,UAAU,QAAQ,QAAQ,SAAS,IAC1C;AACJ,SAAO,MAAM,MAAM,KAAK,QAAQ,SAAS,OAAO,OAC5C;AAAA,IACE,GAAG,SAAS,QAAQ,KAAK,SAAS;AAAA,MAChC;AAAA,MACA,GAAI,KAAK,QAAQ,WAAW,EAAE,UAAU,KAAK,QAAQ,SAAS,IAAI,CAAC;AAAA,IACrE,CAAC;AAAA,IACD,OAAO;AAAA,IACP,aAAa;AAAA,EACf,IACA,SAAS,QAAQ,SAAS;AAAA,IACxB;AAAA,IACA,GAAG;AAAA,IACH,aAAa;AAAA,EACf,CAAC;AACP;;;AC1RO,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,OAAmB;AAC7B,UAAM,MAAM,OAAO;AACnB,SAAK,OAAO,MAAM,QAAQ,KAAK,YAAY;AAC3C,SAAK,OAAO,MAAM,QAAQ;AAC1B,SAAK,YAAY,MAAM;AACvB,SAAK,QAAQ,MAAM;AACnB,SAAK,YAAY,MAAM,aAAa;AACpC,SAAK,eAAe,MAAM,gBAAgB;AAC1C,SAAK,UAAU,MAAM;AAAA,EACvB;AACF;;;AC7DO,IAAM,6BAAN,cAAyC,UAAU;AAAA,EACxD,YAAqBC,YAAmB;AACtC,UAAM;AAAA,MACJ,SAAS,OAAOA,UAAS;AAAA,MACzB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,WAAAA,YAAW,QAAQ,UAAU;AAAA,IAC1C,CAAC;AATkB,qBAAAA;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAEO,IAAM,wBAAN,cAAoC,UAAU;AAAA,EACnD,YAAqBA,YAAmB;AACtC,UAAM;AAAA,MACJ,SAAS,OAAOA,UAAS;AAAA,MACzB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,WAAAA,WAAU;AAAA,IACvB,CAAC;AATkB,qBAAAA;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAGO,IAAM,uBAAN,cAAmC,UAAU;AAAA,EAClD,YAAqBA,YAAmB;AACtC,UAAM;AAAA,MACJ,SAAS,OAAOA,UAAS;AAAA,MACzB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,WAAAA,WAAU;AAAA,IACvB,CAAC;AATkB,qBAAAA;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAGO,IAAM,0BAAN,cAAsC,UAAU;AAAA,EACrD,YACWA,YACA,OACA,aACT;AACA,UAAM;AAAA,MACJ,SAAS,OAAOA,UAAS,qBAAqB,WAAW;AAAA,MACzD;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,WAAAA,YAAW,OAAO,aAAa,QAAQ,UAAU;AAAA,IAC9D,CAAC;AAZQ,qBAAAA;AACA;AACA;AAAA,EAWX;AAAA,EAbW;AAAA,EACA;AAAA,EACA;AAYb;AASO,IAAM,4BAAN,cAAwC,UAAU;AAAA,EACvD,YACW,aACAC,eACA,cACA,UACT;AACA,UAAM;AAAA,MACJ,SAAS,iBAAiB,WAAW,gBAAgBA,aAAY,+BAA+B,YAAY;AAAA,MAC5G;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,aAAa,cAAAA,eAAc,cAAc,SAAS;AAAA,IAC/D,CAAC;AAbQ;AACA,wBAAAA;AACA;AACA;AAAA,EAWX;AAAA,EAdW;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAYb;AAUO,IAAM,wBAAN,cAAoC,UAAU;AAAA,EACnD,YACW,KACA,UACT;AACA,UAAM;AAAA,MACJ,SAAS,OAAO,GAAG,0DAAqD,SAAS,KAAK,IAAI,CAAC;AAAA,MAC3F;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,KAAK,UAAU,SAAS,KAAK,IAAI,EAAE;AAAA,IAChD,CAAC;AAXQ;AACA;AAAA,EAWX;AAAA,EAZW;AAAA,EACA;AAYb;AAUO,IAAM,0BAAN,cAAsC,UAAU;AAAA,EACrD,YAAqB,MAAc;AACjC,UAAM;AAAA,MACJ,SAAS,OAAO,IAAI,8BAAyB,IAAI,eAAe,IAAI;AAAA,MACpE;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,KAAK;AAAA,IAClB,CAAC;AATkB;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAEO,IAAM,0BAAN,cAAsC,UAAU;AAAA,EACrD,YAAY,SAAiB,SAAiC;AAC5D,UAAM;AAAA,MACJ,SAAS,OAAO,OAAO;AAAA,MACvB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAGO,IAAM,uBAAN,cAAmC,UAAU;AAAA,EAClD,YAAqB,OAAe;AAClC,UAAM;AAAA,MACJ,SAAS,eAAe,KAAK;AAAA,MAC7B;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,MAAM;AAAA,IACnB,CAAC;AATkB;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAGO,IAAM,6BAAN,cAAyC,UAAU;AAAA,EACxD,YAAqB,OAAe;AAClC,UAAM;AAAA,MACJ,SAAS,eAAe,KAAK;AAAA,MAC7B;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,MAAM;AAAA,IACnB,CAAC;AATkB;AAAA,EAUrB;AAAA,EAVqB;AAWvB;;;AClLA,SAAS,UAAU,OAAkC;AACnD,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,CAAC;AACzD,QAAMC,SAAQ;AACd,QAAM,OAAO,CAAC,KAAa,QAAgB;AACzC,UAAM,MAAMA,OAAM,GAAG;AACrB,WAAO,OAAO,QAAQ,YAAY,OAAO,UAAU,GAAG,KAAK,OAAO,MAC9D,MACA;AAAA,EACN;AACA,QAAM,eAAe,KAAK,gBAAgB,CAAC;AAE3C,QAAM,kBAAkB,KAAK,mBAAmB,CAAC;AACjD,SAAO;AAAA,IACL,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,oBAAoB,SAAY,EAAE,gBAAgB,IAAI,CAAC;AAAA,EAC7D;AACF;AAOO,SAAS,sBACd,UACA,SACkB;AAClB,QAAMA,SAAQ,SAAS;AACvB,MAAIA,WAAU,QAAQ,OAAOA,WAAU,SAAU,QAAO,CAAC;AACzD,QAAM,UAAUA;AAChB,SAAO;AAAA,IACL,GAAG,UAAU,QAAQ,SAAS,CAAC;AAAA,IAC/B,GAAI,UAAU,UAAU,QAAQ,OAAO,CAAC,IAAI,CAAC;AAAA,EAC/C;AACF;AAOO,SAAS,qBACd,QACA,SACkB;AAClB,QAAM,UAAW,CAAC,QAAQ,SAAS,SAAS,EAAY,IAAI,CAAC,UAAU;AACrE,UAAM,WAAW,OAAO,UAAU,KAAK;AACvC,WAAO,WAAW,sBAAsB,UAAU,OAAO,IAAI,CAAC;AAAA,EAChE,CAAC;AACD,SAAO,EAAE,GAAG,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,EAAE;AACvD;;;ACvDO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,YAAY,MAAc,OAAe;AACvC,UAAM,gBAAgB,IAAI,qBAAqB,KAAK,2BAAsB;AAC1E,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAC3C,YAAYC,aAAoB,OAAmB;AACjD;AAAA,MACE,GAAGA,WAAU,8CAA8C,KAAK;AAAA,IAClE;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;AChBA,IAAAC,oBAAwB;;;ACAxB,IAAAC,mBAA2C;AAC3C,IAAAC,kBAAwB;AACxB,IAAAC,oBAAkE;;;ACFlE,IAAAC,oBAAqB;AACrB,IAAAC,cAAkB;AAuBX,IAAM,gBAAY,wBAAK,YAAY,cAAc;AACjD,IAAM,sBAAkB,wBAAK,YAAY,oBAAoB;AAE7D,IAAM,aAAa,CAAC,WAAW,SAAS,MAAM;AAS9C,IAAM,YAAY,cACtB,OAAO;AAAA;AAAA,EAEN,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,UAAU,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUrC,MAAM,cAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,MAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1D,UAAU,cAAE,MAAM,cAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,MAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,QAAQ,cAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,MAAS;AAChD,CAAC,EACA,YAAY;AAER,IAAM,qBAAqB,cAC/B,OAAO;AAAA,EACN,MAAM,cAAE,MAAM,SAAS,EAAE,QAAQ,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASnC,SAAS,cAAE,QAAQ,EAAE,SAAS;AAChC,CAAC,EACA,YAAY;;;ADnEf,SAAS,WAAmB;AAC1B,SAAO,QAAQ,IAAI,4BAAwB,yBAAQ;AACrD;AAGO,SAAS,UAAU,cAAsB,OAA2B;AACzE,SAAO,UAAU,SAAS,SAAS,QAAI,2BAAQ,YAAY;AAC7D;AAEA,SAAS,UAAU,cAAsB,OAA2B;AAClE,aAAO;AAAA,IACL,UAAU,cAAc,KAAK;AAAA,IAC7B,UAAU,UAAU,kBAAkB;AAAA,EACxC;AACF;AAWA,eAAsB,cACpB,cACA,OACyB;AACzB,QAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,MAAI;AACJ,MAAI;AACF,UAAM,UAAM,2BAAS,MAAM,MAAM;AAAA,EACnC,QAAQ;AACN,WAAO,EAAE,MAAM,CAAC,EAAE;AAAA,EACpB;AAEA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR;AAAA,MACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF;AACA,QAAM,WAAW,mBAAmB,UAAU,MAAM;AACpD,MAAI,CAAC,SAAS,SAAS;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,MACA,SAAS,MAAM,OAAO,CAAC,GAAG,WAAW;AAAA,IACvC;AAAA,EACF;AACA,SAAO,SAAS;AAClB;AAEA,eAAsB,eACpB,cACA,OACA,UACe;AACf,QAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,YAAM,4BAAM,2BAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,YAAM,4BAAU,MAAM,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AACxE;AAGO,SAAS,eAAe,SAAiB,MAAsB;AACpE,aAAO,8BAAW,IAAI,QAClB,2BAAQ,IAAI,QACZ,2BAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,KAAK,qBAAG,CAAC;AAChD;AAGO,SAAS,aAAa,SAAiBC,aAA4B;AACxE,QAAM,UAAM,gCAAS,2BAAQ,OAAO,OAAG,2BAAQA,WAAU,CAAC;AAC1D,UAAQ,QAAQ,KAAK,MAAM,KAAK,MAAM,qBAAG,EAAE,KAAK,GAAG;AACrD;AAQA,eAAsB,eACpB,cACuB;AACvB,QAAM,YAAyD,CAAC;AAChE,QAAM,OAAsB,CAAC;AAC7B,QAAM,OAAO,oBAAI,IAAY;AAE7B,aAAW,SAAS,YAAY;AAC9B,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,cAAc,cAAc,KAAK;AAAA,IACpD,QAAQ;AACN;AAAA,IACF;AACA,cAAU,KAAK,IAAI;AACnB,UAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,eAAW,SAAS,SAAS,MAAM;AACjC,YAAM,eAAe,eAAe,MAAM,MAAM,IAAI;AACpD,UAAI,KAAK,IAAI,YAAY,EAAG;AAC5B,WAAK,IAAI,YAAY;AACrB,WAAK,KAAK,EAAE,GAAG,OAAO,OAAO,aAAa,CAAC;AAAA,IAC7C;AAAA,EACF;AACA,SAAO,EAAE,MAAM,UAAU;AAC3B;;;ADlHA,eAAsB,oBACpB,cACAC,aACe;AACf,QAAM,SAAS,MAAM,eAAe,YAAY;AAChD,QAAM,eAAW,2BAAQA,WAAU;AACnC,QAAM,MAAM,OAAO,KAAK,KAAK,CAAC,UAAU,MAAM,iBAAiB,QAAQ;AACvE,MAAI,KAAK,WAAW,MAAM;AACxB,UAAM,IAAI,kBAAkB,IAAI,MAAM,IAAI,KAAK;AAAA,EACjD;AACF;;;AGfA,eAAsB,SACpB,OACA,cACwB;AACxB,QAAM,SAAS,MAAM,eAAe,YAAY;AAChD,SAAO,QAAQ;AAAA,IACb,OAAO,KAAK,IAAI,OAAO,UAAU;AAC/B,YAAM,UAAU,MAAM,MAAM,KAAK,MAAM,YAAY;AACnD,aAAO;AAAA,QACL,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM;AAAA,QACb,UAAU,MAAM,YAAY;AAAA,QAC5B,cAAc,MAAM;AAAA,QACpB,OAAO,QAAQ,SAAS;AAAA,QACxB,aAAa,QAAQ;AAAA,QACrB,MAAM,MAAM,QAAQ;AAAA,QACpB,UAAU,MAAM,YAAY;AAAA,QAC5B,QAAQ,MAAM,WAAW;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACRA,eAAsB,QACpB,OACA,cACAC,aACAC,KACA,UAAwB,CAAC,GACH;AACtB,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,QAAM,WAAW,MAAM,cAAc,cAAc,KAAK;AACxD,QAAM,WAAW,eAAe,MAAM,aAAa,MAAMD,WAAU,CAAC;AAEpE,QAAM,WAAW,SAAS,KAAK;AAAA,IAC7B,CAACE,WAAU,eAAe,MAAMA,OAAM,IAAI,MAAM;AAAA,EAClD;AACA,QAAM,UAAU,MAAM,MAAM,KAAK,QAAQ;AACzC,QAAM,UACJ,QAAQ,WAAW,IACf,uBAAuB,QAAQ,gFAC/B;AAEN,QAAM,SAAS;AAAA,IACb,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC7C,GAAI,QAAQ,UAAU,SAAS,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,IACjE,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,EACnE;AAEA,MAAI,UAAU;AACZ,UAAM,UAAiB,EAAE,GAAG,UAAU,GAAG,OAAO;AAChD,QAAI,OAAO,KAAK,MAAM,EAAE,QAAQ;AAC9B,YAAM,eAAe,cAAc,OAAO;AAAA,QACxC,GAAG;AAAA,QACH,MAAM,SAAS,KAAK;AAAA,UAAI,CAACA,WACvBA,WAAU,WAAW,UAAUA;AAAA,QACjC;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO;AAAA,MACL,MAAM,SAAS;AAAA,MACf;AAAA,MACA,UAAU,SAAS,YAAYD;AAAA,MAC/B,eAAe;AAAA,MACf,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,MAC7C,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,MACzD,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,MACjE,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,QAAe;AAAA,IACnB,MAAM,aAAa,MAAMD,WAAU;AAAA,IACnC,UAAUC;AAAA,IACV,GAAG;AAAA,EACL;AACA,QAAM,eAAe,cAAc,OAAO;AAAA,IACxC,GAAG;AAAA,IACH,MAAM,CAAC,GAAG,SAAS,MAAM,KAAK;AAAA,EAChC,CAAC;AACD,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ;AAAA,IACA,UAAUA;AAAA,IACV,eAAe;AAAA,IACf,GAAG;AAAA,IACH,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC/B;AACF;;;ACpFA,IAAAE,oBAAwB;AAgBxB,eAAsB,UACpB,cACAC,aACmE;AACnE,QAAM,SAAuB,CAAC;AAC9B,aAAW,SAAS,YAAY;AAC9B,UAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,cAAc,cAAc,KAAK;AAAA,IACpD,QAAQ;AACN;AAAA,IACF;AACA,UAAM,WAAW,eAAe,MAAM,aAAa,MAAMA,WAAU,CAAC;AACpE,UAAM,OAAO,SAAS,KAAK;AAAA,MACzB,CAAC,UAAU,eAAe,MAAM,MAAM,IAAI,MAAM;AAAA,IAClD;AACA,QAAI,KAAK,WAAW,SAAS,KAAK,QAAQ;AACxC,YAAM,eAAe,cAAc,OAAO,EAAE,GAAG,UAAU,MAAM,KAAK,CAAC;AACrE,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,iBAAa,2BAAQ,YAAY,GAAGA,WAAU;AAAA,IACpD,SAAS,OAAO,SAAS;AAAA,IACzB;AAAA,EACF;AACF;;;AC3CA,IAAAC,cAAkB;AA6EX,IAAM,aAAa,cACvB,OAAO,EACP,IAAI,CAAC,EACL,SAAS,gDAAgD;AAErD,IAAM,YAAY,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,yBAAyB;AAUtE,IAAM,YAAY,cACtB,OAAO,EACP,IAAI,CAAC,EACL,SAAS,EACT;AAAA,EACC;AACF;AAEK,SAAS,OACd,SAC0B;AAC1B,SAAO;AACT;AAiBO,SAAS,SAAS,MAAgB,MAAkC;AACzE,QAAM,SAAS,KAAK,KAAK,CAAC,QAAQ,IAAI,WAAW,GAAG,IAAI,GAAG,CAAC;AAC5D,MAAI,WAAW,QAAW;AACxB,UAAMC,SAAQ,OAAO,MAAM,KAAK,SAAS,CAAC;AAC1C,QAAI,CAACA,OAAO,OAAM,IAAI,wBAAwB,IAAI;AAClD,WAAOA;AAAA,EACT;AAEA,QAAMC,MAAK,KAAK,QAAQ,IAAI;AAC5B,MAAIA,QAAO,GAAI,QAAO;AAEtB,QAAM,QAAQ,KAAKA,MAAK,CAAC;AACzB,MAAI,UAAU,UAAa,MAAM,WAAW,IAAI,GAAG;AACjD,UAAM,IAAI,wBAAwB,IAAI;AAAA,EACxC;AACA,SAAO;AACT;;;A/B9EA,SAAS,gBAAgB,SAAwC;AAC/D,QAAM,QAAQ;AAAA,IACZ,GAAG,IAAI;AAAA,MACL,QAAQ,QAAQ,CAAC,UAAW,MAAM,WAAW,CAAC,MAAM,QAAQ,IAAI,CAAC,CAAE;AAAA,IACrE;AAAA,EACF,EAAE,KAAK;AACP,SAAO,MAAM,SAAS,GAAG,MAAM,KAAK,KAAK,CAAC,cAAc;AAC1D;AAEO,IAAM,uBAAuB,OAAO;AAAA,EACzC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,cAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,UAAU,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IACrC,SAAS,cACN,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,YAAY,cACT,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,SAAS,cACN,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,UAAU,SAAS,MAAM,aAAa;AAAA,IACtC,SAAS,KAAK,SAAS,WAAW;AAAA,IAClC,YAAY,KAAK,SAAS,cAAc;AAAA,IACxC,SAAS,KAAK,SAAS,WAAW;AAAA,EACpC;AAAA,EACA,KAAK,OACH,EAAE,OAAO,OAAO,IAAI,GACpB,EAAE,YAAY,MAAM,WAAW,IAAI,UAAU,SAAS,YAAY,QAAQ,MACvE;AACH,UAAM,OAAO,YAAY,QAAQ,IAAI;AACrC,UAAM,SAAS,MAAM,MAAM,KAAK,MAAM,EAAE;AACxC,QAAI,CAAC,OAAQ,OAAM,IAAI,sBAAsB,EAAE;AAE/C,UAAM,UAAU,OAAO,YAAY,mBAAmB,CAAC;AACvD,QAAI,CAAC,QAAQ,QAAQ;AACnB,aAAO;AAAA,QACL,WAAW;AAAA,QACX,SAAS,CAAC;AAAA,QACV,UAAU;AAAA,QACV,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,UAAiC,CAAC;AACxC,UAAM,UAAsB,CAAC;AAC7B,QAAI,QAAQ;AAEZ,UAAM,UAAU,MAAM,YAAY,SAAS,MAAM,YAAY,IAAI;AACjE,UAAM,YAAY,uBAAuB,EAAE,SAAS,YAAY,KAAK,CAAC;AACtE,UAAM;AAAA,MACJ;AAAA,MACA,QAAQ,IAAI,CAAC,WAAW,OAAO,IAAI;AAAA,IACrC;AAEA,eAAW,UAAU,SAAS;AAC5B,YAAMC,QAGF;AAAA,QACF,MAAM,OAAO;AAAA,QACb,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,QAIjD,GAAI,OAAO,OAAO,EAAE,YAAY,OAAO,KAAK,IAAI,CAAC;AAAA,MACnD;AACA,YAAM,SAAS,QAAQ,IAAI,MAAM;AACjC,UAAI,OAAO,KAAM,CAAAA,MAAK,OAAO,OAAO;AAEpC,UAAI,CAAC,OAAO,IAAI;AACd,gBAAQ,KAAK,EAAE,GAAGA,OAAM,OAAO,cAAc,QAAQ,OAAO,OAAO,CAAC;AACpE,gBAAQ,KAAK,MAAM;AACnB;AAAA,MACF;AAEA,YAAM,UAAU,kBAAkB,OAAO,QAAQ,QAAQ,SAAS;AAClE,UAAI,CAAC,QAAQ,IAAI;AACf,gBAAQ,KAAK;AAAA,UACX,GAAGA;AAAA,UACH,OAAO;AAAA,UACP,QAAQ,QAAQ;AAAA,QAClB,CAAC;AACD,gBAAQ,KAAK,MAAM;AACnB;AAAA,MACF;AAEA,YAAM,WAAW,QAAQ;AACzB,YAAM,aAAa,QAAQ;AAC3B,YAAM,EAAE,MAAM,aAAa,KAAK,IAAI,aAAa,QAAQ,OAAO;AAChE,YAAM,eAAe,SAAS,UAAU,SAAS,YAAY;AAM7D,YAAM,cAAc,QAAQ,aAAa,QAAQ;AACjD,YAAM,cAAc,QAAQ,aACxB,aAAa,EAAE,GAAG,QAAQ,MAAM,OAAU,GAAG,OAAO,EAAE,OACtD;AAGJ,YAAM,UAAoB;AAAA,QACxB,GAAG;AAAA,QACH,MAAM;AAAA,QACN,WAAW;AAAA,QACX,OAAO;AAAA,QACP,aAAa,IAAI;AAAA,QACjB,GAAI,aAAa,EAAE,UAAU,WAAW,IAAI,CAAC;AAAA,MAC/C;AACA,YAAM,SAAS,OAAO,QAAQ,UAAa,OAAO,SAAS;AAE3D,UAAI,CAAC,OAAO,MAAM;AAGhB,gBAAQ,KAAK;AAAA,UACX,GAAGA;AAAA,UACH,OAAO;AAAA,UACP,aAAa;AAAA,UACb,UAAU;AAAA,UACV,GAAI,aAAa,EAAE,UAAU,WAAW,IAAI,CAAC;AAAA,QAC/C,CAAC;AACD,gBAAQ,KAAK,OAAO;AACpB,gBAAQ;AACR;AAAA,MACF;AAEA,UAAI,OAAO,SAAS,aAAa;AAC/B,gBAAQ,KAAK;AAAA,UACX,GAAGA;AAAA,UACH,OAAO;AAAA,UACP;AAAA,UACA,UAAU;AAAA,UACV,UAAU,UAAU,QAAQ,YAAY;AAAA,UACxC,GAAI,aAAa,EAAE,UAAU,WAAW,IAAI,CAAC;AAAA;AAAA;AAAA,UAG7C,GAAI,gBAAgB,OAAO,QAAQ,QAAQ,UAAU,IACjD,EAAE,QAAQ,mBAA4B,IACtC,CAAC;AAAA,UACL,GAAI,SAAS,EAAE,aAAa,mBAA4B,IAAI,CAAC;AAAA,UAC7D,GAAI,aAAa,EAAE,aAAa,KAAK,IAAI,CAAC;AAAA,QAC5C,CAAC;AACD,gBAAQ,KAAK,aAAa,UAAU,MAAM;AAC1C,YAAI,WAAY,SAAQ;AACxB;AAAA,MACF;AAKA,YAAM,YAAY,SACd,SAAS,QAAQ,QAAQ,SAAS,IAClC;AACJ,UAAI,aAAa,UAAU,SAAS,OAAO,MAAM;AAC/C,gBAAQ,KAAK;AAAA,UACX,GAAGA;AAAA,UACH,OAAO;AAAA,UACP,aAAa,UAAU;AAAA,UACvB,UAAU,UAAU,QAAQ,UAAU,KAAK;AAAA,UAC3C,aAAa;AAAA,QACf,CAAC;AACD,gBAAQ,KAAK,MAAM;AACnB;AAAA,MACF;AAEA,cAAQ,KAAK;AAAA,QACX,GAAGA;AAAA,QACH,OAAO;AAAA,QACP;AAAA,QACA,UAAU;AAAA,QACV,GAAI,aAAa,EAAE,UAAU,WAAW,IAAI,CAAC;AAAA,QAC7C,GAAI,SAAS,EAAE,aAAa,cAAuB,IAAI,CAAC;AAAA,MAC1D,CAAC;AAKD,YAAM,UAAU,WAAW,OAAO,gBAAgB;AAClD,cAAQ,KAAK,UAAU,EAAE,GAAG,QAAQ,aAAa,IAAI,EAAE,IAAI,MAAM;AACjE,UAAI,QAAS,SAAQ;AAAA,IACvB;AAMA,QAAI,SAAS;AACb,QAAI,OAAO;AACT,UAAI;AACF,cAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAAA,MAC/C,SAAS,OAAO;AACd,YAAI,EAAE,iBAAiB,mBAAoB,OAAM;AACjD,iBAAS;AAAA,MACX;AACA,UAAI,CAAC,OAAQ,OAAM,MAAM,cAAc,MAAM,IAAI,SAAS,KAAK;AAAA,IACjE;AACA,UAAM,aAAa,SACf,EAAE,QAAQ,MAAM,MAAM,sCAAsC,IAC5D,CAAC;AAGL,UAAM,QAAQ,aAAa;AAC3B,UAAM,WAAW,MAAM,SAAS,EAAE,MAAM,IAAI,CAAC;AAM7C,UAAM,cAAc,QAAQ;AAAA,MAAO,CAAC,UAClC,kBAAkB,MAAM,MAAM;AAAA,IAChC,EAAE;AACF,UAAM,UAAU,QAAQ,SAAS;AACjC,UAAMC,WAAU,QAAQ,OAAO,CAAC,UAAU,MAAM,UAAU,OAAO,EAAE;AACnE,UAAM,OAAO,GAAGA,QAAO,IAAI,OAAO,iBAChC,cAAc,KAAK,WAAW,iBAAiB,EACjD;AACA,UAAM,QAAQ,UAAU,KAAKA,aAAY,WAAW,gBAAgB;AACpE,QAAI,OAAO;AACT,UAAI;AACF,cAAM,MAAM;AAAA,UACV;AAAA,UACA;AAAA,UACA,mBAAmB,IAAI,KAAK,gBAAgB,OAAO,CAAC;AAAA,UACpD;AAAA,UACA,IAAI;AAAA,QACN;AAAA,MACF,SAAS,OAAO;AAGd,YAAI,EAAE,iBAAiB,yBAA0B,OAAM;AACvD,eAAO;AAAA,UACL,WAAW;AAAA,UACX;AAAA,UACA,UAAU;AAAA,UACV,eAAe;AAAA,UACf,GAAG;AAAA,UACH,GAAG;AAAA,QACL;AAAA,MACF;AACA,aAAO;AAAA,QACL,WAAW;AAAA,QACX;AAAA,QACA,UAAU;AAAA,QACV,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,IACF;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,MACX;AAAA,MACA,UAAU;AAAA,MACV,GAAI,cAAc,EAAE,KAAK,IAAI,CAAC;AAAA,MAC9B,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,CAAC,WACT,OAA8C,QAAQ;AAAA,IACrD,CAAC,UACC,MAAM,UAAU,aACf,MAAM,UAAU,gBACf,MAAM,eAAe,UACrB,CAAC,kBAAkB,MAAM,MAAM;AAAA,EACrC;AACJ,CAAC;AAED,SAAS,UAAU,QAAkB,SAAgC;AACnE,SAAO,OAAO,UAAU,SAAY,OAAO,KAAK,IAAI,UAAU,OAAO,KAAK;AAC5E;AAGA,SAAS,SACP,QACA,QACA,WAC6C;AAC7C,MAAI,OAAO,SAAS,OAAW,QAAO;AACtC,QAAM,UAAU,kBAAkB,OAAO,MAAM,QAAQ,SAAS;AAChE,MAAI,CAAC,QAAQ,GAAI,QAAO;AACxB,SAAO;AAAA,IACL,MAAM,eAAe,QAAQ,KAAK,IAAI;AAAA,IACtC,OAAO,QAAQ,KAAK,UAAU,QAAQ,KAAK,YAAY;AAAA,EACzD;AACF;AAOA,eAAe,YACb,SACA,MACA,SACsC;AACtC,QAAM,SAAS,IAAI,WAAW,IAAI;AAClC,MAAI,QAAQ,KAAK,CAAC,WAAW,OAAO,IAAI,EAAG,OAAM,OAAO,MAAM;AAC9D,QAAM,UAAU,IAAI;AAAA,IAClB,QAAQ,IAAI,CAAC,WAAW,CAAC,QAAQ,OAAO,UAAU,MAAM,CAAC,CAAU;AAAA,EACrE;AAEA,QAAM,QAAQ,QAAQ,OAAO,CAAC,WAAW,CAAC,QAAQ,IAAI,MAAM,CAAC;AAC7D,QAAM,SAAS,QAAQ,OAAO,CAAC,WAAW,QAAQ,IAAI,MAAM,CAAC;AAC7D,QAAM,QAAQ,MAAM;AAAA,IAClB,MAAM,IAAI,CAAC,WAAW,OAAO,IAAI;AAAA,IACjC,iBAAiB,IAAI;AAAA,EACvB;AACA,QAAM,QAAQ,MAAM,kBAAkB,OAAO,QAAQ,WAAW,GAAG;AAAA,IACjE;AAAA,EACF,CAAC;AAED,QAAM,UAAU,oBAAI,IAA4B;AAChD,aAAW,UAAU,OAAO;AAC1B,UAAM,OAAO,MAAM,IAAI,OAAO,IAAI;AAClC,YAAQ;AAAA,MACN;AAAA,MACA,KAAK,KACD,EAAE,IAAI,MAAM,QAAQ,KAAK,OAAO,IAChC,EAAE,IAAI,OAAO,QAAQ,KAAK,OAAO;AAAA,IACvC;AAAA,EACF;AACA,aAAW,UAAU,QAAQ;AAC3B,UAAM,OAAO,OAAO;AACpB,UAAM,MAAM,iBAAiB,IAAI;AACjC,UAAM,YAAY,MAAM,IAAI,QAAQ,KAAK,QAAW,OAAO,IAAI,CAAC;AAChE,UAAM,UAAU,OAAO,MACnB,MAAM,IAAI,QAAQ,KAAK,OAAO,KAAK,OAAO,IAAI,CAAC,IAC/C;AACJ,QAAI,CAAC,SAAS,IAAI;AAChB,cAAQ,IAAI,QAAQ;AAAA,QAClB,IAAI;AAAA,QACJ,QAAQ,SAAS,OAAO,QAAQ,QAAQ,SAAS;AAAA,QACjD;AAAA,MACF,CAAC;AACD;AAAA,IACF;AACA,YAAQ,IAAI,QAAQ;AAAA,MAClB,IAAI;AAAA,MACJ,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA,GAAI,OAAO,OAAO,WAAW,KAAK,EAAE,MAAM,UAAU,OAAO,IAAI,CAAC;AAAA,IAClE,CAAC;AAAA,EACH;AACA,SAAO;AACT;;;AgChbA,IAAAC,cAAkB;AAIX,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,cAAE,OAAO,EAAE,YAAY,WAAW,QAAQ,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,EACpE,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,QAAQ,KAAK,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK;AAAA,EACvC;AAAA,EACA,KAAK,OACH,EAAE,OAAO,MAAM,GACf,EAAE,YAAY,MAAM,WAAW,IAAI,OAAO,MACvC;AACH,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM,OAAO,MAAM,IAAI,QAAQ,KAAK;AACzD,WAAO,EAAE,WAAW,OAAO,UAAU;AAAA,EACvC;AACF,CAAC;;;ACxBD,IAAAC,cAAkB;AAGX,IAAM,mBAAmB,OAAO;AAAA,EACrC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,cAAE,OAAO,EAAE,YAAY,UAAU,CAAC;AAAA,EACzC,UAAU,CAAC,MAAM,UAAU,EAAE,YAAY,MAAM,WAAW,KAAK,CAAC,EAAE;AAAA,EAClE,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,WAAW,GAAG,MACvD,MAAM,UAAU,MAAM,EAAE;AAC5B,CAAC;;;ACbD,IAAAC,eAAkB;;;ACmElB,IAAM,WAA+C;AAAA,EACnD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AAAA,EACN,UAAU;AAAA,EACV,YAAY;AACd;AASO,SAAS,WACd,MACA,QACA,MAAM,oBAAI,KAAK,GAGf,aACiB;AACjB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,SAAO,KAAK,IAAI,CAAC,WAAW;AAC1B,UAAM,SAAS,OAAO,YAAY;AAClC,UAAM,WAAwB,CAAC;AAC/B,QAAI,QAAoB,CAAC;AAEzB,QAAI,WAAW,cAAc;AAC3B,YAAM,WAAW,aAAa,QAAQ,IAAI;AAC1C,cAAQ,SAAS;AACjB,eAAS,KAAK,GAAG,SAAS,QAAQ;AAClC,UAAI,MAAM,QAAQ;AAChB,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,QACxC,CAAC;AAAA,MACH;AAAA,IACF,WAAW,WAAW,YAAY;AAChC,eAAS,KAAK,EAAE,MAAM,WAAW,CAAC;AAAA,IACpC,WAAW,WAAW,WAAW,WAAW,YAAY;AACtD,eAAS,KAAK,EAAE,MAAM,aAAa,OAAO,CAAC;AAAA,IAC7C,WAAW,WAAW,QAAQ;AAC5B,eAAS,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAAA,IAC/C;AAEA,UAAM,aAAa,OAAO,YAAY;AACtC,QAAI,cAAc,KAAK,MAAM,UAAU,IAAI,IAAI,QAAQ,GAAG;AACxD,eAAS,KAAK,EAAE,MAAM,SAAS,WAAW,CAAC;AAAA,IAC7C;AACA,QAAI,CAAC,OAAO,YAAY,UAAU,QAAQ;AACxC,eAAS,KAAK,EAAE,MAAM,aAAa,CAAC;AAAA,IACtC;AAIA,UAAM,SAAS,aAAa,IAAI,OAAO,SAAS,KAAK,CAAC,GAAG;AAAA,MACvD,CAAC,UAAU,MAAM,UAAU;AAAA,IAC7B;AACA,UAAMC,aAAY,MAAM,OAAO,CAAC,UAAU,kBAAkB,MAAM,MAAM,CAAC;AACzE,UAAM,QAAQ,MAAM,OAAO,CAAC,UAAU,CAAC,kBAAkB,MAAM,MAAM,CAAC;AACtE,QAAI,MAAM,QAAQ;AAChB,eAAS,KAAK,EAAE,MAAM,WAAW,SAAS,MAAM,IAAI,aAAa,EAAE,CAAC;AAAA,IACtE;AACA,QAAIA,WAAU,QAAQ;AACpB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAASA,WAAU,IAAI,aAAa;AAAA,MACtC,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,QAAQ,UAAU,SAAS,MAAM,GAAG,OAAO,SAAS;AAAA,EAC/D,CAAC;AACH;AAEA,SAAS,cAAc,OAA4C;AACjE,QAAM,EAAE,MAAM,QAAQ,UAAU,QAAQ,MAAM,YAAY,IAAI;AAC9D,SAAO;AAAA,IACL;AAAA,IACA,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,IACzC;AAAA,IACA,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,IACzC,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,IACrC,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,IACnD,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,EAC5D;AACF;AAeO,SAAS,aACd,MACA,MAC8C;AAC9C,QAAM,WAAwB,CAAC;AAC/B,QAAM,QAAQ,oBAAI,IAAsB;AACxC,QAAM,OAAO,oBAAI,IAAY,CAAC,KAAK,SAAS,CAAC;AAC7C,QAAM,QAAoB,CAAC,IAAI;AAE/B,SAAO,MAAM,QAAQ;AACnB,UAAM,UAAU,MAAM,MAAM;AAC5B,UAAM,OAAO,WAAW,SAAS,IAAI;AAErC,eAAWC,YAAW,KAAK,SAAS;AAClC,eAAS,KAAK,EAAE,MAAM,gBAAgB,SAAAA,SAAQ,CAAC;AAAA,IACjD;AACA,QAAI,CAAC,KAAK,QAAQ,QAAQ;AACxB,UAAI,QAAQ,cAAc,KAAK;AAC7B,cAAM,IAAI,QAAQ,WAAW,OAAO;AACtC;AAAA,IACF;AACA,eAAW,UAAU,KAAK,SAAS;AACjC,UAAI,KAAK,IAAI,OAAO,SAAS,GAAG;AAC9B,iBAAS,KAAK,EAAE,MAAM,eAAe,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC;AACzD;AAAA,MACF;AACA,WAAK,IAAI,OAAO,SAAS;AACzB,YAAM,KAAK,MAAM;AAAA,IACnB;AAAA,EACF;AAEA,MAAI,MAAM,OAAO,GAAG;AAClB,aAAS,KAAK,EAAE,MAAM,gBAAgB,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,EAClE;AACA,SAAO,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,SAAS;AAChD;AAEA,SAAS,WACP,QACA,MAC4C;AAC5C,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,UAAU,OAAO,YAAY;AACnC,MAAI,QAAS,KAAI,IAAI,OAAO;AAC5B,aAAW,CAAC,IAAI,SAAS,KAAK,MAAM;AAClC,QAAI,UAAU,YAAY,oBAAoB,SAAS,OAAO,SAAS,GAAG;AACxE,UAAI,IAAI,EAAE;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,UAAsB,CAAC;AAC7B,QAAMA,WAAoB,CAAC;AAC3B,aAAW,MAAM,KAAK;AACpB,UAAM,QAAQ,KAAK,IAAI,EAAE;AACzB,QAAI,MAAO,SAAQ,KAAK,KAAK;AAAA,QACxB,CAAAA,SAAQ,KAAK,EAAE;AAAA,EACtB;AACA,SAAO,EAAE,SAAS,SAAAA,SAAQ;AAC5B;;;ACjMA,IAAM,kBAA8C;AAAA,EAClD,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM;AACR;AAgCO,SAAS,QACd,QACA,UAAyC,CAAC,GACzB;AACjB,QAAM,SAAS,QAAQ,OACnB,OAAO,OAAO,CAAC,WAAW,OAAO,YAAY,SAAS,QAAQ,IAAI,IAClE;AAKJ,QAAM,UAAU,WAAW,QAAQ,QAAQ,QAAQ,OAAO,oBAAI,KAAK,CAAC,EACjE,IAAI,CAAC,SAAS;AAAA,IACb,WAAW,IAAI,OAAO;AAAA,IACtB,MAAM,IAAI,OAAO,YAAY;AAAA,IAC7B,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,IACvC,UAAU,IAAI;AAAA,IACd,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,IACpD,OAAO,IAAI,SAAS,KAAK,CAAC,YAAY,QAAQ,SAAS,OAAO;AAAA,EAChE,EAAE,EACD,KAAK,eAAe;AAEvB,QAAM,YAAY,EAAE,GAAG,gBAAgB;AACvC,aAAW,SAAS,QAAS,WAAU,MAAM,QAAQ,KAAK;AAE1D,SAAO;AAAA,IACL;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB;AAAA,IACA,cAAc,UAAU;AAAA,IACxB,iBAAiB,UAAU;AAAA,IAC3B,YAAY,QAAQ,OAAO,CAAC,UAAU,MAAM,KAAK,EAAE;AAAA,EACrD;AACF;AAGA,SAAS,gBAAgB,MAAsB,OAA+B;AAC5E,SACE,WAAW,KAAK,MAAM,MAAM,IAAI,KAChC,WAAW,KAAK,SAAS,IAAI,MAAM,SAAS,EAAE,KAC9C,WAAW,KAAK,WAAW,MAAM,SAAS;AAE9C;AAUA,SAAS,WAAW,MAAc,OAAuB;AACvD,SAAO,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AAChD;AAQO,SAAS,kBAAkB,OAA+B;AAC/D,QAAM,QAAQ;AAAA,IACZ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM,SAAS;AAAA,IACf,MAAM,aAAa,eACf,qBAAgB,MAAM,aAAa,KAAK,IAAI,KAAK,qBAAqB,KACtE,MAAM;AAAA,EACZ;AACA,MAAI,MAAM,MAAO,OAAM,KAAK,OAAO;AACnC,SAAO,KAAK,MAAM,KAAK,QAAK,CAAC;AAC/B;;;AF7IO,IAAM,iBAAiB,OAAO;AAAA,EACnC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,MAAM,eAAE,KAAK,eAAe,EAAE,SAAS;AAAA,EACzC,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,GAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,WAAW,IAAI,IAAI,EAAE,MAAM,KAAK,CAAC,EAAE,IAAI,CAAC;AAAA,EAClE;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,KAAK,MAC9C;AAAA,IACE,MAAM,MAAM,QAAQ,MAAM,EAAE,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG,CAAC;AAAA,IACvD;AAAA,IACA;AAAA,EACF;AACJ,CAAC;AAMD,SAAS,OACP,QACA,QACA,MACQ;AACR,QAAM,QAAQ;AAAA,IACZ,eAAe,OAAO,WAAM,IAAI,KAAK,EAAE;AAAA,IACvC,WAAW,MAAM;AAAA,IACjB,GAAG,MAAM,OAAO,aAAa,QAAQ,CAAC,KAAK,eAAe,MAAM,CAAC;AAAA,EACnE;AAKA,MAAI,OAAO,YAAY;AACrB,UAAM;AAAA,MACJ,GAAG,OAAO,UAAU;AAAA,IACtB;AAAA,EACF;AAEA,QAAM,KAAK,EAAE;AAEb,MAAI,CAAC,OAAO,QAAQ,QAAQ;AAC1B,UAAM;AAAA,MACJ,OACI,uBAAuB,IAAI,MAC3B;AAAA,IACN;AAAA,EACF,OAAO;AACL,eAAW,SAAS,OAAO,QAAS,OAAM,KAAK,kBAAkB,KAAK,CAAC;AAAA,EACzE;AAEA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAOA,SAAS,eAAe,QAAiC;AACvD,QAAM,QAA+B;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAQ,MAAM,OAAO,CAAC,aAAa,OAAO,UAAU,QAAQ,CAAC,EAAE;AAAA,IACnE,CAAC,aAAa,GAAG,OAAO,UAAU,QAAQ,CAAC,IAAI,QAAQ;AAAA,EACzD;AACA,SAAO,MAAM,SAAS,MAAM,KAAK,QAAK,IAAI;AAC5C;AAEA,SAAS,MAAM,OAAe,MAAsB;AAClD,SAAO,GAAG,KAAK,IAAI,UAAU,IAAI,OAAO,GAAG,IAAI,GAAG;AACpD;;;AG7FA,IAAAC,eAAkB;;;ACAlB,IAAAC,mBAAoC;;;ACE7B,IAAM,aAAa;AAE1B,IAAM,UAAU;AAcT,SAAS,YAAY,SAA6B;AACvD,QAAM,QAAQ,CAAC,GAAG,OAAO,EACtB,KAAK,CAAC,MAAM,UAAU,KAAK,UAAU,cAAc,MAAM,SAAS,CAAC,EACnE,IAAI,eAAe;AAEtB,SAAO,GAAG,OAAO;AAAA;AAAA,EAAO,MAAM,KAAK,IAAI,CAAC;AAAA;AAC1C;AAOO,SAAS,gBAAgB,QAA0B;AACxD,QAAM,EAAE,aAAa,GAAG,IAAI;AAC5B,QAAM,QAAQ,CAAC,GAAG,MAAM,GAAG,cAAc;AACzC,MAAI,GAAG,MAAM,OAAQ,OAAM,KAAK,SAAS,GAAG,KAAK,KAAK,IAAI,CAAC,EAAE;AAC7D,MAAI,GAAG,YAAa,OAAM,KAAK,GAAG,WAAW;AAC7C,SAAO,MAAM,GAAG,SAAS,OAAO,SAAS,KAAK,OAAO,SAAS,eAAU,MAAM,KAAK,QAAK,CAAC;AAC3F;AAGO,SAAS,aAAa,QAAuB,UAA2B;AAC7E,SAAO,WAAW;AACpB;;;ADlBA,IAAMC,WAAU;AAMhB,IAAM,yBAAyB;AASxB,IAAM,mBAAqD;AAAA,EAChE,iBAAiB,EAAE,iBAAiB,KAAM;AAAA,EAC1C,SAAS,EAAE,cAAc,KAAM;AAAA,EAC/B,MAAM,EAAE,cAAc,KAAM;AAC9B;AAkCA,SAAS,aAAa,MAAsB;AAC1C,SAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AAClC;AAEA,SAAS,WAAmB;AAC1B,SAAO;AAAA,IACLA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAeA,eAAe,WACb,OACA,MACA,cACA,iBACA,SACA,cACsB;AACtB,QAAM,SAAS,MAAM,MAAM,KAAK,YAAY;AAC5C,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAMA,QAAM,UACJ,YAAY,SACR,eACA,YAAY,UACV,IACA;AAER,MAAI;AACJ,MAAI,UAAU,GAAG;AACf,UAAM,OAAO,MAAM,MAAM,KAAK,cAAc;AAAA,MAC1C,cAAc;AAAA,IAChB,CAAC;AACD,QAAI,CAAC,KAAK,UAAU,YAAY,QAAQ;AACtC,qBAAe,EAAE,cAAc,KAAK,aAAa;AAAA,IACnD;AACA,QAAI,KAAK,QAAQ;AACf,YAAM,UAAU,KAAK,QAAQ;AAAA,QAAI,CAAC,QAChC;AAAA,UACE,QAAQ,IAAI,OAAO,SAAS,WAAM,IAAI,OAAO,YAAY,SAAS,YAAY,KAAK,IAAI,QAAQ;AAAA,UAC/F;AAAA,UACA,IAAI,OAAO,KAAK,KAAK;AAAA,QACvB,EAAE,KAAK,IAAI;AAAA,MACb;AACA,YAAMC,cAAa,KAAK,WAAW;AAAA,QACjC,CAAC,UACC,OAAO,MAAM,SAAS,2BAAsB,MAAM,aAAa,IAAI,CAAC,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,uBAAuB;AAAA,MACjI;AACA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,GAAG;AAAA,UACH,GAAIA,YAAW,SACX;AAAA,YACE;AAAA,YACA,GAAGA;AAAA,UACL,IACA,CAAC;AAAA,QACP,EAAE,KAAK,MAAM;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAKA,QAAM,cAAc,WAAW,QAAQ,MAAM;AAC7C,QAAM,QAAQ,YACX,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C,IAAI,CAAC,QAAQ,gBAAgB,IAAI,MAAM,CAAC;AAC3C,QAAM,aAAa,YAChB,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C;AAAA,IACC,CAAC,QACC,OAAO,IAAI,OAAO,SAAS,2BAAsB,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,KAAK,uBAAuB;AAAA,EAC3I;AACF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM,CAAC,GAAG,OAAO,GAAG,UAAU,EAAE,KAAK,IAAI;AAAA,IACzC,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,EACzC;AACF;AAOA,eAAsB,aACpB,OACA,cACA,UAA4B,CAAC,GACH;AAC1B,QAAM,UAAU,QAAQ,UACnB,iBAAiB,QAAQ,OAAO,KAAK,CAAC,IACvC,CAAC;AACL,MAAI,eACF,QAAQ,gBAAgB,QAAQ,gBAAgB;AAClD,MAAI,kBAAkB,QAAQ,mBAAmB,QAAQ,mBAAmB;AAM5E,QAAM,SAAS,MAAM,eAAe,YAAY;AAIhD,QAAM,eAAe,qBAAqB,QAAQ,QAAQ,OAAO;AACjE,iBACE,QAAQ,gBACR,aAAa,gBACb,QAAQ,gBACR;AACF,oBACE,QAAQ,mBACR,aAAa,mBACb,QAAQ,mBACR;AAKF,QAAM,OAAO,OAAO,KAAK;AAAA,IACvB,CAAC,QACC,CAAC,IAAI,UAAU,UACf,CAAC,QAAQ,WACT,IAAI,SAAS,SAAS,QAAQ,OAAO;AAAA,EACzC;AACA,MAAI,KAAK,WAAW,GAAG;AACrB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,MACA,OAAO,CAAC;AAAA,IACV;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,KAAK,IAAI,OAAO,SAAS;AAAA,MACvB,SAAS,MAAM;AAAA,QACb;AAAA,QACA,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,MACF;AAAA,MACA,QAAQ,IAAI,WAAW;AAAA,IACzB,EAAE;AAAA,EACJ;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAMA,aAAW,EAAE,QAAQ,KAAK,UAAU;AAClC,QAAI,QAAQ,cAAc;AACxB,cAAQ,OAAO;AAAA,QACb,WAAW;AAAA,QACX,MAAM,QAAQ;AAAA,QACd,cAAc,QAAQ,aAAa;AAAA,QACnC;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,WAAW,SAAS,IAAI,CAAC,EAAE,SAAS,OAAO,MAAM;AACrD,UAAM,QAAQ,QAAQ,eAClB,qDAAgD,QAAQ,aAAa,YAAY,+BAA+B,YAAY,mGAC5H,UAAU,QAAQ,IAAI;AAC1B,WAAO;AAAA,MACL,OAAO,QAAQ,IAAI,KAAK,KAAK,GAAG,SAAS,4BAAyB,EAAE;AAAA,MACpE;AAAA,MACA,iBAAiB,QAAQ,YAAY;AAAA,MACrC;AAAA,MACA,QAAQ;AAAA,IACV,EAAE,KAAK,IAAI;AAAA,EACb,CAAC;AAED,QAAM,QAAQ,CAAC,SAAS,GAAG,IAAI,SAAS,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI;AACnE,QAAM,QAAQ,SAAS,IAAI,CAAC,EAAE,QAAQ,OAAO;AAAA,IAC3C,MAAM,QAAQ;AAAA,IACd,cAAc,QAAQ;AAAA,IACtB,cAAc,aAAa,QAAQ,IAAI;AAAA,EACzC,EAAE;AACF,QAAM,QAAQ,aAAa,KAAK;AAEhC,MAAI,QAAQ,cAAc;AACxB,YAAQ,OAAO;AAAA,MACb,WAAW;AAAA,MACX,cAAc;AAAA,MACd;AAAA,MACA,OAAO,MAAM,IAAI,CAACC,UAASA,MAAK,IAAI;AAAA,IACtC,CAAC;AAKD,UAAM,UAAU;AAAA,MACdF;AAAA,MACA;AAAA,MACA,6BAA6B,KAAK,qBAAqB,YAAY;AAAA,MACnE;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG,MAAM;AAAA,QACP,CAACE,UACC,KAAKA,MAAK,IAAI,YAAOA,MAAK,YAAY,0BAA0BA,MAAK,YAAY;AAAA,MACrF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AACX,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS,OAAO,cAAc,OAAO,cAAc,MAAM;AAC3E;AAQO,SAAS,WAAW,OAAe,OAAuB;AAC/D,SAAO,KAAK,UAAU;AAAA,IACpB,oBAAoB;AAAA,MAClB,eAAe;AAAA,MACf,mBAAmB;AAAA,IACrB;AAAA,EACF,CAAC;AACH;AAEO,IAAM,gBAAgB;AACtB,IAAM,cAAc;AAa3B,eAAsB,iBACpB,MACA,OACuB;AACvB,QAAM,WAAW,UAAM,2BAAS,MAAM,MAAM,EAAE,MAAM,MAAM,IAAI;AAC9D,QAAM,SAAS,QACX,GAAG,aAAa;AAAA,EAAK,MAAM,KAAK,CAAC;AAAA,EAAK,WAAW,KACjD;AAEJ,MAAI,aAAa,MAAM;AACrB,QAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,QAAQ,YAAY;AAChD,cAAM,4BAAU,MAAM,GAAG,MAAM;AAAA,GAAM,MAAM;AAC3C,WAAO,EAAE,MAAM,QAAQ,UAAU;AAAA,EACnC;AAEA,QAAM,QAAQ,SAAS,QAAQ,aAAa;AAC5C,QAAM,MAAM,SAAS,QAAQ,WAAW;AACxC,MAAI,UAAU,MAAM,QAAQ,MAAM,OAAO,OAAO;AAC9C,UAAM,SAAS,SAAS,MAAM,GAAG,KAAK;AACtC,UAAM,QAAQ,SAAS,MAAM,MAAM,YAAY,MAAM;AACrD,UAAM,OAAO,SACT,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,KAC1B,GAAG,OAAO,QAAQ,QAAQ,IAAI,CAAC,GAAG,MAAM,QAAQ,QAAQ,IAAI,CAAC;AACjE,QAAI,SAAS,SAAU,QAAO,EAAE,MAAM,QAAQ,YAAY;AAC1D,cAAM,4BAAU,MAAM,MAAM,MAAM;AAClC,WAAO,EAAE,MAAM,QAAQ,SAAS,aAAa,UAAU;AAAA,EACzD;AAEA,MAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,QAAQ,YAAY;AAChD,YAAM;AAAA,IACJ;AAAA,IACA,GAAG,SAAS,QAAQ,QAAQ,MAAM,CAAC,GAAG,MAAM;AAAA;AAAA,IAC5C;AAAA,EACF;AACA,SAAO,EAAE,MAAM,QAAQ,WAAW;AACpC;;;ADtaO,IAAM,iBAAiB,OAAO;AAAA,EACnC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd,cAAc,eACX,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,iBAAiB,eACd,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,SAAS,eACN,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,QAAQ,eACL,KAAK,CAAC,YAAY,MAAM,CAAC,EACzB,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,OAAO,eACJ,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,SAAS;AAClB,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAM,YAAY,SAAS,MAAM,cAAc;AAC/C,UAAM,UAAU,SAAS,MAAM,WAAW;AAC1C,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAM,QAAQ,SAAS,MAAM,SAAS;AACtC,WAAO;AAAA,MACL,GAAI,SAAS,EAAE,cAAc,OAAO,MAAM,EAAE,IAAI,CAAC;AAAA,MACjD,GAAI,YAAY,EAAE,iBAAiB,OAAO,SAAS,EAAE,IAAI,CAAC;AAAA,MAC1D,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,MAAM,GACR,EAAE,cAAc,iBAAiB,SAAS,QAAQ,MAAM,MACrD;AACH,UAAM,SAAS,MAAM,aAAa,OAAO,QAAQ,IAAI,GAAG;AAAA,MACtD,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,MACvC,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,MAC7C,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,MAK7B,MAAM,CAAC,UAAU,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI;AAAA,IACpE,CAAC;AAGD,QAAI,CAAC,OAAO,MAAO,QAAO;AAC1B,WAAO,WAAW,SACd,WAAW,OAAO,OAAO,SAAS,cAAc,IAChD,OAAO;AAAA,EACb;AACF,CAAC;;;AGlFD,IAAAC,eAAkB;;;ACAlB,IAAAC,6BAAyB;AACzB,IAAAC,oBAA0B;AAG1B,IAAMC,qBAAgB,6BAAU,mCAAQ;AAkBjC,IAAM,uBAAuB;AAEpC,IAAM,iBAAiB;AASvB,eAAeC,KAAI,KAAa,MAAoC;AAClE,QAAM,MAAM,EAAE,GAAG,QAAQ,IAAI;AAC7B,SAAO,IAAI,SAAS;AACpB,SAAO,IAAI,eAAe;AAC1B,SAAO,IAAI,gBAAgB;AAC3B,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAMD,eAAc,OAAO,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG;AAAA,MAClE,SAAS;AAAA,MACT,WAAW;AAAA,MACX;AAAA,IACF,CAAC;AACD,WAAO,EAAE,IAAI,MAAM,OAAO;AAAA,EAC5B,QAAQ;AACN,WAAO,EAAE,IAAI,MAAM;AAAA,EACrB;AACF;AAGA,eAAsB,cAAc,UAAqC;AACvE,QAAM,SAAS,MAAMC,KAAI,UAAU,CAAC,YAAY,MAAM,UAAU,CAAC;AACjE,MAAI,CAAC,OAAO,GAAI,QAAO,CAAC;AACxB,SAAO,OAAO,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO;AACjD;AA2BA,eAAsB,cACpB,UACA,QACoB;AACpB,MAAI,CAAC,eAAe,OAAO,IAAI;AAC7B,WAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAE9C,MAAI,OAAO,OAAO,eAAe,OAAO,GAAG,GAAG;AAC5C,UAAMC,SAAQ,MAAM,SAAS,UAAU,OAAO,KAAK,OAAO,IAAI;AAC9D,QAAIA,WAAU,MAAM;AAClB,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,QAAQA;AAAA,QACR,QAAQ,EAAE,MAAM,OAAO,KAAK,OAAO,IAAI;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAEA,QAAMC,MAAK,OAAO;AAClB,MAAI,CAACA,OAAM,OAAO,MAAM,KAAK,MAAMA,GAAE,CAAC,GAAG;AACvC,WAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAAA,EAC9C;AAGA,QAAM,QAAQ,MAAMF,KAAI,UAAU;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAYE,GAAE;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,EACT,CAAC;AACD,QAAM,MAAM,MAAM,KAAK,MAAM,OAAO,KAAK,IAAI;AAC7C,MAAI,CAAC,OAAO,CAAC,eAAe,GAAG;AAC7B,WAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAE9C,QAAM,QAAQ,MAAM,SAAS,UAAU,KAAK,OAAO,IAAI;AACvD,MAAI,UAAU,KAAM,QAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAChE,SAAO,EAAE,IAAI,MAAM,QAAQ,OAAO,QAAQ,EAAE,MAAM,WAAW,KAAK,IAAI,EAAE;AAC1E;AAGA,eAAe,SACb,UACA,KACA,MACwB;AACxB,QAAM,OAAO,KAAK,QAAQ,SAAS,EAAE;AACrC,QAAM,SAAS,MAAMF,KAAI,UAAU;AAAA,IACjC;AAAA,IACA;AAAA,IACA,GAAG,GAAG,IAAI,IAAI;AAAA,EAChB,CAAC;AACD,SAAO,OAAO,KAAK,OAAO,SAAS;AACrC;;;AC1IA,IAAAG,mBAAqB;AAoCd,IAAM,yBAAyB;AAUtC,IAAM,eAAe;AA8Bd,SAAS,YACd,UACA,UAA8B,CAAC,GAClB;AACb,QAAM,OAAO,QAAQ,UAAU,iBAAiB,QAAQ;AACxD,QAAM,SAAS,QAAQ,UAAU,SAAS,QAAQ;AAClD,QAAM,WAAW,IAAI,mBAAmB;AACxC,MAAI;AACJ,QAAM,WAAW,oBAAI,IAAY;AAEjC,QAAM,mBAAmB,OAAO,aAAwC;AACtE,kBAAc,cAAc,QAAQ;AACpC,YAAQ,MAAM,WACX,OAAO,CAAC,SAAS,gBAAgB,IAAI,MAAM,QAAQ,EACnD,MAAM,GAAG,sBAAsB;AAAA,EACpC;AAEA,SAAO;AAAA,IACL,MAAM,KAAK,QAAQ;AACjB,YAAM,SAAS,OAAO;AACtB,UAAI,CAAC,OAAQ,QAAO;AAEpB,YAAM,WAAW,gBAAgB,OAAO,IAAI;AAI5C,UAAI,CAAC,SAAU,QAAO,eAAe,QAAQ,MAAM,MAAM;AAEzD,YAAM,aAAa,MAAM,iBAAiB,QAAQ;AAClD,UAAI,CAAC,SAAS,IAAI,QAAQ,GAAG;AAC3B,cAAM,SAAS,QAAQ,WAAW,SAAS,aAAa,CAAC,OAAO,IAAI,CAAC;AACrE,iBAAS,IAAI,QAAQ;AAAA,MACvB;AAIA,YAAM,QAAQ,OAAO,SAAS;AAE9B,eAASC,MAAK,GAAGA,MAAK,WAAW,QAAQA,OAAM,cAAc;AAC3D,cAAM,QAAQ,WAAW,MAAMA,KAAIA,MAAK,YAAY;AACpD,cAAM,OAAO,MAAM;AAAA,UACjB;AAAA,UACA;AAAA,UACA,OAAO,SAAS;AACd,kBAAMC,QAAO,MAAM,OAAO,IAAI;AAG9B,gBAAIA,UAAS,QAAQA,QAAO,MAAO,QAAO;AAC1C,mBAAO,QAAQ,UAAU,MAAM,QAAQ,QAAQ,IAAI;AAAA,UACrD;AAAA,QACF;AAGA,cAAM,QAAQ,KAAK,KAAK,CAAC,QAAQ,QAAQ,MAAS;AAClD,YAAI,MAAO,QAAO;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,eAAe,QACb,UACA,MACA,QACA,QACA,MACqC;AACrC,QAAM,SAAS,MAAM,KAAK,IAAI;AAC9B,MAAI,CAAC,OAAO,GAAI,QAAO;AACvB,QAAM,aAAa,OAAO,OAAO,QAAQ,SAAS,IAAI;AAEtD,aAAW,SAAS,SAAS,MAAM,YAAY,IAAI,GAAG;AAGpD,UAAM,OACJ,OAAO,cAAc,QACjB,SAAS,UAAU,MAAM,KAAK,MAAM,IAAI,IACxC,MAAM,KAAK;AACjB,QAAI,SAAS,QAAQ,eAAe,IAAI,MAAM,OAAQ;AAGtD,QAAI,SAAS,OAAO,QAAQ,MAAM,WAAW,OAAO,OAAQ;AAC5D,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,MAAM;AAAA,MACd,WAAW,MAAM,KAAK;AAAA,MACtB,SAAS,MAAM,KAAK;AAAA,IACtB;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,SAAS,UAA4D;AAC5E,SAAO,OAAO,SAAS;AACrB,UAAM,OAAO,eAAe,UAAU,IAAI;AAC1C,QAAI,SAAS,KAAM,QAAO;AAC1B,QAAI;AACF,cAAQ,UAAM,uBAAK,IAAI,GAAG;AAAA,IAC5B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,eAAe,eACb,QACA,MACA,QACqC;AACrC,QAAM,SAAS,OAAO;AAItB,MAAI,CAAC,UAAU,OAAO,cAAc,MAAO,QAAO;AAElD,QAAM,SAAS,MAAM,KAAK,OAAO,IAAI;AACrC,MAAI,CAAC,OAAO,GAAI,QAAO;AACvB,QAAM,QAAQ,OAAO,OAAO,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI;AAE7D,WAASD,MAAK,GAAGA,MAAK,UAAU,MAAM,QAAQA,OAAM;AAClD,QAAI,eAAe,MAAM,MAAMA,KAAIA,MAAK,MAAM,EAAE,KAAK,IAAI,CAAC,MAAM,QAAQ;AACtE;AAAA,IACF;AACA,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,MACb,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,MACjD,WAAWA,MAAK;AAAA,MAChB,SAASA,MAAK;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;;;ACxJA,eAAsB,cACpB,UACA,QACA,SACA,UAA2B,CAAC,GACC;AAG7B,QAAM,WAAW,OAAO,YAAY,mBAAmB,CAAC,GAAG;AAAA,IACzD,CAAC,WAAW,OAAO;AAAA,EACrB;AACA,QAAM,SAAS,QAAQ,UAAU,iBAAiB,QAAQ;AAC1D,QAAM,aAAa,IAAI,mBAAmB;AAC1C,QAAM,YAA8B,CAAC,YAAY,aAAa;AAC9D,QAAM,SACJ,QAAQ,UACR,YAAY,UAAU,EAAE,GAAI,QAAQ,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAEjE,QAAM,SAA4D,CAAC;AACnE,UAAQ,QAAQ,CAAC,OAAOE,QAAO;AAC7B,UAAM,SAAS,QAAQA,GAAE;AACzB,QAAI,CAAC,OAAQ;AACb,QAAI,MAAM,UAAU,WAAW,kBAAkB,MAAM,MAAM,EAAG;AAChE,WAAO,KAAK,EAAE,QAAQ,MAAM,CAAC;AAAA,EAC/B,CAAC;AACD,MAAI,CAAC,OAAO,OAAQ,QAAO,CAAC;AAE5B,QAAM;AAAA,IACJ;AAAA,IACA,OAAO,IAAI,CAAC,EAAE,OAAO,MAAM,OAAO,IAAI;AAAA,EACxC;AAEA,QAAM,MAA0B,CAAC;AACjC,aAAW,EAAE,QAAQ,MAAM,KAAK,QAAQ;AACtC,UAAM,UAAU,MAAM,OAAO,KAAK,MAAM;AACxC,QAAI,SAAS;AACX,UAAI,KAAK;AAAA,QACP;AAAA,QACA,OAAO,EAAE,GAAG,OAAO,OAAO,SAAS,QAAQ;AAAA,QAC3C,OAAO;AAAA,MACT,CAAC;AACD;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,YAAY,QAAQ,QAAQ,SAAS;AAC3D,UAAM,MACJ,QAAQ,gBAAgB,QACpB,EAAE,IAAI,OAAgB,QAAQ,gBAAyB,IACvD,MAAM,cAAc,UAAU,MAAM;AAC1C,UAAM,UAAU,IAAI,KAAK,OAAO,IAAI,QAAQ,QAAQ,SAAS,IAAI;AAEjE,UAAM,UACJ,YAAY,UACZ,YAAY,UACZ,WAAW,YAAY,OAAO,MAAM,SAAS,OAAO,IAChD,aACC,MAAM,SAAS;AAEtB,QAAI,KAAK;AAAA,MACP;AAAA,MACA,OAAO,EAAE,GAAG,OAAO,OAAO,QAAQ;AAAA,MAClC,OAAO;AAAA,MACP,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC3C,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC3C,GAAI,IAAI,KAAK,EAAE,WAAW,IAAI,OAAO,IAAI,CAAC;AAAA,IAC5C,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAOA,SAAS,WACP,UACA,MACA,QACA,OACS;AACT,MAAI,WAAW,MAAO,QAAO;AAC7B,QAAM,OAAO,SAAS,UAAU,QAAQ,IAAI;AAC5C,QAAM,QAAQ,SAAS,UAAU,OAAO,IAAI;AAC5C,SAAO,SAAS,QAAQ,SAAS;AACnC;AAEA,eAAe,YACb,QACA,QACA,WAC6B;AAC7B,QAAM,OAAO,MAAM,OAAO,OAAO,IAAI;AACrC,MAAI,CAAC,KAAK,GAAI,QAAO;AACrB,SAAO,OAAO,KAAK,QAAQ,QAAQ,SAAS;AAC9C;AAGA,SAAS,OACP,QACA,QACA,WACoB;AACpB,QAAM,UAAU,kBAAkB,QAAQ,QAAQ,SAAS;AAC3D,SAAO,QAAQ,KAAK,QAAQ,KAAK,OAAO;AAC1C;;;AC1JO,IAAM,wBAAwB;AAO9B,IAAM,0BAA0B;AAGhC,IAAM,wBAAwB;AAG9B,SAAS,WAAW,SAAyB;AAClD,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO,KAAK;AAAA,IACV;AAAA,IACA,KAAK;AAAA,MACH;AAAA,MACA,KAAK,MAAM,0BAA0B,OAAO;AAAA,IAC9C;AAAA,EACF;AACF;AAoBO,SAAS,YACd,QACA,OACA,UAAuE,CAAC,GAC3D;AACb,QAAM,MAAM,QAAQ,YAAY;AAChC,QAAM,OAAO,OAAO,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI;AACrD,QAAM,QAAQ,MAAM,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI;AAErD,QAAM,OAAiB,CAAC;AACxB,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,aAAW,QAAQ,MAAM,MAAM,KAAK,GAAG;AACrC,QAAI,KAAK,SAAS,OAAQ,MAAK,KAAK,IAAI,KAAK,IAAI,EAAE;AAAA,aAC1C,KAAK,SAAS,UAAU;AAC/B,WAAK,KAAK,IAAI,KAAK,IAAI,EAAE;AACzB,iBAAW;AAAA,IACb,OAAO;AACL,WAAK,KAAK,IAAI,KAAK,IAAI,EAAE;AACzB,eAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,YAAY,KAAK,SAAS;AAChC,QAAM,QAAQ,YAAY,KAAK,MAAM,GAAG,GAAG,IAAI;AAC/C,QAAM,SAAS,SAAS,KAAK,MAAM,OAAO,MAAM,MAAM,MACpD,QAAQ,WACJ,IAAI,QAAQ,QAAQ,WAAM,QAAQ,YAAY,EAAE,GAAG,QAAQ,IAC3D,EACN;AACA,QAAM,QAAQ,CAAC,QAAQ,GAAG,KAAK;AAC/B,MAAI,UAAW,OAAM,KAAK,UAAK,KAAK,SAAS,GAAG,kBAAkB;AAElE,SAAO,EAAE,MAAM,MAAM,KAAK,IAAI,GAAG,OAAO,SAAS,UAAU;AAC7D;AAKA,SAAS,MAAM,MAAgB,OAAyB;AACtD,QAAM,OAAO,KAAK;AAClB,QAAM,OAAO,MAAM;AACnB,QAAMC,SAAoB,MAAM;AAAA,IAAK,EAAE,QAAQ,OAAO,EAAE;AAAA,IAAG,MACzD,IAAI,MAAc,OAAO,CAAC,EAAE,KAAK,CAAC;AAAA,EACpC;AACA,WAASC,OAAM,OAAO,GAAGA,QAAO,GAAGA,QAAO;AACxC,aAASC,OAAM,OAAO,GAAGA,QAAO,GAAGA,QAAO;AACxC,MAACF,OAAMC,IAAG,EAAeC,IAAG,IAC1B,KAAKD,IAAG,MAAM,MAAMC,IAAG,IACjBF,OAAMC,OAAM,CAAC,EAAeC,OAAM,CAAC,IAAe,IACpD,KAAK;AAAA,QACFF,OAAMC,OAAM,CAAC,EAAeC,IAAG;AAAA,QAC/BF,OAAMC,IAAG,EAAeC,OAAM,CAAC;AAAA,MAClC;AAAA,IACR;AAAA,EACF;AAEA,QAAM,MAAc,CAAC;AACrB,MAAI,MAAM;AACV,MAAI,MAAM;AACV,SAAO,MAAM,QAAQ,MAAM,MAAM;AAC/B,QAAI,KAAK,GAAG,MAAM,MAAM,GAAG,GAAG;AAC5B,UAAI,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,GAAG,EAAY,CAAC;AACpD,aAAO;AACP,aAAO;AAAA,IACT,WACIF,OAAM,MAAM,CAAC,EAAe,GAAG,KAC/BA,OAAM,GAAG,EAAe,MAAM,CAAC,GACjC;AACA,UAAI,KAAK,EAAE,MAAM,UAAU,MAAM,KAAK,GAAG,EAAY,CAAC;AACtD,aAAO;AAAA,IACT,OAAO;AACL,UAAI,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,GAAG,EAAY,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,MAAM,MAAM;AACjB,QAAI,KAAK,EAAE,MAAM,UAAU,MAAM,KAAK,GAAG,EAAY,CAAC;AACxD,SAAO,MAAM,MAAM;AACjB,QAAI,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,GAAG,EAAY,CAAC;AACtD,SAAO;AACT;;;AClEA,IAAM,mBAA4C;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAM,qBAA8C,CAAC,YAAY,MAAM;AAEvE,IAAM,gBAAmD;AAAA,EACvD,wBACE;AAAA,EACF,yBACE;AAAA,EACF,QAAQ;AACV;AA0CA,eAAsB,eACpB,UACA,QACA,SACA,UAAyB,CAAC,GAIzB;AACD,QAAM,aAAa,MAAM,cAAc,UAAU,QAAQ,SAAS;AAAA,IAChE,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IACnD,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IACnD,aAAa,QAAQ,aAAa;AAAA,EACpC,CAAC;AAED,QAAM,OAAO,WAAW;AAAA,IACtB,CAAC,UAAU,MAAM,UAAU,aAAa,MAAM,UAAU;AAAA,EAC1D;AACA,MAAI,CAAC,KAAK,OAAQ,QAAO,EAAE,QAAQ,MAAM,WAAW;AAEpD,QAAM,SAAS,WAAW,KAAK,MAAM;AACrC,QAAM,UAAU,KAAK;AAAA,IAAI,CAAC,UACxB,aAAa,OAAO,QAAQ,aAAa,MAAM,MAAM;AAAA,EACvD;AAEA,QAAM,OAAO,OAAO,YAAY;AAChC,QAAM,WAA8B,eAAe,IAAI,IACnD,iBAAiB,SAAS,IAAI,IAC5B,yBACA,mBAAmB,SAAS,IAAI,IAC9B,0BACA,WACJ;AAEJ,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,MACN,WAAW,OAAO;AAAA,MAClB,OAAO,OAAO,YAAY,SAAS;AAAA,MACnC;AAAA,MACA,UAAU,QAAQ,YAAY;AAAA,MAC9B,KAAK,OAAO,YAAY,eAAe;AAAA,MACvC,OAAO,QAAQ,MAAM;AAAA,MACrB;AAAA,MACA,SAAS,QAAQ,QAAQ,YAAY,CAAC,GAAG,IAAI,CAAC,WAAW;AAAA,QACvD,WAAW,MAAM;AAAA,QACjB,OAAO,MAAM;AAAA,QACb,UAAU,MAAM;AAAA,QAChB,OAAO,MAAM;AAAA,MACf,EAAE;AAAA,MACF,iBAAiB,QAAQ,QAAQ,aAAa;AAAA,MAC9C,SAAS;AAAA,MACT,aAAa,cAAc,QAAQ;AAAA,IACrC;AAAA,EACF;AACF;AAEA,SAAS,aACP,OACA,UACA,UACkB;AAClB,QAAM,EAAE,MAAM,IAAI;AAClB,QAAMG,QAAyB;AAAA,IAC7B,MAAM,MAAM;AAAA,IACZ,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IAC/C,OAAO,MAAM;AAAA,IACb,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IAC/C,YAAY,MAAM;AAAA,IAClB,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;AAAA,IAC9D,UAAU,MAAM;AAAA,IAChB,GAAI,MAAM,UAAU,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,EACpD;AACA,MAAI,CAAC,SAAU,QAAOA;AAEtB,MAAI,MAAM,YAAY,UAAa,CAAC,MAAM,WAAW;AACnD,WAAO,EAAE,GAAGA,OAAM,MAAM,EAAE,QAAQ,gBAAgB,EAAE;AAAA,EACtD;AAGA,QAAM,WAAW,YAAY,MAAM,SAAS,MAAM,WAAW,IAAI;AAAA,IAC/D;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL,GAAGA;AAAA,IACH,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ,MAAM,UAAU;AAAA,MACxB,KAAK,MAAM,UAAU;AAAA,MACrB,SAAS,SAAS;AAAA,MAClB,OAAO,SAAS;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB,WAAW,SAAS;AAAA,IACtB;AAAA,EACF;AACF;AAOA,SAAS,QAAQ,QAA4D;AAC3E,QAAM,OAAO,OAAO,YAAY;AAChC,QAAM,UAAU,eAAe,IAAI,IAC/B,aAAa,IAAI,EAAE,SAAS,CAAC,IAC7B;AACJ,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI;AAC3D,QAAM,QAAQ,MAAM;AAAA,IAClB,CAAC,SAAS,KAAK,KAAK,EAAE,YAAY,MAAM,MAAM,OAAO,GAAG,YAAY;AAAA,EACtE;AACA,MAAI,QAAQ,EAAG,QAAO;AACtB,QAAM,OAAO,MAAM,MAAM,QAAQ,CAAC;AAClC,QAAM,MAAM,KAAK,UAAU,CAAC,SAAS,KAAK,WAAW,KAAK,CAAC;AAC3D,QAAM,QAAQ,MAAM,IAAI,OAAO,KAAK,MAAM,GAAG,GAAG,GAAG,KAAK,IAAI,EAAE,KAAK;AACnE,SAAO,OAAO,EAAE,SAAS,KAAK,IAAI;AACpC;;;ACnNO,IAAM,gBAAgB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAaA,IAAM,mBAAmB,IAAI;AAAA,EAC3B,UAAU,sBAAsB,OAAO,QAAQ,YAAY,EAAE,CAAC;AAAA,EAC9D;AACF;AAWO,IAAM,0BAA6C;AAOnD,SAAS,WACd,MACA,QACA,QAA+B,eAC/B,WAA8B,yBACf;AACf,QAAM,QAAQ,oBAAI,IAAyB;AAC3C,aAAW,QAAQ,OAAO;AACxB,eAAW,UAAU,eAAe,MAAM,QAAQ,MAAM,QAAQ,GAAG;AACjE,YAAM,WAAW,MAAM,IAAI,OAAO,SAAS;AAC3C,UAAI,UAAU;AACZ,YAAI,CAAC,SAAS,IAAI,SAAS,IAAI,EAAG,UAAS,IAAI,KAAK,IAAI;AACxD;AAAA,MACF;AACA,YAAM,IAAI,OAAO,WAAW,EAAE,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;AAAA,IACrD;AAAA,EACF;AACA,SAAO,CAAC,GAAG,MAAM,OAAO,CAAC;AAC3B;AAQO,SAAS,eACd,MACA,QACA,MACA,WAA8B,yBAClB;AACZ,UAAQ,MAAM;AAAA;AAAA;AAAA;AAAA,IAIZ,KAAK,aAAa;AAChB,YAAM,UAAU,IAAI;AAAA,QAClB,CAAC,GAAG,KAAK,KAAK,SAAS,gBAAgB,CAAC,EAAE,IAAI,CAAC,UAAU,MAAM,CAAC,CAAC;AAAA,MACnE;AACA,UAAI,CAAC,QAAQ,KAAM,QAAO,CAAC;AAC3B,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,aAC7B,QAAQ,IAAI,UAAU,SAAS;AAAA,MACnC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,KAAK,cAAc;AACjB,YAAM,UAAU,IAAI,IAAI,QAAQ;AAChC,YAAM,UAAU,IAAI;AAAA,SACjB,KAAK,YAAY,iBAAiB,CAAC,GACjC,OAAO,CAACC,UAAS,QAAQ,IAAIA,MAAK,GAAG,CAAC,EACtC,IAAI,CAACA,UAASA,MAAK,MAAM;AAAA,MAC9B;AACA,UAAI,CAAC,QAAQ,KAAM,QAAO,CAAC;AAC3B,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,aAC7B,QAAQ,IAAI,UAAU,SAAS;AAAA,MACnC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,KAAK;AACH,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,cAC5B,UAAU,cAAc,KAAK,YAAY,yBACxC,KAAK,YAAY,oBAAoB;AAAA,UACnC,UAAU;AAAA,QACZ,KACA,UAAU,YAAY,0BAA0B,KAAK,aACrD,UAAU,YAAY,oBAAoB,SAAS,KAAK,SAAS;AAAA,MACvE;AAAA;AAAA;AAAA,IAIF,KAAK,UAAU;AACb,YAAM,OAAO,KAAK,YAAY,mBAAmB,CAAC;AAClD,UAAI,CAAC,KAAK,OAAQ,QAAO,CAAC;AAC1B,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,cAC5B,UAAU,YAAY,mBAAmB,CAAC,GAAG;AAAA,UAAK,CAAC,WAClD,KAAK,KAAK,CAAC,SAAS,aAAa,MAAM,MAAM,CAAC;AAAA,QAChD;AAAA,MACJ;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,OAAO,IAAI,KAAK,KAAK,YAAY,WAAW,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACtE,UAAI,CAAC,KAAK,KAAM,QAAO,CAAC;AACxB,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,cAC5B,UAAU,YAAY,WAAW,CAAC,GAAG;AAAA,UAAK,CAAC,WAC1C,KAAK,IAAI,OAAO,EAAE;AAAA,QACpB;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAWA,SAAS,aACP,MACA,OACS;AACT,MAAI,KAAK,SAAS,MAAM,KAAM,QAAO;AACrC,MAAI,CAAC,KAAK,UAAU,CAAC,MAAM,OAAQ,QAAO;AAC1C,SAAO,KAAK,WAAW,MAAM;AAC/B;;;ACjLO,SAAS,eAAe,SAA4C;AACzE,QAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACxE,QAAM,WAAkC,CAAC;AACzC,QAAM,SAAS,CACb,OACAC,YACA,MACA,WAAiC,YAC9B,SAAS,KAAK,EAAE,OAAO,WAAAA,YAAW,MAAM,SAAS,CAAC;AAEvD,aAAW,UAAU,SAAS;AAC5B,UAAM,EAAE,WAAAA,YAAW,aAAa,GAAG,IAAI;AAIvC,QAAI,CAAC,eAAe,GAAG,IAAI,GAAG;AAC5B,aAAO,QAAQA,YAAW,sBAAsB,GAAG,IAAI,GAAG;AAAA,IAC5D;AAEA,QAAI,GAAG,mBAAmB,cAAc;AACtC,YAAM,KAAK,GAAG;AACd,UAAI,CAAC,IAAI;AACP,eAAO,iBAAiBA,YAAW,gCAAgC;AAAA,MACrE,WAAW,CAAC,KAAK,IAAI,EAAE,GAAG;AACxB,eAAO,iBAAiBA,YAAW,eAAe,EAAE,aAAa;AAAA,MACnE,WACE,CAAC,KAAK,IAAI,EAAE,GAAG,YAAY,oBAAoB,SAASA,UAAS,GACjE;AACA,eAAO,YAAY,IAAI,iBAAiBA,UAAS,gBAAgB;AAAA,MACnE;AAAA,IACF;AAEA,eAAW,OAAO,GAAG,sBAAsB,CAAC,GAAG;AAC7C,YAAM,WAAW,KAAK,IAAI,GAAG;AAC7B,UAAI,CAAC,UAAU;AACb,eAAO,cAAcA,YAAW,UAAU,GAAG,aAAa;AAAA,MAC5D,WAAW,SAAS,YAAY,mBAAmB,cAAc;AAC/D,eAAO,cAAcA,YAAW,GAAG,GAAG,2BAA2B;AAAA,MACnE;AAAA,IACF;AAEA,eAAWC,SAAQ,GAAG,iBAAiB,CAAC,GAAG;AAMzC,UAAI,CAAC,YAAYA,MAAK,GAAG,GAAG;AAC1B;AAAA,UACE;AAAA,UACAD;AAAA,UACA,gBAAgBC,MAAK,GAAG,gBAAgBA,MAAK,MAAM,2BAAsB,aAAa,KAAK,IAAI,CAAC;AAAA,QAClG;AAAA,MACF;AAQA,UAAI,CAAC,sBAAsB,KAAKA,MAAK,MAAM,GAAG;AAC5C;AAAA,UACE;AAAA,UACAD;AAAA,UACA,WAAWC,MAAK,MAAM;AAAA,QACxB;AAAA,MACF,WAAWA,MAAK,WAAWD,YAAW;AAGpC;AAAA,UACE;AAAA,UACAA;AAAA,UACA,oBAAoBC,MAAK,GAAG;AAAA,UAC5B;AAAA,QACF;AAAA,MACF,WAAW,CAAC,KAAK,IAAIA,MAAK,MAAM,GAAG;AACjC;AAAA,UACE;AAAA,UACAD;AAAA,UACA,UAAUC,MAAK,MAAM;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAMA,eAAW,UAAU,GAAG,mBAAmB,CAAC,GAAG;AAC7C,UAAI,OAAO,QAAQ,CAAC,mBAAmB,OAAO,IAAI,GAAG;AACnD;AAAA,UACE;AAAA,UACAD;AAAA,UACA,gBAAgB,OAAO,IAAI;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,GAAG,sBAAsB,GAAG,SAAS,QAAQ;AAC/C,aAAO,cAAcA,YAAW,wCAAwC;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO;AACT;;;AChGO,IAAM,wBAAwB;AAC9B,IAAM,0BAA0B;AAChC,IAAM,qBAAqB;AAiBlC,IAAM,kBAAiD;AAAA,EACrD,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,uBAAuB;AAAA,EACvB,wBACE;AAAA,EACF,SAAS;AAAA,EACT,WAAW;AACb;AAiEA,IAAM,SAAS;AAGf,SAAS,qBAAqB,QAA4C;AACxE,MAAI,aAAa;AACjB,MAAI,QAAQ;AACZ,aAAW,UAAU,QAAQ;AAC3B,eAAW,UAAU,OAAO,YAAY,mBAAmB,CAAC,GAAG;AAC7D,UAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,OAAQ;AACpC,UAAI,OAAO,aAAa,cAAe,eAAc;AAAA,UAChD,UAAS;AAAA,IAChB;AAAA,EACF;AACA,SAAO,EAAE,OAAO,aAAa,OAAO,YAAY,MAAM;AACxD;AAEO,SAAS,OACd,QACA,UAA2B,CAAC,GACZ;AAChB,QAAM,aAAiC;AAAA,IACrC,cAAc,QAAQ,gBAAgB;AAAA,IACtC,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,WAAW,QAAQ,aAAa;AAAA,EAClC;AACA,QAAM,MAAM,QAAQ,OAAO,oBAAI,KAAK;AAEpC,QAAM,cAAc,WAAW,QAAQ,QAAQ,KAAK,QAAQ,WAAW;AACvE,QAAM,YAAY,IAAI;AAAA,IACpB,YAAY,IAAI,CAAC,QAAQ,CAAC,IAAI,OAAO,WAAW,IAAI,QAAQ,CAAC;AAAA,EAC/D;AAIA,QAAM,UAAU,YAAY;AAAA,IAC1B,CAAC,QAAQ,IAAI,aAAa,gBAAgB,IAAI,aAAa;AAAA,EAC7D;AAEA,QAAM,SAA0B;AAAA,IAC9B,MAAM,WAAW,QAAQ,SAAS,GAAG,CAAC;AAAA,IACtC,MAAM,YAAY,SAAS,SAAS,KAAK,WAAW,YAAY,CAAC;AAAA,IACjE,MAAM,cAAc,WAAW,SAAS,KAAK,WAAW,cAAc,CAAC;AAAA,IACvE,MAAM,SAAS,MAAM,SAAS,KAAK,WAAW,SAAS,CAAC;AAAA,IACxD,MAAM,YAAY,SAAS,MAAM,CAAC;AAAA,IAClC,MAAM,uBAAuB,mBAAmB,QAAQ,WAAW,CAAC;AAAA,IACpE,MAAM,wBAAwB,mBAAmB,QAAQ,SAAS,CAAC;AAAA,IACnE,MAAM,WAAW,QAAQ,OAAO,CAAC;AAAA,IACjC,MAAM,aAAa,UAAU,OAAO,CAAC;AAAA,EACvC;AAEA,QAAM,SAAS,OAAO;AAAA,IACpB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,OAAO,MAAM,KAAK,CAAC;AAAA,EAClD;AACA,QAAM,eAAe,OAAO,OAAO,CAAC,OAAO,UAAU,QAAQ,MAAM,OAAO,CAAC;AAE3E,SAAO;AAAA,IACL,aAAa,OAAO;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB,qBAAqB,MAAM;AAAA,IAC5C,SAAS,iBAAiB;AAAA,EAC5B;AACF;AAEA,SAAS,MACP,OACA,UACe;AACf,SAAO;AAAA,IACL;AAAA,IACA,UAAU,gBAAgB,KAAK;AAAA,IAC/B,OAAO,SAAS;AAAA,IAChB;AAAA,EACF;AACF;AAaA,SAAS,QACP,MACA,KACmB;AACnB,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,IAAI,OAAO,YAAY;AACnC,QAAI,CAAC,IAAK;AACV,UAAME,MAAK,KAAK,MAAM,GAAG;AACzB,QAAI,OAAO,MAAMA,GAAE,GAAG;AACpB,eAAS;AAAA,QACP,QAAQ,IAAI,QAAQ,gBAAgB,GAAG,0BAA0B;AAAA,MACnE;AACA;AAAA,IACF;AACA,QAAIA,MAAK,IAAI,QAAQ,GAAG;AACtB,eAAS;AAAA,QACP;AAAA,UACE,IAAI;AAAA,UACJ,eAAe,GAAG,KAAK,YAAYA,KAAI,IAAI,QAAQ,CAAC,CAAC;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SACP,MACA,KACA,YACmB;AACnB,QAAM,UAAU,IAAI,QAAQ,IAAI,aAAa;AAC7C,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,IAAI,OAAO,YAAY;AACnC,QAAI,CAAC,IAAK;AACV,UAAMA,MAAK,KAAK,MAAM,GAAG;AACzB,QAAI,OAAO,MAAMA,GAAE,KAAKA,MAAK,IAAI,QAAQ,KAAKA,MAAK,QAAS;AAC5D,aAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,cAAc,GAAG,QAAQ,YAAY,IAAI,QAAQ,GAAGA,GAAE,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,WACP,MACA,KACA,eACmB;AACnB,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,QAAI,IAAI,OAAO,YAAY,UAAU,OAAQ;AAC7C,UAAM,MAAM,UAAU,IAAI,QAAQ,GAAG;AACrC,QAAI,QAAQ,QAAQ,OAAO,cAAe;AAC1C,aAAS;AAAA,MACP,QAAQ,IAAI,QAAQ,2BAA2B,GAAG,WAAW;AAAA,IAC/D;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,MACP,MACA,KACA,eACmB;AACnB,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,UAAM,SAAS,IAAI,OAAO,YAAY;AACtC,QAAI,WAAW,UAAU,WAAW,WAAY;AAChD,UAAM,MAAM,UAAU,IAAI,QAAQ,GAAG;AACrC,QAAI,QAAQ,QAAQ,OAAO,cAAe;AAC1C,aAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,WAAW,SACP,YAAY,GAAG,UACf,YAAY,GAAG;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACA,SAAO,SAAS;AAAA,IAAK,CAAC,MAAM,UAC1B,KAAK,UAAU,cAAc,MAAM,SAAS;AAAA,EAC9C;AACF;AAmBA,SAAS,SAAS,QAAuC;AACvD,QAAM,UAAU,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,OAAO,SAAS,CAAC;AAChE,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,UAAU,QAAQ;AAC3B,eAAW,aAAa,eAAe,QAAQ,QAAQ,WAAW,GAAG;AACnE,iBAAW,IAAI,UAAU,SAAS;AAAA,IACpC;AAGA,eAAW,YAAY,OAAO,YAAY,sBAAsB,CAAC,GAAG;AAClE,iBAAW,IAAI,QAAQ;AAAA,IACzB;AACA,UAAM,cAAc,OAAO,YAAY;AACvC,QAAI,eAAe,QAAQ,IAAI,WAAW,GAAG;AAC3C,iBAAW,IAAI,OAAO,SAAS;AAAA,IACjC;AAAA,EACF;AACA,SAAO,OACJ,OAAO,CAAC,WAAW,CAAC,WAAW,IAAI,OAAO,SAAS,CAAC,EACpD,IAAI,CAAC,WAAW,QAAQ,QAAQ,6BAA6B,CAAC;AACnE;AAaA,IAAM,sBAAsB,oBAAI,IAAI;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,mBACP,QACA,aACmB;AACnB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,QAAM,WAA8B,CAAC;AACrC,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAM,CAAC,QAAkB,SAAiB;AAC9C,UAAM,MAAM,GAAG,OAAO,SAAS,KAAS,IAAI;AAC5C,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,aAAS,KAAK,QAAQ,QAAQ,IAAI,CAAC;AAAA,EACrC;AAEA,aAAW,WAAW,eAAe,MAAM,GAAG;AAC5C,QAAI,CAAC,oBAAoB,IAAI,QAAQ,KAAK,EAAG;AAC7C,UAAM,SAAS,KAAK,IAAI,QAAQ,SAAS;AACzC,QAAI,OAAQ,KAAI,QAAQ,QAAQ,IAAI;AAAA,EACtC;AAQA,aAAW,UAAU,QAAQ;AAC3B,UAAM,cAAc,OAAO,YAAY;AACvC,QAAI,CAAC,YAAa;AAClB,QAAI,CAAC,KAAK,IAAI,WAAW,GAAG;AAC1B,UAAI,QAAQ,eAAe,WAAW,aAAa;AAAA,IACrD,WAAW,OAAO,YAAY,mBAAmB,cAAc;AAC7D;AAAA,QACE;AAAA,QACA,SAAS,WAAW;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,aAAW,OAAO,aAAa;AAC7B,eAAW,WAAW,IAAI,UAAU;AAClC,UAAI,QAAQ,SAAS,gBAAgB;AACnC,YAAI,IAAI,QAAQ,eAAe,QAAQ,OAAO,aAAa;AAAA,MAC7D,WAAW,QAAQ,SAAS,eAAe;AACzC;AAAA,UACE,IAAI;AAAA,UACJ,qCAAqC,QAAQ,QAAQ,KAAK,UAAK,CAAC;AAAA,QAClE;AAAA,MACF,WAAW,QAAQ,SAAS,gBAAgB;AAC1C;AAAA,UACE,IAAI;AAAA,UACJ,oCAAoC,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,SAAS;AAAA,IAAK,CAAC,MAAM,UAC1B,KAAK,UAAU,cAAc,MAAM,SAAS;AAAA,EAC9C;AACF;AAoBA,SAAS,mBACP,QACA,WACmB;AACnB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,QAAM,WAA8B,CAAC;AACrC,aAAW,UAAU,QAAQ;AAC3B,UAAM,WAAW,UAAU,IAAI,OAAO,SAAS;AAC/C,QAAI,aAAa,gBAAgB,aAAa,WAAY;AAC1D,eAAW,UAAU,eAAe,QAAQ,QAAQ,WAAW,GAAG;AAChE,YAAM,iBAAiB,UAAU,IAAI,OAAO,SAAS;AACrD,UAAI,mBAAmB,gBAAgB,mBAAmB,YAAY;AACpE;AAAA,MACF;AACA,UAAI,SAAS,QAAQ,MAAM,EAAG;AAC9B,YAAM,cAAc,OAAO,YAAY;AACvC,eAAS;AAAA,QACP;AAAA,UACE;AAAA,UACA,SAAS,cAAc,IAAI,OAAO,SAAS,GACzC,mBAAmB,gBACnB,eACA,KAAK,IAAI,WAAW,IAChB,uBAAkB,WAAW,KAC7B,EACN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAcA,SAAS,QAAQ,MAAwD;AACvE,SAAO;AAAA,IAAe;AAAA,IAAM;AAAA,IAAW,CAACC,WACtCA,WAAU,IAAI,6BAA6B;AAAA,EAC7C;AACF;AAQA,SAAS,UAAU,MAAwD;AACzE,SAAO;AAAA,IAAe;AAAA,IAAM;AAAA,IAAa,CAACA,WACxCA,WAAU,IAAI,2BAA2B;AAAA,EAC3C;AACF;AAGA,SAAS,eACP,MACA,MACA,UACmB;AACnB,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,UAAM,UAAU,IAAI,SAAS;AAAA,MAC3B,CAAC,UACC,MAAM,SAAS;AAAA,IACnB;AACA,QAAI,CAAC,QAAS;AACd,UAAM,SAAS,oBAAI,IAAsB;AACzC,eAAW,UAAU,QAAQ,SAAS;AACpC,YAAM,OAAO,OAAO,QAAQ;AAC5B,aAAO,IAAI,MAAM,CAAC,GAAI,OAAO,IAAI,IAAI,KAAK,CAAC,GAAI,eAAe,MAAM,CAAC,CAAC;AAAA,IACxE;AACA,UAAM,SAAS,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE;AAAA,MAAI,CAAC,CAAC,MAAM,OAAO,MACtD,OAAO,GAAG,IAAI,KAAK,QAAQ,KAAK,IAAI,CAAC,KAAK,QAAQ,KAAK,IAAI;AAAA,IAC7D;AACA,aAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,GAAG,QAAQ,QAAQ,MAAM,IAAI,SAAS,QAAQ,QAAQ,MAAM,CAAC,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AACA,SAAO,SAAS;AAAA,IAAK,CAAC,MAAM,UAC1B,KAAK,UAAU,cAAc,MAAM,SAAS;AAAA,EAC9C;AACF;AAEA,SAAS,eAAe,QAAiC;AACvD,QAAMD,MAAK,OAAO,SAAS,GAAG,OAAO,IAAI,IAAI,OAAO,MAAM,KAAK,OAAO;AACtE,MAAI,OAAO,UAAU,QAAQ;AAC3B,WAAO,GAAGA,GAAE,QAAQ,OAAO,SAAS,KAAK,OAAO,MAAM,MAAM,EAAE;AAAA,EAChE;AACA,MAAI,OAAO,OAAQ,QAAO,GAAGA,GAAE,KAAK,OAAO,MAAM;AACjD,MAAI,OAAO,gBAAgB,sBAAsB;AAC/C,WAAO,GAAGA,GAAE;AAAA,EACd;AACA,MAAI,OAAO,aAAa,KAAM,QAAO,GAAGA,GAAE;AAG1C,SAAO,OAAO,aAAa,IACvB,GAAGA,GAAE,wCACL,GAAGA,GAAE,KAAK,OAAO,QAAQ,QAAQ,OAAO,aAAa,IAAI,KAAK,GAAG;AACvE;AAGA,SAAS,SAAS,OAAiB,SAA4B;AAC7D,UACG,MAAM,YAAY,sBAAsB,CAAC,GAAG,SAAS,QAAQ,SAAS,KACvE,QAAQ,YAAY,0BAA0B,MAAM;AAExD;AAEA,SAAS,QAAQ,QAAkB,MAA+B;AAChE,SAAO;AAAA,IACL,WAAW,OAAO;AAAA,IAClB,OAAO,OAAO,YAAY,SAAS;AAAA,IACnC,QAAQ,OAAO,YAAY;AAAA,IAC3B;AAAA,EACF;AACF;AAGA,SAAS,YAAY,MAAc,IAAoB;AACrD,SAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,QAAQ,MAAM,CAAC;AACrD;AAEA,SAAS,UAAU,QAAkB,KAA0B;AAC7D,QAAMA,MAAK,OAAO,YAAY,WAAW;AACzC,MAAI,CAACA,IAAI,QAAO;AAChB,QAAM,UAAU,KAAK,MAAMA,GAAE;AAC7B,MAAI,OAAO,MAAM,OAAO,EAAG,QAAO;AAClC,SAAO,YAAY,SAAS,IAAI,QAAQ,CAAC;AAC3C;;;ACnlBA,IAAAE,eAAkB;AA2BX,IAAM,kBAAkB,OAAO;AAAA,EACpC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,UAAU,eACP,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,WAAW,KAAK,CAAC;AAAA,MACjB,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,MAC7C,GAAI,KAAK,SAAS,aAAa,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,IAC3D;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,OAAO,MAAM,GACf,EAAE,YAAY,MAAM,WAAW,IAAI,UAAU,SAAS,MACxB;AAC9B,UAAM,OAAO,YAAY,QAAQ,IAAI;AACrC,UAAM,SAAS,MAAM,MAAM,KAAK,IAAI;AACpC,UAAM,SAAS,OAAO,KAAK,CAAC,UAAU,MAAM,cAAc,EAAE;AAC5D,QAAI,CAAC,OAAQ,OAAM,IAAI,sBAAsB,EAAE;AAE/C,UAAM,QAAQ,MAAM,MAAM,YAAY,CAAC,MAAM,GAAG,QAAQ;AACxD,UAAM,UAAU,OAAO,IAAI,EAAE,KAAK,CAAC;AACnC,QAAI,CAAC,QAAQ,KAAK,CAAC,UAAU,MAAM,UAAU,OAAO,GAAG;AACrD,aAAO,EAAE,WAAW,IAAI,QAAQ,MAAM,aAAa,CAAC,GAAG,UAAU,EAAE;AAAA,IACrE;AAEA,UAAM,WAAW,WAAW,QAAQ,MAAM,EAAE;AAAA,MAC1C,CAAC,QAAQ,IAAI,OAAO,cAAc;AAAA,IACpC,GAAG;AAGH,UAAMC,UAAS,MAAM,MAAM,OAAO,MAAM,EAAE;AAE1C,UAAM,EAAE,QAAQ,WAAW,IAAI,MAAM,eAAe,MAAM,QAAQ,SAAS;AAAA,MACzE,GAAI,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,MACrC,QAAAA;AAAA,MACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IACjC,CAAC;AAMD,UAAM,QAAQ,WAAW,OAAO,CAAC,UAAU,MAAM,UAAU,OAAO;AAClE,QAAI,SAAS;AACb,UAAM,cAAqC,CAAC;AAC5C,QAAI,MAAM,QAAQ;AAChB,YAAM,YAAY,oBAAI,IAAwB;AAC9C,iBAAW,SAAS,OAAO;AACzB,cAAM,KAAK,MAAM,MAAM;AACvB,YAAI,CAAC,GAAI;AACT,kBAAU,IAAI,MAAM,QAAQ;AAAA,UAC1B,GAAG,MAAM;AAAA,UACT,MAAM,GAAG;AAAA,UACT,GAAI,GAAG,SAAS,EAAE,QAAQ,GAAG,OAAO,IAAI,CAAC;AAAA,QAC3C,CAAC;AACD,oBAAY,KAAK;AAAA,UACf,MAAM,MAAM,OAAO;AAAA,UACnB,GAAI,MAAM,OAAO,SAAS,EAAE,QAAQ,MAAM,OAAO,OAAO,IAAI,CAAC;AAAA,UAC7D,QAAQ,GAAG;AAAA,UACX,GAAI,GAAG,SAAS,EAAE,UAAU,GAAG,OAAO,IAAI,CAAC;AAAA,QAC7C,CAAC;AAAA,MACH;AACA,UAAI;AACF,cAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAAA,MAC/C,SAAS,OAAO;AACd,YAAI,EAAE,iBAAiB,mBAAoB,OAAM;AACjD,iBAAS;AAAA,MACX;AACA,UAAI,CAAC,QAAQ;AACX,cAAM,MAAM;AAAA,UACV;AAAA,UACA;AAAA,WACC,OAAO,YAAY,mBAAmB,CAAC,GAAG;AAAA,YACzC,CAAC,WAAW,UAAU,IAAI,MAAM,KAAK;AAAA,UACvC;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,MACX;AAAA,MACA,aAAa,SAAS,CAAC,IAAI;AAAA,MAC3B,UAAU,WAAW,OAAO,CAAC,UAAU,MAAM,UAAU,UAAU,EAAE;AAAA,MACnE,GAAI,SACA;AAAA,QACE,QAAQ;AAAA,QACR,MAAM;AAAA,MACR,IACA,CAAC;AAAA,IACP;AAAA,EACF;AAAA,EACA,QAAQ,CAAC,WAAW,eAAe,MAA0B;AAC/D,CAAC;AAOM,SAAS,eAAe,QAAkC;AAC/D,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,OAAO,aAAa;AACrC,UAAM;AAAA,MACJ,gBAAgB,GAAG,KAAK,MAAM,KAAK,MAAM,CAAC,WAAM,GAAG,KAAK,QAAQ,KAAK,QAAQ,CAAC;AAAA,IAChF;AAAA,EACF;AACA,MAAI,OAAO,UAAU;AACnB,UAAM;AAAA,MACJ,GAAG,OAAO,QAAQ,UAAU,OAAO,aAAa,IAAI,KAAK,GAAG;AAAA,IAC9D;AAAA,EACF;AACA,MAAI,OAAO,KAAM,OAAM,KAAK,OAAO,IAAI;AAEvC,QAAM,SAAS,OAAO;AACtB,MAAI,CAAC,QAAQ;AACX,UAAM,KAAK,GAAG,OAAO,SAAS,wBAAwB;AACtD,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAEA,QAAM;AAAA,IACJ;AAAA,IACA,KAAK,OAAO,SAAS,GAAG,OAAO,QAAQ,WAAM,OAAO,KAAK,KAAK,EAAE;AAAA,IAChE,SAAS,OAAO,IAAI,gBAAgB,OAAO,QAAQ;AAAA,IACnD,GAAI,OAAO,MAAM,CAAC,QAAQ,OAAO,GAAG,EAAE,IAAI,CAAC;AAAA,IAC3C,GAAI,OAAO,QACP,CAAC,IAAI,MAAM,OAAO,MAAM,OAAO,IAAI,OAAO,MAAM,IAAI,IACpD,CAAC;AAAA,IACL;AAAA,IACA,eAAe,OAAO,QAAQ,MAAM;AAAA,EACtC;AAEA,aAAW,UAAU,OAAO,SAAS;AACnC,UAAM;AAAA,MACJ,KAAK,GAAG,OAAO,MAAM,OAAO,MAAM,CAAC,WAAM,OAAO,KAAK,GAAG,OAAO,SAAS,KAAK,OAAO,MAAM,MAAM,EAAE;AAAA,IACpG;AACA,QAAI,CAAC,OAAO,KAAM;AAClB,QAAI,OAAO,KAAK,WAAW,iBAAiB;AAC1C,YAAM;AAAA,QACJ;AAAA,MACF;AACA;AAAA,IACF;AACA,UAAM;AAAA,MACJ,aAAa,OAAO,KAAK,GAAG,KAAK,OAAO,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,UAAK,OAAO,KAAK,OAAO;AAAA,MACnG,GAAG,OAAO,KAAK,QAAQ,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE;AAAA,IAC9D;AAAA,EACF;AAEA,MAAI,OAAO,OAAO,QAAQ;AACxB,UAAM,KAAK,IAAI,cAAc,OAAO,OAAO,MAAM,GAAG;AACpD,eAAW,SAAS,OAAO,QAAQ;AACjC,YAAM;AAAA,QACJ,KAAK,MAAM,SAAS,KAAK,MAAM,QAAQ,IAAI,MAAM,QAAQ,WAAM,MAAM,KAAK,KAAK,EAAE;AAAA,MACnF;AAAA,IACF;AACA,QAAI,OAAO,gBAAiB,OAAM,KAAK,yBAAoB;AAAA,EAC7D;AAEA,QAAM,KAAK,IAAI,YAAY,OAAO,OAAO,WAAM,OAAO,WAAW,GAAG;AACpE,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,GAAG,MAAc,QAAyB;AACjD,SAAO,SAAS,GAAG,IAAI,IAAI,MAAM,KAAK;AACxC;;;AT5KA,IAAM,OAAO,CAAC,MAAc,aAC1B,eACG,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT,SAAS,GAAG,IAAI,gBAAgB,QAAQ,GAAG;AAEzC,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,MACZ;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB;AAAA,MACd;AAAA,MACA;AAAA,IACF;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS,eACN,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,QAAQ,eACL,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,SAAS,eACN,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,UAAU,eACP,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAMC,YAAW,SAAS,MAAM,iBAAiB;AACjD,UAAMC,cAAa,SAAS,MAAM,mBAAmB;AACrD,UAAM,YAAY,SAAS,MAAM,cAAc;AAC/C,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,MAC7C,GAAID,cAAa,SAAY,EAAE,cAAc,OAAOA,SAAQ,EAAE,IAAI,CAAC;AAAA,MACnE,GAAIC,gBAAe,SACf,EAAE,gBAAgB,OAAOA,WAAU,EAAE,IACrC,CAAC;AAAA,MACL,GAAI,cAAc,SAAY,EAAE,WAAW,OAAO,SAAS,EAAE,IAAI,CAAC;AAAA,MAClE,GAAI,KAAK,SAAS,WAAW,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;AAAA,MACtD,GAAI,KAAK,SAAS,UAAU,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;AAAA,MACpD,GAAI,KAAK,SAAS,WAAW,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;AAAA,MACtD,GAAI,KAAK,SAAS,aAAa,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,IAC3D;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,OAAO,IAAI,GACb;AAAA,IACE,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAAC;AAAA,IACA;AAAA,EACF,MACG;AACH,UAAM,YAAY,IAAI;AACtB,UAAM,UAAU,MAAM,MAAM,KAAK,IAAI;AAIrC,UAAM,cAAc,MAAM,MAAM,YAAY,SAAS,UAAU;AAAA,MAC7D,SAAS,YAAY;AAAA,IACvB,CAAC;AACD,UAAM,SAAS,OAAO,SAAS;AAAA,MAC7B,GAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,MACrD,GAAI,mBAAmB,SAAY,EAAE,eAAe,IAAI,CAAC;AAAA,MACzD,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MAC/C,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,MACnD,KAAK,IAAI,KAAK,SAAS;AAAA,IACzB,CAAC;AACD,UAAM,QAAQ,aAAa;AAC3B,QAAI,CAACA,UAAS;AACZ,aAAO;AAAA,QACL,YAAY;AAAA,QACZ;AAAA,QACA,GAAG;AAAA,QACH,GAAI,MAAM,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,MAClC;AAAA,IACF;AAIA,UAAM,YAAY,IAAI;AAAA,MACpB,WAAW,SAAS,SAAS,IAAI,KAAK,SAAS,CAAC,EAAE,IAAI,CAAC,QAAQ;AAAA,QAC7D,IAAI,OAAO;AAAA,QACX,IAAI;AAAA,MACN,CAAC;AAAA,IACH;AACA,UAAM,UAA8B,CAAC;AACrC,UAAM,gBAA0B,CAAC;AAGjC,UAAM,SAAS,YAAY,YAAY,QAAQ,IAAI,CAAC;AACpD,eAAW,SAAS,OAAO,OAAO,KAAK,CAAC,MAAM,EAAE,UAAU,SAAS,GAC/D,YAAY,CAAC,GAAG;AAClB,YAAM,SAAS,QAAQ;AAAA,QACrB,CAAC,UAAU,MAAM,cAAc,MAAM;AAAA,MACvC;AACA,UAAI,CAAC,OAAQ;AACb,YAAM,WAAW,UAAU,IAAI,OAAO,SAAS;AAC/C,YAAM,QAAQ,MAAM;AAAA,QAClB,YAAY,QAAQ,IAAI;AAAA,QACxB;AAAA,QACA,aAAa,IAAI,OAAO,SAAS,KAAK,CAAC;AAAA,QACvC;AAAA,UACE,GAAI,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,UACrC,QAAQ,MAAM,MAAM,OAAO,MAAM,OAAO,SAAS;AAAA,UACjD,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,OAAQ,SAAQ,KAAK,MAAM,MAAM;AAC3C,UAAI,MAAM,WAAW,KAAK,CAAC,UAAU,MAAM,UAAU,OAAO,GAAG;AAC7D,sBAAc,KAAK,OAAO,SAAS;AAAA,MACrC;AAAA,IACF;AACA,WAAO;AAAA,MACL,YAAY;AAAA,MACZ;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA,GAAI,MAAM,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,IAClC;AAAA,EACF;AAAA,EACA,QAAQ,CAAC,WAAWC,QAAO,MAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1D,WAAW,CAAC,QAAQ,UAClB,MAAM,WAAW,QAChB,OAAiC,OAAO,UAAU;AACvD,CAAC;AASD,SAASA,QAAO,QAAuC;AACrD,MAAI,OAAO,QAAS,QAAO,cAAc,MAAM;AAC/C,QAAM,EAAE,WAAW,IAAI;AACvB,QAAM,QAAQ;AAAA,IACZ,sBAAiB,OAAO,UAAU;AAAA,IAClC,YAAY,OAAO,WAAW;AAAA,IAC9B,+BAA+B,WAAW,YAAY,sBAAsB,WAAW,cAAc,iBAAiB,WAAW,SAAS;AAAA,IAC1I,YAAY,OAAO,SAAS;AAAA,IAC5B,GAAI,OAAO,gBAAgB,QACvB;AAAA,MACE,YAAY,OAAO,gBAAgB,KAAK,kBAAa,OAAO,gBAAgB,UAAU,iBAAiB,OAAO,gBAAgB,KAAK;AAAA,IACrI,IACA,CAAC;AAAA,IACL;AAAA,EACF;AAEA,QAAMC,SAAQ,KAAK,IAAI,GAAG,OAAO,OAAO,IAAI,CAACC,WAAUA,OAAM,MAAM,MAAM,CAAC;AAC1E,aAAWA,UAAS,OAAO,QAAQ;AACjC,UAAM;AAAA,MACJ,KAAKA,OAAM,MAAM,OAAOD,MAAK,CAAC,KAAK,OAAOC,OAAM,KAAK,EAAE,SAAS,CAAC,CAAC,KAAKA,OAAM,QAAQ;AAAA,IACvF;AAAA,EACF;AAEA,aAAWA,UAAS,OAAO,QAAQ;AACjC,QAAI,CAACA,OAAM,MAAO;AAClB,UAAM,KAAK,IAAI,MAAMA,OAAM,KAAK,KAAKA,OAAM,KAAK,GAAG;AACnD,eAAW,SAASA,OAAM,UAAU;AAClC,YAAM;AAAA,QACJ,KAAK,MAAM,SAAS,GAAG,MAAM,QAAQ,WAAM,MAAM,KAAK,KAAK,EAAE,KAAK,MAAM,IAAI;AAAA,MAC9E;AAAA,IACF;AAAA,EACF;AAEA,aAAW,QAAQ,OAAO,SAAS,CAAC,EAAG,OAAM,KAAK,IAAI,IAAI;AAE1D,QAAM;AAAA,IACJ;AAAA,IACA,OAAO,UACH,uBACA,GAAG,OAAO,YAAY,WAAW,OAAO,iBAAiB,IAAI,KAAK,GAAG,WACnE,OAAO,OAAO,OAAO,CAACA,WAAUA,OAAM,KAAK,EAAE,MAC/C,OAAO,OAAO,OAAO,MAAM;AAAA,EACjC;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAOA,SAAS,cAAc,QAAuC;AAC5D,QAAM,UAAU,OAAO,WAAW,CAAC;AACnC,QAAM,QAAQ;AAAA,IACZ,qBAAgB,OAAO,UAAU;AAAA,IACjC,YAAY,OAAO,SAAS;AAAA,IAC5B,GAAG,QAAQ,MAAM,UAAU,QAAQ,WAAW,IAAI,KAAK,GAAG,oBACxD,OAAO,OAAO,OAChB;AAAA,EACF;AACA,MAAI,OAAO,eAAe,QAAQ;AAChC,UAAM;AAAA,MACJ,2CAA2C,OAAO,cAAc,KAAK,IAAI,CAAC;AAAA,IAC5E;AAAA,EACF;AACA,aAAW,UAAU,SAAS;AAC5B,UAAM;AAAA,MACJ,eAAe;AAAA,QACb,WAAW,OAAO;AAAA,QAClB;AAAA,QACA,aAAa,CAAC;AAAA,QACd,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AUtSA,IAAAC,eAAkB;AAIX,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,OAAO,eACJ,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,MAAM,eACH,MAAM,eAAE,KAAK,mBAAmB,CAAC,EACjC,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,QAAQ,SAAS,MAAM,SAAS;AACtC,UAAM,OAAO,SAAS,MAAM,QAAQ;AACpC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,WAAW,KAAK,CAAC;AAAA,MACjB,GAAI,QAAQ,EAAE,OAAO,OAAO,KAAK,EAAE,IAAI,CAAC;AAAA,MACxC,GAAI,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,WAAW,IAAI,OAAO,KAAK,MACpE,MAAM,OAAO,MAAM,IAAI;AAAA,IACrB,GAAI,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC;AAAA,IACvC,GAAI,MAAM,SAAS,EAAE,KAAK,IAAI,CAAC;AAAA,EACjC,CAAC;AACL,CAAC;;;AC3CD,IAAAC,eAAkB;AAIX,IAAM,cAAc,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,YAAY,MAAM,eAAE,KAAK,eAAe,EAAE,SAAS,EAAE,CAAC;AAAA,EACxE,UAAU,CAAC,MAAM,UAAU,EAAE,YAAY,MAAM,MAAM,KAAK,CAAC,EAAE;AAAA,EAC7D,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,KAAK,OAC7C,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY;AAAA,IAC9C,WAAW,OAAO;AAAA,IAClB,OAAO,OAAO,YAAY,SAAS;AAAA,IACnC,aAAa,OAAO,YAAY,eAAe;AAAA,IAC/C,QAAQ,OAAO,YAAY;AAAA,IAC3B,SAAS,OAAO,YAAY,mBAAmB,CAAC;AAAA,EAClD,EAAE;AACN,CAAC;;;ACpBD,IAAAC,eAAkB;AAIX,IAAM,cAAc,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eACJ,OAAO;AAAA,IACN;AAAA,IACA,MAAM,eAAE,KAAK,eAAe,EAAE,SAAS;AAAA,IACvC,cAAc,eACX,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT,SAAS,+CAA+C;AAAA,IAC3D,KAAK,eACF,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,UAAU;AAAA,EACZ,CAAC,EACA,OAAO,CAAC,UAAU,EAAE,MAAM,OAAO,MAAM,iBAAiB,SAAY;AAAA,IACnE,SACE;AAAA,EACJ,CAAC;AAAA,EACH,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,GAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,WAAW,IAAI,IAAI,EAAE,MAAM,KAAK,CAAC,EAAE,IAAI,CAAC;AAAA,MAChE,GAAI,SAAS,EAAE,cAAc,OAAO,MAAM,EAAE,IAAI,CAAC;AAAA,MACjD,GAAI,KAAK,SAAS,OAAO,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;AAAA,MAC9C,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,MAAM,GACR,EAAE,YAAY,MAAM,MAAM,cAAc,KAAK,SAAS,MACnD;AACH,UAAM,SAAS,MAAM,MAAM,KAAK,MAAM;AAAA,MACpC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,MACvC,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;AAAA,MACrB,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/C,CAAC;AACD,QAAI,CAAC,OAAO,OAAQ,QAAO;AAC3B,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS,OAAO,QAAQ,IAAI,CAAC,SAAS;AAAA,QACpC,WAAW,IAAI,OAAO;AAAA,QACtB,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,QACvC,UAAU,IAAI;AAAA,QACd,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,QACpD,UAAU,IAAI;AAAA,QACd,SAAS,IAAI,OAAO,YAAY,mBAAmB,CAAC;AAAA,QACpD,MAAM,IAAI,OAAO;AAAA,MACnB,EAAE;AAAA,IACJ;AAAA,EACF;AACF,CAAC;;;ACnED,IAAAC,eAAkB;AAGX,IAAM,aAAa,OAAO;AAAA,EAC/B,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,WAAW,CAAC;AAAA,EAC9B,UAAU,CAAC,OAAO,UAAU,EAAE,YAAY,KAAK;AAAA,EAC/C,KAAK,CAAC,EAAE,MAAM,GAAG,EAAE,YAAY,KAAK,MAAM,MAAM,QAAQ,IAAI;AAC9D,CAAC;;;ACZD,IAAAC,eAAkB;AAKX,IAAM,oBAAoB,OAAO;AAAA,EACtC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,YAAY,QAAQ,eAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,EACzD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,QAAQ,KAAK,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK;AAAA,EACvC;AAAA,EACA,KAAK,OAAO,EAAE,OAAO,OAAO,IAAI,GAAG,EAAE,YAAY,MAAM,OAAO,MAAM;AAClE,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM;AAAA,MACzB;AAAA,MACA,EAAE,GAAG,wBAAwB,QAAQ,OAAO,IAAI,CAAC,GAAG,WAAW,KAAK;AAAA,MACpE;AAAA,IACF;AACA,WAAO,EAAE,WAAW,OAAO,UAAU;AAAA,EACvC;AACF,CAAC;;;ACzBD,IAAAC,eAAkB;AAKX,IAAM,cAAc,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,MAAM,eACH,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT,SAAS,0DAA0D;AAAA,IACtE,UAAU,eACP,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,cAAc,eACX,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,OAAO,SAAS,MAAM,QAAQ;AACpC,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,WAAW,KAAK,CAAC;AAAA,MACjB,GAAI,OAAO,EAAE,MAAM,OAAO,IAAI,EAAE,IAAI,CAAC;AAAA,MACrC,GAAI,WAAW,EAAE,UAAU,OAAO,QAAQ,EAAE,IAAI,CAAC;AAAA,MACjD,GAAI,SAAS,EAAE,cAAc,OAAO,MAAM,EAAE,IAAI,CAAC;AAAA,IACnD;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,OAAO,IAAI,GACb,EAAE,YAAY,MAAM,WAAW,MAAM,MAAM,UAAU,aAAa,MAC/D;AACH,UAAM,SAAS,MAAM,MAAM,KAAK,MAAM,MAAM;AAAA,MAC1C,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,MACrC,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,MAC7C,GAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,IACvD,CAAC;AACD,WAAOC,QAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,EACnC;AACF,CAAC;AAOD,SAASA,QAAO,QAAsB,QAAgBC,KAAoB;AACxE,QAAM,QAAQ;AAAA,IACZ,oBAAe,OAAO,IAAI;AAAA,IAC1B,WAAW,MAAM;AAAA,IACjB,YAAY,OAAO,YAAY,OAAO,OAAO,YAAY,YAAY,OAAO,WAAW;AAAA,IACvF,WAAWA,GAAE;AAAA,IACb;AAAA,IACA,eAAe,OAAO,QAAQ,MAAM;AAAA,EACtC;AAEA,aAAW,UAAU,OAAO,SAAS;AACnC,UAAM;AAAA,MACJ;AAAA,MACA,OAAO,OAAO,SAAS,GAAG,OAAO,QAAQ,WAAM,OAAO,KAAK,KAAK,EAAE,KAAK,OAAO,QAAQ;AAAA,IACxF;AACA,QAAI,OAAO,SAAS,QAAQ;AAC1B,YAAM,KAAK,aAAa,OAAO,SAAS,IAAI,YAAY,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,IACxE;AACA,QAAI,OAAO,QAAQ,QAAQ;AACzB,YAAM;AAAA,QACJ,YAAY,OAAO,QAChB;AAAA,UAAI,CAAC,WACJ,OAAO,SAAS,GAAG,OAAO,IAAI,IAAI,OAAO,MAAM,KAAK,OAAO;AAAA,QAC7D,EACC,KAAK,IAAI,CAAC;AAAA,MACf;AAAA,IACF;AACA,UAAM,KAAK,IAAI,OAAO,KAAK,QAAQ,CAAC;AAAA,EACtC;AAEA,MAAI,OAAO,WAAW,QAAQ;AAC5B,UAAM,KAAK,IAAI,kBAAkB,OAAO,WAAW,MAAM,GAAG;AAC5D,eAAW,SAAS,OAAO,YAAY;AACrC,YAAM;AAAA,QACJ,KAAK,MAAM,SAAS,WAClB,MAAM,aAAa,KAAK,IAAI,KAAK,qBACnC,GAAG,MAAM,KAAK,KAAK,MAAM,EAAE,MAAM,EAAE;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,QAAQ;AAC1B,UAAM,KAAK,IAAI,gBAAgB,OAAO,SAAS,MAAM,GAAG;AACxD,eAAW,OAAO,OAAO,SAAU,OAAM,KAAK,KAAK,GAAG,EAAE;AAAA,EAC1D;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,aAAa,SAA4B;AAChD,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO,iBAAiB,QAAQ,GAAG,KAAK,IAAI,CAAC;AAAA,IAC/C,KAAK;AACH,aAAO,cAAc,QAAQ,MAAM;AAAA,IACrC,KAAK;AACH,aAAO,uBAAkB,QAAQ,OAAO;AAAA,IAC1C,KAAK;AACH,aAAO,uBAAuB,QAAQ,QAAQ,KAAK,UAAK,CAAC;AAAA,IAC3D,KAAK;AACH,aAAO,6BAAwB,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,IACzD,KAAK;AACH,aAAO,eAAe,QAAQ,UAAU;AAAA,IAC1C,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO,QAAQ;AAAA,EACnB;AACF;;;ACvIA,IAAAC,eAAkB;AAIX,IAAM,aAAa,OAAO;AAAA,EAC/B,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,MAAM,eACH,KAAK,CAAC,QAAQ,OAAO,CAAC,EACtB,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,UAAU,eACP,MAAM,eAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,6DAA6D;AAAA,IACzE,OAAO,eACJ,KAAK,CAAC,WAAW,SAAS,MAAM,CAAC,EACjC,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,QAAQ,eACL,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,aAAa,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,WAAW,IAAI,IAAI,KAAK,CAAC,IAAI;AACpE,UAAM,OAAO,SAAS,MAAM,QAAQ;AACpC,UAAM,WAAW,SAAS,MAAM,YAAY;AAC5C,UAAM,QAAQ,KAAK,SAAS,QAAQ,IAChC,SACA,KAAK,SAAS,SAAS,IACrB,UACA;AACN,UAAM,SAAS,KAAK,SAAS,UAAU,IACnC,OACA,KAAK,SAAS,YAAY,IACxB,QACA;AACN,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,WACA;AAAA,QACE,UAAU,SACP,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAAA,MACnB,IACA,CAAC;AAAA,MACL,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,MACzB,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3C;AAAA,EACF;AAAA,EACA,KAAK,CAAC,EAAE,OAAO,IAAI,GAAG,EAAE,YAAY,MAAM,MAAM,UAAU,OAAO,OAAO,MACtE,QAAQ,OAAO,QAAQ,IAAI,GAAG,MAAM,IAAI,GAAG;AAAA,IACzC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACvB,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IACzB,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,EAC3C,CAAC;AACL,CAAC;;;ACxED,IAAAC,eAAkB;AAIX,IAAM,cAAc,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,CAAC,CAAC;AAAA,EAClB,UAAU,OAAO,CAAC;AAAA,EAClB,KAAK,CAAC,EAAE,MAAM,MAAM,SAAS,OAAO,QAAQ,IAAI,CAAC;AACnD,CAAC;;;ACbD,IAAAC,eAAkB;AAIX,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,MAAM,eAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,MAAM,eAAE,KAAK,eAAe,EAAE,SAAS;AAAA,IACvC,mBAAmB,eAAE,QAAQ,EAAE,SAAS;AAAA,IACxC,UAAU;AAAA,EACZ,CAAC;AAAA;AAAA,EAED,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,UAAM,QAAQ,KAAK,MAAM,CAAC;AAC1B,UAAM,OAAO,MAAM,QAAQ,aAAa;AACxC,QAAI,SAAS,GAAI,OAAM,OAAO,MAAM,CAAC;AACrC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM,MAAM,KAAK,GAAG,EAAE,KAAK;AAAA,MAC3B,mBAAmB;AAAA,MACnB,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,MAAM,GACR,EAAE,YAAY,MAAM,MAAM,MAAM,mBAAmB,SAAS,OAG1D,MAAM,MAAM,MAAM,MAAM,QAAQ,IAAI;AAAA,IAClC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACvB,mBAAmB,sBAAsB;AAAA,IACzC,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,EAC/C,CAAC,GACD,IAAI,CAAC,SAAS;AAAA,IACd,WAAW,IAAI,OAAO;AAAA,IACtB,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,IACvC,aAAa,IAAI,OAAO,YAAY,eAAe;AAAA,IACnD,UAAU,IAAI;AAAA,IACd,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,IACpD,UAAU,IAAI;AAAA,IACd,MAAM,IAAI,OAAO;AAAA,EACnB,EAAE;AACN,CAAC;;;ACjDD,IAAAC,eAAkB;AAGX,IAAM,mBAAmB,OAAO;AAAA,EACrC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,WAAW,CAAC;AAAA,EAC9B,UAAU,CAAC,OAAO,UAAU,EAAE,YAAY,KAAK;AAAA,EAC/C,KAAK,CAAC,EAAE,MAAM,GAAG,EAAE,YAAY,KAAK,MAAM,MAAM,UAAU,IAAI;AAChE,CAAC;;;ACZD,IAAAC,eAAkB;;;ACAlB,IAAAC,eAAkB;;;ACAlB,IAAAC,eAAkB;AAEX,IAAM,WAAW;AAEjB,IAAM,mBAAmB,eAC7B,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASN,IAAI,eAAE,IAAI,SAAS;AAAA,EACnB,IAAI,eAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,WAAW,eAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC3B,WAAW,eAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAE3B,QAAQ,eAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACrC,CAAC,EACA,OAAO;AAwBH,SAAS,eAAe,OAA2B;AACxD,SAAO,GAAG,KAAK,UAAU,iBAAiB,MAAM,KAAK,CAAC,CAAC;AAAA;AACzD;AAQO,SAAS,SAAS,KAA8B;AACrD,QAAM,UAAwB,CAAC;AAC/B,QAAM,YAA8C,CAAC;AACrD,QAAM,OAAO,oBAAI,IAAY;AAE7B,MAAI,MAAM,IAAI,EAAE,QAAQ,CAAC,MAAMC,WAAU;AACvC,QAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAI;AACJ,QAAI;AACF,cAAQ,KAAK,MAAM,IAAI;AAAA,IACzB,QAAQ;AACN,gBAAU,KAAK,EAAE,MAAMA,SAAQ,GAAG,KAAK,CAAC;AACxC;AAAA,IACF;AACA,UAAM,SAAS,iBAAiB,UAAU,KAAK;AAC/C,QAAI,CAAC,OAAO,SAAS;AACnB,gBAAU,KAAK,EAAE,MAAMA,SAAQ,GAAG,KAAK,CAAC;AACxC;AAAA,IACF;AAYA,UAAM,MAAM,KAAK,UAAU,OAAO,IAAI;AACtC,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AAEZ,YAAQ,KAAK,OAAO,IAAI;AAAA,EAC1B,CAAC;AAQD,UAAQ;AAAA,IAAK,CAAC,MAAM,UAClB,KAAK,KAAK,MAAM,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI;AAAA,EACrD;AAEA,SAAO,EAAE,SAAS,UAAU;AAC9B;;;ADtFO,SAAS,gBAAyC;AACvD,SAAO;AAAA,IACL,mBAAmB,eAAE,aAAa,2BAA2B;AAAA,MAC3D,IAAI;AAAA,IACN,CAAC;AAAA,IACD,cAAc,eAAE,aAAa,oBAAoB,EAAE,IAAI,QAAQ,CAAC;AAAA,IAChE,UAAU,eAAE,aAAa,kBAAkB,EAAE,IAAI,QAAQ,CAAC;AAAA,EAC5D;AACF;;;ADrBO,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,CAAC,CAAC;AAAA,EAClB,UAAU,OAAO,CAAC;AAAA,EAClB,KAAK,MAAM,QAAQ,QAAQ,cAAc,CAAC;AAC5C,CAAC;;;AGbD,IAAAC,mBAAyB;AACzB,IAAAC,eAAkB;AAelB,IAAM,SAAS;AAER,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd,YAAY,eACT,OAAO,EACP,IAAI,CAAC,EACL,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,OAAO,eACJ,OAAO,EACP,IAAI,CAAC,EACL,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,MAAM,QAAQ,mBAAmB;AAChD,UAAM,QAAQ,SAAS,MAAM,SAAS;AACtC,WAAO;AAAA,MACL,GAAI,iBAAiB,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,MAC7C,GAAI,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC;AAAA,IACzC;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAAC,aAAY,MAAM,MAAM;AAC/C,UAAM,UAAUA,cACZ,CAACA,WAAU,KACV,MAAM,eAAe,QAAQ,IAAI,CAAC,GAAG,KAAK;AAAA,MACzC,CAAC,QAAQ,IAAI;AAAA,IACf;AAKJ,QAAI,UAAU,UAAa,OAAO,KAAK,KAAK,KAAK,QAAQ,SAAS,GAAG;AACnE,YAAM,IAAI,2BAA2B,KAAK;AAAA,IAC5C;AAEA,UAAM,SAAS,MAAM,QAAQ;AAAA,MAC3B,QAAQ,IAAI,CAAC,WAAW,MAAM,MAAM,MAAM,CAAC;AAAA,IAC7C;AACA,QAAI,UAAU,QAAW;AACvB,aAAO,OAAO,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,SAAS,KAAK,EAAE;AAAA,IAC5D;AAEA,UAAM,WAAW,MAAM,aAAa,KAAK;AACzC,UAAM,UAA2B,CAAC;AAClC,eAAW,SAAS,QAAQ;AAC1B,YAAM,SAAS,SAAS,OAAO,IAAI,MAAM,IAAI;AAC7C,UAAI,SAAS,WAAW,MAAM;AAC5B,YAAI,SAAS,WAAW,MAAM,OAAQ;AACtC,gBAAQ,KAAK,EAAE,GAAG,OAAO,SAAS,KAAK,CAAC;AACxC;AAAA,MACF;AAGA,UAAI,UAAU,OAAO,WAAW,MAAM,OAAQ;AAC9C,cAAQ,KAAK,EAAE,GAAG,OAAO,SAAS,WAAW,QAAQ,SAAS,KAAK,EAAE,CAAC;AAAA,IACxE;AACA,WAAO;AAAA,EACT;AAAA,EACA,QAAQ,CAAC,WACN,OACE,IAAI,CAAC,WAAW;AACf,UAAM,SAAS,GAAG,OAAO,WAAW,eAAe,OAAO,UAAU,cAClE,OAAO,UAAU,KAAK,OAAO,OAAO,aAAa,EACnD;AACA,UAAM,OAAO,GAAG,OAAO,IAAI,KAAK,OAAO,MAAM,KAAK,MAAM,GACtD,OAAO,WAAW,YAAY,OAAO,QAAQ,KAAK,EACpD;AACA,WAAO,OAAO,SAAS,SACnB,GAAG,IAAI;AAAA,aAAgB,OAAO,QAAQ,KAAK,IAAI,CAAC,KAChD;AAAA,EACN,CAAC,EACA,KAAK,IAAI;AAChB,CAAC;AAED,SAAS,WACP,QACA,OACU;AACV,QAAM,MAAM,IAAI;AAAA,IACd,MAAM,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,OAAO,MAAM,CAAC;AAAA,EACjE;AACA,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,CAACC,YAAW,MAAM,KAAK,KAAK;AACrC,QAAI,QAAQ,IAAIA,UAAS,MAAM,OAAQ,KAAI,IAAIA,UAAS;AAAA,EAC1D;AACA,aAAWA,cAAa,QAAQ,KAAK,KAAK,CAAC,GAAG;AAC5C,QAAI,CAAC,IAAI,IAAIA,UAAS,EAAG,KAAI,IAAIA,UAAS;AAAA,EAC5C;AACA,SAAO,CAAC,GAAG,GAAG,EAAE,KAAK;AACvB;AAOA,eAAe,aAAa,OAGzB;AACD,MAAI,OAAO,KAAK,KAAK,EAAG,QAAO,EAAE,QAAQ,OAAO,QAAQ,oBAAI,IAAI,EAAE;AAElE,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,UAAM,2BAAS,OAAO,MAAM,CAAC;AAAA,EACnD,QAAQ;AACN,UAAM,IAAI,qBAAqB,KAAK;AAAA,EACtC;AAIA,QAAM,UAAU,MAAM,QAAQ,MAAM,IAChC,SACE,QAAmC,UAAU,CAAC;AACpD,QAAM,SAAS,oBAAI,IAGjB;AACF,aAAW,SAAS,SAIf;AACH,QAAI,OAAO,OAAO,SAAS,YAAY,OAAO,OAAO,WAAW,UAAU;AACxE;AAAA,IACF;AACA,WAAO,IAAI,MAAM,MAAM;AAAA,MACrB,QAAQ,MAAM;AAAA,MACd,SAAS,IAAI;AAAA,SACV,MAAM,WAAW,CAAC,GAAG,IAAI,CAAC,WAAW;AAAA,UACpC,OAAO;AAAA,UACP,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO,EAAE,QAAQ,MAAM,OAAO;AAChC;;;ACnKA,IAAAC,eAAkB;AAKX,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,QAAQ,eAAE,KAAK,kBAAkB;AAAA,EACnC,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,KAAK,OACH,EAAE,OAAO,MAAM,GACf,EAAE,YAAY,MAAM,WAAW,IAAI,OAAO,MACvC;AACH,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM,UAAU,MAAM,IAAI,QAAQ,KAAK;AAC5D,WAAO,EAAE,WAAW,OAAO,WAAW,OAAO;AAAA,EAC/C;AACF,CAAC;;;AC7BD,IAAAC,eAAkB;AAIX,IAAM,mBAAmB,OAAO;AAAA,EACrC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,YAAY,WAAW,eAAe,UAAU,CAAC;AAAA,EACnE,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,eAAe,KAAK,CAAC;AAAA,EACvB;AAAA,EACA,KAAK,OACH,EAAE,OAAO,MAAM,GACf,EAAE,YAAY,MAAM,WAAW,IAAI,cAAc,MAC9C;AACH,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,MAAM,UAAU,MAAM,IAAI,eAAe,KAAK;AACpD,WAAO,EAAE,YAAY,IAAI,YAAY,cAAc;AAAA,EACrD;AACF,CAAC;;;ACxBD,IAAAC,eAAkB;AAIX,IAAM,0BAA0B,OAAO;AAAA,EAC5C,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd,MAAM,eAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,wCAAwC;AAAA,IACzE,cAAc,eAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,IACnD,iBAAiB,eAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,IACtD,SAAS,eAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,CAAC;AAAA,EACD,UAAU,CAAC,SAAS;AAClB,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAM,YAAY,SAAS,MAAM,cAAc;AAC/C,UAAM,UAAU,SAAS,MAAM,WAAW;AAC1C,WAAO;AAAA,MACL,MAAM,KAAK,CAAC;AAAA,MACZ,GAAI,SAAS,EAAE,cAAc,OAAO,MAAM,EAAE,IAAI,CAAC;AAAA,MACjD,GAAI,YAAY,EAAE,iBAAiB,OAAO,SAAS,EAAE,IAAI,CAAC;AAAA,MAC1D,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC/B;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,MAAM,cAAc,iBAAiB,QAAQ,MAAM;AAC1E,UAAM,SAAS,MAAM,aAAa,OAAO,QAAQ,IAAI,GAAG;AAAA,MACtD,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,MACvC,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,MAC7C,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,MAAM,CAAC,UAAU,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI;AAAA,IACpE,CAAC;AACD,WAAO,iBAAiB,MAAM,OAAO,KAAK;AAAA,EAC5C;AACF,CAAC;;;ACpCD,IAAAC,eAAkB;;;ACsBX,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AA6BO,SAAS,MACd,QACA,QACA,UAA0B,CAAC,GACZ;AACf,QAAM,QAAQ,QAAQ,OAAO,SAAS,QAAQ,QAAQ;AACtD,QAAM,WAAW,QAAQ,SAAS;AAClC,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,QAAM,OAAO,KAAK,IAAI,MAAM;AAC5B,MAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,QAAM,UAAU,oBAAI,IAAyB;AAAA,IAC3C,CAAC,QAAQ,EAAE,QAAQ,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC;AAAA,EAC9C,CAAC;AACD,MAAI,WAAuB,CAAC,IAAI;AAEhC,WAAS,QAAQ,GAAG,SAAS,YAAY,SAAS,QAAQ,SAAS,GAAG;AACpE,UAAM,OAAmB,CAAC;AAC1B,eAAW,QAAQ,UAAU;AAC3B,iBAAW,QAAQ,OAAO;AACxB,mBAAW,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,GAAG;AACD,gBAAM,WAAW,QAAQ,IAAI,OAAO,SAAS;AAC7C,cAAI,UAAU;AAKZ,gBAAI,SAAS,QAAQ,KAAK,CAAC,SAAS,IAAI,SAAS,IAAI,GAAG;AACtD,uBAAS,IAAI,KAAK,IAAI;AAAA,YACxB;AACA;AAAA,UACF;AACA,kBAAQ,IAAI,OAAO,WAAW,EAAE,QAAQ,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AAC5D,eAAK,KAAK,MAAM;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AACA,eAAW;AAAA,EACb;AAEA,SAAO,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,KAAK,aAAa;AACjD;AAEA,SAAS,cAAc,MAAmB,OAA4B;AACpE,QAAMC,MAAK,CAAC,SAAsB,KAAK,OAAO,YAAY,WAAW,MAAM;AAC3E,SAAOA,IAAG,IAAI,EAAE,cAAcA,IAAG,KAAK,CAAC,KAAK,KAAK,QAAQ,MAAM;AACjE;;;ADvGO,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,OAAO,eAAE,MAAM,eAAE,KAAK,WAAW,CAAC,EAAE,SAAS;AAAA,IAC7C,OAAO,eAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,EAC9C,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,OAAO,KACJ,MAAM,CAAC,EACP,OAAO,CAAC,SAAU,YAAkC,SAAS,IAAI,CAAC;AAAA,EACvE;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,WAAW,IAAI,OAAO,MAAM,OAEnE,MAAM,MAAM,MAAM,MAAM,IAAI;AAAA,IAC1B,GAAI,OAAO,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,IACjC,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,EAC3B,CAAC,GACD,IAAI,CAAC,UAAU;AAAA,IACf,WAAW,KAAK,OAAO;AAAA,IACvB,IAAI,KAAK,OAAO,YAAY,WAAW,MAAM;AAAA,IAC7C,QAAQ,KAAK,OAAO,YAAY;AAAA,IAChC,OAAO,KAAK,OAAO,YAAY,SAAS;AAAA,IACxC,OAAO,KAAK;AAAA,IACZ,KAAK,KAAK;AAAA,IACV,MAAM,KAAK,OAAO;AAAA,EACpB,EAAE;AACN,CAAC;;;AEtCD,IAAAC,eAAkB;AAIX,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,CAAC,CAAC;AAAA,EAClB,UAAU,OAAO,CAAC;AAAA,EAClB,KAAK,MAAM,QAAQ,QAAQ,YAAY;AACzC,CAAC;;;ACbD,IAAAC,eAAkB;AAIX,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,WAAW,CAAC;AAAA,EAC9B,UAAU,CAAC,MAAM,UAAU,EAAE,YAAY,KAAK,CAAC,KAAK,KAAK;AAAA,EACzD,KAAK,CAAC,MAAM,EAAE,YAAY,KAAK,MAAM,UAAU,QAAQ,IAAI,GAAG,IAAI;AACpE,CAAC;;;ACbD,IAAAC,eAAkB;AAIX,IAAM,kBAAkB,OAAO;AAAA,EACpC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,WAAW,CAAC;AAAA,EAC9B,UAAU,CAAC,OAAO,UAAU,EAAE,YAAY,KAAK;AAAA,EAC/C,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,KAAK,MACxC,eAAe,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA,EAEvC,WAAW,CAAC,WACV,MAAM,QAAQ,MAAM,KACnB,OAAiC;AAAA,IAChC,CAAC,YAAY,QAAQ,aAAa;AAAA,EACpC;AACJ,CAAC;;;ACpBD,IAAAC,eAAkB;AAIX,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,MAAM,eAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG;AAAA,MAClD,SAAS;AAAA,IACX,CAAC;AAAA,EACH,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,MAAM,SAAS,MAAM,QAAQ;AAAA,EAC/B;AAAA,EACA,KAAK,OACH,EAAE,OAAO,OAAO,IAAI,GACpB,EAAE,YAAY,MAAM,WAAW,IAAI,KAAK,MACrC;AACH,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM,OAAO,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC;AAC9D,WAAO;AAAA,MACL,WAAW,OAAO;AAAA,MAClB,UAAU,OAAO,YAAY,UAAU,UAAU;AAAA,IACnD;AAAA,EACF;AACF,CAAC;;;ACjCD,IAAAC,eAAkB;AAMX,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,MAAM,eAAE,KAAK,eAAe;AAAA,IAC5B,OAAO;AAAA,EACT,CAAC;AAAA,EACD,UAAU,OAAO,MAAM,MAAM,WAAW;AAAA,IACtC,YAAY;AAAA,IACZ,MAAM,KAAK,CAAC;AAAA,IACZ,OAAO,KAAK,MAAM,MAAM,MAAM,CAAC;AAAA,EACjC;AAAA,EACA,KAAK,OAAO,EAAE,OAAO,OAAO,IAAI,GAAG,EAAE,YAAY,MAAM,MAAM,MAAM,MAAM;AACvE,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM;AAAA,MACzB;AAAA,MACA,cAAc,MAAsB,OAAO,OAAO,IAAI,CAAC;AAAA,MACvD;AAAA,IACF;AACA,WAAO;AAAA,MACL,WAAW,OAAO;AAAA,MAClB,QAAQ,OAAO;AAAA,MACf,eAAe,OAAO;AAAA,IACxB;AAAA,EACF;AACF,CAAC;;;ACnCD,IAAAC,eAAkB;AAQX,IAAM,uBAAuB,OAAO;AAAA,EACzC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,YAAY,OAAO,oBAAoB,CAAC;AAAA,EAC1D,UAAU,OAAO,OAAO,MAAM,WAAW;AAAA,IACvC,YAAY;AAAA,IACZ,OAAO,KAAK,MAAM,MAAM,MAAM,CAAC;AAAA,EACjC;AAAA,EACA,KAAK,OAAO,EAAE,OAAO,OAAO,IAAI,GAAG,EAAE,YAAY,MAAM,MAAM,MAAM;AACjE,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM;AAAA,MACzB;AAAA,MACA,sBAAsB,OAAO,OAAO,IAAI,CAAC;AAAA,MACzC;AAAA,IACF;AACA,WAAO;AAAA,MACL,WAAW,OAAO;AAAA,MAClB,QAAQ,OAAO;AAAA,MACf,eAAe,OAAO;AAAA,IACxB;AAAA,EACF;AACF,CAAC;;;ACMM,IAAM,cAA2B;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,sBAAsB,IAAI;AAAA,EACrC,YAAY,IAAI,CAAC,YAAY,CAAC,QAAQ,MAAM,OAAO,CAAC;AACtD;;;ACxEA,IAAAC,oBASO;AACP,IAAAC,qBAAmC;;;ACVnC,yBAAmB;AAWZ,SAAS,iCACd,SACA,aACQ;AACR,SAAO,mBAAAC,QAAO,UAAU,SAAS,WAAW;AAC9C;AAEO,SAAS,yBAAyB,MAIvC;AACA,QAAM,WAAO,mBAAAA,SAAO,IAAI;AAExB,SAAO;AAAA,IACL,SAAS,KAAK;AAAA;AAAA;AAAA,IAGd,QAAQ,KAAK,MAAM,GAAG,KAAK,SAAS,KAAK,QAAQ,MAAM;AAAA,IACvD,KAAK,KAAK;AAAA,EACZ;AACF;AASO,SAAS,6BACd,MACA,QAMA;AACA,QAAM,EAAE,SAAS,QAAQ,IAAI,IAAI,yBAAyB,IAAI;AAE9D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,OAAO,UAAU,GAAG;AAAA,EACnC;AACF;;;AClDA,IAAAC,sBAA2B;AASpB,SAASC,QAAO,UAA0B;AAC/C,aAAO,gCAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AAC3D;AAQO,SAAS,YACd,SACA,YACe;AACf,QAAM,UAA2B;AAAA,IAC/B,GAAG,QAAQ,IAAI,CAAC,SAAS;AAAA,MACvB,WAAW,IAAI,OAAO;AAAA,MACtB,QAAQ,WAAWA;AAAA,QACjB;AAAA,UACE,IAAI,OAAO;AAAA,UACX,IAAI,OAAO;AAAA,QACb;AAAA,MACF,CAAC;AAAA,IACH,EAAE;AAAA,IACF,GAAG,WAAW,IAAI,CAAC,WAAW;AAAA,MAC5B,WAAW,MAAM;AAAA,MACjB,QAAQ,cAAcA,QAAO,KAAK,UAAU,KAAK,CAAC,CAAC;AAAA,IACrD,EAAE;AAAA,EACJ,EAAE,KAAK,CAAC,GAAG,MAAO,EAAE,YAAY,EAAE,YAAY,KAAK,CAAE;AAErD,SAAO;AAAA,IACL,QAAQA;AAAA,MACN,QAAQ,IAAI,CAAC,UAAU,GAAG,MAAM,SAAS,IAAI,MAAM,MAAM,EAAE,EAAE,KAAK,IAAI;AAAA,IACxE;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAEO,SAAS,aACd,SACA,YACQ;AACR,SAAO,YAAY,SAAS,UAAU,EAAE;AAC1C;;;AC5DA,IAAAC,mBAAqB;AACrB,IAAAC,qBAAqB;AAKd,IAAM,oBAAoB;AAEjC,IAAM,aAAa;AAmFnB,eAAsB,WACpBC,aACA,OACA,UAAyB,CAAC,GACG;AAC7B,QAAM,MAAM,QAAQ,OAAQ,MAAM,QAAQ,QAAQ,MAAM;AACxD,MAAI,CAAC,IAAK,QAAO;AAEjB,MAAI,QAAyB;AAC7B,MAAI;AACF,YAAS,MAAM,IAAI,YAAY;AAAA,MAC7B,YAAQ,yBAAKA,aAAY,iBAAiB;AAAA,MAC1C,QAAQ;AAAA,QACN,aAAa;AAAA,UACX,CAAC,UAAU,GAAG;AAAA,YACZ,MAAMA;AAAA,YACN,SAAS;AAAA;AAAA,YAET,QAAQ,CAAC,YAAY,QAAQ;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,MAAM,QAAQA,WAAU,GAAG;AAC7B,YAAM,MAAM,OAAO,EAAE,aAAa,CAAC,UAAU,EAAE,CAAC;AAAA,IAClD;AAEA,UAAM,OAAO,MAAM,MAAM,UAAU,OAAO;AAAA,MACxC,YAAY;AAAA,MACZ,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,IAClD,CAAC;AACD,WAAO,KACJ,IAAI,CAAC,SAAS;AAAA,MACb,aAAa,IAAI,eAAe,IAAI,YAAY;AAAA,MAChD,OAAO,IAAI,SAAS;AAAA,IACtB,EAAE,EACD,OAAO,CAAC,QAAQ,IAAI,YAAY,SAAS,CAAC;AAAA,EAC/C,SAAS,OAAO;AAGd,YAAQ,QAAQ,OAAO;AAAA,MACrB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD,CAAC;AACD,WAAO;AAAA,EACT,UAAE;AACA,UAAM,OAAO,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,EAC5C;AACF;AAQA,eAAe,QAAQA,aAAsC;AAC3D,QAAM,UAAU,UAAM,2BAAK,yBAAKA,aAAY,iBAAiB,CAAC,EAC3D,KAAK,CAAC,MAAM,EAAE,OAAO,EACrB,MAAM,MAAM,CAAC;AAChB,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,EAAE,SAAAC,SAAQ,IAAI,MAAM,OAAO,aAAkB;AACnD,QAAM,SAAS,MAAMA,SAAQD,WAAU,EAAE,MAAM,MAAM,CAAC,CAAa,GAAG;AAAA,IACpE,CAAC,SAAS,KAAK,SAAS,KAAK,KAAK,SAAS;AAAA,EAC7C;AAEA,MAAI,QAAQ;AACZ,QAAM,SAAS,OAAO,wBAAwB,OAAO,SAAS;AAC5D,QAAI,MAAO;AACX,UAAME,MAAK,UAAM,2BAAK,yBAAKF,aAAY,IAAI,CAAC,EACzC,KAAK,CAAC,MAAM,EAAE,OAAO,EACrB,MAAM,MAAM,CAAC;AAChB,QAAIE,MAAK,QAAS,SAAQ;AAAA,EAC5B,CAAC;AACD,SAAO;AACT;AASO,SAAS,YACd,MACA,SACK;AACL,QAAM,SAAS,oBAAI,IAAe;AAClC,aAAW,UAAU,SAAS;AAC5B,UAAM,OAAO,QAAQ,OAAO,SAAS;AAErC,QAAI,OAAO,IAAI,IAAI,EAAG,QAAO,OAAO,IAAI;AAAA,QACnC,QAAO,IAAI,MAAM,MAAM;AAAA,EAC9B;AAEA,QAAM,WAAgB,CAAC;AACvB,aAAW,OAAO,MAAM;AACtB,UAAM,OAAO,IAAI,YAAY,MAAM,GAAG,EAAE,IAAI,KAAK;AACjD,UAAM,OAAO,KAAK,SAAS,KAAK,IAAI,KAAK,MAAM,GAAG,CAAC,MAAM,MAAM,IAAI;AACnE,UAAM,SAAS,OAAO,IAAI,QAAQ,IAAI,CAAC;AACvC,QAAI,OAAQ,UAAS,KAAK,MAAM;AAAA,EAClC;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAuB;AACtC,SAAO,MAAM,QAAQ,QAAQ,GAAG,EAAE,YAAY;AAChD;AAQA,IAAM,aAAa;AAQnB,eAAsB,QACpB,QAC2B;AAC3B,MAAI;AACF,WAAQ,MAAM,OAAO;AAAA,EACvB,QAAQ;AACN,YAAQ,OAAO,EAAE,WAAW,aAAa,SAAS,kBAAkB,CAAC;AACrE,WAAO;AAAA,EACT;AACF;;;AChNO,IAAM,oBAAoB;AAC1B,IAAM,yBAAyB;AA0CtC,IAAM,gBAAmC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG,gBAAgB;AAAA,IACjB,CAAC,SAAS,CAAC,CAAC,YAAY,cAAc,aAAa,EAAE,SAAS,IAAI;AAAA,EACpE;AACF;AAkBO,SAAS,KACd,QACA,QACA,UAAyB,CAAC,GACZ;AACd,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,eAAe,QAAQ,gBAAgB;AAE7C,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,QAAM,OAAO,KAAK,IAAI,MAAM;AAC5B,MAAI,CAAC,KAAM,OAAM,IAAI,sBAAsB,MAAM;AAKjD,QAAM,UAAqB,CAAC,EAAE,QAAQ,MAAM,OAAO,EAAE,CAAC;AACtD,QAAM,OAAO,oBAAI,IAAI,CAAC,MAAM,CAAC;AAC7B,MAAI,WAAuB,CAAC,IAAI;AAChC,WAAS,QAAQ,GAAG,SAAS,QAAQ,SAAS,GAAG;AAC/C,UAAM,OAAmB,CAAC;AAC1B,eAAW,QAAQ,UAAU;AAC3B,iBAAW,EAAE,OAAO,KAAK,WAAW,MAAM,MAAM,GAAG;AACjD,YAAI,KAAK,IAAI,OAAO,SAAS,EAAG;AAChC,aAAK,IAAI,OAAO,SAAS;AACzB,gBAAQ,KAAK,EAAE,QAAQ,MAAM,CAAC;AAC9B,aAAK,KAAK,MAAM;AAAA,MAClB;AAAA,IACF;AACA,eAAW;AAAA,EACb;AAEA,UAAQ,KAAK,MAAM;AACnB,QAAM,SAAS,QAAQ,OAAO,CAAC,UAAU,MAAM,SAAS,IAAI;AAC5D,QAAM,OAAO,OAAO,MAAM,GAAG,QAAQ;AACrC,QAAM,WAAW;AAAA,IACf,GAAG,OAAO,MAAM,QAAQ;AAAA,IACxB,GAAG,QAAQ,OAAO,CAAC,UAAU,MAAM,QAAQ,IAAI;AAAA,EACjD,EACG,IAAI,CAAC,UAAU,MAAM,OAAO,SAAS,EACrC,KAAK;AAER,QAAM,cAAc;AAAA,IAClB,KAAK,IAAI,CAAC,UAAU,MAAM,MAAM;AAAA,IAChC;AAAA,EACF;AACA,QAAM,aAAa,YAChB,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C,IAAI,IAAI;AACX,QAAM,QAAQ,YAAY,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY;AAEvE,QAAM,eACJ,MAAM,OAAO,CAAC,OAAO,QAAQ,QAAQ,eAAe,IAAI,MAAM,GAAG,CAAC,IAClE,WAAW,OAAO,CAAC,OAAO,UAAU,QAAQ,mBAAmB,KAAK,GAAG,CAAC;AAC1E,QAAM,cAAc,YAAY;AAEhC,MAAI,eAAe,cAAc;AAC/B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,MAAM,IAAI,CAAC,SAAS;AAAA,MAC3B,WAAW,IAAI,OAAO;AAAA,MACtB,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,MACvC,UAAU,IAAI;AAAA,MACd,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,MACpD,UAAU,IAAI;AAAA,MACd,SAAS,IAAI,OAAO,YAAY,mBAAmB,CAAC;AAAA,MACpD,MAAM,IAAI,OAAO;AAAA,IACnB,EAAE;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,OAAO,MAAe,OAAwB;AACrD,SACE,KAAK,QAAQ,MAAM,SACnB,SAAS,KAAK,MAAM,IAAI,SAAS,MAAM,MAAM,MAC5C,KAAK,OAAO,YAAY,SAAS,IAAI;AAAA,IACpC,MAAM,OAAO,YAAY,SAAS;AAAA,EACpC,KACA,KAAK,OAAO,UAAU,cAAc,MAAM,OAAO,SAAS;AAE9D;AAGA,SAAS,SAAS,QAA0B;AAC1C,QAAMC,SAAQ,cAAc,QAAQ,OAAO,YAAY,IAAI;AAC3D,SAAOA,WAAU,KAAK,cAAc,SAASA;AAC/C;;;AClLO,SAAS,aAAa,QAAkD;AAC7E,QAAM,WAAW,oBAAI,IAA6B;AAElD,aAAW,UAAU,QAAQ;AAC3B,eAAWC,SAAQ,OAAO,YAAY,iBAAiB,CAAC,GAAG;AAGzD,UAAIA,MAAK,WAAW,OAAO,UAAW;AAEtC,YAAM,QAAQ,SAAS,IAAIA,MAAK,MAAM,KAAK,CAAC;AAE5C,UACE,MAAM;AAAA,QACJ,CAAC,SAAS,KAAK,SAAS,OAAO,aAAa,KAAK,QAAQA,MAAK;AAAA,MAChE,GACA;AACA;AAAA,MACF;AACA,YAAM,KAAK,EAAE,MAAM,OAAO,WAAW,KAAKA,MAAK,IAAI,CAAC;AACpD,eAAS,IAAIA,MAAK,QAAQ,KAAK;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AACT;;;ACrBO,SAAS,UACd,UACA,QACmB;AACnB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,MAAI,CAAC,KAAK,IAAI,QAAQ,EAAG,OAAM,IAAI,sBAAsB,QAAQ;AAEjE,QAAM,aAAa,IAAI;AAAA,IACrB,WAAW,QAAQ,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,OAAO,WAAW,GAAG,CAAC;AAAA,EACrE;AAEA,QAAM,OAAqB,CAAC;AAC5B,aAAW,QAAQ,aAAa,MAAM,EAAE,IAAI,QAAQ,KAAK,CAAC,GAAG;AAC3D,UAAM,SAAS,KAAK,IAAI,KAAK,IAAI;AACjC,QAAI,CAAC,OAAQ;AACb,UAAM,MAAM,WAAW,IAAI,KAAK,IAAI;AACpC,SAAK,KAAK;AAAA,MACR,GAAG;AAAA,MACH,OAAO,OAAO,YAAY,SAAS;AAAA,MACnC,UAAU,KAAK,YAAY;AAAA,MAC3B,UAAU,KAAK,YAAY,CAAC;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,WAAW,KAAK;AAAA,MACd,CAAC,MAAM,UACL,KAAK,KAAK,cAAc,MAAM,IAAI,KAClC,KAAK,IAAI,cAAc,MAAM,GAAG;AAAA,IACpC;AAAA,EACF;AACF;;;ACrBO,SAAS,OACd,UACA,QACA,UAA2B,CAAC,GACZ;AAChB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,MAAI,CAAC,KAAK,IAAI,QAAQ,EAAG,OAAM,IAAI,sBAAsB,QAAQ;AAEjE,QAAM,OAAO,YAAY,QAAQ,IAAI;AACrC,QAAM,WAAW,QAAQ,SAAS,OAAO;AACzC,QAAM,UAAU,aAAa,MAAM;AAInC,QAAM,aAAa,IAAI;AAAA,IACrB,WAAW,QAAQ,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,OAAO,WAAW,GAAG,CAAC;AAAA,EACrE;AAEA,QAAM,UAAU,oBAAI,IAA8B;AAClD,QAAM,UAAoB,CAAC;AAC3B,MAAI,WAAW,CAAC,QAAQ;AACxB,MAAI,QAAQ;AAEZ,SAAO,SAAS,UAAU,QAAQ,UAAU;AAC1C,aAAS;AACT,UAAM,OAAiB,CAAC;AAExB,UAAM,WAAW,CAAC,aAAqB,SAAqB;AAE1D,UAAI,gBAAgB,SAAU;AAE9B,YAAM,WAAW,QAAQ,IAAI,WAAW;AACxC,UAAI,UAAU;AACZ,YAAI,CAAC,QAAQ,SAAS,KAAK,IAAI,EAAG,UAAS,IAAI,KAAK,IAAI;AACxD;AAAA,MACF;AAEA,YAAM,SAAS,KAAK,IAAI,WAAW;AAInC,UAAI,CAAC,OAAQ;AAEb,YAAM,MAAM,WAAW,IAAI,WAAW;AACtC,YAAM,QAA0B;AAAA,QAC9B,WAAW;AAAA,QACX,OAAO,OAAO,YAAY,SAAS;AAAA,QACnC,UAAU,KAAK,YAAY;AAAA,QAC3B,UAAU,KAAK,YAAY,CAAC;AAAA,QAC5B;AAAA,QACA,KAAK,CAAC,IAAI;AAAA,MACZ;AACA,cAAQ,IAAI,aAAa,KAAK;AAE9B,UAAI,MAAM,aAAa,gBAAgB,MAAM,aAAa,YAAY;AACpE,gBAAQ,KAAK,WAAW;AACxB;AAAA,MACF;AACA,WAAK,KAAK,WAAW;AAAA,IACvB;AAEA,eAAW,MAAM,UAAU;AAEzB,iBAAW,QAAQ,QAAQ,IAAI,EAAE,KAAK,CAAC,GAAG;AACxC,YAAI,CAAC,KAAK,IAAI,KAAK,GAAG,EAAG;AACzB,YAAI,aAAa,KAAK,GAAG,MAAM,SAAU;AACzC,iBAAS,KAAK,MAAM,EAAE,QAAQ,KAAK,MAAM,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAAA,MACtE;AAGA,iBAAWC,SAAQ,KAAK,IAAI,EAAE,GAAG,YAAY,iBAAiB,CAAC,GAAG;AAChE,YAAI,CAAC,KAAK,IAAIA,MAAK,GAAG,EAAG;AACzB,YAAI,aAAaA,MAAK,GAAG,MAAM,SAAU;AACzC,YAAIA,MAAK,WAAW,GAAI;AACxB,iBAASA,MAAK,QAAQ;AAAA,UACpB,QAAQ;AAAA,UACR,QAAQA,MAAK;AAAA,UACb,KAAKA,MAAK;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAEA,eAAW;AAAA,EACb;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE;AAAA,MAC9B,CAAC,MAAM,UACL,KAAK,QAAQ,MAAM,SACnB,KAAK,UAAU,cAAc,MAAM,SAAS;AAAA,IAChD;AAAA,IACA,SAAS,QAAQ,KAAK;AAAA,IACtB,WAAW,SAAS,SAAS;AAAA,IAC7B,YAAY,CAAC,GAAG,QAAQ,EAAE,KAAK;AAAA,EACjC;AACF;AASA,SAAS,YAAY,MAAkD;AACrE,MAAI,CAAC,MAAM,OAAQ,QAAO,IAAI,IAAY,mBAAmB;AAC7D,aAAW,OAAO,MAAM;AACtB,QAAI,CAAC,YAAY,GAAG,KAAK,UAAU,GAAG,EAAE,cAAc,MAAM;AAC1D,YAAM,IAAI,sBAAsB,KAAK,mBAAmB;AAAA,IAC1D;AAAA,EACF;AACA,SAAO,IAAI,IAAI,IAAI;AACrB;AAGA,SAAS,aAAa,KAAyC;AAC7D,SAAO,YAAY,GAAG,IAAI,UAAU,GAAG,EAAE,YAAY;AACvD;AAEA,SAAS,QAAQ,OAAqB,MAA2B;AAC/D,SAAO,MAAM;AAAA,IACX,CAAC,aACC,SAAS,WAAW,KAAK,UACzB,SAAS,WAAW,KAAK,UACzB,SAAS,QAAQ,KAAK;AAAA,EAC1B;AACF;;;ACnJO,IAAM,qBAAqB;AAmB3B,IAAM,mBAAmB,GAAG,QAAQ;AAO3C,SAAS,UAAU,MAA2D;AAC5E,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG,QAAO;AAChD,QAAM,CAAC,SAAS,GAAG,KAAK,IAAI,QAAQ,MAAM,KAAK;AAC/C,SAAO,YAAY,SAAY,OAAO,EAAE,SAAS,MAAM;AACzD;AAuBO,SAAS,oBAAoB,UAA2B;AAC7D,SAAO,SAAS,MAAM,IAAI,EAAE,KAAK,CAAC,SAAS;AACzC,UAAM,SAAS,UAAU,IAAI;AAC7B,QAAI,CAAC,UAAU,OAAO,YAAY,SAAU,QAAO;AACnD,WAAO,OAAO,MAAM;AAAA,MAClB,CAAC,SACC,SAAS,WAAW,SAAS,YAAY,KAAK,WAAW,QAAQ;AAAA,IACrE;AAAA,EACF,CAAC;AACH;AAQO,SAAS,qBAAqB,UAA0B;AAC7D,QAAM,YACJ,SAAS,WAAW,KAAK,SAAS,SAAS,IAAI,IAAI,KAAK;AAC1D,SAAO,GAAG,SAAS,GAAG,gBAAgB;AAAA;AACxC;;;ARHO,IAAM,aAAS,yBAAK,YAAY,IAAI;AAE3C,IAAM,cAAc,oBAAI,IAAI,CAAC,YAAY,UAAU,iBAAiB,CAAC;AAQ9D,IAAM,sBAAsB;AAqG5B,IAAM,UAAN,MAAc;AAAA,EACnB,YAA6B,SAAmB,CAAC,GAAG;AAAvB;AAAA,EAAwB;AAAA,EAAxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7B,MAAM,MACJC,aACA,OACA,QAAQ,WACgB;AACxB,QAAI,CAAC,gBAAgB,KAAK,MAAM,IAAI,GAAG;AACrC,YAAM,IAAI,wBAAwB,2BAA2B;AAAA,QAC3D,MAAM,MAAM;AAAA,MACd,CAAC;AAAA,IACH;AACA,QAAI,CAAC,gBAAgB,KAAK,MAAM,IAAI,GAAG;AACrC,YAAM,IAAI,wBAAwB,2BAA2B;AAAA,QAC3D,MAAM,MAAM;AAAA,MACd,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,0BAA0B,MAAM;AAAA,MAClD,GAAG,MAAM;AAAA,MACT,MAAM,MAAM;AAAA,IACd,CAAC;AACD,UAAMC,aAAY,GAAG,MAAM,IAAI,IAAI,MAAM,IAAI;AAC7C,UAAM,OAAO,KAAK,KAAKD,WAAU;AACjC,UAAM,SAAS,KAAK,WAAWA,aAAYC,UAAS;AAEpD,cAAM,yBAAM,MAAM,EAAE,WAAW,KAAK,CAAC;AACrC,UAAM,KAAK;AAAA,MACT;AAAA,MACA,iCAAiC,MAAM,MAAM,WAAW;AAAA,MACxD,MAAM,aAAa;AAAA,MACnBA;AAAA,IACF;AAEA,UAAM,KAAK,OAAO,MAAM;AAAA,MACtB,WAAW,MAAM,YAAY,cAAc;AAAA,MAC3C,WAAAA;AAAA,MACA,IAAI;AAAA,IACN,CAAC;AASD,UAAM,UAAU,IAAI,IAAI,YAAY,sBAAsB,CAAC,CAAC;AAC5D,YAAQ,OAAOA,UAAS;AAKxB,UAAM,gBAA0B,CAAC;AACjC,eAAW,OAAO,SAAS;AACzB,UACE,MAAM,KAAK,uBAAuBD,aAAY,KAAKC,YAAW,KAAK,GACnE;AACA,sBAAc,KAAK,GAAG;AAAA,MACxB;AAAA,IACF;AAEA,SAAK,OAAO,OAAO;AAAA,MACjB,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAAA;AAAA,MACA,SAAS,YAAY,iBAAiB,UAAU;AAAA,IAClD,CAAC;AAED,WAAO;AAAA,MACL,WAAAA;AAAA,MACA;AAAA,MACA,MAAM,MAAM;AAAA,MACZ,QAAQ,cAAc,SAAS,qBAAqB;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAAKD,aAAoBC,YAA6C;AAG1E,UAAM,SAAS,KAAK,WAAWD,aAAYC,UAAS;AACpD,QAAI;AACJ,QAAI;AACF,YAAM,UAAM,4BAAS,QAAQ,MAAM;AAAA,IACrC,QAAQ;AACN,aAAO;AAAA,IACT;AACA,WAAO,KAAK,MAAMA,YAAW,GAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,KAAKD,aAAoB,MAAoC;AACjE,UAAM,OAAO,KAAK,KAAKA,WAAU;AACjC,QAAI;AACJ,QAAI;AACF,cAAQ,UAAM,2BAAQ,IAAI;AAAA,IAC5B,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAKA,UAAM,SAAS,MACZ,KAAK,EAIL,OAAO,CAAC,SAAS,KAAK,SAAS,KAAK,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,EAC/D,IAAI,CAAC,UAAU,EAAE,MAAM,WAAW,KAAK,MAAM,GAAG,CAAC,MAAM,MAAM,EAAE,EAAE,EACjE,OAAO,CAAC,EAAE,WAAAC,WAAU,MAAM,CAAC,QAAQA,WAAU,WAAW,GAAG,IAAI,GAAG,CAAC;AAEtE,UAAM,UAAU,MAAM;AAAA,MACpB;AAAA,MACA;AAAA,MACA,OAAO,EAAE,MAAM,WAAAA,WAAU,MACvB,KAAK,MAAMA,YAAW,UAAM,gCAAS,yBAAK,MAAM,IAAI,GAAG,MAAM,CAAC;AAAA,IAClE;AACA,WAAO,QAAQ,OAAO,CAAC,WAA+B,WAAW,IAAI;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,UACJD,aACAC,YACA,QACA,QAAQ,WACW;AACnB,WAAO,KAAK;AAAA,MACVD;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB,EAAE,GAAG,aAAa,gBAAgB,OAAO;AAAA,MAC3D,EAAE,WAAW,UAAU,MAAM,IAAI,IAAI,MAAM;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cACJD,aACAC,YACA,SACA,QAAQ,WACW;AACnB,WAAO,KAAK;AAAA,MACVD;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB,EAAE,GAAG,aAAa,iBAAiB,QAAQ;AAAA,MAC7D,EAAE,WAAW,kBAAkB,IAAI,MAAM;AAAA,IAC3C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,OACJD,aACAC,YACA,MACA,QAAQ,WACRC,OAAK,oBAAI,KAAK,GAAE,YAAY,GACT;AACnB,UAAM,QAAQ,sBAAsB,MAAM,EAAE,IAAI,OAAO,IAAAA,KAAI,KAAK,CAAC;AAEjE,UAAM,WAAW,MAAM,KAAK,KAAKF,aAAYC,UAAS;AACtD,QAAI,CAAC,SAAU,OAAM,IAAI,sBAAsBA,UAAS;AAMxD,UAAM,cAAc,SAAS,YAAY,WAAW;AACpD,QACE,gBAAgB,UAChB,MAAM,YAAY,MAAM,YAAY,YAAY,KAChD,CAAC,eAAe,KAAK,EAAE,WAAW,QAAQ,GAC1C;AACA,YAAM,KAAK,OAAO,KAAK,KAAKD,WAAU,GAAG;AAAA,QACvC,WAAW;AAAA,QACX,WAAAC;AAAA,QACA,IAAI;AAAA,MACN,CAAC;AACD,YAAM,IAAI,wBAAwBA,YAAW,OAAO,WAAW;AAAA,IACjE;AAEA,WAAO,KAAK;AAAA,MACVD;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB;AAAA,QAChB,GAAG;AAAA,QACH,UAAU,CAAC,GAAI,YAAY,YAAY,CAAC,GAAI,KAAK;AAAA,MACnD;AAAA,MACA,EAAE,WAAW,UAAU,IAAI,MAAM;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UACJD,aACAC,YACA,eACA,QAAQ,WACW;AACnB,UAAM,cAAc,MAAM,KAAK,KAAKD,aAAY,aAAa;AAC7D,QAAI,CAAC,YAAa,OAAM,IAAI,sBAAsB,aAAa;AAE/D,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5BA;AAAA,MACAC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,KAAK;AAAA,MACTD;AAAA,MACA;AAAA,MACA,CAAC,iBAAiB;AAAA,QAChB,GAAG;AAAA,QACH,oBAAoB;AAAA,UAClB,GAAG,oBAAI,IAAI,CAAC,GAAI,YAAY,sBAAsB,CAAC,GAAIC,UAAS,CAAC;AAAA,QACnE;AAAA,MACF;AAAA,MACA,EAAE,WAAW,cAAc,IAAI,OAAO,QAAQA,WAAU;AAAA,IAC1D;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,OACJD,aACAC,YACA,QACA,QAAQ,WACRC,OAAK,oBAAI,KAAK,GAAE,YAAY,GACT;AACnB,WAAO,KAAK;AAAA,MACVF;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB;AAAA,QAChB,GAAG;AAAA,QACH,gBAAgB;AAAA,QAChB,kBAAkB,EAAE,IAAI,OAAO,IAAAC,IAAG;AAAA,MACpC;AAAA,MACA,EAAE,WAAW,UAAU,IAAI,MAAM;AAAA,MACjC,CAAC,SAAS,GAAG,KAAK,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,EAAoB,MAAM;AAAA;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,MACJF,aACA,MACA,UAII,CAAC,GACqB;AAC1B,UAAM,SAAS,MAAM,KAAK,KAAKA,WAAU;AACzC,UAAM,SAAS,KAAK,KAAK;AACzB,UAAM,OAAO,SAAS,MAAM,KAAK,KAAKA,aAAY,QAAQ,MAAM,IAAI;AACpE,UAAM,WAAW,QAAQ,OACrB,KAAK,OAAO,CAAC,MAAM,EAAE,YAAY,SAAS,QAAQ,IAAI,IACtD;AACJ,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA,oBAAI,KAAK;AAAA,MACT,MAAM,KAAK,YAAY,UAAU,QAAQ,QAAQ;AAAA,IACnD;AAEA,QAAI,QAAQ,kBAAmB,QAAO;AAItC,UAAM,UAAU,IAAI,IAAI,YAAY,IAAI,CAAC,QAAQ,IAAI,OAAO,SAAS,CAAC;AACtE,WAAO,YAAY;AAAA,MACjB,CAAC,QACC,IAAI,aAAa,gBACjB,CAAC,IAAI,MAAM,KAAK,CAAC,SAAS,QAAQ,IAAI,KAAK,SAAS,CAAC;AAAA,IACzD;AAAA,EACF;AAAA,EAEA,MAAc,KACZA,aACA,QACA,QACqB;AACrB,UAAM,SAAS,MAAM,WAAW,KAAK,KAAKA,WAAU,GAAG,QAAQ;AAAA,MAC7D,QAAQ,KAAK;AAAA,IACf,CAAC;AACD,QAAI,QAAQ;AACV,YAAM,QAAQ,YAAY,QAAQ,MAAM;AACxC,UAAI,MAAM,OAAQ,QAAO;AAAA,IAC3B;AACA,UAAM,UAAU,OAAO,YAAY;AACnC,WAAO,OAAO,OAAO,CAAC,WAAWG,SAAQ,QAAQ,OAAO,CAAC;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,MAAM,YACJ,SACA,UACA,UAAiC,CAAC,GACsB;AACxD,QAAI;AACF,YAAM,QAAQ,MAAM,kBAAkB,SAAS;AAAA,QAC7C,UAAU,YAAY,QAAQ,IAAI;AAAA;AAAA;AAAA,QAGlC,QAAQ,EAAE,SAAS,QAAQ,YAAY,MAAM;AAAA,MAC/C,CAAC;AACD,UAAI,aAAa,UAAa,uBAAuB,KAAK,GAAG;AAC3D,aAAK,OAAO,OAAO;AAAA,UACjB,WAAW;AAAA,UACX,SAAS;AAAA,UACT,QAAQ;AAAA,QACV,CAAC;AACD,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,MAAM,KACJH,aACA,UAKI,CAAC,GACkB;AACvB,UAAM,eAAe,QAAQ,gBAAgB;AAC7C,UAAM,SAAS,MAAM,KAAK,KAAKA,WAAU;AACzC,UAAM,SAAS,QAAQ,OACnB,OAAO,OAAO,CAAC,WAAW,OAAO,YAAY,SAAS,QAAQ,IAAI,IAClE;AAIJ,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA,oBAAI,KAAK;AAAA,MACT,MAAM,KAAK,YAAY,QAAQ,QAAQ,QAAQ;AAAA,IACjD;AACA,UAAM,UAAU,YAAY,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY;AACzE,UAAM,aAAa,YAChB,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C,IAAI,IAAI;AAIX,UAAMI,gBACJ,QAAQ,OAAO,CAAC,OAAO,QAAQ,QAAQ,eAAe,IAAI,MAAM,GAAG,CAAC,IACpE,WAAW,OAAO,CAAC,OAAO,UAAU,QAAQ,mBAAmB,KAAK,GAAG,CAAC;AAI1E,UAAM,oBAAoB,aAAa,SAAS,UAAU;AAE1D,QAAI,CAAC,QAAQ,OAAOA,gBAAe,cAAc;AAC/C,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,aAAa,OAAO;AAAA,QACpB,cAAAA;AAAA,QACA;AAAA,QACA,SAAS,eAAe;AAAA,UACtB,cAAAA;AAAA,UACA;AAAA,UACA,MAAM,QAAQ;AAAA,QAChB,CAAC;AAAA,QACD,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa,OAAO;AAAA,MACpB,cAAcA;AAAA,MACd,cAAc,QAAQ,MAAM,OAAO;AAAA,MACnC;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,MACJJ,aACA,UAAiC,CAAC,GACV;AACxB,UAAM,SAAS,MAAM,KAAK,KAAKA,WAAU;AACzC,UAAM,cAAc,WAAW,QAAQ,QAAQ,oBAAI,KAAK,CAAC;AACzD,UAAM,UAAU,YAAY,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY;AACzE,UAAM,aAAa,YAChB,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C,IAAI,IAAI;AAEX,UAAM,UAAU,YAAY,SAAS,UAAU;AAC/C,UAAM,QAAQ,OACX,IAAI,CAAC,WAAW,OAAO,YAAY,WAAW,MAAM,IAAI,EACxD,OAAO,CAACE,QAAqB,OAAOA,QAAO,QAAQ,EACnD,KAAK;AAaR,UAAM,QAAQ,MAAM,KAAK,YAAY,QAAQ,QAAQ,QAAQ;AAC7D,UAAMG,WACJ,UAAU,SACN,OACA,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE;AAAA,MAAO,CAAC,YAC1B,QAAQ;AAAA,QACN,CAAC,UACC,MAAM,UAAU,WAAW,CAAC,kBAAkB,MAAM,MAAM;AAAA,MAC9D;AAAA,IACF,EAAE;AAER,WAAO;AAAA,MACL,MAAML;AAAA,MACN,QAAQ,QAAQ;AAAA,MAChB,aAAa,OAAO;AAAA,MACpB,YAAY,WAAW;AAAA,MACvB,UAAU,MAAM,GAAG,EAAE,KAAK;AAAA,MAC1B,SAAS,QAAQ;AAAA,MACjB,SAAAK;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,MACJL,aACA,QACA,UAA0B,CAAC,GACH;AACxB,WAAO,MAAM,QAAQ,MAAM,KAAK,KAAKA,WAAU,GAAG,OAAO;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAM,QACJA,aACA,UAAyC,CAAC,GAChB;AAC1B,WAAO,QAAQ,MAAM,KAAK,KAAKA,WAAU,GAAG,OAAO;AAAA,EACrD;AAAA;AAAA,EAGA,MAAM,KACJA,aACA,QACA,UAAyB,CAAC,GACH;AACvB,WAAO,KAAK,MAAM,KAAK,KAAKA,WAAU,GAAG,QAAQ,OAAO;AAAA,EAC1D;AAAA;AAAA,EAGA,MAAM,OACJA,aACA,UACA,UAA2B,CAAC,GACH;AACzB,WAAO,OAAO,UAAU,MAAM,KAAK,KAAKA,WAAU,GAAG,OAAO;AAAA,EAC9D;AAAA;AAAA,EAGA,MAAM,UACJA,aACA,UAC4B;AAC5B,WAAO,UAAU,UAAU,MAAM,KAAK,KAAKA,WAAU,CAAC;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAAUA,aAAqC;AACnD,UAAM,OAAO,KAAK,KAAKA,WAAU;AACjC,UAAM,WAAW,YAAY,MAAM,KAAK,KAAKA,WAAU,CAAC;AACxD,UAAM,SAAS,UAAM,gCAAS,yBAAK,MAAM,UAAU,GAAG,MAAM,EAAE;AAAA,MAC5D,MAAM;AAAA,IACR;AAEA,QAAI,aAAa,QAAQ,QAAQ,GAAG;AAClC,YAAM,KAAK,YAAQ,yBAAK,MAAM,UAAU,GAAG,UAAU,MAAM,UAAU;AACrE,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,QAAQ,WAAW,OAAO,YAAY;AAAA,MACxC,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQA,aAA0D;AACtE,UAAM,MAAM,UAAM;AAAA,UAChB,yBAAK,KAAK,KAAKA,WAAU,GAAG,QAAQ;AAAA,MACpC;AAAA,IACF,EAAE,MAAM,MAAM,EAAE;AAChB,UAAM,SAAS,SAAS,GAAG;AAC3B,eAAW,OAAO,OAAO,WAAW;AAClC,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,MAAM,IAAI;AAAA,QACV,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAc,uBACZA,aACAC,YACA,eACA,OACA,UAAU,GACQ;AAClB,aAAS,UAAU,GAAG,WAAW,SAAS,WAAW;AACnD,UAAI;AACF,cAAM,KAAK,eAAeD,aAAYC,YAAW,eAAe,KAAK;AACrE,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI,iBAAiB,sBAAuB,QAAO;AACnD,YAAI,EAAE,iBAAiB,sBAAuB,OAAM;AACpD,YAAI,YAAY,QAAS,QAAO;AAAA,MAClC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAc,eACZD,aACAC,YACA,eACA,OACmB;AACnB,WAAO,KAAK;AAAA,MACVD;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB;AAAA,QAChB,GAAG;AAAA,QACH,gBAAgB;AAAA,QAChB,uBAAuB;AAAA,MACzB;AAAA,MACA,EAAE,WAAW,aAAa,IAAI,OAAO,QAAQ,cAAc;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAc,OACZD,aACAC,YACA,QACA,OACA,aAAuC,CAAC,SAAS,MAC9B;AACnB,UAAM,SAAS,KAAK,WAAWD,aAAYC,UAAS;AACpD,UAAM,SAAS,UAAM,4BAAS,QAAQ,MAAM,EAAE,MAAM,MAAM,IAAI;AAC9D,QAAI,WAAW,KAAM,OAAM,IAAI,sBAAsBA,UAAS;AAE9D,UAAM,SAAS,KAAK,MAAMA,YAAW,MAAM;AAC3C,QAAI,CAAC,OAAQ,OAAM,IAAI,sBAAsBA,UAAS;AAEtD,UAAM,cAAc,OAAO,OAAO,WAAW;AAC7C,UAAM,OAAO,WAAW,OAAO,IAAI;AACnC,UAAM,WAAW,iCAAiC,MAAM,WAAW;AAOnE,UAAM,UAAU,UAAM,4BAAS,QAAQ,MAAM,EAAE,MAAM,MAAM,IAAI;AAC/D,QAAI,YAAY,QAAQK,QAAO,OAAO,MAAMA,QAAO,MAAM,GAAG;AAC1D,YAAM,IAAI,qBAAqBL,UAAS;AAAA,IAC1C;AACA,UAAM,KAAK,QAAQ,QAAQ,UAAU,MAAMA,UAAS;AACpD,UAAM,KAAK,OAAO,KAAK,KAAKD,WAAU,GAAG,EAAE,GAAG,OAAO,WAAAC,WAAU,CAAC;AAEhE,WAAO,EAAE,WAAAA,YAAW,aAAa,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAc,QACZ,QACA,UACA,WACAA,YACe;AACf,UAAM,UAAU,GAAG,MAAM,IAAI,QAAQ,GAAG;AACxC,cAAM,6BAAU,SAAS,UAAU,MAAM;AAEzC,QAAI;AACF,UAAI,WAAW;AACb,kBAAM,0BAAO,SAAS,MAAM;AAC5B;AAAA,MACF;AACA,gBAAM,wBAAK,SAAS,MAAM;AAAA,IAC5B,SAAS,OAAO;AACd,UAAK,MAAgC,SAAS,UAAU;AACtD,cAAM,IAAI,2BAA2BA,UAAS;AAAA,MAChD;AACA,YAAM;AAAA,IACR,UAAE;AAEA,gBAAM,0BAAO,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0CA,MAAc,oBAAoB,MAA6B;AAC7D,UAAM,aAAS,yBAAK,MAAM,kBAAkB;AAC5C,QAAI;AACF,UAAI;AACJ,UAAI;AACF,mBAAW,UAAM,4BAAS,QAAQ,MAAM;AAAA,MAC1C,SAAS,OAAO;AACd,YAAK,MAAgC,SAAS,SAAU,OAAM;AAC9D,mBAAW;AAAA,MACb;AAEA,UAAI,aAAa,MAAM;AACrB,YAAI;AACF,oBAAM,6BAAU,QAAQ,qBAAqB,EAAE,GAAG;AAAA,YAChD,UAAU;AAAA,YACV,MAAM;AAAA,UACR,CAAC;AAAA,QACH,SAAS,OAAO;AAId,cAAK,MAAgC,SAAS,SAAU,OAAM;AAC9D,eAAK,OAAO,OAAO;AAAA,YACjB,WAAW;AAAA,YACX,YAAY;AAAA,YACZ,SAAS;AAAA,UACX,CAAC;AACD;AAAA,QACF;AACA,aAAK,OAAO,OAAO;AAAA,UACjB,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,SAAS;AAAA,QACX,CAAC;AACD;AAAA,MACF;AACA,UAAI,CAAC,oBAAoB,QAAQ,GAAG;AAClC,kBAAM,8BAAW,QAAQ,qBAAqB,QAAQ,GAAG,MAAM;AAC/D,aAAK,OAAO,OAAO;AAAA,UACjB,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF,SAAS,OAAO;AACd,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,OACZ,MACA,OACe;AACf,UAAM,KAAK,oBAAoB,IAAI;AACnC,UAAM,OAAO,eAAe,EAAE,KAAI,oBAAI,KAAK,GAAE,YAAY,GAAG,GAAG,MAAM,CAAC;AACtE,cAAM,kCAAW,yBAAK,MAAM,QAAQ,GAAG,MAAM,MAAM,EAAE,MAAM,CAAC,UAAU;AACpE,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,MAAMA,YAAmB,KAA8B;AAC7D,UAAM,SAAS,6BAA6B,KAAK,yBAAyB;AAC1E,QAAI,CAAC,OAAO,YAAY,SAAS;AAC/B,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,WAAAA;AAAA,QACA,SAAS;AAAA,QACT,OAAO,OAAO,YAAY,MAAM,OAAO,CAAC,GAAG,WAAW;AAAA,MACxD,CAAC;AACD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,WAAAA;AAAA,MACA,aAAa,OAAO,YAAY;AAAA,MAChC,MAAM,OAAO;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,KAAKD,aAA4B;AACvC,eAAO,4BAAQA,WAAU;AAAA,EAC3B;AAAA;AAAA;AAAA,EAIQ,WAAWA,aAAoBC,YAA2B;AAChE,QAAIA,WAAU,SAAS,sBAAG,KAAKA,WAAU,SAAS,GAAG,GAAG;AACtD,YAAM,IAAI;AAAA,QACR;AAAA,QACA,EAAE,WAAAA,WAAU;AAAA,MACd;AAAA,IACF;AACA,eAAO,yBAAK,KAAK,KAAKD,WAAU,GAAG,GAAGC,UAAS,KAAK;AAAA,EACtD;AACF;AAWO,SAAS,eAAe,QAA0B;AACvD,SAAO,KAAK;AAAA,KACT,OAAO,KAAK,SAAS,KAAK,UAAU,OAAO,WAAW,EAAE,UAAU;AAAA,EACrE;AACF;AAEO,SAAS,mBAAmB,OAAiC;AAClE,SAAO,KAAK,KAAK,KAAK,UAAU,KAAK,EAAE,SAAS,CAAC;AACnD;AAGA,SAAS,eAAe,SAIb;AACT,QAAM,QAAQ,QAAQ,OAAO,YAAY,QAAQ,IAAI,KAAK;AAE1D,SAAO;AAAA,IACL,sCAAsC,QAAQ,YAAY,uBAAuB,QAAQ,YAAY;AAAA,IACrG,0CAA0C,KAAK;AAAA,IAC/C,iDAAiD,QAAQ,YAAY;AAAA,EACvE,EAAE,KAAK,GAAG;AACZ;AASO,SAAS,KAAK,KAAsC;AACzD,SAAO;AAAA,IACL,WAAW,IAAI,OAAO;AAAA,IACtB,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,IACvC,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,IACpD,IAAI,IAAI,OAAO,YAAY,WAAW,MAAM;AAAA,EAC9C;AACF;AAEA,SAASE,SAAQ,QAAkB,QAAyB;AAC1D,QAAM,EAAE,OAAO,YAAY,IAAI,OAAO;AAItC,SAAO,CAAC,OAAO,WAAW,OAAO,aAAa,OAAO,IAAI,EAAE;AAAA,IAAK,CAAC,UAC/D,OAAO,YAAY,EAAE,SAAS,MAAM;AAAA,EACtC;AACF;AAQA,SAAS,eAAe,IAAoB;AAC1C,QAAM,QAAQ,GAAG,QAAQ,GAAG;AAC5B,MAAI,UAAU,GAAI,QAAO,GAAG,YAAY;AACxC,SAAO,GAAG,MAAM,GAAG,QAAQ,CAAC,EAAE,YAAY,IAAI,GAAG,MAAM,QAAQ,CAAC;AAClE;;;ASvoCO,IAAM,UACX,OACI,WACA;;;A1FAC,SAAS,oBAA+B;AAC7C,QAAM,SAAS,IAAI,qBAAU,EAAE,MAAM,cAAc,SAAS,QAAQ,CAAC;AACrE,QAAM,QAAQ,IAAI,QAAQ;AAAA,IACxB,MAAM,CAAC,UAAU,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI;AAAA,EACpE,CAAC;AACD,QAAM,MAAM;AAAA,IACV;AAAA,IACA,OAAO,QAAQ,IAAI,oBAAoB;AAAA,IACvC,KAAK,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AAEA,aAAW,WAAW,aAAa;AAGjC,QAAI,CAAC,QAAQ,KAAM;AACnB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,EAAE,aAAa,QAAQ,aAAa,aAAa,QAAQ,MAAM,MAAM;AAAA,MACrE,OAAO,SAAkB;AACvB,cAAM,SAAS,MAAM,QAAQ,IAAI,KAAK,QAAQ,MAAM,MAAM,IAAI,CAAC;AAC/D,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MACE,OAAO,WAAW,WACd,SACA,KAAK,UAAU,QAAQ,MAAM,CAAC;AAAA,YACtC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAsB,iBAAgC;AACpD,QAAM,kBAAkB,EAAE,QAAQ,IAAI,kCAAqB,CAAC;AAC9D;;;A2FtDA,eAAe,EAAE,MAAM,CAAC,UAAmB;AACzC,UAAQ,OAAO;AAAA,IACb,GAAG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA;AAAA,EAC3D;AACA,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["import_zod","import_zod","link","impact","import_zod","at","at","import_node_child_process","import_node_util","execFileAsync","at","group","rejected","at","cached","import_promises","import_node_path","at","import_node_crypto","import_node_path","import_promises","import_promises","import_node_os","import_node_path","sha256","base","resolve","import_node_path","import_zod","sha256","pack","at","pack","import_node_crypto","matches","at","at","at","pack","matches","cached","index","at","tokens","span","conceptId","approxTokens","table","bundlePath","import_node_path","import_promises","import_node_os","import_node_path","import_node_path","import_zod","bundlePath","bundlePath","bundlePath","at","entry","import_node_path","bundlePath","import_zod","value","at","base","matches","import_zod","import_zod","import_zod","unchecked","missing","import_zod","import_promises","HEADING","superseded","base","import_zod","import_node_child_process","import_node_util","execFileAsync","git","shown","at","import_promises","at","size","at","table","row","col","base","link","conceptId","link","at","count","import_zod","impact","expiring","unverified","drifted","render","width","group","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","render","at","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","index","import_promises","import_zod","bundlePath","conceptId","import_zod","import_zod","import_zod","import_zod","at","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_promises","import_node_path","matter","import_node_crypto","sha256","import_promises","import_node_path","bundlePath","readdir","at","index","link","link","bundlePath","conceptId","at","matches","approxTokens","drifted","sha256"]}
1
+ {"version":3,"sources":["../../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.26_supports-color@8.1.1_typescript@6.0.3_yaml@2.9.0/node_modules/tsup/assets/cjs_shims.js","../src/mcp.ts","../src/decision-record.ts","../src/compose.ts","../src/kb-record.schema.ts","../src/record-types.ts","../src/commands/anchor-resolve.ts","../src/concurrency.ts","../src/remote-repo/cache.ts","../src/anchor-resolver/repo-identity.ts","../src/remote-repo/model.ts","../src/remote-repo/read.ts","../src/remote-repo/git.ts","../src/anchor-resolver/model.ts","../src/remote-repo/validate.ts","../src/anchor-resolver/read.ts","../src/anchor-resolver/resolver.ts","../src/tree-sitter-resolver/languages.ts","../src/grammars/index.ts","../src/grammars/store.ts","../src/grammars/fetch.ts","../src/grammars/manifest.ts","../src/grammars/model.ts","../src/tree-sitter-resolver/resolver.ts","../src/tree-sitter-resolver/definitions.ts","../src/tree-sitter-resolver/tokens.ts","../src/anchor-resolver/drift.ts","../src/errors.ts","../src/kb-errors.ts","../src/kb-pins/budgets.ts","../src/kb-pins/errors.ts","../src/kb-pins/frozen.ts","../src/kb-pins/layers.ts","../src/kb-pins/model.ts","../src/kb-pins/list.ts","../src/kb-pins/pin.ts","../src/kb-pins/unpin.ts","../src/commands/model.ts","../src/commands/answer.ts","../src/commands/backlinks.ts","../src/commands/catalog.ts","../src/adjudicate.ts","../src/kb-tags.ts","../src/catalog.ts","../src/commands/context.ts","../src/kb-context.ts","../src/kb-index.ts","../src/commands/doctor.ts","../src/drift/git.ts","../src/drift/moved.ts","../src/drift/classify.ts","../src/drift/diff.ts","../src/drift/packet.ts","../src/kb-edges.ts","../src/validate.ts","../src/doctor.ts","../src/commands/reassess.ts","../src/commands/impact.ts","../src/commands/list.ts","../src/commands/load.ts","../src/commands/log.ts","../src/commands/no-decision.ts","../src/commands/pack.ts","../src/commands/pin.ts","../src/commands/pins.ts","../src/commands/query.ts","../src/commands/read-index.ts","../src/commands/schema.ts","../src/json-schema.ts","../src/kb-log.ts","../src/commands/stamp.ts","../src/commands/status.ts","../src/commands/supersede.ts","../src/commands/sync-instructions.ts","../src/commands/trace.ts","../src/trace.ts","../src/commands/types.ts","../src/commands/unpin.ts","../src/commands/validate.ts","../src/commands/verify.ts","../src/commands/write.ts","../src/commands/write-decision.ts","../src/commands/index.ts","../src/kb-store.ts","../src/markdown.ts","../src/kb-stamp.ts","../src/search-index.ts","../src/pack.ts","../src/kb-links/inbound.ts","../src/kb-links/backlinks.ts","../src/kb-links/impact.ts","../src/kb-gitattributes.ts","../src/version.ts","../src/mcp-main.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { KB_COMMANDS } from \"./commands/index.js\";\nimport { KbStore } from \"./kb-store.js\";\nimport { VERSION } from \"./version.js\";\n\n/**\n * A knowledge base's own MCP server, over stdio.\n *\n * Standalone because a base is self-contained: a directory of markdown that\n * needs no database, no HTTP surface, and no running service to read. Folding\n * these tools into a larger server would make every consumer start that server\n * to open files it could open itself.\n *\n * Every tool is a projection of `KB_COMMANDS`, which the CLI also projects, so\n * the two cannot drift.\n */\nexport function createKbMcpServer(): McpServer {\n const server = new McpServer({ name: \"strauss-kb\", version: VERSION });\n const store = new KbStore({\n warn: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n });\n const ctx = {\n store,\n actor: process.env.STRAUSS_KB_ACTOR ?? \"mcp\",\n now: () => new Date().toISOString(),\n };\n\n for (const command of KB_COMMANDS) {\n // CLI-only plumbing (sync-instructions) edits files for hooks and\n // instruction blocks; the agent capability it serves is kb_context.\n if (!command.tool) continue;\n server.registerTool(\n command.tool,\n { description: command.description, inputSchema: command.input.shape },\n async (args: unknown) => {\n const result = await command.run(ctx, command.input.parse(args));\n return {\n content: [\n {\n type: \"text\" as const,\n text:\n typeof result === \"string\"\n ? result\n : JSON.stringify(result, null, 2),\n },\n ],\n };\n },\n );\n }\n\n return server;\n}\n\nexport async function runKbMcpServer(): Promise<void> {\n await createKbMcpServer().connect(new StdioServerTransport());\n}\n","import { z } from \"zod\";\nimport {\n composeInputSchema,\n composeRecord,\n type ComposedRecord,\n} from \"./compose.js\";\nimport type { KbRecord } from \"./kb-record.schema.js\";\n\n/**\n * The record written while a change is being made: why it is shaped the way it\n * is, anchored to the symbols it touches.\n *\n * A decision is the one thing a later pass cannot recover. The diff shows what\n * changed; nothing in it says which alternative was rejected, or which\n * constraint a future reader would otherwise \"simplify\" away. Everything else a\n * review needs — categories, moves, formatting — is derivable from the finished\n * diff and does not belong here.\n */\nexport const DECISION_TYPE = \"decision\";\n\n/**\n * Slug for the explicit \"nothing to record here\" answer.\n *\n * Gating on \"did you write a decision?\" rewards writing a junk decision. Gating\n * on \"did you answer?\" does not, so silence has to be expressible as a claim:\n * one record, one sentence, auditable after the fact. Work that genuinely\n * needed no decision says so; work that says nothing at all is the case worth\n * surfacing.\n */\nexport const NO_DECISION_SLUG = \"none\";\n\n/**\n * Decisions keep a typed input of their own where the generic composer takes a\n * section map. `alternative` is not a nicety here — \"what was rejected\" is the\n * part of a decision that a later reader cannot reconstruct, so it gets a field\n * rather than a heading a writer may forget to fill.\n */\nexport const decisionInputSchema = composeInputSchema\n .omit({ sections: true })\n .extend({\n alternative: z.string().min(1).optional(),\n impact: z.string().min(1).optional(),\n })\n .strict();\n\nexport type DecisionInput = z.infer<typeof decisionInputSchema>;\n\nexport function composeDecisionRecord(\n input: DecisionInput,\n writtenBy: string,\n writtenAt: string,\n): ComposedRecord {\n const { alternative, impact, ...rest } = input;\n return composeRecord(\n DECISION_TYPE,\n {\n ...rest,\n sections: {\n Decision: input.title,\n Rationale: input.why,\n ...(alternative ? { Rejected: alternative } : {}),\n ...(impact ? { Impact: impact } : {}),\n },\n },\n writtenBy,\n writtenAt,\n );\n}\n\n/** The explicit no-decision claim, so an absence and an answer stay distinct. */\nexport function composeNoDecisionRecord(\n reason: string,\n writtenBy: string,\n writtenAt: string,\n): ComposedRecord {\n return composeRecord(\n DECISION_TYPE,\n {\n slug: NO_DECISION_SLUG,\n title: \"No decision to record\",\n why: reason,\n sections: { Decision: reason },\n },\n writtenBy,\n writtenAt,\n );\n}\n\n/** Whether a record is the explicit no-decision claim rather than a decision. */\nexport function isNoDecisionRecord(record: KbRecord): boolean {\n return record.conceptId === `${DECISION_TYPE}.${NO_DECISION_SLUG}`;\n}\n\n/**\n * Decisions in the bundle, excluding the no-decision claim.\n *\n * Callers asking \"what was decided\" must not be handed the record that exists\n * precisely to say nothing was.\n */\nexport function selectDecisions(records: KbRecord[]): KbRecord[] {\n return records.filter(\n (record) =>\n record.conceptId.startsWith(`${DECISION_TYPE}.`) &&\n !isNoDecisionRecord(record),\n );\n}\n","import { z } from \"zod\";\nimport {\n kbAnchorSchema,\n kbConceptIdSchema,\n kbSourceSchema,\n KB_CONFIDENCES,\n KB_MATERIALITIES,\n type KbRecordFrontmatter,\n type KbRecordType,\n} from \"./kb-record.schema.js\";\nimport { KB_LINK_RELS, LINK_RELS, RECORD_TYPES } from \"./record-types.js\";\n\n/**\n * One typed causal edge, as a producer states it.\n *\n * Strict where `kbLinkSchema` is tolerant, the same split\n * `kbVerifiedEventSchema` makes against `kbActorStampSchema`: what this package\n * writes must be inside the closed vocabulary, what it reads may not be, since\n * a foreign record has to stay loadable for `kb_validate` to fault it.\n */\nexport const composeLinkSchema = z\n .object({\n target: kbConceptIdSchema,\n rel: z.enum(KB_LINK_RELS),\n })\n .strict();\n\nexport type ComposeLink = z.infer<typeof composeLinkSchema>;\n\nexport const composeInputSchema = z\n .object({\n slug: z.string().min(1),\n /** One line, in the reader's terms. Becomes OKF `title`. */\n title: z.string().min(1),\n /** The consequence — what breaks if this is wrong. Becomes `description`. */\n why: z.string().min(1),\n /** Keyed by section heading from the type's spec. Unknown keys rejected. */\n sections: z.record(z.string(), z.string().min(1)).optional(),\n anchors: z.array(kbAnchorSchema).optional(),\n sources: z.array(kbSourceSchema).optional(),\n /** No source exists, as a claim rather than a sentinel in `sources`. */\n assumption: z.boolean().optional(),\n /**\n * OKF `stale_after`: the absolute date this record stops being trusted.\n * Anything the outside world can change — pricing, quotas, versions,\n * reception counts — should carry one.\n */\n stale_after: z\n .string()\n .regex(/^\\d{4}-\\d{2}-\\d{2}$/, {\n message: \"stale_after must be YYYY-MM-DD\",\n })\n .refine((date) => !Number.isNaN(Date.parse(date)), {\n message: \"stale_after must be a real date\",\n })\n .optional(),\n verify: z.array(z.string().min(1)).optional(),\n tags: z.array(z.string().min(1)).optional(),\n /** Concept ids this record relates to; rendered as body links. */\n relatedConceptIds: z.array(kbConceptIdSchema).optional(),\n /**\n * Typed causal edges, source → target: `{ target: \"fact.b\", rel:\n * \"depends_on\" }` on record A says A needs B. Stored in frontmatter and\n * also rendered as one prose sentence each, so the meaning survives a\n * reader that knows only OKF. The vocabulary goes into the description from\n * the same table the walk uses, so `kb_schema` emits it.\n */\n links: z\n .array(composeLinkSchema)\n .max(64)\n .optional()\n .describe(\n `Typed causal edges, source → target — a link on this record says this record <rel> the target. ${KB_LINK_RELS.map(\n (rel) => `${rel}: ${LINK_RELS[rel].purpose}`,\n ).join(\"; \")}.`,\n ),\n /** Concept ids this record replaces. The store settles the backlinks. */\n supersedes: z.array(kbConceptIdSchema).max(32).optional(),\n materiality: z.enum(KB_MATERIALITIES).optional(),\n confidence: z.enum(KB_CONFIDENCES).optional(),\n owner: z.string().min(1).optional(),\n })\n .strict();\n\nexport type ComposeInput = z.infer<typeof composeInputSchema>;\n\nexport type ComposedRecord = {\n type: string;\n slug: string;\n frontmatter: Omit<KbRecordFrontmatter, \"type\">;\n body: string;\n};\n\n/**\n * Builds one record's frontmatter and body from its type's spec.\n *\n * Edges go in the body rather than frontmatter because that is where OKF puts\n * them: consumers read markdown links as directed but untyped relationships,\n * with \"the specific kind conveyed by the surrounding prose, not by the link\n * itself\". Broken links are explicitly legal, which matters here — records are\n * routinely written before the ones they point at exist.\n */\nexport function composeRecord(\n type: KbRecordType,\n input: ComposeInput,\n writtenBy: string,\n writtenAt: string,\n): ComposedRecord {\n // Parsed here rather than trusted from the caller: the CLI validates its own\n // stdin, but a library caller has no such gate, and `relatedConceptIds` is\n // interpolated into a markdown link unescaped a few lines down.\n const parsed = composeInputSchema.parse(input);\n const spec = RECORD_TYPES[type];\n const sections = parsed.sections ?? {};\n\n const unknown = Object.keys(sections).filter(\n (heading) => !spec.sections.includes(heading),\n );\n if (unknown.length) {\n throw new Error(\n `kb: ${type} has no section ${unknown.join(\", \")} — expected one of ${spec.sections.join(\", \")}`,\n );\n }\n\n const frontmatter: Omit<KbRecordFrontmatter, \"type\"> = {\n title: parsed.title,\n description: parsed.why,\n generated: { by: writtenBy, at: writtenAt },\n // Empty rather than absent: a later verification pass appends here, and an\n // empty list says \"not yet verified\" where a missing key would only say\n // \"this producer didn't think about it\".\n verified: [],\n strauss_status: spec.initialStatus,\n };\n if (parsed.stale_after) frontmatter.stale_after = parsed.stale_after;\n if (parsed.anchors?.length) frontmatter.strauss_anchors = parsed.anchors;\n if (parsed.verify?.length) frontmatter.strauss_verify = parsed.verify;\n if (parsed.tags?.length) frontmatter.tags = parsed.tags;\n if (parsed.sources?.length) frontmatter.sources = parsed.sources;\n if (parsed.assumption) frontmatter.strauss_assumption = true;\n if (parsed.materiality) frontmatter.strauss_materiality = parsed.materiality;\n if (parsed.confidence) frontmatter.strauss_confidence = parsed.confidence;\n if (parsed.owner) frontmatter.strauss_owner = parsed.owner;\n if (parsed.supersedes?.length)\n frontmatter.strauss_supersedes = parsed.supersedes;\n // Refused on the write path, where the caller can still fix it: a self-link\n // asserts a record depends on itself, which every walk skips. `kb_validate`\n // keeps it a warning, since by then the choice is between reporting it and\n // refusing to load the file.\n const selfLink = parsed.links?.find(\n (link) => link.target === `${type}.${parsed.slug}`,\n );\n if (selfLink) {\n throw new Error(\n `kb: ${type}.${parsed.slug} cannot ${selfLink.rel} itself — a link must name another record`,\n );\n }\n if (parsed.links?.length) frontmatter.strauss_links = parsed.links;\n\n const blocks: string[] = [];\n for (const heading of spec.sections) {\n const text = sections[heading];\n // Omitted rather than stubbed: an empty \"## Evidence\" reads as evidence\n // that was sought and not found.\n if (text) blocks.push(`## ${heading}\\n\\n${text}`);\n }\n if (!blocks.length) blocks.push(parsed.why);\n\n for (const related of parsed.relatedConceptIds ?? []) {\n blocks.push(`Relates to [${related}](${related}.md).`);\n }\n\n // One sentence per typed link, from a fixed template per rel. A walk reads\n // the edge from frontmatter, but a plain-OKF consumer ignores frontmatter it\n // does not recognise, so the claim is also stated as prose around a markdown\n // link — OKF's own spelling for a typed relationship. Fixed rather than free\n // text so the sentence cannot say something the rel does not.\n for (const link of parsed.links ?? []) {\n blocks.push(\n `${LINK_RELS[link.rel].phrase} [${link.target}](${link.target}.md).`,\n );\n }\n\n if (parsed.sources?.length) {\n blocks.push(\n parsed.sources\n .map((source) => `[^${source.id}]: ${source.title ?? source.resource}`)\n .join(\"\\n\"),\n );\n }\n\n return {\n type,\n slug: parsed.slug,\n frontmatter,\n body: `${blocks.join(\"\\n\\n\")}\\n`,\n };\n}\n","import { z } from \"zod\";\n\n/**\n * Knowledge records, shaped as OKF v0.2 concepts.\n *\n * OKF (Google Cloud `knowledge-catalog`) requires exactly one key — `type` —\n * and explicitly permits extension: \"Producers MAY include any additional keys.\n * Consumers SHOULD preserve unknown keys when round-tripping and MUST NOT\n * reject documents with unrecognized fields.\"\n *\n * A record's identity is its `concept_id`: the file path within the bundle with\n * `.md` removed. `<type>.<slug>.md` therefore yields `decision.some-slug`.\n *\n * Keys prefixed `strauss_` are this package's extensions rather than\n * conformance, and are namespaced so a later OKF version defining the same\n * names cannot collide: OKF names files through path-valued `resource` fields\n * and has no notion of a span, so anchoring a concept to a range of code has no\n * standard spelling, and standing has none either.\n */\n\n/** A source the record draws on. Footnotes in the body key to `id`. */\nexport const kbSourceSchema = z\n .object({\n id: z.string().min(1),\n resource: z.string().min(1),\n title: z.string().min(1).optional(),\n author: z.string().min(1).optional(),\n last_modified: z.string().min(1).optional(),\n })\n .passthrough();\n\n/** An actor/time pair — OKF's shape for both `generated` and `verified[]`. */\nexport const kbActorStampSchema = z\n .object({\n by: z.string().min(1),\n at: z.string().min(1),\n })\n .passthrough();\n\n/**\n * A `verified[]` event as this package writes one: the actor stamp plus a\n * required note saying what the check found. Write-side only — the frontmatter\n * keeps reading `verified` with `kbActorStampSchema`, because OKF-native\n * entries carry no note and a consumer must not reject conformant records.\n */\nexport const kbVerifiedEventSchema = kbActorStampSchema.extend({\n note: z.string().refine((s) => s.trim().length > 0, {\n message: \"note must say what the check found\",\n }),\n});\n\n/**\n * Where a record attaches in the code.\n *\n * Symbolic on purpose. These are written while the code is still moving: a\n * `line: 379` recorded at minute five is wrong by minute forty, but\n * `OrderService.cancel` survives every edit that does not rename it. Once the\n * change settles, a resolution pass (`anchor-resolver/`) stamps `hash`,\n * `resolved_at`, and `lines`; drift detection later re-resolves and compares.\n *\n * `hash` is prefixed with the algorithm so a future one can coexist with\n * stored values. `lines` exists because the anchor keeps a hash, not the text:\n * without the line count at hash time, a drift report could say \"changed\" but\n * never how much.\n *\n * `repo` and `ref` say *which* code, for bases that describe more than one\n * repository. They are author-owned identity: a resolver stamps `hash`,\n * `lines`, and `resolved_at`, and never writes these two. Both are optional and\n * independent of each other, so every anchor written before they existed stays\n * valid.\n */\nexport const kbAnchorSchema = z\n .object({\n file: z.string().min(1),\n symbol: z.string().min(1).optional(),\n /**\n * Which repository the file lives in — a remote URL\n * (`https://github.com/org/name`) or a short name. Absent means the base's\n * own repository, which is what nearly every anchor means.\n *\n * Unvalidated beyond not-blank: one repository has many spellings, matched\n * after normalisation. Only a full URL can be fetched from, so `validate`\n * warns on a short one; see ARCHITECTURE.\n */\n repo: z.string().trim().min(1).optional(),\n /**\n * The git rev the evidence was taken at. Prefer a commit SHA: a branch\n * name is a moving pointer, so an anchor pinned to one says the evidence\n * came from wherever that branch happens to be now, which is not a\n * baseline. A foreign anchor is checked at this rev, and compared against\n * the remote's default branch on top of it.\n */\n ref: z.string().trim().min(1).optional(),\n hash: z\n .string()\n .regex(/^sha256:[0-9a-f]{64}$/, {\n message: \"hash must be sha256:<64 hex chars>\",\n })\n .optional(),\n /**\n * What `hash` was taken over: the span's raw text, or the normalised token\n * stream a parser sees (`ast`). Absent means `raw`, which is what every\n * anchor stamped before this field carries, so old hashes keep comparing\n * the way they were written. An `ast` hash is blind to whitespace and\n * comments, so reformatting the anchored code is not drift.\n */\n hash_kind: z.enum([\"raw\", \"ast\"]).optional(),\n /** ISO 8601 timestamp of the last successful resolution. */\n resolved_at: z.string().min(1).optional(),\n /** Line count of the text the hash was taken over. */\n lines: z.number().int().positive().optional(),\n /**\n * Which resolver produced the hashed span. Absent means an anchor stamped\n * before resolvers were named, which is read as `regex` — the only one\n * there was. A hash from a different resolver is drift, not a match.\n */\n resolver: z.enum([\"tree-sitter\", \"regex\"]).optional(),\n })\n .strict();\n\n/**\n * One typed causal edge, as the frontmatter stores it.\n *\n * Read-side, and therefore tolerant: `rel` is a plain string here even though\n * the vocabulary is closed, for the same reason `type` is. Rejecting an unknown\n * rel at parse time would make the file vanish from `list()`, and a bundle\n * cannot report a defect in a record it refuses to load. `kb_validate` turns an\n * unknown rel into an error; `composeRecord` stops one being written.\n *\n * `target` is likewise not required to resolve — a dangling target is a\n * validation warning rather than a parse failure.\n */\nexport const kbLinkSchema = z\n .object({\n target: z.string().min(1),\n rel: z.string().min(1),\n })\n .passthrough();\n\nexport const KB_RECORD_TYPES = [\n \"fact\",\n \"requirement\",\n \"constraint\",\n \"decision\",\n \"assumption\",\n \"open-question\",\n \"risk\",\n \"contract\",\n \"flow\",\n \"affected-system\",\n \"test-obligation\",\n \"source-note\",\n] as const;\n\nexport type KbRecordType = (typeof KB_RECORD_TYPES)[number];\n\n/** Both halves of `<type>.<slug>` are kebab-case, and neither may be empty. */\nexport const KB_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;\nexport const KB_CONCEPT_ID_PATTERN =\n /^[a-z0-9]+(?:-[a-z0-9]+)*\\.[a-z0-9]+(?:-[a-z0-9]+)*$/;\n\n/**\n * Concept ids are rendered into markdown links unescaped, so an id carrying a\n * `]` or `)` would emit a broken edge rather than fail. Validating at the entry\n * point keeps the renderer from having to care.\n */\nexport const kbConceptIdSchema = z.string().regex(KB_CONCEPT_ID_PATTERN, {\n message: \"concept id must be <type>.<slug>, both kebab-case\",\n});\n\n/**\n * Standing, not freshness.\n *\n * OKF's `verified[]` and `stale_after` answer \"is this still true?\"; nothing in\n * the spec answers \"is this settled, and does it still apply?\". A base\n * supersedes its own conclusions as work proceeds, so that second question\n * needs an answer, and it is this package's to define — hence `strauss_`.\n */\nexport const KB_RECORD_STATUSES = [\n \"draft\",\n \"proposed\",\n \"accepted\",\n \"open\",\n \"resolved\",\n \"rejected\",\n \"superseded\",\n] as const;\n\nexport type KbRecordStatus = (typeof KB_RECORD_STATUSES)[number];\n\nexport const KB_MATERIALITIES = [\n \"blocking\",\n \"important\",\n \"non-blocking\",\n] as const;\nexport const KB_CONFIDENCES = [\"low\", \"medium\", \"high\"] as const;\n\nexport const kbRecordFrontmatterSchema = z\n .object({\n // OKF: the only always-required key. A concept carrying just `type` is\n // fully conformant, so everything below stays optional.\n type: z.string().min(1),\n\n // OKF recommended.\n title: z.string().min(1).optional(),\n description: z.string().min(1).optional(),\n resource: z.string().min(1).optional(),\n tags: z.array(z.string()).optional(),\n\n // OKF optional: provenance and freshness.\n sources: z.array(kbSourceSchema).optional(),\n generated: kbActorStampSchema.optional(),\n verified: z.array(kbActorStampSchema).optional(),\n stale_after: z.string().min(1).optional(),\n\n // strauss extensions — see the module comment.\n strauss_anchors: z.array(kbAnchorSchema).optional(),\n strauss_verify: z.array(z.string().min(1)).optional(),\n\n // Typed causal edges, source → target, living on the source. `A depends_on\n // B` means A needs B, so `kb_impact` walks these inbound: what breaks if B\n // changes is whatever declared a dependence on it.\n strauss_links: z.array(kbLinkSchema).optional(),\n\n // Total after parsing, tolerant before it. Our producers must supply a\n // status — an absent one would leave every reader inventing its own default\n // — but OKF calls a concept carrying only `type` fully conformant, so\n // rejecting a foreign record for the lack of one would put us outside the\n // spec. The default resolves it in the single place that can: here.\n strauss_status: z.enum(KB_RECORD_STATUSES).default(\"draft\"),\n strauss_supersedes: z.array(z.string().min(1)).optional(),\n strauss_superseded_by: z.string().min(1).optional(),\n strauss_answered: kbActorStampSchema.optional(),\n strauss_materiality: z.enum(KB_MATERIALITIES).optional(),\n strauss_confidence: z.enum(KB_CONFIDENCES).optional(),\n strauss_owner: z.string().min(1).optional(),\n\n // \"No source exists\" as a field rather than a sentinel entry inside\n // `sources`. A sentinel in a reference list is a value doing work a field\n // should do; as a field, `sources` may be legitimately empty.\n strauss_assumption: z.boolean().optional(),\n })\n // Unknown keys are kept rather than stripped: OKF requires consumers to\n // preserve them when round-tripping, and a producer we don't know about may\n // be writing into the same bundle.\n .passthrough();\n\nexport type KbSource = z.infer<typeof kbSourceSchema>;\nexport type KbActorStamp = z.infer<typeof kbActorStampSchema>;\nexport type KbVerifiedEvent = z.infer<typeof kbVerifiedEventSchema>;\nexport type KbAnchor = z.infer<typeof kbAnchorSchema>;\nexport type KbLink = z.infer<typeof kbLinkSchema>;\nexport type KbRecordFrontmatter = z.infer<typeof kbRecordFrontmatterSchema>;\n\nexport type KbRecord = {\n /** Path minus `.md`, relative to the bundle root. OKF's concept identity. */\n conceptId: string;\n frontmatter: KbRecordFrontmatter;\n body: string;\n};\n","import type { KbRecordStatus, KbRecordType } from \"./kb-record.schema.js\";\n\n/**\n * What each record type is for, and the shape of its body.\n *\n * A table rather than twelve composer modules. The types differ only in which\n * questions their body answers and where they start in the lifecycle; encoding\n * that as data keeps the one composer honest and makes adding a type an edit\n * rather than a file.\n *\n * `sections` are ordered. A section the caller leaves empty is omitted rather\n * than rendered with a placeholder — an empty \"## Evidence\" reads as evidence\n * that was looked for and not found.\n */\nexport type KbRecordTypeSpec = {\n /** One line, for `INDEX.md` legends and CLI help. */\n purpose: string;\n /** Ordered body headings. The first is the record's central claim. */\n sections: readonly string[];\n /** Where a freshly written record of this type starts. */\n initialStatus: KbRecordStatus;\n};\n\nexport const RECORD_TYPES: Readonly<Record<KbRecordType, KbRecordTypeSpec>> = {\n fact: {\n purpose: \"Observed or sourced fact\",\n sections: [\"Claim\", \"Evidence\", \"Implication\"],\n initialStatus: \"accepted\",\n },\n requirement: {\n purpose: \"Required behavior or outcome\",\n sections: [\"Claim\", \"Evidence\", \"Implication\"],\n initialStatus: \"proposed\",\n },\n constraint: {\n purpose: \"Limitation, compatibility boundary, policy, or restriction\",\n sections: [\"Claim\", \"Evidence\", \"Implication\"],\n initialStatus: \"accepted\",\n },\n decision: {\n purpose: \"Chosen or proposed direction\",\n sections: [\"Decision\", \"Rationale\", \"Rejected\", \"Impact\"],\n initialStatus: \"accepted\",\n },\n assumption: {\n purpose: \"Unsourced or not-yet-confirmed working assumption\",\n sections: [\"Claim\", \"Why we think so\", \"What would falsify it\"],\n initialStatus: \"draft\",\n },\n \"open-question\": {\n purpose: \"Question needing resolution\",\n sections: [\"Question\", \"Why it matters\", \"Default assumption\"],\n initialStatus: \"open\",\n },\n risk: {\n purpose: \"Something that can go wrong\",\n sections: [\"Risk\", \"Why it matters\", \"Mitigation\", \"Verification\"],\n initialStatus: \"open\",\n },\n contract: {\n purpose: \"API, data, event, schema, or permission contract\",\n sections: [\"Contract\", \"Producer\", \"Consumer\", \"Compatibility\"],\n initialStatus: \"proposed\",\n },\n flow: {\n purpose: \"Sequence, lifecycle, or state behavior\",\n sections: [\"Flow\", \"Trigger\", \"Steps\", \"Failure modes\"],\n initialStatus: \"accepted\",\n },\n \"affected-system\": {\n purpose: \"Component, service, package, integration, or external system\",\n sections: [\"System\", \"How it is affected\", \"Blast radius\"],\n initialStatus: \"accepted\",\n },\n \"test-obligation\": {\n purpose: \"Behavior or contract that must be verified\",\n sections: [\"Obligation\", \"Why it matters\", \"How to verify\"],\n initialStatus: \"open\",\n },\n \"source-note\": {\n purpose: \"Extracted note from source material\",\n sections: [\"Note\", \"Where it came from\"],\n initialStatus: \"accepted\",\n },\n};\n\nexport function isKbRecordType(value: string): value is KbRecordType {\n return Object.prototype.hasOwnProperty.call(RECORD_TYPES, value);\n}\n\n/**\n * The closed vocabulary of typed causal edges — `strauss_links[].rel` — which a\n * producer may not extend. `related_to` is the non-dependence escape hatch and\n * the one rel `kb_impact` does not follow. Every edge lives on the source's\n * frontmatter, source → target; `phrase` is the template compose.ts renders.\n */\nexport type KbLinkRelSpec = {\n /** One line, for schema output and CLI help. */\n purpose: string;\n /** Sentence stem: `<phrase> [target](target.md).` */\n phrase: string;\n /**\n * Which end of the edge breaks when the other end changes.\n *\n * The rel's *direction of dependence*, which does not follow the edge's own\n * direction. `A depends_on B` puts the dependant at the source: A breaks when\n * B moves. `A informs B` puts it at the target. A walk that treated both as\n * \"inbound\" would report the blast radius of `informs`, `blocks`,\n * `invalidates` and `constrains` backwards.\n *\n * `null` means the rel asserts no dependence either way, so nothing\n * propagates along it. `related_to` is the only such rel.\n */\n dependant: \"source\" | \"target\" | null;\n};\n\nexport const KB_LINK_RELS = [\n \"depends_on\",\n \"constrains\",\n \"informs\",\n \"blocks\",\n \"invalidates\",\n \"verified_by\",\n \"satisfies\",\n \"related_to\",\n] as const;\n\nexport type KbLinkRel = (typeof KB_LINK_RELS)[number];\n\nexport const LINK_RELS: Readonly<Record<KbLinkRel, KbLinkRelSpec>> = {\n depends_on: {\n purpose:\n \"The source needs the target to hold; the source breaks if the target changes\",\n phrase: \"Depends on\",\n dependant: \"source\",\n },\n constrains: {\n purpose:\n \"The source bounds what the target may do; the target breaks if the constraint changes\",\n phrase: \"Constrains\",\n dependant: \"target\",\n },\n informs: {\n purpose:\n \"The source shaped the target without binding it; the target is what needs revisiting\",\n phrase: \"Informs\",\n dependant: \"target\",\n },\n blocks: {\n purpose:\n \"The target cannot proceed until the source is settled; the target is what waits\",\n phrase: \"Blocks\",\n dependant: \"target\",\n },\n invalidates: {\n purpose:\n \"The source makes the target no longer hold; the target is what stops holding\",\n phrase: \"Invalidates\",\n dependant: \"target\",\n },\n verified_by: {\n purpose:\n \"The target is the check that confirms the source; the source's confirmation moves with it\",\n phrase: \"Verified by\",\n dependant: \"source\",\n },\n satisfies: {\n purpose:\n \"The source discharges the target's requirement; the source must change if the requirement does\",\n phrase: \"Satisfies\",\n dependant: \"source\",\n },\n related_to: {\n purpose: \"A pointer worth following, with no claim of dependence\",\n phrase: \"Relates to\",\n dependant: null,\n },\n};\n\n/**\n * The rels that carry a direction of dependence, and therefore the only ones\n * anything can propagate along. `kb_impact`'s default edge set, and what\n * `trace` follows.\n *\n * Derived from the table rather than restated, so a rel cannot be causal in one\n * place and inert in another. The cast is a non-emptiness assertion for\n * `z.enum`.\n */\nexport const KB_CAUSAL_LINK_RELS = KB_LINK_RELS.filter(\n (rel) => LINK_RELS[rel].dependant !== null,\n) as [KbLinkRel, ...KbLinkRel[]];\n\nexport function isKbLinkRel(value: string): value is KbLinkRel {\n return Object.prototype.hasOwnProperty.call(LINK_RELS, value);\n}\n","import { z } from \"zod\";\nimport {\n anchorFileReader,\n anchorHashOf,\n defaultAnchorResolvers,\n hashAnchorText,\n LazyOrigin,\n normalizeRepoUrl,\n prepareResolvers,\n readAnchorFiles,\n remoteWants,\n resolveAnchorSpan,\n resolverChanged,\n type AnchorDriftReason,\n type AnchorHashKind,\n type AnchorRead,\n type AnchorResolver,\n type AnchorResolverName,\n type AnchorUnresolvedReason,\n type RemoteAnchorState,\n} from \"../anchor-resolver/index.js\";\nimport { grammarHints } from \"../grammars/index.js\";\nimport {\n KbRecordNotFoundError,\n KbSelfVerificationError,\n} from \"../kb-errors.js\";\nimport { assertBaseNotFrozen, KbBaseFrozenError } from \"../kb-pins/index.js\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport {\n isUncheckedReason,\n readRemoteAnchors,\n wantKey,\n} from \"../remote-repo/index.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\ntype AnchorResolveResult = {\n file: string;\n symbol?: string;\n state: \"stamped\" | \"match\" | \"drifted\" | \"unresolved\";\n storedHash?: string;\n currentHash?: string;\n /** What the compared hashes were taken over. */\n hashKind?: AnchorHashKind;\n /** `null` when the anchor recorded no `lines` — size unknown, not zero. */\n diffSize?: number | null;\n reason?: AnchorUnresolvedReason | AnchorDriftReason;\n resolver?: AnchorResolverName;\n rebaselined?: boolean;\n /** Set only when the anchor was resolved against another repository. */\n repo?: string;\n remoteState?: RemoteAnchorState;\n};\n\n/** What one anchor was compared against, and what \"current\" is beside it. */\ntype AnchorSource =\n | { ok: true; source: string; repo?: string; head?: string }\n | { ok: false; reason: AnchorUnresolvedReason; repo?: string };\n\n/** Which resolvers produced this run's spans, for the verify note. */\nfunction resolverSummary(results: AnchorResolveResult[]): string {\n const names = [\n ...new Set(\n results.flatMap((entry) => (entry.resolver ? [entry.resolver] : [])),\n ),\n ].sort();\n return names.length ? `${names.join(\" + \")} resolver` : \"whole-file\";\n}\n\nexport const anchorResolveCommand = define({\n name: \"anchor-resolve\",\n tool: \"kb_anchor_resolve\",\n usage:\n \"anchor-resolve <concept-id> [--repo-root <path>] [--offline] [--rebaseline] [--restamp]\",\n description:\n \"Resolve a record's anchors: stamp a hash onto anchors that lack one, report drift where the code moved. An anchor naming another repository is read from that remote through a bare cache; --offline uses the cache only. kb_verify's mechanical counterpart — reach for it when the question is whether the code still is what it was. Exits non-zero on drift.\",\n input: z.object({\n bundlePath,\n conceptId,\n repoRoot: z.string().min(1).optional(),\n offline: z\n .boolean()\n .optional()\n .describe(\n \"Resolve foreign anchors from the local repo cache only, never fetching.\",\n ),\n rebaseline: z\n .boolean()\n .optional()\n .describe(\n \"Accept the current code as the new baseline for anchors that drifted.\",\n ),\n restamp: z\n .boolean()\n .optional()\n .describe(\n \"Refresh `resolved_at` on anchors that already match. Off by default, so a green run writes nothing.\",\n ),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n repoRoot: argvFlag(argv, \"--repo-root\"),\n offline: argv.includes(\"--offline\"),\n rebaseline: argv.includes(\"--rebaseline\"),\n restamp: argv.includes(\"--restamp\"),\n }),\n run: async (\n { store, actor, now },\n { bundlePath: path, conceptId: id, repoRoot, offline, rebaseline, restamp },\n ) => {\n const root = repoRoot ?? process.cwd();\n const record = await store.read(path, id);\n if (!record) throw new KbRecordNotFoundError(id);\n\n const anchors = record.frontmatter.strauss_anchors ?? [];\n if (!anchors.length) {\n return {\n conceptId: id,\n results: [] as AnchorResolveResult[],\n verified: false,\n note: \"record has no anchors\",\n };\n }\n\n const results: AnchorResolveResult[] = [];\n const updated: KbAnchor[] = [];\n let dirty = false;\n\n const sources = await readSources(anchors, root, offline === true);\n const resolvers = defaultAnchorResolvers({ offline: offline === true });\n await prepareResolvers(\n resolvers,\n anchors.map((anchor) => anchor.file),\n );\n\n for (const anchor of anchors) {\n const base: Pick<\n AnchorResolveResult,\n \"file\" | \"symbol\" | \"storedHash\" | \"repo\"\n > = {\n file: anchor.file,\n ...(anchor.symbol ? { symbol: anchor.symbol } : {}),\n // Carried onto unresolved findings too: an anchor that once hashed\n // and now resolves to nothing is a broken anchor, and the exit code\n // has to be able to tell it from one nobody ever stamped.\n ...(anchor.hash ? { storedHash: anchor.hash } : {}),\n };\n const source = sources.get(anchor) as AnchorSource;\n if (source.repo) base.repo = source.repo;\n\n if (!source.ok) {\n results.push({ ...base, state: \"unresolved\", reason: source.reason });\n updated.push(anchor);\n continue;\n }\n\n const outcome = resolveAnchorSpan(source.source, anchor, resolvers);\n if (!outcome.ok) {\n results.push({\n ...base,\n state: \"unresolved\",\n reason: outcome.reason,\n });\n updated.push(anchor);\n continue;\n }\n\n const resolved = outcome.span;\n const producedBy = outcome.resolver;\n const { hash: currentHash, kind } = anchorHashOf(anchor, outcome);\n const currentLines = resolved.endLine - resolved.startLine + 1;\n // A fresh or rebaselined stamp takes the strongest hash the resolver can\n // offer: `hash_kind: \"ast\"` is over the parsed token stream, so\n // reformatting the anchored code stops registering as drift. An anchor\n // already carrying a raw hash keeps comparing raw until it is\n // rebaselined — see `anchorHashOf`.\n const stampedKind = outcome.normalized ? \"ast\" : \"raw\";\n const stampedHash = outcome.normalized\n ? anchorHashOf({ ...anchor, hash: undefined }, outcome).hash\n : currentHash;\n // `resolver` records which resolver the stored hash came from, so a\n // later run can tell a precise span from a heuristic one.\n const stamped: KbAnchor = {\n ...anchor,\n hash: stampedHash,\n hash_kind: stampedKind,\n lines: currentLines,\n resolved_at: now(),\n ...(producedBy ? { resolver: producedBy } : {}),\n };\n const pinned = anchor.ref !== undefined && source.repo !== undefined;\n\n if (!anchor.hash) {\n // The write path for hashes: kb_write callers record symbols, not\n // digests, and this pass fills them in once the code settles.\n results.push({\n ...base,\n state: \"stamped\",\n currentHash: stampedHash,\n hashKind: stampedKind,\n ...(producedBy ? { resolver: producedBy } : {}),\n });\n updated.push(stamped);\n dirty = true;\n continue;\n }\n\n if (anchor.hash !== currentHash) {\n results.push({\n ...base,\n state: \"drifted\",\n currentHash,\n hashKind: kind,\n diffSize: lineDelta(anchor, currentLines),\n ...(producedBy ? { resolver: producedBy } : {}),\n // A regex-stamped anchor re-read by tree-sitter drifts because the\n // resolver changed, not because the code did.\n ...(resolverChanged(source.source, anchor, producedBy)\n ? { reason: \"resolver-changed\" as const }\n : {}),\n ...(pinned ? { remoteState: \"drifted-from-ref\" as const } : {}),\n ...(rebaseline ? { rebaselined: true } : {}),\n });\n updated.push(rebaseline ? stamped : anchor);\n if (rebaseline) dirty = true;\n continue;\n }\n\n // The evidence still holds at the pinned commit and the default branch\n // has moved past it. Never rebaselined: the repair is to move `ref`,\n // which is the author's field, not this command's.\n const onDefault = pinned\n ? headHash(source, anchor, resolvers)\n : undefined;\n if (onDefault && onDefault.hash !== anchor.hash) {\n results.push({\n ...base,\n state: \"drifted\",\n currentHash: onDefault.hash,\n diffSize: lineDelta(anchor, onDefault.lines),\n remoteState: \"drifted-on-default\",\n });\n updated.push(anchor);\n continue;\n }\n\n results.push({\n ...base,\n state: \"match\",\n currentHash,\n hashKind: kind,\n ...(producedBy ? { resolver: producedBy } : {}),\n ...(pinned ? { remoteState: \"matches-ref\" as const } : {}),\n });\n // Nothing changed, so nothing is written: a re-dated record on every\n // green CI run would be a mutation, a log line, and a git diff saying\n // only that a check ran. `resolved_at` is filled in when it is absent\n // (the anchor predates hashing), or on request.\n const refresh = restamp || anchor.resolved_at === undefined;\n updated.push(refresh ? { ...anchor, resolved_at: now() } : anchor);\n if (refresh) dirty = true;\n }\n\n // Frozen bases refuse writes, not reads: pure drift reporting is\n // legitimate on a concluded base, so the report is computed first and the\n // freeze only costs the mutation. Reported rather than thrown — a caller\n // asking a concluded base whether its code moved deserves the answer.\n let frozen = false;\n if (dirty) {\n try {\n await assertBaseNotFrozen(process.cwd(), path);\n } catch (error) {\n if (!(error instanceof KbBaseFrozenError)) throw error;\n frozen = true;\n }\n if (!frozen) await store.updateAnchors(path, id, updated, actor);\n }\n const frozenNote = frozen\n ? { frozen: true, note: \"base is frozen: nothing was stamped\" }\n : {};\n // What to do about a grammar this run could not obtain. Written once, in\n // the grammars module, so doctor and this command say the same thing.\n const hints = grammarHints();\n const hintNote = hints.length ? { hints } : {};\n\n // Evidence only when every checkable anchor already matched: a freshly\n // stamped anchor is a baseline nobody has checked. An anchor nothing could\n // reach stays outside the denominator rather than against it, and also\n // keeps the run from verifying — \"could not look\" is not \"matches\".\n const unreachable = results.filter((entry) =>\n isUncheckedReason(entry.reason),\n ).length;\n const checked = results.length - unreachable;\n const matches = results.filter((entry) => entry.state === \"match\").length;\n const note = `${matches}/${checked} anchors match${\n unreachable ? `, ${unreachable} unreachable` : \"\"\n }`;\n const clean = checked > 0 && matches === checked && unreachable === 0;\n if (clean) {\n try {\n await store.verify(\n path,\n id,\n `anchor-resolve: ${note} (${resolverSummary(results)})`,\n actor,\n now(),\n );\n } catch (error) {\n // A mechanical resolve run by the record's own generator is still a\n // useful drift report; only the verified[] stamp is refused.\n if (!(error instanceof KbSelfVerificationError)) throw error;\n return {\n conceptId: id,\n results,\n verified: false,\n verifyRefused: \"self-verification\",\n ...frozenNote,\n ...hintNote,\n };\n }\n return {\n conceptId: id,\n results,\n verified: true,\n ...frozenNote,\n ...hintNote,\n };\n }\n\n return {\n conceptId: id,\n results,\n verified: false,\n ...(unreachable ? { note } : {}),\n ...frozenNote,\n ...hintNote,\n };\n },\n // A stored hash that no longer resolves is a broken anchor, not an absence:\n // the file was deleted or the symbol renamed, and exiting zero on it would\n // let the one edit that destroys an anchor pass the gate that exists to\n // catch it. An anchor nobody ever stamped is still just unstamped, and one\n // whose remote nothing could reach was never checked — failing CI on either\n // would gate on work this command did not do.\n failsWhen: (result) =>\n (result as { results: AnchorResolveResult[] }).results.some(\n (entry) =>\n entry.state === \"drifted\" ||\n (entry.state === \"unresolved\" &&\n entry.storedHash !== undefined &&\n !isUncheckedReason(entry.reason)),\n ),\n});\n\nfunction lineDelta(anchor: KbAnchor, current: number): number | null {\n return anchor.lines === undefined ? null : Math.abs(current - anchor.lines);\n}\n\n/** The anchor's hash on the remote's default branch, when one was read. */\nfunction headHash(\n source: { head?: string },\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n): { hash: string; lines: number } | undefined {\n if (source.head === undefined) return undefined;\n const outcome = resolveAnchorSpan(source.head, anchor, resolvers);\n if (!outcome.ok) return undefined;\n return {\n hash: hashAnchorText(outcome.span.text),\n lines: outcome.span.endLine - outcome.span.startLine + 1,\n };\n}\n\n/**\n * What each anchor is read from: the working tree for this repository's own\n * anchors, a bare remote cache for every other. Both sets are collected first,\n * so git is spawned once per (repo, rev) and never inside the loop.\n */\nasync function readSources(\n anchors: readonly KbAnchor[],\n root: string,\n offline: boolean,\n): Promise<Map<KbAnchor, AnchorSource>> {\n const origin = new LazyOrigin(root);\n if (anchors.some((anchor) => anchor.repo)) await origin.prime();\n const foreign = new Map(\n anchors.map((anchor) => [anchor, origin.isForeign(anchor)] as const),\n );\n\n const local = anchors.filter((anchor) => !foreign.get(anchor));\n const remote = anchors.filter((anchor) => foreign.get(anchor));\n const reads = await readAnchorFiles(\n local.map((anchor) => anchor.file),\n anchorFileReader(root),\n );\n const blobs = await readRemoteAnchors(remote.flatMap(remoteWants), {\n offline,\n });\n\n const sources = new Map<KbAnchor, AnchorSource>();\n for (const anchor of local) {\n const read = reads.get(anchor.file) as AnchorRead;\n sources.set(\n anchor,\n read.ok\n ? { ok: true, source: read.source }\n : { ok: false, reason: read.reason },\n );\n }\n for (const anchor of remote) {\n const repo = anchor.repo as string;\n const key = normalizeRepoUrl(repo);\n const atDefault = blobs.get(wantKey(key, undefined, anchor.file));\n const primary = anchor.ref\n ? blobs.get(wantKey(key, anchor.ref, anchor.file))\n : atDefault;\n if (!primary?.ok) {\n sources.set(anchor, {\n ok: false,\n reason: primary?.ok === false ? primary.reason : \"remote-unreachable\",\n repo,\n });\n continue;\n }\n sources.set(anchor, {\n ok: true,\n source: primary.source,\n repo,\n ...(anchor.ref && atDefault?.ok ? { head: atDefault.source } : {}),\n });\n }\n return sources;\n}\n","/**\n * Bounded fan-out for the store's I/O paths.\n *\n * Unbounded `Promise.all` over a bundle hits EMFILE on a large base; a serial\n * loop pays full syscall latency per file. One shared pool sits between them.\n */\n\n/** Default in-flight file operations. Bounded so a large base cannot hit EMFILE. */\nexport const DEFAULT_IO_CONCURRENCY = 16;\n\n/**\n * Runs `fn` over `items` with at most `limit` in flight.\n *\n * Results are index-aligned with `items` regardless of completion order. A\n * rejection propagates; a caller wanting per-item isolation catches inside `fn`.\n */\nexport async function mapLimit<T, R>(\n items: readonly T[],\n limit: number,\n fn: (item: T, index: number) => Promise<R>,\n): Promise<R[]> {\n if (!Number.isInteger(limit) || limit < 1) {\n throw new RangeError(\n `mapLimit: \"limit\" must be a positive integer, got ${limit}`,\n );\n }\n const out = new Array<R>(items.length);\n let next = 0;\n let failed = false;\n const runners = Array.from(\n { length: Math.min(limit, items.length) },\n async () => {\n while (!failed && next < items.length) {\n const at = next++;\n try {\n out[at] = await fn(items[at] as T, at);\n } catch (error) {\n failed = true;\n throw error;\n }\n }\n },\n );\n await Promise.all(runners);\n return out;\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { normalizeRepoUrl } from \"../anchor-resolver/repo-identity.js\";\n\n/** Where bare mirrors live. Overridable so a test never writes to `$HOME`. */\nexport function repoCacheDir(override?: string): string {\n return (\n override ??\n process.env[\"STRAUSS_KB_REPO_CACHE\"] ??\n join(homedir(), \".strauss\", \"repo-cache\")\n );\n}\n\n/** Fetch timeout in ms; a remote that hangs must not hang the run. */\nexport const DEFAULT_FETCH_TIMEOUT_MS = 30_000;\n\nexport function fetchTimeoutMs(override?: number): number {\n if (override !== undefined) return override;\n const fromEnv = Number(process.env[\"STRAUSS_KB_FETCH_TIMEOUT_MS\"]);\n return Number.isFinite(fromEnv) && fromEnv > 0\n ? fromEnv\n : DEFAULT_FETCH_TIMEOUT_MS;\n}\n\n/**\n * `<cache>/<host>/<org>/<name>.git` for a repository URL.\n *\n * `null` when the declared `repo` carries no path git could fetch — a short\n * form like `org/name` names a repository without saying where it lives.\n */\nexport function cachePathFor(repo: string, cacheDir: string): string | null {\n const normalized = normalizeRepoUrl(repo);\n const scheme = /^[a-z0-9+.-]+:\\/\\//.exec(normalized);\n if (!scheme) return null;\n const segments = normalized\n .slice(scheme[0].length)\n .split(\"/\")\n .filter(Boolean)\n .map((segment: string) => safeSegment(segment));\n if (segments.length < 2 || segments.some((segment) => segment === null)) {\n return null;\n }\n const path = segments as string[];\n return join(cacheDir, ...path.slice(0, -1), `${path[path.length - 1]}.git`);\n}\n\n/**\n * A path segment a repository URL may contribute to a directory name. A\n * Windows `file:///C:/…` contributes its drive as the first one, and `:` is\n * not legal in a directory name there, so it is folded like any other\n * separator rather than special-cased.\n */\nfunction safeSegment(value: string): string | null {\n return value === \".\" || value === \"..\" || value.includes(\"\\0\")\n ? null\n : value.replace(/[/\\\\:]/g, \"-\");\n}\n\n/**\n * A git ref name holding one fetched rev, stable across runs so a second run\n * reads the cache instead of fetching again.\n */\nexport function revRef(rev: string): string {\n // `.` is dropped rather than kept: `v1..2` would be an invalid ref name.\n const safe = rev.replace(/[^A-Za-z0-9_-]/g, \"-\").slice(0, 64);\n let hash = 5381;\n for (let at = 0; at < rev.length; at++) {\n hash = ((hash * 33) ^ rev.charCodeAt(at)) >>> 0;\n }\n return `refs/strauss/${safe}-${hash.toString(16)}`;\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/* -------------------------------------------------------------------------\n * Which repository is this?\n * ---------------------------------------------------------------------- */\n\n/**\n * Repository identity, normalised on both sides and compared rather than\n * parsed; see ARCHITECTURE.\n *\n * Trailing slashes come off in a loop rather than with `/\\/+$/`, which\n * backtracks quadratically on untrusted bundle data.\n */\nexport function normalizeRepoUrl(value: string): string {\n let url = value.trim().replace(/^git\\+/, \"\");\n // scp-style: git@host:org/name\n const scp = /^[\\w.-]+@([\\w.-]+):(.+)$/.exec(url);\n if (scp) url = `https://${scp[1]}/${scp[2]}`;\n url = url.replace(/^ssh:\\/\\/(?:[^@/]+@)?/, \"https://\");\n // Slashes, then `.git`, then slashes again: a remote is written `…/name`,\n // `…/name.git`, and `…/name.git/` interchangeably, and all three name one\n // repository.\n url = trimTrailingSlashes(url);\n if (url.endsWith(\".git\")) url = url.slice(0, -4);\n return trimTrailingSlashes(url).toLowerCase();\n}\n\nfunction trimTrailingSlashes(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n}\n\n/**\n * Does this spelling say where the repository lives?\n *\n * Only a full URL can be fetched from. A short form still matches this root's\n * own origin, which is why `validate` warns rather than rejects.\n */\nexport function isCanonicalRepoUrl(value: string): boolean {\n return /^[a-z0-9+.-]+:\\/\\//.test(normalizeRepoUrl(value));\n}\n\n/** `org/name` from a normalized URL, or \"\" when it carries no host. */\nfunction repoPath(normalized: string): string {\n const withoutScheme = normalized.replace(/^[a-z0-9+.-]+:\\/\\//, \"\");\n const segments = withoutScheme.split(\"/\").filter(Boolean);\n return segments.length > 1 ? segments.slice(1).join(\"/\") : \"\";\n}\n\n/**\n * Does `declared` name the repository `originUrl` points at?\n *\n * Three spellings are accepted, narrowest first: the whole URL, the `org/name`\n * path, and the bare repository name. The bare name is the loosest and could\n * in principle collide across organisations; it is accepted because it is what\n * people actually write, and the cost of a false positive here is resolving an\n * anchor that was already meant for a repository of that name.\n */\nexport function repoIdentifies(\n declared: string,\n originUrl: string | null,\n): boolean {\n if (!originUrl) return false;\n const origin = normalizeRepoUrl(originUrl);\n const want = normalizeRepoUrl(declared);\n if (!want || !origin) return false;\n if (want === origin) return true;\n\n const path = repoPath(origin);\n if (!path) return false;\n return want === path || want === (path.split(\"/\").pop() ?? \"\");\n}\n\n/**\n * The `origin` remote of the tree at `repoRoot`, or `null`.\n *\n * `null` for anything that is not a git checkout, has no `origin`, or where\n * git is unavailable — all of which mean the same thing here: this root cannot\n * prove which repository it is. An anchor naming a repository is then treated\n * as foreign rather than resolved hopefully, because a hash that matched by\n * coincidence would be recorded as evidence.\n */\nexport async function repoOriginUrl(repoRoot: string): Promise<string | null> {\n try {\n const { stdout } = await execFileAsync(\n \"git\",\n [\"-C\", repoRoot, \"config\", \"--get\", \"remote.origin.url\"],\n { timeout: 5_000 },\n );\n return stdout.trim() || null;\n } catch {\n return null;\n }\n}\n\n/**\n * \"Is this anchor for another repository?\", answered without asking git until\n * an anchor actually declares a `repo`, and only once per run after that.\n */\nexport class LazyOrigin {\n private url: string | null = null;\n private asked = false;\n\n constructor(private readonly repoRoot: string) {}\n\n /** Asks git once, so later `isForeign` calls need no await. */\n async prime(): Promise<void> {\n if (this.asked) return;\n this.url = await repoOriginUrl(this.repoRoot);\n this.asked = true;\n }\n\n /** Only meaningful after `prime`; an unprimed origin identifies nothing. */\n isForeign(anchor: KbAnchor): boolean {\n if (!anchor.repo) return false;\n return !repoIdentifies(anchor.repo, this.url);\n }\n\n async foreign(anchor: KbAnchor): Promise<boolean> {\n if (!anchor.repo) return false;\n await this.prime();\n return this.isForeign(anchor);\n }\n}\n","import type {\n AnchorDriftReason,\n AnchorUnresolvedReason,\n} from \"../anchor-resolver/model.js\";\n\n/**\n * A foreign anchor's file at one rev. `ref` absent means the remote's default\n * branch — the \"current\" side of a ref-pinned comparison.\n */\nexport type RemoteWant = { repo: string; ref?: string; file: string };\n\nexport type RemoteRead =\n { ok: true; source: string } | { ok: false; reason: AnchorUnresolvedReason };\n\nexport type RemoteOptions = {\n /** Cache only: no `fetch`, no `ls-remote`. */\n offline?: boolean;\n cacheDir?: string;\n fetchTimeoutMs?: number;\n /** Repositories worked on at once; fetches within one repo stay serial. */\n concurrency?: number;\n};\n\n/** Reasons that mean \"not checked\", as opposed to evidence that moved. */\nexport const UNCHECKED_REASONS: readonly AnchorUnresolvedReason[] = [\n \"remote-unreachable\",\n \"repo-unauthorized\",\n \"default-branch-unknown\",\n];\n\nexport function isUncheckedReason(\n reason: AnchorUnresolvedReason | AnchorDriftReason | undefined,\n): boolean {\n return (\n reason !== undefined &&\n UNCHECKED_REASONS.includes(reason as AnchorUnresolvedReason)\n );\n}\n\n/** One key per (repo, rev, file); `ref` absent is the default branch. */\nexport function wantKey(\n repo: string,\n ref: string | undefined,\n file: string,\n): string {\n return `${repo}\\u0000${ref ?? \"\"}\\u0000${file}`;\n}\n","import { mkdir } from \"node:fs/promises\";\nimport type { AnchorUnresolvedReason } from \"../anchor-resolver/model.js\";\nimport { normalizeRepoUrl } from \"../anchor-resolver/repo-identity.js\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport { cachePathFor, fetchTimeoutMs, repoCacheDir, revRef } from \"./cache.js\";\nimport { git, transportReason } from \"./git.js\";\nimport {\n wantKey,\n type RemoteOptions,\n type RemoteRead,\n type RemoteWant,\n} from \"./model.js\";\nimport {\n filePathIsSafe,\n isShortRepoName,\n protocolArgs,\n refIsWellFormed,\n refShapeIsSafe,\n repoUrlIsSafe,\n} from \"./validate.js\";\n\n/** Repositories fetched at once. Fetches within one repo stay serial. */\nconst DEFAULT_REPO_CONCURRENCY = 4;\n\n/** A full commit sha can never mean different content, so it is fetched once. */\nconst IMMUTABLE_REV = /^[0-9a-f]{40}$/;\n\n/**\n * Reads each wanted (repo, rev, file) out of a bare cache under\n * `~/.strauss/repo-cache`, fetching once per (repo, rev) and never per anchor.\n *\n * Every failure lands as an `unresolved` reason on the wants it affects; no\n * path is read from disk, so containment does not apply here.\n */\nexport async function readRemoteAnchors(\n wants: readonly RemoteWant[],\n options: RemoteOptions = {},\n): Promise<Map<string, RemoteRead>> {\n const out = new Map<string, RemoteRead>();\n if (!wants.length) return out;\n\n const cacheDir = repoCacheDir(options.cacheDir);\n const timeoutMs = fetchTimeoutMs(options.fetchTimeoutMs);\n const byRepo = new Map<string, { url: string; wants: RemoteWant[] }>();\n for (const want of wants) {\n const key = normalizeRepoUrl(want.repo);\n const group = byRepo.get(key) ?? { url: want.repo.trim(), wants: [] };\n group.wants.push(want);\n byRepo.set(key, group);\n }\n\n const groups = [...byRepo.entries()];\n const results = await mapLimit(\n groups,\n Math.max(1, options.concurrency ?? DEFAULT_REPO_CONCURRENCY),\n ([repo, group]) =>\n readOneRepo(repo, group.url, group.wants, {\n cacheDir,\n timeoutMs,\n offline: options.offline === true,\n }),\n );\n for (const result of results) {\n for (const [key, read] of result) out.set(key, read);\n }\n return out;\n}\n\ntype RepoContext = { cacheDir: string; timeoutMs: number; offline: boolean };\n\nasync function readOneRepo(\n repo: string,\n url: string,\n declared: readonly RemoteWant[],\n context: RepoContext,\n): Promise<Map<string, RemoteRead>> {\n let wants: readonly RemoteWant[] = declared;\n const all = (read: RemoteRead) =>\n new Map(wants.map((want) => [wantKey(repo, want.ref, want.file), read]));\n\n // A short `repo` (`org/name`) names a repository without saying where it\n // lives, so there is nothing to fetch from. `validate` warns on the spelling.\n if (isShortRepoName(url)) {\n return all({ ok: false, reason: \"remote-unreachable\" });\n }\n // Anything else that is not a remote we will fetch over is a finding about\n // the record, decided before a single `git` runs.\n if (!repoUrlIsSafe(url)) return all({ ok: false, reason: \"repo-invalid\" });\n\n const cache = cachePathFor(repo, context.cacheDir);\n if (!cache) return all({ ok: false, reason: \"remote-unreachable\" });\n\n // Ref and path shapes are checked with no subprocess, so a want carrying an\n // option-shaped `ref` or `file` never reaches git — not even `git init`.\n const rejected = new Map<string, RemoteRead>();\n const usable: RemoteWant[] = [];\n for (const want of wants) {\n const reason = wantReason(want);\n if (reason)\n rejected.set(wantKey(repo, want.ref, want.file), { ok: false, reason });\n else usable.push(want);\n }\n if (!usable.length) return rejected;\n wants = usable;\n\n const opened = await openCache(cache, url, context);\n if (opened) return new Map([...rejected, ...all(opened)]);\n\n const wantsDefault = wants.some((want) => want.ref === undefined);\n const branch: Branch = wantsDefault\n ? await defaultBranch(cache, context)\n : {};\n\n // One fetch per rev, serial: two `git fetch` in one bare repo race for the\n // same lock.\n const revs = new Map<string, RemoteRead | undefined>();\n for (const rev of distinctRevs(wants, branch.name)) {\n revs.set(\n rev,\n (await refIsWellFormed(rev))\n ? await ensureRev(cache, rev, context)\n : { ok: false, reason: \"ref-invalid\" },\n );\n }\n\n const reads = await mapLimit(\n wants,\n DEFAULT_IO_CONCURRENCY,\n async (want): Promise<RemoteRead> => {\n const rev = want.ref ?? branch.name;\n if (rev === undefined) {\n return {\n ok: false,\n reason: branch.reason ?? \"default-branch-unknown\",\n };\n }\n const failed = revs.get(rev);\n if (failed) return failed;\n return readBlob(cache, rev, want.file, context);\n },\n );\n return new Map([\n ...rejected,\n ...wants.map(\n (want, at) =>\n [wantKey(repo, want.ref, want.file), reads[at] as RemoteRead] as const,\n ),\n ]);\n}\n\n/**\n * Why this want cannot be handed to git, or `undefined`. A ref that would be\n * read as an option (`--upload-pack=…`) or a range (`a..b`) is a finding on the\n * record; a `file` that would be read as an option or climbs out of the tree is\n * the same `outside-repo` a working-tree read reports.\n */\nfunction wantReason(want: RemoteWant): AnchorUnresolvedReason | undefined {\n if (want.ref !== undefined && !refShapeIsSafe(want.ref)) return \"ref-invalid\";\n return filePathIsSafe(want.file) ? undefined : \"outside-repo\";\n}\n\nfunction distinctRevs(\n wants: readonly RemoteWant[],\n branch: string | undefined,\n): string[] {\n const revs = new Set<string>();\n for (const want of wants) {\n if (want.ref !== undefined) revs.add(want.ref);\n else if (branch) revs.add(branch);\n }\n return [...revs];\n}\n\n/** Creates the bare mirror if it is not there and points it at `url`. */\nasync function openCache(\n cache: string,\n url: string,\n context: RepoContext,\n): Promise<RemoteRead | undefined> {\n try {\n await mkdir(cache, { recursive: true });\n } catch {\n return { ok: false, reason: \"remote-unreachable\" };\n }\n const init = await git([\"init\", \"--bare\", \"--quiet\", cache], {\n timeoutMs: context.timeoutMs,\n });\n if (!init.ok) return { ok: false, reason: \"remote-unreachable\" };\n // `config`, not `remote add` or `remote set-url`: the first run has no\n // `origin` to set and the second must not fail because the first added it.\n // The URL is safe to pass unguarded only because the allowlist has already\n // run — nothing starting with `-` reaches here.\n const remote = await git([\"config\", \"remote.origin.url\", url], {\n cwd: cache,\n timeoutMs: context.timeoutMs,\n });\n return remote.ok ? undefined : { ok: false, reason: \"remote-unreachable\" };\n}\n\ntype Branch = { name?: string; reason?: AnchorUnresolvedReason };\n\n/**\n * The remote's default branch: asked once per repo per run, then remembered in\n * the cache so `--offline` and the next run have an answer.\n */\nasync function defaultBranch(\n cache: string,\n context: RepoContext,\n): Promise<Branch> {\n if (!context.offline) {\n const listed = await git(\n [...protocolArgs(), \"ls-remote\", \"--symref\", \"origin\", \"HEAD\"],\n {\n cwd: cache,\n timeoutMs: context.timeoutMs,\n },\n );\n const found = /^ref:\\s+refs\\/heads\\/(\\S+)\\s+HEAD$/m.exec(listed.stdout);\n if (listed.ok && found?.[1]) {\n const name = found[1];\n await git([\"config\", \"strauss.defaultBranch\", name], { cwd: cache });\n return { name };\n }\n if (!listed.ok) {\n const reason = transportReason(listed.stderr);\n if (reason !== \"ref-not-found\") {\n const cached = await cachedBranch(cache);\n return cached ? { name: cached } : { reason };\n }\n }\n }\n const cached = await cachedBranch(cache);\n if (cached) return { name: cached };\n // Offline with nothing cached is not a repository without a HEAD: the cause\n // is that nothing was reached, and that is what the finding should say.\n return {\n reason: context.offline ? \"remote-unreachable\" : \"default-branch-unknown\",\n };\n}\n\nasync function cachedBranch(cache: string): Promise<string | undefined> {\n const stored = await git([\"config\", \"--get\", \"strauss.defaultBranch\"], {\n cwd: cache,\n });\n if (stored.ok && stored.stdout.trim()) return stored.stdout.trim();\n const head = await git(\n [\"symbolic-ref\", \"--short\", \"refs/remotes/origin/HEAD\"],\n {\n cwd: cache,\n },\n );\n const name = head.stdout.trim().replace(/^origin\\//, \"\");\n return head.ok && name ? name : undefined;\n}\n\n/**\n * Fetches `rev` into a stable local ref, or reports why it could not.\n *\n * A full commit sha already in the cache is never refetched — its content\n * cannot change — while a branch is fetched every online run, because \"current\"\n * is exactly what a branch means.\n */\nasync function ensureRev(\n cache: string,\n rev: string,\n context: RepoContext,\n): Promise<RemoteRead | undefined> {\n const ref = revRef(rev);\n const have = await git(\n [\"rev-parse\", \"--verify\", \"--quiet\", `${ref}^{commit}`],\n {\n cwd: cache,\n },\n );\n const cached = have.ok && have.stdout.trim().length > 0;\n if (cached && (context.offline || IMMUTABLE_REV.test(rev))) return undefined;\n if (context.offline) return { ok: false, reason: \"remote-unreachable\" };\n\n // `--end-of-options` is what stops a rev from being parsed as an option; the\n // ref shape already refused one, and this is the layer that does not depend\n // on the shape being right.\n const fetched = await git(\n [\n ...protocolArgs(),\n \"fetch\",\n \"--depth\",\n \"1\",\n \"origin\",\n \"--end-of-options\",\n rev,\n ],\n { cwd: cache, timeoutMs: context.timeoutMs },\n );\n if (!fetched.ok) {\n // A stale cached copy beats no answer when the network is the problem;\n // a rev the remote no longer has is a finding either way.\n const reason = transportReason(fetched.stderr);\n if (cached && reason !== \"ref-not-found\") return undefined;\n return { ok: false, reason };\n }\n const head = await git([\"rev-parse\", \"FETCH_HEAD\"], { cwd: cache });\n const sha = head.stdout.trim();\n if (!head.ok || !sha) return { ok: false, reason: \"remote-unreachable\" };\n const updated = await git([\"update-ref\", ref, sha], { cwd: cache });\n return updated.ok ? undefined : { ok: false, reason: \"remote-unreachable\" };\n}\n\n/** `git cat-file blob <rev>:<file>`, capped at the same 1 MiB as a local read. */\nasync function readBlob(\n cache: string,\n rev: string,\n file: string,\n context: RepoContext,\n): Promise<RemoteRead> {\n const path = file.replace(/^\\.\\//, \"\");\n const blob = await git(\n [\"cat-file\", \"blob\", \"--end-of-options\", `${revRef(rev)}:${path}`],\n {\n cwd: cache,\n timeoutMs: context.timeoutMs,\n },\n );\n if (blob.ok) return { ok: true, source: blob.stdout };\n if (blob.overflowed) return { ok: false, reason: \"file-too-large\" };\n const text = blob.stderr.toLowerCase();\n return text.includes(\"does not exist\") || text.includes(\"not a valid object\")\n ? { ok: false, reason: \"file-missing\" }\n : { ok: false, reason: \"file-unreadable\" };\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport {\n MAX_ANCHOR_FILE_BYTES,\n type AnchorUnresolvedReason,\n} from \"../anchor-resolver/model.js\";\n\nconst execFileAsync = promisify(execFile);\n\nexport type GitRun = {\n ok: boolean;\n stdout: string;\n stderr: string;\n /** Set when the child died because its output passed the blob cap. */\n overflowed: boolean;\n};\n\n/**\n * The environment a `git` child gets. `GIT_TERMINAL_PROMPT` is cleared so a\n * credential helper that decides to prompt cannot block the run forever on a\n * repository the caller has no access to. `GIT_DIR`, `GIT_WORK_TREE`, and\n * `GIT_INDEX_FILE` are stripped because they override `cwd` — a caller's\n * environment must not be able to redirect a cache operation at another\n * repository. The global config stays: it is where the user's own credential\n * helper lives.\n */\nfunction childEnv(): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...process.env, GIT_TERMINAL_PROMPT: \"0\" };\n for (const name of [\"GIT_DIR\", \"GIT_WORK_TREE\", \"GIT_INDEX_FILE\"]) {\n delete env[name];\n }\n return env;\n}\n\n/**\n * One `git` invocation, argv only — never a shell, because `repo`, `ref`, and\n * `file` are bundle data. A non-zero exit is a result, not a throw.\n */\nexport async function git(\n args: string[],\n options: { cwd?: string; timeoutMs?: number; maxBytes?: number } = {},\n): Promise<GitRun> {\n try {\n const { stdout, stderr } = await execFileAsync(\"git\", args, {\n ...(options.cwd ? { cwd: options.cwd } : {}),\n timeout: options.timeoutMs ?? 30_000,\n maxBuffer: options.maxBytes ?? MAX_ANCHOR_FILE_BYTES,\n encoding: \"utf8\",\n windowsHide: true,\n env: childEnv(),\n });\n return { ok: true, stdout, stderr, overflowed: false };\n } catch (error) {\n const failure = error as {\n stdout?: string;\n stderr?: string;\n code?: string | number;\n };\n return {\n ok: false,\n stdout: failure.stdout ?? \"\",\n stderr: failure.stderr ?? \"\",\n overflowed: failure.code === \"ERR_CHILD_PROCESS_STDIO_MAXBUFFER\",\n };\n }\n}\n\n/**\n * Which failure a git transport error was. Matched on message text because\n * git returns 128 for all of them; an unrecognised failure is unreachable,\n * the reason that never accuses the record of being wrong.\n */\nexport function transportReason(stderr: string): AnchorUnresolvedReason {\n const text = stderr.toLowerCase();\n if (\n text.includes(\"authentication failed\") ||\n text.includes(\"permission denied\") ||\n text.includes(\"could not read username\") ||\n text.includes(\"403 forbidden\") ||\n text.includes(\"access denied\")\n ) {\n return \"repo-unauthorized\";\n }\n if (\n text.includes(\"couldn't find remote ref\") ||\n text.includes(\"unadvertised object\") ||\n text.includes(\"not our ref\")\n ) {\n return \"ref-not-found\";\n }\n return \"remote-unreachable\";\n}\n","/**\n * The vocabulary anchor resolution is reported in.\n *\n * Every failure is a finding with a reason, never a throw: a record pointing\n * at code that moved is information, not a broken run.\n */\n\nexport type ResolvedSymbol = {\n text: string;\n /** 1-based, inclusive. */\n startLine: number;\n endLine: number;\n};\n\n/** Which resolver produced a span. Stamped on the anchor. */\nexport type AnchorResolverName = \"tree-sitter\" | \"regex\";\n\n/**\n * A resolver's verdict. `abstain` (\"not my language\") and `symbol-not-found`\n * (\"nothing I recognize declares this\") both pass the symbol down the chain;\n * `symbol-ambiguous` and `resolver-unavailable` end it, because neither may be\n * answered by a looser resolver guessing.\n */\nexport type ResolverAttempt =\n | { kind: \"resolved\"; span: ResolvedSymbol }\n | {\n kind: \"unresolved\";\n reason: \"symbol-not-found\" | \"symbol-ambiguous\" | \"resolver-unavailable\";\n }\n | { kind: \"abstain\" };\n\nexport interface AnchorResolver {\n name: string;\n /** Loads whatever these files need, before any `resolve` call. Optional. */\n prepare?(files: readonly string[]): Promise<void>;\n /** The richer verdict the chain uses; defaults to `resolve`. */\n attempt?(source: string, symbol: string, file?: string): ResolverAttempt;\n resolve(source: string, symbol: string, file?: string): ResolvedSymbol | null;\n /**\n * The span's normalised token stream — comments dropped, runs of whitespace\n * collapsed — or `null` when this resolver cannot parse the text.\n *\n * Only a resolver that understands the language can offer one, which is why\n * it is optional: a text heuristic normalising by guess would call two\n * different programs equal.\n */\n normalize?(text: string, file?: string): string | null;\n}\n\n/** A resolved span, and which resolver produced it. */\nexport type AnchorResolution =\n | {\n ok: true;\n span: ResolvedSymbol;\n resolver?: AnchorResolverName;\n /** The span's token stream, when the resolver that spanned it can parse. */\n normalized?: string;\n }\n | { ok: false; reason: AnchorUnresolvedReason };\n\n/** Why an anchor could not be compared. Never an error — always a finding. */\nexport type AnchorUnresolvedReason =\n | \"file-missing\"\n | \"symbol-not-found\"\n /** More than one definition carries the name, and guessing is not allowed. */\n | \"symbol-ambiguous\"\n /** The extension has a grammar, but it would not load. Never a throw. */\n | \"resolver-unavailable\"\n | \"outside-repo\"\n | \"file-too-large\"\n | \"file-unreadable\"\n /** The remote could not be fetched, or `--offline` found nothing cached. */\n | \"remote-unreachable\"\n /** The anchor's `ref` is not on the remote any more. */\n | \"ref-not-found\"\n | \"repo-unauthorized\"\n /** No default branch, so there is no \"current\" to compare against. */\n | \"default-branch-unknown\"\n /** The anchor's `ref` is not a name git may safely be handed. */\n | \"ref-invalid\"\n /** The anchor's `repo` is not a remote we will fetch from. */\n | \"repo-invalid\";\n\n/**\n * A hash that changed because a more precise resolver took over, not because\n * the code did. Reported as drift so nothing is restamped silently, and\n * accepted by `--rebaseline` like any other.\n */\nexport type AnchorDriftReason = \"resolver-changed\";\n\n/**\n * How a ref-pinned foreign anchor stands. `drifted-on-default` is the one a\n * working-tree anchor has no equivalent of: the evidence is still true at the\n * commit it was taken from, and the code has moved since.\n */\nexport type RemoteAnchorState =\n \"matches-ref\" | \"drifted-from-ref\" | \"drifted-on-default\";\n\n/** Big enough for any hand-written source file, small enough to read eagerly. */\nexport const MAX_ANCHOR_FILE_BYTES = 1_048_576;\n\n/** What `hash` was taken over. Absent on an anchor means `raw`. */\nexport type AnchorHashKind = \"raw\" | \"ast\";\n\n/**\n * How an anchor's code changed, once the bytes are known to differ.\n *\n * The classes a machine can settle, so a reader only sees the ones it cannot:\n * `moved` and `cosmetic` are answered and closed, `gone` and `changed` are\n * handed on. Deliberately shallow — whether the record's *claim* still holds\n * is a reading, and no hash can stand in for one.\n */\nexport const KB_DRIFT_CLASSES = [\n \"moved\",\n \"cosmetic\",\n \"gone\",\n \"changed\",\n] as const;\n\nexport type KbDriftClass = (typeof KB_DRIFT_CLASSES)[number];\n\n/** Where a `moved` anchor's stored hash turned up. */\nexport type KbDriftMovedTo = {\n file: string;\n symbol?: string;\n startLine: number;\n endLine: number;\n};\n\nexport type KbAnchorDriftEntry = {\n file: string;\n symbol?: string;\n state: \"match\" | \"drifted\" | \"unresolved\";\n storedHash: string;\n currentHash?: string;\n /** `null` when the anchor recorded no `lines` — size unknown, not zero. */\n diffSize: number | null;\n reason?: AnchorUnresolvedReason | AnchorDriftReason;\n /** Which resolver produced `currentHash`. Absent for a whole-file anchor. */\n resolver?: AnchorResolverName;\n /** Set only when the anchor was resolved against another repository. */\n repo?: string;\n remoteState?: RemoteAnchorState;\n /** What the compared hashes were taken over. */\n hashKind?: AnchorHashKind;\n /**\n * Provisional: `gone` or `changed`, the two a hash comparison alone can\n * settle. `moved` and `cosmetic` cost a repository search and a git read, so\n * `classifyDrift` refines this on the reassessment path rather than on every\n * `load`.\n */\n class?: KbDriftClass;\n /** Set by `classifyDrift` when the class is `moved`. */\n movedTo?: KbDriftMovedTo;\n};\n\nexport type AnchorRead =\n { ok: true; source: string } | { ok: false; reason: AnchorUnresolvedReason };\n\nexport type AnchorFileReader = (file: string) => Promise<AnchorRead>;\n","import { git } from \"./git.js\";\n\n/**\n * `repo`, `ref`, and `file` are bundle data — a `.md` file the reader did not\n * write — and every one of them reaches `git` argv. An argv array stops the\n * shell, not git's own option parsing: `git fetch origin --upload-pack=<cmd>`\n * runs `<cmd>`, `ext::sh -c <cmd>` is a transport that does the same, and\n * `file:///` reads any repository the process can see. So each value is checked\n * against a shape before git ever sees it, and a value that fails is a finding\n * on the record rather than a command.\n */\n\n/** Long enough for any real branch, short enough to bound the argv. */\nconst MAX_REF_LENGTH = 200;\n\n/**\n * The shape a `ref` must have to reach git at all. The leading character class\n * excludes `-`, so no ref can be read as an option; `@`, `{`, `\\`, spaces, and\n * control characters are outside the class entirely.\n */\nconst REF_SHAPE = /^[A-Za-z0-9][A-Za-z0-9._/-]*$/;\n\n/** Checked with no subprocess, so an invalid ref never spawns git. */\nexport function refShapeIsSafe(ref: string): boolean {\n if (!ref || ref.length > MAX_REF_LENGTH) return false;\n // `a..b` is a range, not a rev, and `git fetch` would resolve it as one.\n if (ref.includes(\"..\")) return false;\n return REF_SHAPE.test(ref);\n}\n\n/**\n * git's own opinion of the name, asked only once the shape has made it safe to\n * pass. `--allow-onelevel` because `main` and a bare sha are both legal here.\n */\nexport async function refIsWellFormed(ref: string): Promise<boolean> {\n if (!refShapeIsSafe(ref)) return false;\n const checked = await git([\"check-ref-format\", \"--allow-onelevel\", ref]);\n return checked.ok;\n}\n\n/**\n * A `file` that may become the path half of `<rev>:<path>`. A leading `-` would\n * be an option; `..` would climb out of the tree the anchor describes.\n */\nexport function filePathIsSafe(file: string): boolean {\n const path = file.replace(/^\\.\\//, \"\");\n if (!path || path.startsWith(\"-\") || path.includes(\"\\0\")) return false;\n return !path.split(\"/\").includes(\"..\");\n}\n\n/** Transports a remote may be fetched over. Plaintext `http` is not one. */\nconst DEFAULT_PROTOCOLS = [\"https\", \"ssh\", \"git\"] as const;\n\n/**\n * `STRAUSS_KB_REPO_PROTOCOLS` widens the set — a comma list. It exists so the\n * test suite can serve `file://` remotes off disk; it is not a production knob,\n * because every protocol it can add is one that reads or runs something local.\n */\nexport function allowedProtocols(): string[] {\n const raw = process.env[\"STRAUSS_KB_REPO_PROTOCOLS\"];\n if (raw === undefined) return [...DEFAULT_PROTOCOLS];\n const listed = raw\n .split(\",\")\n .map((entry) => entry.trim().toLowerCase())\n .filter(Boolean);\n return listed.length ? listed : [...DEFAULT_PROTOCOLS];\n}\n\n/**\n * A `repo` naming a repository without saying where it lives (`org/name`).\n * There is nothing to fetch from, which is not the same finding as a `repo`\n * spelled in a transport we refuse to use.\n */\nexport function isShortRepoName(repo: string): boolean {\n return /^[A-Za-z0-9._-]+(?:\\/[A-Za-z0-9._-]+)*$/.test(repo.trim());\n}\n\n/** scp-style `git@host:org/name`, which git reads as ssh. */\nconst SCP_LIKE = /^[\\w.-]+@[\\w.-]+:(?!\\/)\\S+$/;\n\nconst URL_SCHEME = /^([A-Za-z0-9+.-]+):\\/\\//;\n\n// eslint-disable-next-line no-control-regex -- refusing control bytes is the point\nconst CONTROL_CHARS = /[\\u0000-\\u001f\\u007f]/;\n\n/** Checked with no subprocess, so a rejected URL never reaches a git remote. */\nexport function repoUrlIsSafe(repo: string): boolean {\n const url = repo.trim();\n if (!url || url.startsWith(\"-\") || CONTROL_CHARS.test(url)) return false;\n\n const allowed = allowedProtocols();\n if (SCP_LIKE.test(url)) return allowed.includes(\"ssh\");\n\n const scheme = URL_SCHEME.exec(url);\n // No `://` means no transport we recognise — `ext::sh -c …` lands here.\n if (!scheme?.[1]) return false;\n if (!allowed.includes(scheme[1].toLowerCase())) return false;\n\n // `https://user:password@host/…` puts a secret in a URL a bundle wrote; a\n // credential belongs in git's own helper, not in a record.\n const authority = url.slice(scheme[0].length).split(\"/\")[0] ?? \"\";\n const at = authority.lastIndexOf(\"@\");\n return at < 0 || !authority.slice(0, at).includes(\":\");\n}\n\n/**\n * Defence in depth behind the allowlist: even if a URL slipped past it, git\n * itself refuses the two transports that run or read something local.\n */\nexport function protocolArgs(): string[] {\n const allowed = allowedProtocols();\n return [\n \"-c\",\n \"protocol.ext.allow=never\",\n \"-c\",\n `protocol.file.allow=${allowed.includes(\"file\") ? \"user\" : \"never\"}`,\n ];\n}\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport {\n MAX_ANCHOR_FILE_BYTES,\n type AnchorFileReader,\n type AnchorRead,\n type KbAnchorDriftEntry,\n} from \"./model.js\";\n\n/**\n * An anchor's `file` must stay inside the repository root — a record points\n * at code, not at arbitrary files on the machine reading it. Bundles are\n * data, so a traversal or absolute path here is untrusted input, not a bug\n * in the caller. Returns the resolved path, or `null` when it escapes.\n *\n * Lexical only, and therefore not the whole containment check: see\n * `readAnchorFile`, which re-tests the real path after following symlinks.\n */\nexport function anchorFilePath(repoRoot: string, file: string): string | null {\n // Anchors are repo-relative, hand-written often enough that `./` shows up.\n const path = resolve(repoRoot, file.replace(/^\\.\\//, \"\"));\n const rel = relative(resolve(repoRoot), path);\n if (\n rel === \"\" ||\n rel === \"..\" ||\n rel.startsWith(`..${sep}`) ||\n isAbsolute(rel)\n ) {\n return null;\n }\n return path;\n}\n\nfunction contains(root: string, path: string): boolean {\n const rel = relative(root, path);\n return (\n rel !== \"\" &&\n rel !== \"..\" &&\n !rel.startsWith(`..${sep}`) &&\n !isAbsolute(rel)\n );\n}\n\nfunction errorCode(error: unknown): string | undefined {\n return typeof error === \"object\" && error !== null && \"code\" in error\n ? String((error as { code: unknown }).code)\n : undefined;\n}\n\n/** Resolves the repo root once, then reads anchor files against it. */\nexport function anchorFileReader(repoRoot: string): AnchorFileReader {\n let rootOnce: Promise<string> | undefined;\n const realRoot = (): Promise<string> => {\n rootOnce ??= realpath(resolve(repoRoot)).catch((error: unknown) => {\n // A rejected promise stays cached forever if left as-is — clear it so\n // the next read retries realpath instead of replaying one transient\n // failure for the rest of the run. This read still reports its own\n // file-missing/file-unreadable result via the catch below.\n rootOnce = undefined;\n throw error;\n });\n return rootOnce;\n };\n return (file) => readAnchorFileWithRoot(repoRoot, file, realRoot);\n}\n\n/** Convenience wrapper: resolves the repo root fresh on every call. */\nexport async function readAnchorFile(\n repoRoot: string,\n file: string,\n): Promise<AnchorRead> {\n return readAnchorFileWithRoot(repoRoot, file, () =>\n realpath(resolve(repoRoot)),\n );\n}\n\n/**\n * Containment is checked twice: lexically, then again against the realpath'd\n * path — a symlink inside the repo pointing out must not leak reads. Only\n * ENOENT/ENOTDIR is `file-missing`; other read errors are `file-unreadable`.\n */\nasync function readAnchorFileWithRoot(\n repoRoot: string,\n file: string,\n realRoot: () => Promise<string>,\n): Promise<AnchorRead> {\n const lexical = anchorFilePath(repoRoot, file);\n if (lexical === null) return { ok: false, reason: \"outside-repo\" };\n\n let root: string;\n let path: string;\n try {\n root = await realRoot();\n path = await realpath(lexical);\n } catch (error) {\n const code = errorCode(error);\n if (code === \"ENOENT\" || code === \"ENOTDIR\") {\n return { ok: false, reason: \"file-missing\" };\n }\n return { ok: false, reason: \"file-unreadable\" };\n }\n if (!contains(root, path)) return { ok: false, reason: \"outside-repo\" };\n\n try {\n const stats = await stat(path);\n if (!stats.isFile()) return { ok: false, reason: \"file-unreadable\" };\n // Anchors point at source. Reading a bundled artefact or a checked-in\n // binary into memory on a read path is a cost with no finding behind it.\n if (stats.size > MAX_ANCHOR_FILE_BYTES) {\n return { ok: false, reason: \"file-too-large\" };\n }\n return { ok: true, source: await readFile(path, \"utf8\") };\n } catch (error) {\n const code = errorCode(error);\n if (code === \"ENOENT\" || code === \"ENOTDIR\") {\n return { ok: false, reason: \"file-missing\" };\n }\n return { ok: false, reason: \"file-unreadable\" };\n }\n}\n\n/**\n * Every checked anchor failed to find its file at all.\n *\n * The signature of a repo root that was never given rather than of code that\n * moved: a bundle read from somewhere other than the tree it describes misses\n * every file, and reporting that as base-wide drift would train a reader to\n * ignore the warning. One file found anywhere makes the root plausible, and\n * the misses become real findings again.\n */\nexport function looksLikeWrongRepoRoot(\n drift: Map<string, KbAnchorDriftEntry[]>,\n): boolean {\n let checked = 0;\n for (const entries of drift.values()) {\n for (const entry of entries) {\n // An anchor read from another repository's remote says nothing about\n // this root. Counting it either way would be wrong: as a miss it would\n // make a correct root look wrong, and as a hit it would keep a\n // genuinely wrong root from being spotted.\n if (entry.repo !== undefined) continue;\n checked += 1;\n if (entry.state !== \"unresolved\" || entry.reason !== \"file-missing\") {\n return false;\n }\n }\n }\n return checked > 0;\n}\n\n/**\n * Reads each distinct file once with at most `concurrency` in flight.\n *\n * A reader that throws is one unreadable file, not a failed run.\n */\nexport async function readAnchorFiles(\n files: readonly string[],\n read: AnchorFileReader,\n concurrency: number = DEFAULT_IO_CONCURRENCY,\n): Promise<Map<string, AnchorRead>> {\n if (!Number.isInteger(concurrency) || concurrency < 1) {\n throw new RangeError(\n `readAnchorFiles: option \"concurrency\" must be a positive integer, got ${concurrency}`,\n );\n }\n const wanted = [...new Set(files)];\n const results = await mapLimit(wanted, concurrency, async (file) => {\n try {\n return await read(file);\n } catch {\n return { ok: false, reason: \"file-unreadable\" } as AnchorRead;\n }\n });\n return new Map(wanted.map((file, at) => [file, results[at] as AnchorRead]));\n}\n","import { createHash } from \"node:crypto\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport type { GrammarOptions } from \"../grammars/index.js\";\nimport { TreeSitterResolver } from \"../tree-sitter-resolver/index.js\";\nimport type {\n AnchorHashKind,\n AnchorResolution,\n AnchorResolverName,\n AnchorResolver,\n ResolvedSymbol,\n ResolverAttempt,\n} from \"./model.js\";\n\n/**\n * Symbol → text, and text → hash.\n *\n * Resolvers are pure: source string in, range out. Any shape the lexer cannot\n * handle confidently returns `null` and is reported `unresolved`, never guessed.\n */\n\n/**\n * How far above a candidate the parent of a dotted symbol may sit and still\n * be taken as scoping it. Crude on purpose: a real parser owns this question,\n * and until one takes the seat a fixed window is at least predictable.\n */\nconst PARENT_SCOPE_LINES = 50;\n\n/* -------------------------------------------------------------------------\n * A crude lexer, sufficient for counting braces\n * ---------------------------------------------------------------------- */\n\ntype ScanState = { blockComment: boolean; template: boolean };\n\nconst CLEAN_STATE: ScanState = { blockComment: false, template: false };\n\n/**\n * Strips comments and string literals from one line, carrying block-comment\n * and template-literal state across lines.\n *\n * Brace counting over raw text is wrong in both directions: a `}` inside a\n * string or a comment ends a block early — the truncation that hashes as\n * stable — and a `{` inside one opens a block that never closes. This is not\n * a tokenizer: a regex literal containing a brace (`/}/`) still fools it, and\n * `#` is left alone because TypeScript spells private fields with it. Both\n * limits are documented in the README.\n */\nfunction stripLine(\n line: string,\n state: ScanState,\n): { code: string; state: ScanState } {\n let out = \"\";\n let index = 0;\n let { blockComment, template } = state;\n\n while (index < line.length) {\n const char = line[index];\n const next = line[index + 1];\n\n if (blockComment) {\n if (char === \"*\" && next === \"/\") {\n blockComment = false;\n index += 2;\n continue;\n }\n index += 1;\n continue;\n }\n\n // Braces inside `${...}` are balanced by construction, so ignoring the\n // whole template rather than re-entering code inside it is safe here.\n if (template) {\n if (char === \"\\\\\") {\n index += 2;\n continue;\n }\n if (char === \"`\") template = false;\n index += 1;\n continue;\n }\n\n if (char === \"/\" && next === \"*\") {\n blockComment = true;\n index += 2;\n continue;\n }\n if (char === \"/\" && next === \"/\") break;\n if (char === \"`\") {\n template = true;\n index += 1;\n continue;\n }\n if (char === \"'\" || char === '\"') {\n const quote = char;\n index += 1;\n while (index < line.length) {\n if (line[index] === \"\\\\\") {\n index += 2;\n continue;\n }\n if (line[index] === quote) {\n index += 1;\n break;\n }\n index += 1;\n }\n continue;\n }\n\n out += char;\n index += 1;\n }\n\n return { code: out, state: { blockComment, template } };\n}\n\n/* -------------------------------------------------------------------------\n * Span capture\n * ---------------------------------------------------------------------- */\n\nfunction span(lines: string[], from: number, to: number): ResolvedSymbol {\n return {\n text: lines.slice(from, to + 1).join(\"\\n\"),\n startLine: from + 1,\n endLine: to + 1,\n };\n}\n\n/**\n * From the matched line to the line where brace depth returns to zero.\n *\n * Depth is tested at end of line, never mid-line, so a destructured signature\n * (`function f({ a, b }) {`) does not end the span. A top-level `;` before any\n * brace opens is a braceless declaration and the matched line alone is the\n * span. Everything else is `null`.\n */\nfunction captureBraceBlock(\n lines: string[],\n matchLine: number,\n): ResolvedSymbol | null {\n let depth = 0;\n let opened = false;\n let state = CLEAN_STATE;\n\n for (let index = matchLine; index < lines.length; index++) {\n const stripped = stripLine(lines[index] ?? \"\", state);\n state = stripped.state;\n\n for (const char of stripped.code) {\n if (char === \"{\") {\n depth += 1;\n opened = true;\n } else if (char === \"}\") {\n depth = Math.max(0, depth - 1);\n } else if (char === \";\" && !opened) {\n return span(lines, matchLine, index);\n }\n }\n\n if (opened && depth === 0) return span(lines, matchLine, index);\n }\n\n return null;\n}\n\n/** `def f(...)` / `class C:` — a header ending in a colon, body by indent. */\nconst PYTHON_HEADER = /^\\s*(?:async\\s+)?(?:def|class)\\s+[A-Za-z_]\\w*\\s*[(:]/;\n\n/**\n * A Python block: the header, however many lines its signature runs to, plus\n * every following line that is blank or indented past the header.\n *\n * Brace counting would capture a `def` line and nothing else — a signature\n * hash that never sees a body change, which is worse than no anchor at all.\n * A header whose body never arrives is `null` for the same reason.\n */\nfunction captureIndentedBlock(\n lines: string[],\n matchLine: number,\n): ResolvedSymbol | null {\n const header = lines[matchLine] ?? \"\";\n const indent = header.length - header.trimStart().length;\n\n let headerEnd = -1;\n for (\n let index = matchLine;\n index < lines.length && index <= matchLine + 20;\n index++\n ) {\n const code = stripLine(lines[index] ?? \"\", CLEAN_STATE).code.trimEnd();\n if (code.endsWith(\":\")) {\n headerEnd = index;\n break;\n }\n // `def f(): pass` — the body is on the header line, so the line is the span.\n if (code.includes(\":\")) return span(lines, matchLine, index);\n }\n if (headerEnd === -1) return null;\n\n let end = headerEnd;\n for (let index = headerEnd + 1; index < lines.length; index++) {\n const line = lines[index] ?? \"\";\n if (line.trim() === \"\") continue;\n const lineIndent = line.length - line.trimStart().length;\n if (lineIndent <= indent) break;\n end = index;\n }\n\n // A signature with no body under it is the false-stability case again.\n return end === headerEnd ? null : span(lines, matchLine, end);\n}\n\n/* -------------------------------------------------------------------------\n * The v1 resolver\n * ---------------------------------------------------------------------- */\n\n/**\n * Candidate lines, best shape first. A declaration outranks an assignment,\n * which outranks a call-shaped line, which outranks a bare mention — so an\n * anchor lands on where a symbol is defined rather than the first place it is\n * used, which `findIndex` over one loose pattern used to do.\n */\nconst TIERS: ((name: string) => RegExp)[] = [\n (name) =>\n new RegExp(\n `(?:function|class|interface|type|enum|const|let|var|def)\\\\s+${name}\\\\b`,\n ),\n (name) => new RegExp(`\\\\b${name}\\\\s*[:=]`),\n (name) => new RegExp(`\\\\b${name}\\\\s*\\\\(`),\n (name) => new RegExp(`\\\\b${name}\\\\b`),\n];\n\n/**\n * v1 heuristic resolver. A dotted symbol like `OrderService.cancel` matches on\n * its last segment, with the parent used to scope the search: a candidate\n * counts only if the parent name appears in the fifty lines above it, when any\n * candidate satisfies that at all.\n *\n * Deterministic, and ambiguity is not resolved by guessing — two lines of\n * equally good shape mean the resolver cannot tell which one the record meant,\n * and it says so by returning `null`.\n */\nexport const regexResolver: AnchorResolver = {\n name: \"regex\",\n resolve(source, symbol) {\n const segments = symbol.split(\".\");\n const name = segments[segments.length - 1];\n if (!name) return null;\n const parent =\n segments.length > 1 ? segments[segments.length - 2] : undefined;\n\n const escaped = escapeRegExp(name);\n const parentPattern = parent\n ? new RegExp(`\\\\b${escapeRegExp(parent)}\\\\b`)\n : null;\n const lines = source.split(\"\\n\");\n\n for (const tier of TIERS) {\n const pattern = tier(escaped);\n let candidates = lines\n .map((line, index) => ({ line, index }))\n .filter((entry) => pattern.test(entry.line))\n .map((entry) => entry.index);\n if (!candidates.length) continue;\n\n // Nearest enclosing parent wins, not merely a parent somewhere above:\n // two classes in one file each declaring `cancel` both see the first\n // class's name in the window, and only distance tells them apart.\n if (parentPattern && candidates.length > 1) {\n const distances = candidates.map((index) =>\n distanceToParent(lines, index, parentPattern),\n );\n const nearest = Math.min(...distances);\n if (Number.isFinite(nearest)) {\n candidates = candidates.filter((_, at) => distances[at] === nearest);\n }\n }\n\n // Two lines of the same shape: which one the record meant is a guess,\n // and a guessed anchor hashes as evidence.\n if (candidates.length !== 1) return null;\n\n const matchLine = candidates[0] as number;\n return PYTHON_HEADER.test(lines[matchLine] ?? \"\")\n ? captureIndentedBlock(lines, matchLine)\n : captureBraceBlock(lines, matchLine);\n }\n\n return null;\n },\n};\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\n/** Lines from the nearest parent mention at or above `index`, or Infinity. */\nfunction distanceToParent(\n lines: string[],\n index: number,\n parent: RegExp,\n): number {\n const floor = Math.max(0, index - PARENT_SCOPE_LINES);\n for (let at = index; at >= floor; at--) {\n if (parent.test(lines[at] ?? \"\")) return index - at;\n }\n return Number.POSITIVE_INFINITY;\n}\n\n/** CRLF normalized to LF before hashing, so checkout style cannot read as drift. */\nexport function hashAnchorText(text: string): string {\n return `sha256:${createHash(\"sha256\")\n .update(text.replace(/\\r\\n/g, \"\\n\"))\n .digest(\"hex\")}`;\n}\n\n/**\n * An anchor without a symbol is about the whole file; with one, the resolver\n * decides. Source newlines are normalized first so line counts and hashes\n * agree with `hashAnchorText`.\n *\n * A file's last line is the last line with content: a trailing newline is a\n * terminator, not an empty line, and counting it would have made every\n * whole-file anchor's `lines` one larger than the file.\n */\nexport function resolveAnchor(\n source: string,\n anchor: KbAnchor,\n resolver: AnchorResolver = regexResolver,\n): ResolvedSymbol | null {\n const outcome = resolveAnchorSpan(source, anchor, [resolver]);\n return outcome.ok ? outcome.span : null;\n}\n\n/**\n * Walks the resolver chain: tree-sitter, then regex, then a whole-file span\n * when the anchor names no symbol.\n *\n * `symbol-not-found` falls through (a tags query defines functions and types,\n * not constants or fields) and the anchor records the resolver that answered.\n * `symbol-ambiguous` and `resolver-unavailable` end the chain: one would be\n * settled by guessing, the other would trade a precise span for a guessed one.\n */\nexport function resolveAnchorSpan(\n source: string,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[] = [regexResolver],\n): AnchorResolution {\n const normalized = source.replace(/\\r\\n/g, \"\\n\");\n if (!anchor.symbol) {\n const lines = normalized.split(\"\\n\");\n if (lines.length > 1 && lines[lines.length - 1] === \"\") lines.pop();\n return {\n ok: true,\n span: {\n text: normalized,\n startLine: 1,\n endLine: Math.max(1, lines.length),\n },\n };\n }\n\n for (const resolver of resolvers) {\n const attempt = resolver.attempt\n ? resolver.attempt(normalized, anchor.symbol, anchor.file)\n : fromResolve(resolver, normalized, anchor.symbol, anchor.file);\n if (attempt.kind === \"abstain\") continue;\n if (attempt.kind === \"unresolved\") {\n if (attempt.reason === \"symbol-not-found\") continue;\n return { ok: false, reason: attempt.reason };\n }\n const tokens = resolver.normalize?.(attempt.span.text, anchor.file);\n return {\n ok: true,\n span: attempt.span,\n ...(isResolverName(resolver.name) ? { resolver: resolver.name } : {}),\n ...(tokens ? { normalized: tokens } : {}),\n };\n }\n return { ok: false, reason: \"symbol-not-found\" };\n}\n\n/** A resolver with no `attempt`: a span or a plain miss, never an abstain. */\nfunction fromResolve(\n resolver: AnchorResolver,\n source: string,\n symbol: string,\n file: string,\n): ResolverAttempt {\n const span = resolver.resolve(source, symbol, file);\n return span\n ? { kind: \"resolved\", span }\n : { kind: \"unresolved\", reason: \"symbol-not-found\" };\n}\n\nfunction isResolverName(name: string): name is AnchorResolverName {\n return name === \"tree-sitter\" || name === \"regex\";\n}\n\n/** Loads every chained resolver's per-language assets, once. */\nexport async function prepareResolvers(\n resolvers: readonly AnchorResolver[],\n files: readonly string[],\n): Promise<void> {\n for (const resolver of resolvers) await resolver.prepare?.(files);\n}\n\n/**\n * The read-path chain. A fresh tree-sitter resolver per call, so its parse\n * cache lives exactly as long as the run that owns it. `offline` rides down to\n * grammar loading: a run that may not reach the network uses the cache or\n * reports `resolver-unavailable`.\n */\nexport function defaultAnchorResolvers(\n grammars: GrammarOptions = {},\n): AnchorResolver[] {\n return [new TreeSitterResolver(grammars), regexResolver];\n}\n\n/**\n * Was the swap the whole story?\n *\n * Only when the resolver that stamped the anchor still reproduces the stored\n * hash against this very source. Otherwise the code moved too, and calling it\n * a resolver change would hide the edit behind a bookkeeping note.\n */\nexport function resolverChanged(\n source: string,\n anchor: KbAnchor,\n produced: AnchorResolverName | undefined,\n): boolean {\n const previous = anchor.resolver ?? \"regex\";\n if (!produced || !anchor.symbol || previous === produced) return false;\n if (previous !== \"regex\") return false;\n const before = regexResolver.resolve(\n source.replace(/\\r\\n/g, \"\\n\"),\n anchor.symbol,\n );\n return before !== null && hashAnchorText(before.text) === anchor.hash;\n}\n\n/**\n * Which hash to compare, and over what.\n *\n * A stored hash is only ever compared against a hash of the same kind — an\n * `ast` hash and a `raw` hash of the same code differ by construction, and\n * treating that as drift would report every anchor once. An anchor with no\n * hash yet takes the strongest kind the resolver can offer, so newly stamped\n * anchors stop drifting on reformatting.\n */\nexport function anchorHashOf(\n anchor: KbAnchor,\n outcome: { span: ResolvedSymbol; normalized?: string },\n): { hash: string; kind: AnchorHashKind } {\n const stored = anchor.hash ? (anchor.hash_kind ?? \"raw\") : undefined;\n const wanted = stored ?? (outcome.normalized ? \"ast\" : \"raw\");\n return wanted === \"ast\" && outcome.normalized\n ? { hash: hashAnchorText(outcome.normalized), kind: \"ast\" }\n : { hash: hashAnchorText(outcome.span.text), kind: \"raw\" };\n}\n","import { extname } from \"node:path\";\nimport { grammarManifest, type GrammarManifest } from \"../grammars/index.js\";\n\n/**\n * Which grammar a file extension is parsed with, and whether a definitions\n * query runs over it. Both are generated — `pnpm grammars pin` — from GitHub\n * Linguist and from each pack's own tags query, so adding a language is a pin\n * run rather than a hand-written query.\n */\n\n/** Inverted once per lock — the lock a test stands in is a different object. */\nlet table:\n { of: GrammarManifest; extensions: Record<string, string> } | undefined;\n\nfunction extensionTable(): Record<string, string> {\n const manifest = grammarManifest();\n if (table?.of !== manifest)\n table = {\n of: manifest,\n extensions: Object.fromEntries(\n Object.entries(manifest.packs).flatMap(([language, pack]) =>\n pack.extensions.map((extension) => [extension, language]),\n ),\n ),\n };\n return table.extensions;\n}\n\n/** Does the lock pin a tags query for this language? The query itself downloads. */\nfunction hasQuery(language: string): boolean {\n return (grammarManifest().packs[language]?.tags.length ?? 0) > 0;\n}\n\n/**\n * Grammar for a path, or `undefined` when the extension has none — or when the\n * pinned grammar release ships no tags query for it, so the regex heuristic\n * keeps those files, as before the resolver existed.\n */\nexport function languageForFile(file: string): string | undefined {\n const language = extensionTable()[extname(file).toLowerCase()];\n return language && hasQuery(language) ? language : undefined;\n}\n\n/** Every language the resolver can resolve in: a grammar and a tags query. */\nexport function treeSitterLanguages(): string[] {\n return [...new Set(Object.values(extensionTable()))].filter(hasQuery).sort();\n}\n","import { readFile } from \"node:fs/promises\";\nimport { downloadPart, grammarsBaseUrl, grammarUrl } from \"./fetch.js\";\nimport { grammarManifest } from \"./manifest.js\";\nimport type { Grammar, GrammarOptions, Pinned } from \"./model.js\";\nimport {\n grammarCachePath,\n grammarsCacheRoot,\n verifyCached,\n writeCached,\n} from \"./store.js\";\n\nexport { grammarsBaseUrl, grammarUrl } from \"./fetch.js\";\nexport {\n grammarManifest,\n grammarsDataPath,\n setGrammarManifest,\n} from \"./manifest.js\";\nexport {\n grammarManifestSchema,\n type Grammar,\n type GrammarManifest,\n type GrammarPack,\n type GrammarOptions,\n} from \"./model.js\";\nexport { grammarCachePath, grammarsCacheRoot } from \"./store.js\";\n\n/** One download per pack per process, however many callers ask at once. */\nconst inFlight = new Map<string, Promise<Grammar | null>>();\n\n/** Packs this process wanted and could not get, and why, for the hint. */\nconst missing = new Map<string, { subject: string; cause?: string }>();\n\n/** Languages whose pinned tags query would not compile, and why. */\nconst uncompilable = new Map<string, string>();\n\n/** Languages whose pinned grammar this runtime refused to load, and why. */\nconst rejected = new Map<string, string>();\n\n/** `STRAUSS_KB_GRAMMARS=off` keeps a run off the wire; the cache still counts. */\nexport function grammarsDownloadDisabled(): boolean {\n return process.env[\"STRAUSS_KB_GRAMMARS\"] === \"off\";\n}\n\n/**\n * Both halves of a verified pack (cached WASM path, tags query text), each\n * downloaded once. `null` on any refused, disabled or mismatched part is what\n * the resolver reports as `resolver-unavailable`; a miss is not remembered.\n */\nexport async function ensureGrammar(\n language: string,\n options: GrammarOptions = {},\n): Promise<Grammar | null> {\n const pack = grammarManifest().packs[language];\n if (!pack) return null;\n\n const root = grammarsCacheRoot(options.cacheRoot);\n const wasm = grammarCachePath(root, language, pack.wasm.sha256);\n // Keyed on the pack rather than the part, so a pack downloads once however\n // many parts it has.\n const key = `${wasm} ${grammarsBaseUrl(options.baseUrl) ?? \"\"}`;\n const existing = inFlight.get(key);\n if (existing) return existing;\n\n const pending = (async () => {\n const grammar = await ensurePart(\n wasm,\n `tree-sitter-${language}`,\n pack.wasm,\n options,\n );\n if (grammar !== true)\n return miss(language, `grammar tree-sitter-${language}`, grammar);\n\n const parts: string[] = [];\n const total = pack.tags.length;\n for (const [at, part] of pack.tags.entries()) {\n const name = `${language} tags${total > 1 ? ` part ${at + 1}/${total}` : \"\"}`;\n const path = grammarCachePath(root, language, part.sha256, \"scm\");\n const held = await ensurePart(path, name, part, options);\n if (held !== true) return miss(language, name, held);\n parts.push(`; ${part.url}\\n${lf(await readFile(path, \"utf8\"))}`);\n }\n\n missing.delete(language);\n return { wasm, query: total ? parts.join(\"\\n\") : undefined };\n })();\n inFlight.set(key, pending);\n const result = await pending;\n if (result === null) inFlight.delete(key);\n return result;\n}\n\n/** `true` once the part is cached and hashes as the lock says, else why not. */\nasync function ensurePart(\n path: string,\n name: string,\n entry: Pinned & { url: string },\n options: GrammarOptions,\n): Promise<true | { cause?: string }> {\n if (await verifyCached(path, entry)) return true;\n if (options.offline === true || grammarsDownloadDisabled()) return {};\n const download = await downloadPart(\n grammarUrl(entry.url, options.baseUrl),\n name,\n entry,\n options,\n );\n if (\"cause\" in download) return { cause: download.cause };\n await writeCached(path, download.bytes).catch(() => null);\n return true;\n}\n\n/** Records which part of the pack this run could not get, for the hint. */\nfunction miss(\n language: string,\n subject: string,\n failure: { cause?: string },\n): null {\n missing.set(language, { subject, ...failure });\n return null;\n}\n\n/** The pin concatenates parts LF-normalised; the runtime must compile the same. */\nfunction lf(body: string): string {\n return body.replace(/\\r\\n/g, \"\\n\");\n}\n\n/**\n * A tags query that will not compile against the grammar release it is pinned\n * to. The resolver reports the language unavailable; the repair is a re-pin.\n */\nexport function noteUncompilableQuery(language: string, cause: string): void {\n uncompilable.set(language, cause);\n}\n\n/**\n * A grammar the runtime will not load — a WASM built at an ABI outside the\n * range this `web-tree-sitter` accepts. The resolver reports the language\n * unavailable; the repair is a re-pin against the installed runtime.\n */\nexport function noteRejectedGrammar(language: string, cause: string): void {\n rejected.set(language, cause);\n}\n\n/**\n * One line per grammar this process could not use, for the doctor and\n * anchor-resolve reports. The only place a repair is spelled out.\n */\nexport function grammarHints(): string[] {\n const manifest = grammarManifest();\n const packs = manifest.packs;\n const lines = new Map<string, string>();\n for (const [language, { subject, cause }] of missing)\n lines.set(\n language,\n `${subject} not cached${cause ? ` (${cause})` : \"\"}; run online once, or set STRAUSS_KB_GRAMMARS_DIR`,\n );\n for (const [language, cause] of rejected)\n lines.set(\n language,\n `${packs[language]?.package ?? `tree-sitter-${language}`} rejected by web-tree-sitter ${manifest.webTreeSitter}${cause ? `: ${cause}` : \"\"}; re-pin with pnpm grammars pin ${language}`,\n );\n for (const [language, cause] of uncompilable)\n lines.set(\n language,\n `tags query for ${language} does not compile against ${packs[language]?.package ?? `tree-sitter-${language}`}: ${cause}; re-pin with pnpm grammars pin ${language}`,\n );\n return [...lines]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([, line]) => line);\n}\n\n/** Test seam: forgets this process's downloads, misses and query failures. */\nexport function resetGrammarState(): void {\n inFlight.clear();\n missing.clear();\n uncompilable.clear();\n rejected.clear();\n}\n","import { createHash, randomBytes } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport type { Pinned } from \"./model.js\";\n\n/** Where downloaded grammars live. Overridable so a test never writes to `$HOME`. */\nexport function grammarsCacheRoot(override?: string): string {\n return (\n override ??\n process.env[\"STRAUSS_KB_GRAMMARS_DIR\"] ??\n join(homedir(), \".strauss\", \"grammars\")\n );\n}\n\n/**\n * Named by the hash the manifest pins, so a re-pin downloads beside the old\n * file instead of over it and a rollback finds its own still there. Both parts\n * of a pack share the layout: `<root>/<language>/<sha12>.wasm|.scm`.\n */\nexport function grammarCachePath(\n root: string,\n language: string,\n sha256: string,\n extension: \"wasm\" | \"scm\" = \"wasm\",\n): string {\n return join(root, language, `${sha256.slice(0, 12)}.${extension}`);\n}\n\nexport function sha256(bytes: Uint8Array): string {\n return createHash(\"sha256\").update(bytes).digest(\"hex\");\n}\n\nexport function matches(bytes: Uint8Array, entry: Pinned): boolean {\n if (entry.bytes !== undefined && bytes.byteLength !== entry.bytes)\n return false;\n return sha256(bytes) === entry.sha256;\n}\n\n/**\n * `true` when the cached file hashes as the manifest says. Checked on every\n * load, not only on download: `$HOME` is writable by anything the user runs\n * and a grammar is code the parser executes. A failing file is deleted.\n */\nexport async function verifyCached(\n path: string,\n entry: Pinned,\n): Promise<boolean> {\n let bytes: Uint8Array;\n try {\n bytes = await readFile(path);\n } catch {\n return false;\n }\n if (matches(bytes, entry)) return true;\n await rm(path, { force: true });\n return false;\n}\n\n/**\n * Write then `rename`, which is atomic within a filesystem: a second process\n * either sees the old file or the whole new one, never a half-written parser.\n */\nexport async function writeCached(\n path: string,\n bytes: Uint8Array,\n): Promise<void> {\n await mkdir(dirname(path), { recursive: true });\n const temporary = `${path}.${process.pid}.${randomBytes(4).toString(\"hex\")}.tmp`;\n try {\n await writeFile(temporary, bytes);\n await rename(temporary, path);\n } catch (error) {\n await rm(temporary, { force: true });\n throw error;\n }\n}\n","import { fetchTimeoutMs } from \"../remote-repo/index.js\";\nimport type { GrammarOptions, Pinned } from \"./model.js\";\nimport { matches } from \"./store.js\";\n\n/** Attempts per grammar, and the pause after attempt `n`. */\nconst ATTEMPTS = 3;\nconst BACKOFF_MS = 250;\n\n/**\n * The manifest pins a fully resolved URL per pack. An override — a mirror, or\n * the suite's own server — replaces its scheme and host and nothing else, so\n * one setting redirects every pack whatever CDN it was pinned from.\n */\nexport function grammarUrl(url: string, override?: string): string {\n const base = grammarsBaseUrl(override);\n if (!base) return url;\n let root = base;\n while (root.endsWith(\"/\")) root = root.slice(0, -1);\n const pinned = new URL(url);\n return `${root}${pinned.pathname}${pinned.search}`;\n}\n\nexport function grammarsBaseUrl(override?: string): string | undefined {\n return override ?? process.env[\"STRAUSS_KB_GRAMMARS_URL\"];\n}\n\n/** Bytes, or why the last attempt failed — for the log line and the hint. */\nexport type Download = { bytes: Uint8Array } | { cause: string };\n\n/**\n * A pinned part's bytes, or a cause — never a throw. Grammar and tags query\n * take the same path: a hash mismatch is not retried (the CDN will serve the\n * same file again; the manifest is the safety), while timeouts, dropped\n * connections, 5xx and 429 get `ATTEMPTS` tries.\n */\nexport async function downloadPart(\n url: string,\n name: string,\n entry: Pinned,\n options: GrammarOptions = {},\n): Promise<Download> {\n const log =\n options.log ?? ((line: string) => void process.stderr.write(line));\n const weight =\n entry.bytes === undefined ? \"\" : ` (${size(entry.bytes)} from manifest)`;\n log(`strauss-kb: downloading ${name}${weight} from ${url}\\n`);\n\n let cause = \"\";\n for (let attempt = 1; attempt <= ATTEMPTS; attempt++) {\n const outcome = await attemptDownload(url, entry, options.fetchTimeoutMs);\n if (\"bytes\" in outcome) return outcome;\n cause = outcome.cause;\n log(\n `strauss-kb: ${name} attempt ${attempt}/${ATTEMPTS} failed: ${cause}\\n`,\n );\n if (!outcome.retry) break;\n if (attempt < ATTEMPTS) await pause(BACKOFF_MS * attempt);\n }\n log(`strauss-kb: ${name} not downloaded: ${cause}\\n`);\n return { cause };\n}\n\nasync function attemptDownload(\n url: string,\n entry: Pinned,\n timeoutMs: number | undefined,\n): Promise<{ bytes: Uint8Array } | { cause: string; retry: boolean }> {\n try {\n const response = await fetch(url, {\n signal: AbortSignal.timeout(fetchTimeoutMs(timeoutMs)),\n });\n if (!response.ok) {\n return {\n cause: `HTTP ${response.status}`,\n retry: response.status >= 500 || response.status === 429,\n };\n }\n const bytes = new Uint8Array(await response.arrayBuffer());\n if (!matches(bytes, entry))\n return { cause: \"sha256 mismatch\", retry: false };\n return { bytes };\n } catch (error) {\n const timedOut =\n error instanceof Error &&\n (error.name === \"TimeoutError\" || error.name === \"AbortError\");\n return { cause: timedOut ? \"timeout\" : \"network error\", retry: true };\n }\n}\n\n/** What the manifest says the file weighs, for the download line. */\nfunction size(bytes: number): string {\n return bytes >= 1024 * 1024\n ? `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n : `${Math.round(bytes / 1024)} KB`;\n}\n\nfunction pause(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { grammarManifestSchema, type GrammarManifest } from \"./model.js\";\n\nlet cached: GrammarManifest | undefined;\n\n/**\n * The shipped `grammars/manifest.json`: the URL, hash and extensions of every\n * language pack. Read once per process.\n */\nexport function grammarManifest(): GrammarManifest {\n cached ??= grammarManifestSchema.parse(\n JSON.parse(readFileSync(grammarsDataPath(\"manifest.json\"), \"utf8\")),\n );\n return cached;\n}\n\n/**\n * Test seam: stands a lock of the test's own in for the shipped one, so a\n * suite can pin a part the shipped lock does not carry. `undefined` restores.\n */\nexport function setGrammarManifest(manifest?: GrammarManifest): void {\n cached = manifest;\n}\n\n/**\n * A path under the package's shipped `grammars/` directory.\n *\n * Source and bundle sit at different depths under the package root — `src/\n * grammars/` and `dist/` — so the directory is found by walking up rather than\n * by a fixed `..`.\n */\nexport function grammarsDataPath(...segments: string[]): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let up = 0; up < 5; up++) {\n const candidate = join(dir, \"grammars\");\n if (existsSync(join(candidate, \"manifest.json\")))\n return join(candidate, ...segments);\n dir = dirname(dir);\n }\n throw new Error(\"grammars/manifest.json is missing from the package\");\n}\n","import { z } from \"zod\";\n\nconst sha256 = z.string().regex(/^[0-9a-f]{64}$/);\n\n/**\n * The WASM half of a pack as the lock records it: the URL it was pinned from\n * and what it hashed to. `bytes` is checked before the hash so a truncated\n * response is rejected without hashing megabytes.\n */\nexport const grammarWasmSchema = z.object({\n url: z.string().min(1),\n sha256,\n bytes: z.number().int().positive(),\n});\n\n/**\n * One part of the tags query. A query is kilobytes, so the hash alone settles\n * it and the lock carries no byte count.\n */\nexport const grammarTagsSchema = z.object({ url: z.string().min(1), sha256 });\n\n/**\n * A language pack: a grammar and the definitions query that runs over it,\n * pinned together at one `package@version`. `tags` is empty where upstream\n * ships no query — that language parses but resolves nothing.\n */\nexport const grammarPackSchema = z.object({\n package: z.string().min(1),\n wasm: grammarWasmSchema,\n tags: z.array(grammarTagsSchema),\n license: z.string().min(1),\n extensions: z.array(z.string().min(1)),\n});\n\nexport const grammarManifestSchema = z.object({\n /** The runtime the packs were proved against. */\n webTreeSitter: z.string().min(1),\n linguist: z.object({ tag: z.string().min(1), commit: z.string().min(1) }),\n packs: z.record(z.string().min(1), grammarPackSchema),\n});\n\nexport type GrammarWasm = z.infer<typeof grammarWasmSchema>;\nexport type GrammarTags = z.infer<typeof grammarTagsSchema>;\n/** What a cached file is checked against: a hash, and a size where one is known. */\nexport type Pinned = { sha256: string; bytes?: number };\nexport type GrammarPack = z.infer<typeof grammarPackSchema>;\nexport type GrammarManifest = z.infer<typeof grammarManifestSchema>;\n\n/** A grammar and the query that runs over it, both verified, both on disk. */\nexport type Grammar = {\n /** Path to the cached WASM. */\n wasm: string;\n /** The pack's tags parts as one query, or `undefined` where it declares none. */\n query: string | undefined;\n};\n\n/** Where a grammar comes from and whether it may be fetched at all. */\nexport type GrammarOptions = {\n /** Cache root; defaults to `STRAUSS_KB_GRAMMARS_DIR` then `~/.strauss/grammars`. */\n cacheRoot?: string;\n /** Replaces the scheme and host of every manifest URL. For tests and mirrors. */\n baseUrl?: string;\n /** Cache only, never the network — what `--offline` passes down. */\n offline?: boolean;\n fetchTimeoutMs?: number;\n /** Where the download lines go. Defaults to stderr, never stdout. */\n log?: (line: string) => void;\n};\n","import { createHash } from \"node:crypto\";\nimport { Language, Parser, Query, type Tree } from \"web-tree-sitter\";\nimport type {\n AnchorResolver,\n ResolvedSymbol,\n ResolverAttempt,\n} from \"../anchor-resolver/index.js\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport {\n ensureGrammar,\n noteRejectedGrammar,\n noteUncompilableQuery,\n type Grammar,\n type GrammarOptions,\n} from \"../grammars/index.js\";\nimport {\n chainOf,\n index,\n select,\n spanOf,\n type Definition,\n type ParsedFile,\n} from \"./definitions.js\";\nimport { languageForFile } from \"./languages.js\";\nimport { tokens } from \"./tokens.js\";\n\n/**\n * AST-backed anchor resolution: a symbol resolves to the byte range of the\n * definition node that declares it, or to nothing.\n *\n * `resolve` stays synchronous because the read path resolves inside a loop;\n * grammar loading is the async part and happens once, in `prepare`.\n */\n\n/** How many parsed trees to keep. Trees are large; anchors cluster in few files. */\nconst TREE_CACHE_LIMIT = 32;\n\ntype Loaded = { language: Language; query: Query };\n\nexport type TreeSitterStats = { parses: number; cacheHits: number };\n\n/** Where both halves of a pack come from, and whether they may be fetched. */\nexport type TreeSitterOptions = GrammarOptions;\n\nexport class TreeSitterResolver implements AnchorResolver {\n readonly name = \"tree-sitter\";\n\n private readonly grammars: GrammarOptions;\n private readonly loaded = new Map<string, Loaded | null>();\n private readonly trees = new Map<string, ParsedFile>();\n private parser: Parser | undefined;\n private initialized = false;\n\n /** Cache effectiveness, for tests and for the latency numbers. */\n readonly stats: TreeSitterStats = { parses: 0, cacheHits: 0 };\n\n constructor(options: TreeSitterOptions = {}) {\n this.grammars = options;\n }\n\n /**\n * Loads the grammars these files need, once per language per process,\n * downloading each one on first use.\n *\n * A grammar that will not load is remembered as unavailable rather than\n * retried per anchor, and never throws: an unobtainable WASM is a finding.\n */\n async prepare(files: readonly string[]): Promise<void> {\n const wanted = new Set<string>();\n for (const file of files) {\n const language = languageForFile(file);\n if (language && !this.loaded.has(language)) wanted.add(language);\n }\n if (!wanted.size) return;\n\n if (!this.initialized) {\n try {\n await Parser.init();\n this.parser = new Parser();\n this.initialized = true;\n } catch {\n for (const language of wanted) this.loaded.set(language, null);\n return;\n }\n }\n\n // Downloads dominate a cold first run, so the languages a bundle needs\n // are fetched together rather than one after another.\n const languages = [...wanted];\n const loaded = await mapLimit(\n languages,\n Math.min(DEFAULT_IO_CONCURRENCY, languages.length),\n (language) => this.load(language),\n );\n languages.forEach((language, at) =>\n this.loaded.set(language, loaded[at] ?? null),\n );\n }\n\n /**\n * An unobtainable grammar, one this runtime refuses, and a query that will\n * not compile are three faults with three repairs; all are reported through\n * the grammars module so every hint has one home.\n */\n private async load(language: string): Promise<Loaded | null> {\n let pack: Grammar | null;\n try {\n pack = await ensureGrammar(language, this.grammars);\n } catch {\n return null;\n }\n if (!pack?.query) return null;\n\n let grammar: Language;\n try {\n grammar = await Language.load(pack.wasm);\n } catch (error) {\n noteRejectedGrammar(language, why(error));\n return null;\n }\n try {\n return { language: grammar, query: new Query(grammar, pack.query) };\n } catch (error) {\n noteUncompilableQuery(language, why(error));\n return null;\n }\n }\n\n /**\n * Abstains on an extension with no grammar so the regex resolver gets a\n * turn; reports `resolver-unavailable` when the grammar exists in principle\n * but could not be loaded, because falling back there would silently trade a\n * precise span for a guessed one.\n */\n attempt(source: string, symbol: string, file?: string): ResolverAttempt {\n const language = file ? languageForFile(file) : undefined;\n if (!language) return { kind: \"abstain\" };\n if (!this.loaded.has(language)) return { kind: \"abstain\" };\n const loaded = this.loaded.get(language);\n if (!loaded) return { kind: \"unresolved\", reason: \"resolver-unavailable\" };\n\n const parsed = this.parse(language, loaded, source);\n if (!parsed) return { kind: \"unresolved\", reason: \"resolver-unavailable\" };\n\n const wanted = symbol.split(\".\").filter(Boolean);\n if (!wanted.length)\n return { kind: \"unresolved\", reason: \"symbol-not-found\" };\n\n const matches = select(parsed, wanted);\n if (!matches.length)\n return { kind: \"unresolved\", reason: \"symbol-not-found\" };\n if (matches.length > 1)\n return { kind: \"unresolved\", reason: \"symbol-ambiguous\" };\n return { kind: \"resolved\", span: spanOf(matches[0] as Definition, source) };\n }\n\n resolve(\n source: string,\n symbol: string,\n file?: string,\n ): ResolvedSymbol | null {\n const attempt = this.attempt(source, symbol, file);\n return attempt.kind === \"resolved\" ? attempt.span : null;\n }\n\n /** Parsed trees are keyed by content hash, so an unchanged file parses once. */\n private parse(\n language: string,\n loaded: Loaded,\n source: string,\n ): ParsedFile | null {\n const key = `${language}:${createHash(\"sha256\").update(source).digest(\"hex\")}`;\n const cached = this.trees.get(key);\n if (cached) {\n this.stats.cacheHits += 1;\n return cached;\n }\n\n const parser = this.parser;\n if (!parser) return null;\n let parsed: ParsedFile;\n try {\n parser.setLanguage(loaded.language);\n const tree = parser.parse(source);\n if (!tree) return null;\n parsed = index(tree, loaded.query);\n } catch {\n return null;\n }\n this.stats.parses += 1;\n\n if (this.trees.size >= TREE_CACHE_LIMIT) {\n const oldest = this.trees.keys().next();\n if (!oldest.done) {\n this.trees.get(oldest.value)?.tree.delete();\n this.trees.delete(oldest.value);\n }\n }\n this.trees.set(key, parsed);\n return parsed;\n }\n\n /**\n * Every definition this file declares, as dotted symbol and span.\n *\n * The inverse of `attempt`: that asks \"where is this name\", this asks \"what\n * names are here\". `moved` needs the second — the stored hash has to be\n * looked for at every definition in the repository, and there is no name to\n * ask about, since the whole question is which name now carries that code.\n */\n spans(\n source: string,\n file: string,\n ): { symbol: string; span: ResolvedSymbol }[] {\n const language = languageForFile(file);\n if (!language) return [];\n const loaded = this.loaded.get(language);\n if (!loaded) return [];\n const parsed = this.parse(language, loaded, source);\n if (!parsed) return [];\n\n return parsed.definitions\n .filter((definition) => definition.target)\n .map((definition) => ({\n symbol: chainOf(definition, parsed.byNodeId).join(\".\"),\n span: spanOf(definition, source),\n }));\n }\n\n /**\n * The token stream of a span: every leaf the parser sees, comments dropped,\n * joined by single spaces.\n *\n * This is what makes a reformat not be drift. Hashing it rather than the raw\n * text means indentation, line breaks, trailing commas the formatter moved,\n * and every comment above or inside the definition are outside the hash —\n * and a renamed identifier or a changed literal is still inside it, because\n * those are leaves.\n *\n * `null` when the file has no grammar, the grammar would not load, or the\n * text will not parse: no normalisation is better than a guessed one.\n */\n normalize(text: string, file?: string): string | null {\n const language = file ? languageForFile(file) : undefined;\n if (!language) return null;\n const loaded = this.loaded.get(language);\n if (!loaded) return null;\n\n const parser = this.parser;\n if (!parser) return null;\n let tree: Tree | null;\n try {\n parser.setLanguage(loaded.language);\n tree = parser.parse(text);\n } catch {\n return null;\n }\n if (!tree) return null;\n try {\n return tokens(tree.rootNode).join(\" \");\n } finally {\n tree.delete();\n }\n }\n\n /** Drops cached trees. Grammars stay loaded — they are immutable. */\n reset(): void {\n for (const parsed of this.trees.values()) parsed.tree.delete();\n this.trees.clear();\n this.stats.parses = 0;\n this.stats.cacheHits = 0;\n }\n}\n\n/** web-tree-sitter throws bare Errors for a rejected module; say so. */\nfunction why(error: unknown): string {\n const text = error instanceof Error ? error.message : String(error);\n return text || \"no reason given\";\n}\n","import type { Node, Query, Tree } from \"web-tree-sitter\";\nimport type { ResolvedSymbol } from \"../anchor-resolver/index.js\";\n\n/**\n * Upstream `tags.scm` vocabulary: `@name` is the symbol, `@definition.*` the\n * node a reader points at, `@reference.*` a use. `@reference.implementation`\n * (a Rust `impl Foo`) scopes the chain without being a target.\n */\n\nconst SCOPE_ONLY = \"reference.implementation\";\n\n/** A definition site, with the node whose range becomes the anchor span. */\nexport type Definition = {\n node: Node;\n name: string;\n /** `false` for chain-only scopes such as a Rust `impl` block. */\n target: boolean;\n};\n\nexport type ParsedFile = {\n tree: Tree;\n /** Definitions by node id, for walking a node's enclosing chain. */\n byNodeId: Map<number, Definition>;\n definitions: Definition[];\n};\n\n/**\n * One definition per name site, innermost node wins — a query that captures\n * the same name twice (upstream Rust makes every `fn` both a function and,\n * inside its `impl` block's `declaration_list`, a method) means the tightest\n * node around the name, never the block that holds its siblings too.\n */\nexport function index(tree: Tree, query: Query): ParsedFile {\n const byName = new Map<number, Definition>();\n\n for (const match of query.matches(tree.rootNode)) {\n const nameNode = match.captures.find((capture) => capture.name === \"name\");\n const defNode = match.captures.find(\n (capture) =>\n capture.name.startsWith(\"definition.\") || capture.name === SCOPE_ONLY,\n );\n if (!nameNode || !defNode) continue;\n\n const candidate: Definition = {\n node: defNode.node,\n name: nameNode.node.text,\n target: defNode.name !== SCOPE_ONLY,\n };\n const existing = byName.get(nameNode.node.id);\n if (existing && width(existing.node) <= width(candidate.node)) continue;\n byName.set(nameNode.node.id, candidate);\n }\n\n const definitions = [...byName.values()];\n return {\n tree,\n byNodeId: new Map(\n definitions.map((definition) => [definition.node.id, definition]),\n ),\n definitions,\n };\n}\n\n/**\n * Definitions whose chain ends with `wanted`. When several match, the ones\n * with a body win: an overload signature declares the same chain as the\n * implementation, and the implementation is what a reader means.\n */\nexport function select(\n parsed: ParsedFile,\n wanted: readonly string[],\n): Definition[] {\n const matches = parsed.definitions.filter(\n (definition) =>\n definition.target &&\n endsWith(chainOf(definition, parsed.byNodeId), wanted),\n );\n if (matches.length < 2) return matches;\n const bodied = matches.filter(\n (definition) => definition.node.childForFieldName(\"body\") !== null,\n );\n return bodied.length === 1 ? bodied : matches;\n}\n\n/**\n * The definition's enclosing chain, outermost first: `[\"OrderService\",\n * \"cancel\"]` for a method of that class.\n *\n * A receiver stands in for an ancestor where a grammar has one — Go's\n * `func (s *Server) Cancel` chains as `Server.Cancel`.\n */\nexport function chainOf(\n definition: Definition,\n byNodeId: Map<number, Definition>,\n): string[] {\n const chain = [definition.name];\n\n const receiver = definition.node.childForFieldName(\"receiver\");\n const type = receiver && typeNameIn(receiver);\n if (type) chain.unshift(type);\n\n for (let node = definition.node.parent; node; node = node.parent) {\n const enclosing = byNodeId.get(node.id);\n if (enclosing && enclosing.node !== definition.node)\n chain.unshift(enclosing.name);\n }\n return chain;\n}\n\n/** `(s *Server)` and `(s Server)` both name `Server`. */\nfunction typeNameIn(receiver: Node): string | undefined {\n const stack: Node[] = [receiver];\n while (stack.length) {\n const node = stack.pop() as Node;\n if (node.type === \"type_identifier\") return node.text;\n for (let at = 0; at < node.childCount; at++) {\n const child = node.child(at);\n if (child) stack.push(child);\n }\n }\n return undefined;\n}\n\n/** Does `chain` end with every segment of `wanted`, in order? */\nfunction endsWith(chain: string[], wanted: readonly string[]): boolean {\n if (wanted.length > chain.length) return false;\n const offset = chain.length - wanted.length;\n return wanted.every((segment, at) => chain[offset + at] === segment);\n}\n\nfunction width(node: Node): number {\n return node.endIndex - node.startIndex;\n}\n\n/**\n * The definition node's lines, widened to what a reader would call the\n * declaration: preceding decorators, and the `export` that fronts it.\n */\nexport function spanOf(definition: Definition, source: string): ResolvedSymbol {\n let start = definition.node;\n let end = definition.node;\n\n for (\n let sibling = start.previousSibling;\n sibling?.type === \"decorator\";\n sibling = sibling.previousSibling\n ) {\n start = sibling;\n }\n\n const parent = end.parent;\n if (\n parent?.type === \"export_statement\" &&\n parent.childForFieldName(\"declaration\")?.id === end.id\n ) {\n start = parent;\n end = parent;\n }\n\n const lines = source.split(\"\\n\");\n const startLine = start.startPosition.row;\n // A node ending at column 0 ends on the previous line's newline.\n const endLine =\n end.endPosition.column === 0 && end.endPosition.row > startLine\n ? end.endPosition.row - 1\n : end.endPosition.row;\n\n return {\n text: lines.slice(startLine, endLine + 1).join(\"\\n\"),\n startLine: startLine + 1,\n endLine: endLine + 1,\n };\n}\n","import type { Node } from \"web-tree-sitter\";\n\n/**\n * Leaf text in source order, comments skipped whole.\n *\n * Iterative rather than recursive: a span is bounded by `MAX_ANCHOR_FILE_BYTES`\n * but its nesting depth is not, and a deeply nested literal must not be able to\n * overflow the stack on a read path.\n */\nexport function tokens(root: Node): string[] {\n const out: string[] = [];\n const stack: Node[] = [root];\n while (stack.length) {\n const node = stack.pop() as Node;\n if (node.type.includes(\"comment\")) continue;\n if (node.childCount === 0) {\n const text = node.text.trim();\n if (text) out.push(text);\n continue;\n }\n for (let at = node.childCount - 1; at >= 0; at--) {\n const child = node.child(at);\n if (child) stack.push(child);\n }\n }\n return out;\n}\n","import { DEFAULT_IO_CONCURRENCY } from \"../concurrency.js\";\nimport type { KbAnchor, KbRecord } from \"../kb-record.schema.js\";\nimport {\n readRemoteAnchors,\n wantKey,\n type RemoteOptions,\n type RemoteRead,\n type RemoteWant,\n} from \"../remote-repo/index.js\";\nimport type {\n AnchorFileReader,\n AnchorHashKind,\n AnchorRead,\n AnchorResolver,\n AnchorResolverName,\n KbAnchorDriftEntry,\n KbDriftClass,\n} from \"./model.js\";\nimport { anchorFileReader, readAnchorFiles } from \"./read.js\";\nimport { LazyOrigin, normalizeRepoUrl } from \"./repo-identity.js\";\nimport {\n anchorHashOf,\n defaultAnchorResolvers,\n prepareResolvers,\n resolveAnchorSpan,\n resolverChanged,\n} from \"./resolver.js\";\n\nexport type AnchorDriftOptions = {\n repoRoot?: string;\n /** Single resolver, no chain. Convenience for tests. */\n resolver?: AnchorResolver;\n /** The chain, tried in order. Defaults to tree-sitter then regex. */\n resolvers?: readonly AnchorResolver[];\n concurrency?: number;\n /** Test seam: replaces the disk reader. */\n reader?: AnchorFileReader;\n /** Remote resolution of foreign anchors; `offline` keeps a run off the wire. */\n remote?: RemoteOptions;\n /** Test seam: replaces the remote blob reader. */\n readRemote?: typeof readRemoteAnchors;\n};\n\ntype Planned = { anchor: KbAnchor; foreign: boolean };\n\n/**\n * Re-resolves every hash-carrying anchor and compares against the stored hash.\n *\n * An anchor naming another repository is read from that repository's remote\n * through a bare cache; everything else is read from the working tree. A\n * missing file, an unreachable remote, or an unresolvable symbol is a finding\n * (`unresolved`), never a throw.\n *\n * Four phases: collect the checkable anchors, read the working tree's distinct\n * files and the remotes' distinct (repo, rev, file) blobs, then resolve and\n * hash in record order — so the output never depends on which read finished\n * first.\n */\nexport async function detectAnchorDrift(\n records: KbRecord[],\n options: AnchorDriftOptions = {},\n): Promise<Map<string, KbAnchorDriftEntry[]>> {\n const repoRoot = options.repoRoot ?? process.cwd();\n const resolvers =\n options.resolvers ??\n (options.resolver\n ? [options.resolver]\n : defaultAnchorResolvers({\n offline: options.remote?.offline === true,\n }));\n const origin = new LazyOrigin(repoRoot);\n\n const planned = new Map<string, Planned[]>();\n let declaresRepo = false;\n for (const record of records) {\n const anchors = (record.frontmatter.strauss_anchors ?? []).filter(\n (anchor) => anchor.hash,\n );\n if (!anchors.length) continue;\n if (anchors.some((anchor) => anchor.repo)) declaresRepo = true;\n planned.set(\n record.conceptId,\n anchors.map((anchor) => ({ anchor, foreign: false })),\n );\n }\n if (declaresRepo) {\n await origin.prime();\n for (const entries of planned.values()) {\n for (const entry of entries)\n entry.foreign = origin.isForeign(entry.anchor);\n }\n }\n\n const files: string[] = [];\n const wants: RemoteWant[] = [];\n for (const entries of planned.values()) {\n for (const { anchor, foreign } of entries) {\n if (!foreign) files.push(anchor.file);\n else wants.push(...remoteWants(anchor));\n }\n }\n\n // Disk and network are independent; neither waits for the other.\n const [reads, remote] = await Promise.all([\n readAnchorFiles(\n files,\n options.reader ?? anchorFileReader(repoRoot),\n options.concurrency ?? DEFAULT_IO_CONCURRENCY,\n ),\n (options.readRemote ?? readRemoteAnchors)(wants, options.remote ?? {}),\n ]);\n await prepareResolvers(resolvers, [\n ...files,\n ...wants.map((want) => want.file),\n ]);\n\n const drift = new Map<string, KbAnchorDriftEntry[]>();\n for (const record of records) {\n const entries: KbAnchorDriftEntry[] = [];\n for (const { anchor, foreign } of planned.get(record.conceptId) ?? []) {\n entries.push(\n foreign\n ? remoteEntry(anchor, remote, resolvers)\n : localEntry(anchor, reads.get(anchor.file) as AnchorRead, resolvers),\n );\n }\n if (entries.length) drift.set(record.conceptId, entries);\n }\n return drift;\n}\n\n/**\n * What must be read for one foreign anchor: the pinned commit, plus the\n * default branch it is \"current\" against when the anchor pins one at all.\n */\nexport function remoteWants(anchor: KbAnchor): RemoteWant[] {\n const repo = anchor.repo as string;\n const wants: RemoteWant[] = [{ repo, file: anchor.file }];\n if (anchor.ref) wants.unshift({ repo, ref: anchor.ref, file: anchor.file });\n return wants;\n}\n\nfunction base(\n anchor: KbAnchor,\n): Pick<KbAnchorDriftEntry, \"file\" | \"symbol\" | \"storedHash\"> {\n return {\n file: anchor.file,\n ...(anchor.symbol ? { symbol: anchor.symbol } : {}),\n storedHash: anchor.hash as string,\n };\n}\n\nfunction unresolved(\n anchor: KbAnchor,\n reason: KbAnchorDriftEntry[\"reason\"],\n repo?: string,\n): KbAnchorDriftEntry {\n return {\n ...base(anchor),\n state: \"unresolved\",\n diffSize: null,\n ...(reason ? { reason } : {}),\n ...(repo ? { repo } : {}),\n ...classOf(reason),\n };\n}\n\n/**\n * The class a hash comparison alone can settle.\n *\n * A vanished file or an undefined symbol is `gone` — the strongest signal\n * there is, because the described code does not exist to be re-read. Anything\n * that resolved and hashed differently is `changed` until a search proves it\n * only moved.\n */\nexport function provisionalDriftClass(\n entry: Pick<KbAnchorDriftEntry, \"state\" | \"reason\">,\n): KbDriftClass | undefined {\n if (entry.state === \"unresolved\") {\n return entry.reason === \"file-missing\" ||\n entry.reason === \"symbol-not-found\"\n ? \"gone\"\n : undefined;\n }\n return entry.state === \"drifted\" ? \"changed\" : undefined;\n}\n\n/** `class` for an unresolved reason, or nothing to spread. */\nfunction classOf(reason: KbAnchorDriftEntry[\"reason\"]): {\n class?: KbDriftClass;\n} {\n const settled = provisionalDriftClass({ state: \"unresolved\", reason });\n return settled ? { class: settled } : {};\n}\n\ntype Current = {\n hash: string;\n kind: AnchorHashKind;\n lines: number;\n resolver?: AnchorResolverName;\n};\n\n/** The hash of an anchor's text in one source, or the reason it has none. */\nfunction hashIn(\n source: string,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n):\n | { ok: true; current: Current }\n | { ok: false; reason: KbAnchorDriftEntry[\"reason\"] } {\n const outcome = resolveAnchorSpan(source, anchor, resolvers);\n if (!outcome.ok) return { ok: false, reason: outcome.reason };\n const { hash, kind } = anchorHashOf(anchor, outcome);\n return {\n ok: true,\n current: {\n hash,\n kind,\n lines: outcome.span.endLine - outcome.span.startLine + 1,\n ...(outcome.resolver ? { resolver: outcome.resolver } : {}),\n },\n };\n}\n\n/**\n * Which resolver produced the hash, and — when it differs from the stored one\n * — whether that swap is the whole difference. A regex-stamped anchor re-read\n * by tree-sitter drifts because the resolver changed, not because the code\n * did; named so a reader can tell the two apart before reaching for\n * `--rebaseline`.\n */\nfunction resolverExtras(\n source: string,\n anchor: KbAnchor,\n current: Current,\n): Partial<KbAnchorDriftEntry> {\n return {\n ...(current.resolver ? { resolver: current.resolver } : {}),\n ...(current.hash !== anchor.hash &&\n resolverChanged(source, anchor, current.resolver)\n ? { reason: \"resolver-changed\" as const }\n : {}),\n };\n}\n\nfunction compared(\n anchor: KbAnchor,\n current: Current,\n extra: Partial<KbAnchorDriftEntry> = {},\n): KbAnchorDriftEntry {\n const matched = current.hash === anchor.hash;\n return {\n ...base(anchor),\n state: matched ? \"match\" : \"drifted\",\n currentHash: current.hash,\n hashKind: current.kind,\n diffSize:\n anchor.lines === undefined\n ? null\n : Math.abs(current.lines - anchor.lines),\n ...(matched ? {} : { class: \"changed\" as const }),\n ...extra,\n };\n}\n\nfunction localEntry(\n anchor: KbAnchor,\n read: AnchorRead,\n resolvers: readonly AnchorResolver[],\n): KbAnchorDriftEntry {\n if (!read.ok) return unresolved(anchor, read.reason);\n const found = hashIn(read.source, anchor, resolvers);\n if (!found.ok) return unresolved(anchor, found.reason);\n return compared(\n anchor,\n found.current,\n resolverExtras(read.source, anchor, found.current),\n );\n}\n\n/**\n * A foreign anchor's three states.\n *\n * The pinned commit decides whether the evidence still holds; the default\n * branch only adds `drifted-on-default` on top of a ref that still matches. A\n * default branch that could not be read therefore never downgrades a `ref` hit\n * — offline, a pinned anchor still verifies.\n */\nfunction remoteEntry(\n anchor: KbAnchor,\n remote: Map<string, RemoteRead>,\n resolvers: readonly AnchorResolver[],\n): KbAnchorDriftEntry {\n const repo = anchor.repo as string;\n const key = normalizeRepoUrl(repo);\n const atDefault = remote.get(wantKey(key, undefined, anchor.file));\n const primary = anchor.ref\n ? remote.get(wantKey(key, anchor.ref, anchor.file))\n : atDefault;\n\n if (!primary) return unresolved(anchor, \"remote-unreachable\", repo);\n if (!primary.ok) return unresolved(anchor, primary.reason, repo);\n\n const found = hashIn(primary.source, anchor, resolvers);\n if (!found.ok) return unresolved(anchor, found.reason, repo);\n const current = found.current;\n const extras = resolverExtras(primary.source, anchor, current);\n if (!anchor.ref) return compared(anchor, current, { repo, ...extras });\n if (current.hash !== anchor.hash) {\n return compared(anchor, current, {\n repo,\n ...extras,\n remoteState: \"drifted-from-ref\",\n });\n }\n\n const head = atDefault?.ok\n ? hashIn(atDefault.source, anchor, resolvers)\n : null;\n return head?.ok && head.current.hash !== anchor.hash\n ? {\n ...compared(anchor, head.current, {\n repo,\n ...(head.current.resolver ? { resolver: head.current.resolver } : {}),\n }),\n state: \"drifted\",\n remoteState: \"drifted-on-default\",\n }\n : compared(anchor, current, {\n repo,\n ...extras,\n remoteState: \"matches-ref\",\n });\n}\n","/**\n * The error shape the store throws.\n *\n * Every caller here is an agent, reached through a CLI or a stdio MCP server,\n * so a bare `Error` arrives as an opaque string. What a caller has to act on is\n * carried as fields instead: `code` separates \"pick a different slug and retry\"\n * from \"this input was never going to work\", and `retriable` says whether\n * re-running the same call could succeed.\n *\n * No dependency, deliberately. This is four fields and a constructor; an error\n * library would be a runtime dependency in aid of that.\n */\nexport enum Fault {\n /** The environment is wrong — a path, a permission, a missing directory. */\n Configuration = \"Configuration\",\n /** Nothing the caller did; retrying may work. */\n System = \"System\",\n /** The call was malformed or asked for something impossible. */\n User = \"User\",\n}\n\n/** Machine-readable discriminant, stable across message rewording. */\nexport enum ErrorTypes {\n KbRecordAlreadyExists = \"KbRecordAlreadyExists\",\n KbInvalidConceptId = \"KbInvalidConceptId\",\n KbMissingFlagValue = \"KbMissingFlagValue\",\n KbPackBudgetExceeded = \"KbPackBudgetExceeded\",\n KbRecordNotFound = \"KbRecordNotFound\",\n KbSelfVerification = \"KbSelfVerification\",\n KbStampBaselineUnreadable = \"KbStampBaselineUnreadable\",\n KbStampDigestBaselineAmbiguous = \"KbStampDigestBaselineAmbiguous\",\n KbUnknownLinkRel = \"KbUnknownLinkRel\",\n KbWriteConflict = \"KbWriteConflict\",\n}\n\nexport type ErrorDetails = Record<\n string,\n string | boolean | number | string[] | boolean[] | number[]\n>;\n\nexport interface ErrorProps {\n message: string;\n errorType?: ErrorTypes;\n details?: ErrorDetails;\n name?: string;\n code?: number;\n fault?: Fault;\n retriable?: boolean;\n reportToUser?: boolean;\n}\n\nexport class BaseError extends Error {\n code: number;\n errorType?: ErrorTypes;\n fault?: Fault;\n retriable: boolean;\n reportToUser: boolean;\n details?: ErrorDetails;\n\n constructor(props: ErrorProps) {\n super(props.message);\n this.name = props.name ?? this.constructor.name;\n this.code = props.code ?? 500;\n this.errorType = props.errorType;\n this.fault = props.fault;\n this.retriable = props.retriable ?? true;\n this.reportToUser = props.reportToUser ?? false;\n this.details = props.details;\n }\n}\n","import { BaseError, ErrorTypes, Fault } from \"./errors.js\";\n\n/**\n * Every caller of this store is an agent, reached through a CLI or a stdio MCP\n * server, so a bare `Error` reaches it as an opaque string. The `code` carries\n * the distinction the caller has to act on: 409 means pick a different slug and\n * retry, 400 means the input was never going to work.\n */\nexport class KbRecordAlreadyExistsError extends BaseError {\n constructor(readonly conceptId: string) {\n super({\n message: `kb: ${conceptId} already exists — choose a more specific slug, or write with overwrite`,\n errorType: ErrorTypes.KbRecordAlreadyExists,\n code: 409,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId, action: \"refused\" },\n });\n }\n}\n\nexport class KbRecordNotFoundError extends BaseError {\n constructor(readonly conceptId: string) {\n super({\n message: `kb: ${conceptId} does not exist`,\n errorType: ErrorTypes.KbRecordNotFound,\n code: 404,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId },\n });\n }\n}\n\n/** Retriable, unlike the others: re-reading and re-applying usually succeeds. */\nexport class KbWriteConflictError extends BaseError {\n constructor(readonly conceptId: string) {\n super({\n message: `kb: ${conceptId} changed while it was being updated — re-read and retry`,\n errorType: ErrorTypes.KbWriteConflict,\n code: 409,\n fault: Fault.System,\n retriable: true,\n reportToUser: true,\n details: { conceptId },\n });\n }\n}\n\n/** A generator confirming its own record adds no independent check. */\nexport class KbSelfVerificationError extends BaseError {\n constructor(\n readonly conceptId: string,\n readonly actor: string,\n readonly generatedBy: string,\n ) {\n super({\n message: `kb: ${conceptId} was generated by ${generatedBy}, and a record's generator cannot verify it — only a human or a different actor can`,\n errorType: ErrorTypes.KbSelfVerification,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { conceptId, actor, generatedBy, action: \"refused\" },\n });\n }\n}\n\n/**\n * A pack that will not fit its token budget. Refusal, not truncation: a\n * partial pack is indistinguishable from a complete one, so the caller gets\n * the full picture — how many records, how many tokens, and every id the\n * walk's own limits already cut — and decides whether to raise the budget or\n * tighten the walk.\n */\nexport class KbPackBudgetExceededError extends BaseError {\n constructor(\n readonly recordCount: number,\n readonly approxTokens: number,\n readonly budgetTokens: number,\n readonly excluded: string[],\n ) {\n super({\n message: `kb: a pack of ${recordCount} records is ~${approxTokens} tokens against a budget of ${budgetTokens} — lower hops or maxNodes, or raise the budget`,\n errorType: ErrorTypes.KbPackBudgetExceeded,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { recordCount, approxTokens, budgetTokens, excluded },\n });\n }\n}\n\n/**\n * A `rels` option naming something the walk can never follow.\n *\n * Refused rather than ignored: dropping an unrecognised rel would return an\n * empty impact set — \"nothing breaks\" — indistinguishable from a genuine\n * result. `related_to` is refused here too, since it asserts no dependence and\n * following it can only produce that same empty set.\n */\nexport class KbUnknownLinkRelError extends BaseError {\n constructor(\n readonly rel: string,\n readonly expected: readonly string[],\n ) {\n super({\n message: `kb: ${rel} is not a rel a walk can follow — expected one of ${expected.join(\", \")}`,\n errorType: ErrorTypes.KbUnknownLinkRel,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { rel, expected: expected.join(\", \") },\n });\n }\n}\n\n/**\n * A flag that takes a value, given none.\n *\n * `strauss-kb load --budget` used to read the next argv entry, find\n * nothing, and quietly fall back to the default — so a caller who meant to\n * raise a ceiling got the ceiling they were trying to move, and a typo looked\n * exactly like success. Refusing is the only way that stays visible.\n */\nexport class KbMissingFlagValueError extends BaseError {\n constructor(readonly flag: string) {\n super({\n message: `kb: ${flag} needs a value — pass ${flag} <value> or ${flag}=<value>`,\n errorType: ErrorTypes.KbMissingFlagValue,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { flag },\n });\n }\n}\n\nexport class KbInvalidConceptIdError extends BaseError {\n constructor(message: string, details: Record<string, string>) {\n super({\n message: `kb: ${message}`,\n errorType: ErrorTypes.KbInvalidConceptId,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details,\n });\n }\n}\n\n/** `--since` named a baseline that is neither a digest nor a readable stamp. */\nexport class KbStampBaselineError extends BaseError {\n constructor(readonly since: string) {\n super({\n message: `kb: --since ${since} is neither a 64-character digest nor a readable stamp file`,\n errorType: ErrorTypes.KbStampBaselineUnreadable,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { since },\n });\n }\n}\n\n/** `--since` named a digest while more than one base is being stamped. */\nexport class KbStampDigestBaselineError extends BaseError {\n constructor(readonly since: string) {\n super({\n message: `kb: --since ${since} is a digest, which needs --bundle (one base) — a file baseline works for many`,\n errorType: ErrorTypes.KbStampDigestBaselineAmbiguous,\n code: 400,\n fault: Fault.User,\n retriable: false,\n reportToUser: true,\n details: { since },\n });\n }\n}\n","import type {\n KbContextBudgets,\n KbMergedPins,\n KbPinsManifest,\n} from \"./model.js\";\n\n/** Sane integers only; anything else is ignored, not an error. */\nfunction asBudgets(value: unknown): KbContextBudgets {\n if (value === null || typeof value !== \"object\") return {};\n const table = value as Record<string, unknown>;\n const pick = (key: string, min: number) => {\n const raw = table[key];\n return typeof raw === \"number\" && Number.isInteger(raw) && raw >= min\n ? raw\n : undefined;\n };\n const budgetTokens = pick(\"budgetTokens\", 1);\n // 0 is meaningful — \"full-under off\", overriding a `default` that set it.\n const fullUnderTokens = pick(\"fullUnderTokens\", 0);\n // An empty array is meaningful too: it lifts a `default`'s exclusions.\n const raw = table[\"excludeTags\"];\n const excludeTags = Array.isArray(raw)\n ? raw.filter((tag): tag is string => typeof tag === \"string\" && tag !== \"\")\n : undefined;\n return {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens !== undefined ? { fullUnderTokens } : {}),\n ...(excludeTags ? { excludeTags } : {}),\n };\n}\n\n/**\n * One manifest's budgets for one profile: the named profile's values over the\n * manifest's `\"default\"` entry. What is absent here falls through to the\n * caller's built-ins — a manifest narrows, it never has to be complete.\n */\nexport function contextProfileBudgets(\n manifest: KbPinsManifest,\n profile?: string,\n): KbContextBudgets {\n const table = manifest.context;\n if (table === null || typeof table !== \"object\") return {};\n const entries = table as Record<string, unknown>;\n return {\n ...asBudgets(entries[\"default\"]),\n ...(profile ? asBudgets(entries[profile]) : {}),\n };\n}\n\n/**\n * Budgets across the layers: user underneath, local over it, project on top —\n * the committed file is the workspace's word — and explicit flags above all\n * of this, applied by the caller.\n */\nexport function mergedContextBudgets(\n merged: KbMergedPins,\n profile?: string,\n): KbContextBudgets {\n const layered = ([\"user\", \"local\", \"project\"] as const).map((layer) => {\n const manifest = merged.manifests[layer];\n return manifest ? contextProfileBudgets(manifest, profile) : {};\n });\n return { ...layered[0], ...layered[1], ...layered[2] };\n}\n","import type { KbPinLayer } from \"./model.js\";\n\nexport class KbPinsMalformedError extends Error {\n constructor(file: string, cause: string) {\n super(`pin manifest ${file} is not readable (${cause}) — fix or remove it`);\n this.name = \"KbPinsMalformedError\";\n }\n}\n\nexport class KbBaseFrozenError extends Error {\n constructor(bundlePath: string, layer: KbPinLayer) {\n super(\n `${bundlePath} is frozen (read-only) by this workspace's ${layer} pin manifest — re-pin with --unfreeze, or unpin, to change it`,\n );\n this.name = \"KbBaseFrozenError\";\n }\n}\n","import { resolve } from \"node:path\";\nimport { KbBaseFrozenError } from \"./errors.js\";\nimport { readMergedPins } from \"./layers.js\";\n\n/**\n * Refuses when a write would land in a base this workspace froze. Called by\n * every mutating command; a workspace that pinned a base `--frozen` said the\n * base is concluded, and a quiet write past that would be exactly the silent\n * drift the pin was meant to stop.\n */\nexport async function assertBaseNotFrozen(\n workspaceDir: string,\n bundlePath: string,\n): Promise<void> {\n const merged = await readMergedPins(workspaceDir);\n const absolute = resolve(bundlePath);\n const pin = merged.pins.find((entry) => entry.absolutePath === absolute);\n if (pin?.frozen === true) {\n throw new KbBaseFrozenError(pin.path, pin.layer);\n }\n}\n","import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport { KbPinsMalformedError } from \"./errors.js\";\nimport {\n PIN_LAYERS,\n PINS_FILE,\n PINS_LOCAL_FILE,\n pinsManifestSchema,\n type KbMergedPin,\n type KbMergedPins,\n type KbPinLayer,\n type KbPinsManifest,\n} from \"./model.js\";\n\nfunction userRoot(): string {\n return process.env.STRAUSS_KB_USER_ROOT || homedir();\n}\n\n/** The directory a layer's stored paths resolve against. */\nexport function layerRoot(workspaceDir: string, layer: KbPinLayer): string {\n return layer === \"user\" ? userRoot() : resolve(workspaceDir);\n}\n\nfunction layerFile(workspaceDir: string, layer: KbPinLayer): string {\n return join(\n layerRoot(workspaceDir, layer),\n layer === \"local\" ? PINS_LOCAL_FILE : PINS_FILE,\n );\n}\n\n/**\n * One layer's manifest, or an empty one when the file is missing.\n *\n * A malformed file throws rather than being treated as empty: every write path\n * does a full rewrite, and rewriting over content we could not read would\n * destroy the one copy of it. Read-only consumers that must stay silent\n * (`context` from a session hook, the merged reader) skip malformed layers\n * themselves.\n */\nexport async function readPinsLayer(\n workspaceDir: string,\n layer: KbPinLayer,\n): Promise<KbPinsManifest> {\n const file = layerFile(workspaceDir, layer);\n let raw: string;\n try {\n raw = await readFile(file, \"utf8\");\n } catch {\n return { pins: [] };\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new KbPinsMalformedError(\n file,\n error instanceof Error ? error.message : \"invalid JSON\",\n );\n }\n const manifest = pinsManifestSchema.safeParse(parsed);\n if (!manifest.success) {\n throw new KbPinsMalformedError(\n file,\n manifest.error.issues[0]?.message ?? \"invalid shape\",\n );\n }\n return manifest.data;\n}\n\nexport async function writePinsLayer(\n workspaceDir: string,\n layer: KbPinLayer,\n manifest: KbPinsManifest,\n): Promise<void> {\n const file = layerFile(workspaceDir, layer);\n await mkdir(dirname(file), { recursive: true });\n await writeFile(file, `${JSON.stringify(manifest, null, 2)}\\n`, \"utf8\");\n}\n\n/** Where a stored pin points, resolved against its layer's root. */\nexport function resolvePinPath(rootDir: string, path: string): string {\n return isAbsolute(path)\n ? resolve(path)\n : resolve(rootDir, path.split(\"/\").join(sep));\n}\n\n/** How a base is spelled in a manifest: relative to the layer root, forward slashes. */\nexport function storablePath(rootDir: string, bundlePath: string): string {\n const rel = relative(resolve(rootDir), resolve(bundlePath));\n return (rel === \"\" ? \".\" : rel).split(sep).join(\"/\");\n}\n\n/**\n * All three layers, merged. A malformed layer is skipped rather than thrown:\n * this feeds hooks at every session start, and one broken personal file must\n * not silence the team's pins — `pin`/`unpin` against the broken layer still\n * refuse loudly.\n */\nexport async function readMergedPins(\n workspaceDir: string,\n): Promise<KbMergedPins> {\n const manifests: Partial<Record<KbPinLayer, KbPinsManifest>> = {};\n const pins: KbMergedPin[] = [];\n const seen = new Set<string>();\n\n for (const layer of PIN_LAYERS) {\n let manifest: KbPinsManifest;\n try {\n manifest = await readPinsLayer(workspaceDir, layer);\n } catch {\n continue;\n }\n manifests[layer] = manifest;\n const root = layerRoot(workspaceDir, layer);\n for (const entry of manifest.pins) {\n const absolutePath = resolvePinPath(root, entry.path);\n if (seen.has(absolutePath)) continue;\n seen.add(absolutePath);\n pins.push({ ...entry, layer, absolutePath });\n }\n }\n return { pins, manifests };\n}\n","import { join } from \"node:path\";\nimport { z } from \"zod\";\n\n/**\n * Pin manifests, in three layers.\n *\n * Pins are workspace state, not base state: they record which bases a session\n * should be shown at every context birth. The pinned base is never touched —\n * not even its log — because a base must remain copyable without knowing who\n * pins it.\n *\n * The layers, nearest wins when the same base appears in more than one:\n *\n * | layer | file | for |\n * | ------- | --------------------------------------- | -------------------------- |\n * | project | <workspace>/.strauss/kb-pins.json | committed, the team's pins |\n * | local | <workspace>/.strauss/kb-pins.local.json | personal, gitignored |\n * | user | ~/.strauss/kb-pins.json | personal, every workspace |\n *\n * Every manifest's paths resolve against its own root — the workspace for\n * project and local, the home directory for user — so each file is portable\n * with the tree it belongs to. `STRAUSS_KB_USER_ROOT` overrides the user root\n * (tests, unusual homes).\n */\nexport const PINS_FILE = join(\".strauss\", \"kb-pins.json\");\nexport const PINS_LOCAL_FILE = join(\".strauss\", \"kb-pins.local.json\");\n\nexport const PIN_LAYERS = [\"project\", \"local\", \"user\"] as const;\nexport type KbPinLayer = (typeof PIN_LAYERS)[number];\n\n/**\n * Primary state — it records an intent nothing else holds — but trivially\n * rewritable, so a full rewrite on change is fine and no append log is needed.\n * Unknown keys are preserved on rewrite, the same tolerance the record reader\n * extends to frontmatter it did not write.\n */\nexport const pinSchema = z\n .object({\n /** Relative to the manifest's root, so the file is committable. */\n path: z.string().min(1),\n pinnedAt: z.string().min(1).optional(),\n /**\n * How `context` renders this base. `full` preloads the whole base into\n * the block regardless of the full-under threshold — for a base whose\n * contents should simply be present, the way an ADR base should be —\n * still answering to the block budget, with an index fallback that says\n * so when it cannot fit. `index` never upgrades, whatever the threshold.\n * Absent: the profile's full-under threshold decides. Invalid values\n * degrade to absent rather than failing the manifest.\n */\n mode: z.enum([\"full\", \"index\"]).optional().catch(undefined),\n /**\n * Context profiles this pin surfaces in (e.g. only at session-start,\n * not per turn). Absent: every profile. A run without a profile sees\n * every pin. A base that only matters to one skill is better loaded by\n * that skill at point of use than pinned at all — pins are what every\n * session should see.\n */\n profiles: z.array(z.string()).optional().catch(undefined),\n /**\n * The base is concluded — a finished piece of research, a frozen ADR\n * set. Write commands against it refuse while this workspace holds the\n * pin, and `context` labels it read-only. Workspace policy, not base\n * state: the base itself stays copyable and writable elsewhere.\n */\n frozen: z.boolean().optional().catch(undefined),\n })\n .passthrough();\n\nexport const pinsManifestSchema = z\n .object({\n pins: z.array(pinSchema).default([]),\n /**\n * Per-repo budgets for the `context` command, keyed by profile —\n * `\"session-start\"`, `\"compact\"`, `\"turn\"`, or `\"default\"` for all of\n * them. Deliberately untyped here: a typo'd budget must degrade to the\n * built-in default, not make the whole manifest unreadable and silence\n * the index at every session start. `contextProfileBudgets` does the\n * tolerant read.\n */\n context: z.unknown().optional(),\n })\n .passthrough();\n\nexport type KbPin = z.infer<typeof pinSchema>;\nexport type KbPinsManifest = z.infer<typeof pinsManifestSchema>;\n\n/** One profile's `context` settings, from the manifest or the built-ins. */\nexport type KbContextBudgets = {\n budgetTokens?: number;\n fullUnderTokens?: number;\n /**\n * Frontmatter tags whose records this profile leaves out of the block —\n * `review`, say, kept out of session-start without unpinning the base.\n */\n excludeTags?: string[];\n};\n\n/** A pin as the merged view hands it back: entry + where it came from. */\nexport type KbMergedPin = KbPin & {\n layer: KbPinLayer;\n absolutePath: string;\n};\n\nexport type KbMergedPins = {\n /** Effective pins after dedup — nearest layer wins per resolved path. */\n pins: KbMergedPin[];\n /** Per-layer manifests that parsed, for budget merging. */\n manifests: Partial<Record<KbPinLayer, KbPinsManifest>>;\n};\n\n/** One pinned base, with whether it currently resolves to anything readable. */\nexport type KbPinStatus = {\n /** As stored — relative to its layer's root. */\n path: string;\n layer: KbPinLayer;\n pinnedAt: string | null;\n absolutePath: string;\n /** The directory exists and yielded at least one parseable record. */\n valid: boolean;\n recordCount: number;\n mode: \"full\" | \"index\" | null;\n profiles: string[] | null;\n frozen: boolean;\n};\n\nexport type KbPinResult = {\n path: string;\n layer: KbPinLayer;\n pinnedAt: string;\n alreadyPinned: boolean;\n mode?: \"full\" | \"index\";\n profiles?: string[];\n frozen?: boolean;\n /** Set when the path holds no readable records — pinned anyway. */\n warning?: string;\n};\n\nexport type KbPinOptions = {\n mode?: \"full\" | \"index\";\n profiles?: string[];\n frozen?: boolean;\n /** Which manifest to write. Defaults to the committed project layer. */\n layer?: KbPinLayer;\n};\n","import type { KbStore } from \"../kb-store.js\";\nimport { readMergedPins } from \"./layers.js\";\nimport type { KbPinStatus } from \"./model.js\";\n\n/** Every effective pin across the layers, with whether it points at records. */\nexport async function listPins(\n store: KbStore,\n workspaceDir: string,\n): Promise<KbPinStatus[]> {\n const merged = await readMergedPins(workspaceDir);\n return Promise.all(\n merged.pins.map(async (entry) => {\n const records = await store.list(entry.absolutePath);\n return {\n path: entry.path,\n layer: entry.layer,\n pinnedAt: entry.pinnedAt ?? null,\n absolutePath: entry.absolutePath,\n valid: records.length > 0,\n recordCount: records.length,\n mode: entry.mode ?? null,\n profiles: entry.profiles ?? null,\n frozen: entry.frozen === true,\n };\n }),\n );\n}\n","import type { KbStore } from \"../kb-store.js\";\nimport {\n layerRoot,\n readPinsLayer,\n resolvePinPath,\n storablePath,\n writePinsLayer,\n} from \"./layers.js\";\nimport type { KbPin, KbPinOptions, KbPinResult } from \"./model.js\";\n\n/**\n * Adds a base to one layer's manifest. Idempotent — re-pinning a pinned path\n * with no options returns the existing entry untouched, and re-pinning with\n * `mode`, `profiles`, or `frozen` updates just those fields, which is how a\n * pin's rendering or writability is changed. A path that is not (yet) a valid\n * base succeeds with a warning: bases are routinely pinned before they are\n * populated, the same way records link to records that do not exist yet.\n */\nexport async function pinBase(\n store: KbStore,\n workspaceDir: string,\n bundlePath: string,\n at: string,\n options: KbPinOptions = {},\n): Promise<KbPinResult> {\n const layer = options.layer ?? \"project\";\n const root = layerRoot(workspaceDir, layer);\n const manifest = await readPinsLayer(workspaceDir, layer);\n const absolute = resolvePinPath(root, storablePath(root, bundlePath));\n\n const existing = manifest.pins.find(\n (entry) => resolvePinPath(root, entry.path) === absolute,\n );\n const records = await store.list(absolute);\n const warning =\n records.length === 0\n ? `no records found at ${absolute} — pinned anyway; bases are routinely pinned before they are populated`\n : undefined;\n\n const fields = {\n ...(options.mode ? { mode: options.mode } : {}),\n ...(options.profiles?.length ? { profiles: options.profiles } : {}),\n ...(options.frozen !== undefined ? { frozen: options.frozen } : {}),\n };\n\n if (existing) {\n const updated: KbPin = { ...existing, ...fields };\n if (Object.keys(fields).length) {\n await writePinsLayer(workspaceDir, layer, {\n ...manifest,\n pins: manifest.pins.map((entry) =>\n entry === existing ? updated : entry,\n ),\n });\n }\n return {\n path: existing.path,\n layer,\n pinnedAt: existing.pinnedAt ?? at,\n alreadyPinned: true,\n ...(updated.mode ? { mode: updated.mode } : {}),\n ...(updated.profiles ? { profiles: updated.profiles } : {}),\n ...(updated.frozen !== undefined ? { frozen: updated.frozen } : {}),\n ...(warning ? { warning } : {}),\n };\n }\n\n const entry: KbPin = {\n path: storablePath(root, bundlePath),\n pinnedAt: at,\n ...fields,\n };\n await writePinsLayer(workspaceDir, layer, {\n ...manifest,\n pins: [...manifest.pins, entry],\n });\n return {\n path: entry.path,\n layer,\n pinnedAt: at,\n alreadyPinned: false,\n ...fields,\n ...(warning ? { warning } : {}),\n };\n}\n","import { resolve } from \"node:path\";\nimport {\n layerRoot,\n readPinsLayer,\n resolvePinPath,\n storablePath,\n writePinsLayer,\n} from \"./layers.js\";\nimport { PIN_LAYERS, type KbPinLayer, type KbPinsManifest } from \"./model.js\";\n\n/**\n * Removes a base from every layer that holds it — unpinned means gone, not\n * \"gone from one file and still injected from another\". A malformed layer is\n * skipped (it cannot be rewritten safely); the layers actually touched are\n * reported.\n */\nexport async function unpinBase(\n workspaceDir: string,\n bundlePath: string,\n): Promise<{ path: string; removed: boolean; layers: KbPinLayer[] }> {\n const layers: KbPinLayer[] = [];\n for (const layer of PIN_LAYERS) {\n const root = layerRoot(workspaceDir, layer);\n let manifest: KbPinsManifest;\n try {\n manifest = await readPinsLayer(workspaceDir, layer);\n } catch {\n continue;\n }\n const absolute = resolvePinPath(root, storablePath(root, bundlePath));\n const kept = manifest.pins.filter(\n (entry) => resolvePinPath(root, entry.path) !== absolute,\n );\n if (kept.length !== manifest.pins.length) {\n await writePinsLayer(workspaceDir, layer, { ...manifest, pins: kept });\n layers.push(layer);\n }\n }\n return {\n path: storablePath(resolve(workspaceDir), bundlePath),\n removed: layers.length > 0,\n layers,\n };\n}\n","import { z } from \"zod\";\nimport { KbMissingFlagValueError } from \"../kb-errors.js\";\nimport type { KbStore } from \"../kb-store.js\";\n\n/**\n * Every operation a knowledge base exposes, defined once.\n *\n * The CLI and the MCP server are both projections of this table. Kept apart\n * they drift within a day — fourteen commands against six tools — which is the\n * same failure as a schema restated in prose beside the code that enforces it,\n * one level up. A command added to the table appears in both surfaces or in\n * neither, and a test asserts exactly that.\n *\n * The two differ only in how arguments arrive: MCP passes an object matching\n * `input`, while the CLI has to turn positional argv into the same object.\n * `fromArgv` is that adapter and is the only per-surface code a command needs.\n *\n * One file per command in this folder; `index.ts` assembles the table.\n */\nexport type KbCommandContext = {\n store: KbStore;\n actor: string;\n now: () => string;\n};\n\nexport type KbCommand<Shape extends z.ZodRawShape = z.ZodRawShape> = {\n /** CLI verb. */\n name: string;\n /**\n * MCP tool name. Absent only for CLI-only plumbing (`sync-instructions`),\n * which exists to edit files for hooks and instruction blocks rather than to\n * give an agent a capability — the capability, \"get the pinned context\n * block\", is `kb_context`.\n */\n tool?: string;\n /** Argument spelling for CLI usage output. */\n usage: string;\n /** Shown to an agent choosing a tool, so it carries the judgment too. */\n description: string;\n input: z.ZodObject<Shape>;\n /**\n * Positional argv → the same object MCP receives. `bundleExplicit` says\n * whether `--bundle` was actually passed, for the one command whose meaning\n * turns on it: `stamp` with no bundle stamps every pinned base.\n */\n fromArgv(\n argv: string[],\n bundlePath: string,\n stdin: () => Promise<string>,\n bundleExplicit?: boolean,\n ): Promise<unknown> | unknown;\n run(\n ctx: KbCommandContext,\n input: z.infer<z.ZodObject<Shape>>,\n ): Promise<unknown>;\n /**\n * A human-readable form of the result, for the CLI. Where it exists the CLI\n * prints it and `--json` asks for the machine shape instead; MCP always gets\n * the machine shape, since a tool result is parsed rather than read.\n *\n * Separate from `run` rather than rendered inside it — as `pack` does, whose\n * result *is* a document — because a command whose result is a report needs\n * both forms: the table for a person, and the object for `failsWhen` and for\n * anything downstream.\n */\n render?(result: unknown): string;\n /**\n * Turns a result into a non-zero exit for the CLI. A check that reports a\n * problem has succeeded as a command and failed as a check, and a shell\n * caller can only see the difference through the exit code.\n *\n * The input comes too, so a command can make the exit conditional on a flag\n * the caller passed rather than on the result alone.\n */\n failsWhen?(result: unknown, input: z.infer<z.ZodObject<Shape>>): boolean;\n};\n\nexport const bundlePath = z\n .string()\n .min(1)\n .describe(\"Absolute path to the knowledge base directory.\");\n\nexport const conceptId = z.string().min(1).describe(\"e.g. decision.cursor-v2\");\n\n/**\n * The tag filter every read surface shares. AND, and no vocabulary: `tags` is\n * free text in frontmatter, so matching is exact and an unknown tag is empty.\n */\nexport const TAGS = z\n .array(z.string().min(1))\n .optional()\n .describe(\n \"Keep only records carrying every one of these frontmatter tags. Matched exactly.\",\n );\n\n/**\n * Where the code an anchor points at lives, for the drift check.\n *\n * Pass it whenever the base is not inside the tree it describes: the default is\n * the working directory, where a bundle read from elsewhere finds none of its\n * anchored files. `KbStore.detectDrift` suppresses that case rather than\n * reporting the whole base as drifted.\n */\nexport const REPO_ROOT = z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Where the anchored source lives, for the drift check. Defaults to the working directory.\",\n );\n\nexport function define<Shape extends z.ZodRawShape>(\n command: KbCommand<Shape>,\n): KbCommand<z.ZodRawShape> {\n return command as unknown as KbCommand<z.ZodRawShape>;\n}\n\n/**\n * The value of `--name`, in either spelling, or undefined when it is absent.\n *\n * Both `--name value` and `--name=value` are accepted, because a caller who\n * writes the second and is silently given the default has been told the\n * opposite of what happened.\n *\n * A flag present with no value is an error rather than an absent flag, for the\n * same reason. `strauss-kb load --budget` reading past the end of argv and\n * falling back to the default would hand the caller the exact ceiling they were\n * trying to move, and a trailing typo would be indistinguishable from success.\n * Note\n * that a following token starting with `--` counts as no value: `--budget\n * --all` is a missing value, not a budget of \"--all\".\n */\nexport function argvFlag(argv: string[], name: string): string | undefined {\n const joined = argv.find((arg) => arg.startsWith(`${name}=`));\n if (joined !== undefined) {\n const value = joined.slice(name.length + 1);\n if (!value) throw new KbMissingFlagValueError(name);\n return value;\n }\n\n const at = argv.indexOf(name);\n if (at === -1) return undefined;\n\n const value = argv[at + 1];\n if (value === undefined || value.startsWith(\"--\")) {\n throw new KbMissingFlagValueError(name);\n }\n return value;\n}\n\n/**\n * Every value of a repeatable `--name`, in both spellings, in argv order.\n * Empty when the flag is absent; a flag with no value is an error, as above.\n */\nexport function argvFlags(argv: string[], name: string): string[] {\n const values: string[] = [];\n for (const [at, arg] of argv.entries()) {\n if (arg.startsWith(`${name}=`)) {\n const value = arg.slice(name.length + 1);\n if (!value) throw new KbMissingFlagValueError(name);\n values.push(value);\n } else if (arg === name) {\n const value = argv[at + 1];\n if (value === undefined || value.startsWith(\"--\")) {\n throw new KbMissingFlagValueError(name);\n }\n values.push(value);\n }\n }\n return values;\n}\n\n/**\n * argv with every occurrence of the named flags, and their values, removed —\n * for the verbs whose remaining words are free prose rather than positionals.\n */\nexport function argvWithout(argv: string[], ...names: string[]): string[] {\n const kept: string[] = [];\n for (let at = 0; at < argv.length; at += 1) {\n const arg = argv[at] as string;\n if (names.some((name) => arg.startsWith(`${name}=`))) continue;\n if (names.includes(arg)) {\n at += 1;\n continue;\n }\n kept.push(arg);\n }\n return kept;\n}\n\n/**\n * The first positional after the verb, once the named value-taking flags are\n * out of the way — so `list --tag review decision` still sees the type. Read\n * at a fixed index it would be dropped whenever a flag came first.\n */\nexport function argvPositional(\n argv: string[],\n ...names: string[]\n): string | undefined {\n return argvWithout(argv.slice(1), ...names).find(\n (arg) => !arg.startsWith(\"--\"),\n );\n}\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const answerCommand = define({\n name: \"answer\",\n tool: \"kb_answer\",\n usage: \"answer <concept-id> <answer...>\",\n description:\n \"Resolve an open question: set status, stamp who and when, append an Answer section. If the answer overturns a decision or assumption, supersede that record explicitly.\",\n input: z.object({ bundlePath, conceptId, answer: z.string().min(1) }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n answer: argv.slice(2).join(\" \").trim(),\n }),\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, answer },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.answer(path, id, answer, actor);\n return { conceptId: record.conceptId };\n },\n});\n","import { z } from \"zod\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const backlinksCommand = define({\n name: \"backlinks\",\n tool: \"kb_backlinks\",\n usage: \"backlinks <concept-id>\",\n description:\n \"Who points at this record: every inbound typed causal link (`strauss_links`), one hop, every rel including `related_to`, each with its rel and the standing of the record that made it. Use it when you need the exact edges — reviewing or renaming a record.\",\n input: z.object({ bundlePath, conceptId }),\n fromArgv: (argv, path) => ({ bundlePath: path, conceptId: argv[1] }),\n run: async ({ store }, { bundlePath: path, conceptId: id }) =>\n store.backlinks(path, id),\n});\n","import { z } from \"zod\";\nimport type { KbStanding } from \"../adjudicate.js\";\nimport { renderCatalogLine, type KbCatalogResult } from \"../catalog.js\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport {\n argvFlags,\n argvPositional,\n bundlePath,\n define,\n TAGS,\n} from \"./model.js\";\n\nexport const catalogCommand = define({\n name: \"catalog\",\n tool: \"kb_catalog\",\n usage: \"catalog [type] [--tag T]...\",\n description:\n \"Lists every record as one line — concept id, type, title, standing, and a stale flag — at roughly thirty tokens each. Pick this over kb_load once kb_load refuses: kb_catalog never refuses. Superseded records show only their replacement; fetch bodies with kb_load, kb_pack, kb_query, or kb_trace.\",\n input: z.object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES).optional(),\n tags: TAGS,\n }),\n fromArgv: (argv, path) => {\n const tags = argvFlags(argv, \"--tag\");\n // The type is the first positional, in either order: a flag in the slot is\n // a flag, and `catalog --tag review decision` still narrows by type.\n const type = argvPositional(argv, \"--tag\");\n return {\n bundlePath: path,\n ...(type ? { type } : {}),\n ...(tags.length ? { tags } : {}),\n };\n },\n run: async ({ store }, { bundlePath: path, type, tags }) =>\n render(\n await store.catalog(path, {\n ...(type ? { type } : {}),\n ...(tags ? { tags } : {}),\n }),\n path,\n type,\n tags,\n ),\n});\n\n/**\n * Markdown, like `index` and `pack`, because the value is one line per record\n * and JSON would spend a third of the tokens on repeated key names.\n */\nfunction render(\n result: KbCatalogResult,\n bundle: string,\n type?: string,\n tags?: string[],\n): string {\n // The filter is named in the heading: an empty catalog otherwise reads as an\n // empty base. Tags carry a prefix so a tag cannot read as a type.\n const narrowed = [\n ...(type ? [type] : []),\n ...(tags?.length ? [`tags: ${tags.join(\", \")}`] : []),\n ].join(\" · \");\n const lines = [\n `# KB Catalog${narrowed ? ` — ${narrowed}` : \"\"}`,\n `bundle: ${bundle}`,\n `${count(result.recordCount, \"record\")}: ${standingCounts(result)}`,\n ];\n\n // Staleness is a flag over a standing, not a standing — a current record can\n // be stale. Adding it to the run above would make the counts stop summing to\n // the record count, which is the one thing that line is for.\n if (result.staleCount) {\n lines.push(\n `${result.staleCount} stale — a flag over the standings above, not one of them`,\n );\n }\n\n lines.push(\"\");\n\n if (!result.entries.length) {\n lines.push(\n narrowed\n ? `(no records matching ${narrowed})`\n : \"(no records — this base is empty)\",\n );\n } else {\n for (const entry of result.entries) lines.push(renderCatalogLine(entry));\n }\n\n lines.push(\n \"\",\n \"Bodies are not here: kb_pack <conceptId> for the neighbourhood around one record, kb_load for the whole base when it fits the budget, kb_query for a lookup by wording, kb_trace <conceptId> for how a position was arrived at.\",\n );\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Every standing that has a record, in order of how live it is. Zero counts are\n * dropped as noise, and what remains sums to the record count — a reader can\n * add the line up and see that nothing went missing.\n */\nfunction standingCounts(result: KbCatalogResult): string {\n const ORDER: readonly KbStanding[] = [\n \"current\",\n \"open\",\n \"unsettled\",\n \"rejected\",\n \"superseded\",\n ];\n const parts = ORDER.filter((standing) => result.standings[standing]).map(\n (standing) => `${result.standings[standing]} ${standing}`,\n );\n return parts.length ? parts.join(\" · \") : \"none\";\n}\n\nfunction count(value: number, noun: string): string {\n return `${value} ${value === 1 ? noun : `${noun}s`}`;\n}\n","import type {\n KbAnchorDriftEntry,\n KbDriftClass,\n} from \"./anchor-resolver/index.js\";\nimport { isUncheckedReason } from \"./remote-repo/index.js\";\nimport type { KbRecord, KbRecordStatus } from \"./kb-record.schema.js\";\n\n/**\n * Why a matched record must not be read as a plain answer.\n *\n * Relevance and standing are different questions, and ranking answers only the\n * first. A superseded record is usually the older, longer, more general one and\n * its replacement is usually a narrowing, so any similarity measure favours the\n * record that is no longer true. Every hit therefore carries its standing, and\n * the caller is never handed a bare match.\n */\nexport type KbWarning =\n /** Explicitly not adopted. The most dangerous status to return unmarked: a\n * well-formed assertion of what someone decided *not* to do. */\n | { kind: \"rejected\" }\n | { kind: \"superseded\"; by: string[] }\n /** Not settled. Acting on a proposal as though it were a decision is a defect. */\n | { kind: \"unsettled\"; status: KbRecordStatus }\n /** Says a matter is unresolved. Valuable as a result, never as an answer. */\n | { kind: \"unresolved-question\" }\n /** `strauss_superseded_by` names a record that is not in the bundle. */\n | { kind: \"broken-chain\"; missing: string }\n | { kind: \"chain-cycle\"; through: string[] }\n /** Two records claim to replace this one; picking either would be a guess. */\n | { kind: \"forked-chain\"; heads: string[] }\n | { kind: \"stale\"; staleAfter: string }\n | { kind: \"unverified\" }\n /** The code this record anchors to has changed since its hash was recorded —\n * the record may describe code that no longer exists in that form. */\n | { kind: \"drifted\"; anchors: KbWarningAnchor[] }\n /** A foreign anchor nothing could check: the remote was unreachable, refused,\n * or the run was offline. Neither drift nor a clean match. */\n | { kind: \"unchecked\"; anchors: KbWarningAnchor[] };\n\nexport type KbWarningAnchor = {\n file: string;\n symbol?: string;\n /** `null` when the anchor recorded no line count — size unknown. */\n diffSize: number | null;\n reason?: string;\n /** Set only for an anchor resolved against another repository. */\n repo?: string;\n remoteState?: string;\n /**\n * `gone` or `changed` — what a hash comparison alone can settle. `moved` and\n * `cosmetic` cost a repository search and a git read, so they are\n * `kb_reassess`'s answer, not a read path's.\n */\n class?: KbDriftClass;\n};\n\nexport type KbStanding =\n \"current\" | \"superseded\" | \"rejected\" | \"unsettled\" | \"open\";\n\nexport type KbAdjudicated = {\n record: KbRecord;\n standing: KbStanding;\n /** Where the supersession chain ends. Empty when it is broken or cyclic. */\n heads: KbRecord[];\n warnings: KbWarning[];\n};\n\nconst STANDING: Record<KbRecordStatus, KbStanding> = {\n accepted: \"current\",\n resolved: \"current\",\n draft: \"unsettled\",\n proposed: \"unsettled\",\n open: \"open\",\n rejected: \"rejected\",\n superseded: \"superseded\",\n};\n\n/**\n * Attaches standing to records a search returned.\n *\n * Adjudicating rather than filtering, deliberately. A filtered result set is\n * invisible: the caller cannot tell it missed anything, so a dropped record is\n * worse than a flagged one — it turns a knowable gap into an unknowable one.\n */\nexport function adjudicate(\n hits: KbRecord[],\n bundle: KbRecord[],\n now = new Date(),\n // Precomputed by the caller: this function stays pure and sync, and the fs\n // work of re-resolving anchors lives in detectAnchorDrift.\n anchorDrift?: Map<string, KbAnchorDriftEntry[]>,\n): KbAdjudicated[] {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n return hits.map((record) => {\n const status = record.frontmatter.strauss_status;\n const warnings: KbWarning[] = [];\n let heads: KbRecord[] = [];\n\n if (status === \"superseded\") {\n const resolved = resolveHeads(record, byId);\n heads = resolved.heads;\n warnings.push(...resolved.warnings);\n if (heads.length) {\n warnings.push({\n kind: \"superseded\",\n by: heads.map((head) => head.conceptId),\n });\n }\n } else if (status === \"rejected\") {\n warnings.push({ kind: \"rejected\" });\n } else if (status === \"draft\" || status === \"proposed\") {\n warnings.push({ kind: \"unsettled\", status });\n } else if (status === \"open\") {\n warnings.push({ kind: \"unresolved-question\" });\n }\n\n const staleAfter = record.frontmatter.stale_after;\n if (staleAfter && Date.parse(staleAfter) < now.getTime()) {\n warnings.push({ kind: \"stale\", staleAfter });\n }\n if (!record.frontmatter.verified?.length) {\n warnings.push({ kind: \"unverified\" });\n }\n\n // Split at the one point every read path and `doctor` share, so none of\n // them can report \"no drift\" for an anchor nobody could reach.\n const found = (anchorDrift?.get(record.conceptId) ?? []).filter(\n (entry) => entry.state !== \"match\",\n );\n const unchecked = found.filter((entry) => isUncheckedReason(entry.reason));\n const moved = found.filter((entry) => !isUncheckedReason(entry.reason));\n if (moved.length) {\n warnings.push({ kind: \"drifted\", anchors: moved.map(warningAnchor) });\n }\n if (unchecked.length) {\n warnings.push({\n kind: \"unchecked\",\n anchors: unchecked.map(warningAnchor),\n });\n }\n\n return { record, standing: STANDING[status], heads, warnings };\n });\n}\n\nfunction warningAnchor(entry: KbAnchorDriftEntry): KbWarningAnchor {\n const { file, symbol, diffSize, reason, repo, remoteState } = entry;\n return {\n file,\n ...(symbol !== undefined ? { symbol } : {}),\n diffSize,\n ...(reason !== undefined ? { reason } : {}),\n ...(repo !== undefined ? { repo } : {}),\n ...(remoteState !== undefined ? { remoteState } : {}),\n ...(entry.class !== undefined ? { class: entry.class } : {}),\n };\n}\n\n/**\n * Walks a supersession chain to whatever currently stands in its place.\n *\n * Both directions are followed, not just `strauss_superseded_by`. `supersede()`\n * writes the pair, but a hand-edit can leave one side behind, and a walk that\n * trusts only the forward pointer would silently return a record that something\n * in the bundle openly claims to replace.\n *\n * Resolution happens here rather than being denormalised onto records at write\n * time: a stored head would have to be rewritten on every ancestor whenever a\n * chain grows, which is derived state that goes stale — the failure this design\n * keeps avoiding elsewhere.\n */\nexport function resolveHeads(\n from: KbRecord,\n byId: Map<string, KbRecord>,\n): { heads: KbRecord[]; warnings: KbWarning[] } {\n const warnings: KbWarning[] = [];\n const heads = new Map<string, KbRecord>();\n const seen = new Set<string>([from.conceptId]);\n const queue: KbRecord[] = [from];\n\n while (queue.length) {\n const current = queue.shift() as KbRecord;\n const next = successors(current, byId);\n\n for (const missing of next.missing) {\n warnings.push({ kind: \"broken-chain\", missing });\n }\n if (!next.records.length) {\n if (current.conceptId !== from.conceptId)\n heads.set(current.conceptId, current);\n continue;\n }\n for (const record of next.records) {\n if (seen.has(record.conceptId)) {\n warnings.push({ kind: \"chain-cycle\", through: [...seen] });\n continue;\n }\n seen.add(record.conceptId);\n queue.push(record);\n }\n }\n\n if (heads.size > 1) {\n warnings.push({ kind: \"forked-chain\", heads: [...heads.keys()] });\n }\n return { heads: [...heads.values()], warnings };\n}\n\nfunction successors(\n record: KbRecord,\n byId: Map<string, KbRecord>,\n): { records: KbRecord[]; missing: string[] } {\n const ids = new Set<string>();\n const forward = record.frontmatter.strauss_superseded_by;\n if (forward) ids.add(forward);\n for (const [id, candidate] of byId) {\n if (candidate.frontmatter.strauss_supersedes?.includes(record.conceptId)) {\n ids.add(id);\n }\n }\n\n const records: KbRecord[] = [];\n const missing: string[] = [];\n for (const id of ids) {\n const found = byId.get(id);\n if (found) records.push(found);\n else missing.push(id);\n }\n return { records, missing };\n}\n","import type { KbRecord } from \"./kb-record.schema.js\";\n\n/**\n * Selection by frontmatter `tags`. Matching is exact and no vocabulary is\n * enforced — a tag is whatever a writer put there.\n */\nexport type KbTagFilter = {\n /** AND: a record matches only when it carries every one of these. */\n tags?: string[];\n /** A record carrying any one of these is dropped, even if `tags` matched. */\n excludeTags?: string[];\n};\n\n/**\n * Whether one record survives the filter. An empty filter keeps everything,\n * so every caller can pass one unconditionally.\n */\nexport function matchesTags(record: KbRecord, filter: KbTagFilter): boolean {\n if (!filter.tags?.length && !filter.excludeTags?.length) return true;\n const carried = new Set(record.frontmatter.tags ?? []);\n return (\n (filter.tags ?? []).every((tag) => carried.has(tag)) &&\n !(filter.excludeTags ?? []).some((tag) => carried.has(tag))\n );\n}\n","import { adjudicate, type KbStanding } from \"./adjudicate.js\";\nimport type { KbRecord } from \"./kb-record.schema.js\";\nimport { matchesTags, type KbTagFilter } from \"./kb-tags.js\";\n\n/** One record as the catalog names it — no body, no description, one line. */\nexport type KbCatalogEntry = {\n conceptId: string;\n type: string;\n title: string | null;\n standing: KbStanding;\n /** Where the supersession chain ends. Empty when broken, cyclic, or n/a. */\n supersededBy: string[];\n /** `stale_after` is in the past. The one freshness signal a line can carry. */\n stale: boolean;\n};\n\nexport type KbCatalogResult = {\n entries: KbCatalogEntry[];\n /** Every record the catalog names, filter applied. */\n recordCount: number;\n /**\n * How many records hold each standing. Sums to `recordCount` — every record\n * has exactly one standing, so the reader can see that nothing went missing.\n */\n standings: Record<KbStanding, number>;\n /** Shorthand for `standings.current` — records that simply hold. */\n currentCount: number;\n /** Shorthand for `standings.superseded`. */\n supersededCount: number;\n /**\n * Records whose `stale_after` has passed. A flag over the standings rather\n * than one of them — a current record can be stale — so this deliberately\n * does not participate in the sum.\n */\n staleCount: number;\n};\n\nconst EMPTY_STANDINGS: Record<KbStanding, number> = {\n current: 0,\n superseded: 0,\n rejected: 0,\n unsettled: 0,\n open: 0,\n};\n\n/**\n * The tier-one listing: every record named, nothing spelled out.\n *\n * `load` hands over bodies and `pack` hands over a neighbourhood; both have to\n * decide what the reader can afford. The catalog is the rung below either — one\n * line per record at roughly thirty tokens, so a base far past `load`'s gate\n * still fits in a single call. What it buys is the ability to choose: a reader\n * that can see every id, type, title and standing knows which record to `pack`\n * and knows when no record covers the question at all, which is the conclusion\n * a truncated read can never support.\n *\n * Standing travels on the line for the same reason it travels with every other\n * result here: a title is a claim, and a superseded claim reads exactly like a\n * live one. A superseded entry names its replacement, so the line the reader\n * should follow instead is already in front of them.\n *\n * Unbounded, alone among the read paths. `load` and `pack` refuse past a\n * ceiling because a partial body set reads as a complete one; a catalog has no\n * such failure — it is the rung a caller lands on *because* something else\n * refused, and a second refusal there would leave nowhere to go. The cost is\n * linear and cheap: roughly thirty tokens a record, so a thousand-record base\n * is about 30k and five thousand about 150k. Past that the `type` filter\n * narrows it, and no ceiling is needed to make that available.\n *\n * Deterministic given a fixed `now`: no timestamp is emitted, and the ordering\n * is total down to the concept id, so two catalogs of an unchanged base within\n * one `stale_after` window are byte-identical and diff to nothing. The default\n * clock is the wall clock, so a line can still flip to stale as a date passes —\n * pass `now` when byte-equality has to hold across that boundary.\n */\nexport function catalog(\n bundle: KbRecord[],\n options: { type?: string; now?: Date } & KbTagFilter = {},\n): KbCatalogResult {\n const wanted = options.type\n ? bundle.filter((record) => record.frontmatter.type === options.type)\n : bundle;\n\n // Adjudicated against the whole base, not the filtered slice: a record's\n // replacement may be of another type, and a filter must not turn a\n // superseded record into a current-looking one.\n const entries = adjudicate(wanted, bundle, options.now ?? new Date())\n // Tags cut after adjudication, for the same reason: a tag narrows what the\n // catalog names, never the standing it names it with.\n .filter((hit) => matchesTags(hit.record, options))\n .map((hit) => ({\n conceptId: hit.record.conceptId,\n type: hit.record.frontmatter.type,\n title: hit.record.frontmatter.title ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n stale: hit.warnings.some((warning) => warning.kind === \"stale\"),\n }))\n .sort(byTypeThenTitle);\n\n const standings = { ...EMPTY_STANDINGS };\n for (const entry of entries) standings[entry.standing] += 1;\n\n return {\n entries,\n recordCount: entries.length,\n standings,\n currentCount: standings.current,\n supersededCount: standings.superseded,\n staleCount: entries.filter((entry) => entry.stale).length,\n };\n}\n\n/** Concept id is the tiebreak, so the order is total and therefore stable. */\nfunction byTypeThenTitle(left: KbCatalogEntry, right: KbCatalogEntry): number {\n return (\n byCodeUnit(left.type, right.type) ||\n byCodeUnit(left.title ?? \"\", right.title ?? \"\") ||\n byCodeUnit(left.conceptId, right.conceptId)\n );\n}\n\n/**\n * Code-unit order, not `localeCompare`.\n *\n * `localeCompare` without an explicit locale reads the host's, so the same\n * base sorts differently on two machines — and this output's whole contract is\n * that two catalogs of an unchanged base diff to nothing. A collation nobody\n * configured is not worth a determinism claim that quietly does not hold.\n */\nfunction byCodeUnit(left: string, right: string): number {\n return left < right ? -1 : left > right ? 1 : 0;\n}\n\n/**\n * One entry, as one line.\n *\n * ` · `-separated rather than a table: a table pays for column alignment on\n * every row, and nothing downstream parses these.\n */\nexport function renderCatalogLine(entry: KbCatalogEntry): string {\n const parts = [\n entry.conceptId,\n entry.type,\n entry.title ?? \"(untitled)\",\n entry.standing === \"superseded\"\n ? `superseded → ${entry.supersededBy.join(\", \") || \"(no surviving head)\"}`\n : entry.standing,\n ];\n if (entry.stale) parts.push(\"stale\");\n return `- ${parts.join(\" · \")}`;\n}\n","import { z } from \"zod\";\nimport { buildContext, toHookJson } from \"../kb-context.js\";\nimport { argvFlag, argvFlags, define } from \"./model.js\";\n\nexport const contextCommand = define({\n name: \"context\",\n tool: \"kb_context\",\n usage:\n \"context [--profile NAME] [--budget N] [--full-under N] [--exclude-tag T]... [--format json] [--event NAME]\",\n description:\n \"Index block of pinned bases (ids, titles, standing) for injection at context birth. Takes no bundlePath — reads the workspace pin manifests. Empty when nothing is pinned; refuses over budget rather than truncating. Budget precedence: flags, then the manifest `context[profile]` over `context.default`, then the built-in profile, then package defaults.\",\n input: z.object({\n budgetTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Ceiling on the whole emitted block; past it the command refuses with a list of bases rather than truncating. Defaults to 4000.\",\n ),\n fullUnderTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Per-base rendering threshold, applied before the budget: a base whose complete load fits under this arrives as full records instead of index lines, and the whole block still answers to budgetTokens. Off by default — index-only is the safe default at a context birth, because injected bodies outlive the qualifiers on them; the session-start profile opts tiny bases in at 1500.\",\n ),\n profile: z\n .string()\n .optional()\n .describe(\n \"Named budget set: built-ins are session-start (full-under 1500), compact and turn (budget 2500); the manifests' `context` tables override per repo. Unknown names fall through to defaults rather than failing.\",\n ),\n excludeTags: z\n .array(z.string().min(1))\n .optional()\n .describe(\n \"Frontmatter tags whose records stay out of the block. The base stays pinned and stays readable by tool; resolved like the budgets.\",\n ),\n format: z\n .enum([\"markdown\", \"json\"])\n .optional()\n .describe(\n \"CLI envelope for hook protocols that require strict JSON on stdout. MCP callers omit this — the block itself is identical.\",\n ),\n event: z\n .string()\n .optional()\n .describe(\n \"hookEventName stamped into the JSON envelope. Only meaningful with format=json.\",\n ),\n }),\n fromArgv: (argv) => {\n const budget = argvFlag(argv, \"--budget\");\n const fullUnder = argvFlag(argv, \"--full-under\");\n const profile = argvFlag(argv, \"--profile\");\n const format = argvFlag(argv, \"--format\");\n const event = argvFlag(argv, \"--event\");\n const excludeTags = argvFlags(argv, \"--exclude-tag\");\n return {\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(fullUnder ? { fullUnderTokens: Number(fullUnder) } : {}),\n ...(profile ? { profile } : {}),\n ...(excludeTags.length ? { excludeTags } : {}),\n ...(format ? { format } : {}),\n ...(event ? { event } : {}),\n };\n },\n run: async (\n { store },\n { budgetTokens, fullUnderTokens, profile, excludeTags, format, event },\n ) => {\n const result = await buildContext(store, process.cwd(), {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens ? { fullUnderTokens } : {}),\n ...(profile ? { profile } : {}),\n ...(excludeTags ? { excludeTags } : {}),\n // Degradations — a full pin that could not fit, a refused block — go\n // to stderr as well as into the block itself: stderr is diagnostics on\n // both surfaces (hooks discard it, MCP logs it), so an operator can\n // see budget pressure without reading injected context.\n warn: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n });\n // Empty means empty in both formats: this runs from hooks at every\n // session start and must be silent when there is nothing to say.\n if (!result.block) return \"\";\n return format === \"json\"\n ? toHookJson(result.block, event ?? \"SessionStart\")\n : result.block;\n },\n});\n","import { readFile, writeFile } from \"node:fs/promises\";\nimport { adjudicate } from \"./adjudicate.js\";\nimport { renderIndexLine } from \"./kb-index.js\";\nimport {\n mergedContextBudgets,\n readMergedPins,\n type KbContextBudgets,\n} from \"./kb-pins/index.js\";\nimport type { KbStore } from \"./kb-store.js\";\nimport { matchesTags } from \"./kb-tags.js\";\n\n/**\n * The context block: an index of every pinned base, emitted at context birth.\n *\n * Two failure modes lose a knowledge base to a long session — attention decay,\n * and compaction, which summarises away both loaded records and the early\n * instruction that said to consult them. This block is the layer against both:\n * small enough to re-inject at every session start, and self-instructing, so a\n * re-injection after compaction reads as a refresh rather than a contradiction.\n *\n * It is an index, not the content: concept ids, titles and standing. The\n * bodies stay behind the tools, loaded at the point of use.\n */\n\n/** A stable heading, so re-injection reads as a refresh. */\nconst HEADING = \"## Knowledge bases (pinned)\";\n\n/**\n * Small by design — this block is paid at every context birth, and on some\n * runtimes on every turn. A base wanting more space is `--full-under`'s job.\n */\nconst DEFAULT_CONTEXT_BUDGET = 4_000;\n\n/**\n * What the hooks ask for by name, so the numbers live in one place and a repo\n * can override them in its pin manifest rather than editing hook commands.\n * `session-start` is a fresh window — room for tiny bases to arrive whole.\n * `compact` competes with a summary for a smaller window — index only.\n * `turn` is per-turn injection (Antigravity) — same tight stance as compact.\n */\nexport const CONTEXT_PROFILES: Record<string, KbContextBudgets> = {\n \"session-start\": { fullUnderTokens: 1_500 },\n compact: { budgetTokens: 2_500 },\n turn: { budgetTokens: 2_500 },\n};\n\nexport type KbContextOptions = {\n /** Refuse past this. Defaults to 4000 tokens. */\n budgetTokens?: number;\n /** Emit bases whose full `load` fits under this as records, not index. 0 = off. */\n fullUnderTokens?: number;\n /**\n * A named budget set. Resolution, most specific wins: explicit options,\n * then the manifest's `context[profile]` over its `context.default`, then\n * the built-in profile, then the package defaults. An unknown profile is\n * not an error — it simply falls through; hooks must never break over a\n * name.\n */\n profile?: string;\n /**\n * Frontmatter tags whose records stay out of the block. Resolved like the\n * budgets, and a profile setting rather than a pin's: it says what this\n * context birth wants, so a base stays pinned and stays readable by tool.\n */\n excludeTags?: string[];\n /**\n * Where budget pressure is reported outside the block itself: a full pin\n * that had to degrade to an index, a block that refused. The block already\n * says both to the agent; this says them to the operator's log.\n */\n warn?: (entry: Record<string, unknown>) => void;\n};\n\nexport type KbContextResult = {\n /** The markdown block. Empty when there are no pins — silence, not a stub. */\n block: string;\n /** Refused: over budget. The block then lists the bases instead of the index. */\n refused: boolean;\n approxTokens: number;\n budgetTokens: number;\n bases: { path: string; absolutePath: string; approxTokens: number }[];\n};\n\n/** The crude estimator everything here shares — see kb-store.ts on why. */\nfunction approxTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\nfunction preamble(): string {\n return [\n HEADING,\n \"\",\n \"What follows is an index of this workspace's pinned knowledge bases —\",\n \"concept ids, titles and standing only. The record bodies are NOT in this\",\n \"context.\",\n \"\",\n \"Consult records only through the strauss-kb MCP tools: `kb_load` (the\",\n \"preferred first call), `kb_query`, and `kb_trace`, passing the\",\n \"`bundlePath` listed with each base. Do not read record files directly:\",\n \"a raw file read bypasses supersession resolution, and a superseded or\",\n \"rejected record file reads exactly like a current one — only the store\",\n \"resolves chains and standing.\",\n \"\",\n \"KB content loaded earlier in a long session may have been compacted\",\n \"away. Before answering a question one of these bases governs, load it\",\n \"again at the point of use — reloading a small base costs a few thousand\",\n \"tokens.\",\n ].join(\"\\n\");\n}\n\ntype BaseSection = {\n path: string;\n absolutePath: string;\n body: string;\n mode: \"index\" | \"full\" | \"empty\";\n /**\n * A `mode: full` pin whose bodies exceeded the block budget, emitted as an\n * index instead. Flagged in the section label, never silent — the reader\n * asked for the whole base and must know it is not looking at it.\n */\n degradedFrom?: { approxTokens: number };\n};\n\nasync function renderBase(\n store: KbStore,\n path: string,\n absolutePath: string,\n fullUnderTokens: number,\n pinMode: \"full\" | \"index\" | undefined,\n budgetTokens: number,\n excludeTags: string[],\n): Promise<BaseSection> {\n const bundle = await store.list(absolutePath);\n if (bundle.length === 0) {\n return {\n path,\n absolutePath,\n mode: \"empty\",\n body: \"No readable records yet — pinned ahead of being populated.\",\n };\n }\n\n // A pin's own mode outranks the threshold. `full` preloads the base whole —\n // capped only by the block budget, because past that the whole block\n // refuses anyway; when even that fails, the base degrades to an index and\n // the label says so, never silently. `index` never upgrades.\n const fullCap =\n pinMode === \"full\"\n ? budgetTokens\n : pinMode === \"index\"\n ? 0\n : fullUnderTokens;\n\n let degradedFrom: { approxTokens: number } | undefined;\n if (fullCap > 0) {\n const full = await store.load(absolutePath, {\n budgetTokens: fullCap,\n excludeTags,\n });\n if (!full.loaded && pinMode === \"full\") {\n degradedFrom = { approxTokens: full.approxTokens };\n }\n if (full.loaded) {\n const records = full.records.map((hit) =>\n [\n `#### ${hit.record.conceptId} — ${hit.record.frontmatter.title ?? \"(untitled)\"} (${hit.standing})`,\n \"\",\n hit.record.body.trim(),\n ].join(\"\\n\"),\n );\n const superseded = full.superseded.map(\n (entry) =>\n `- \\`${entry.conceptId}\\` → superseded by ${entry.supersededBy.map((id) => `\\`${id}\\``).join(\", \") || \"(missing replacement)\"}`,\n );\n return {\n path,\n absolutePath,\n mode: \"full\",\n body: [\n ...records,\n ...(superseded.length\n ? [\n \"#### Superseded (bodies withheld — kb_trace reaches them)\",\n ...superseded,\n ]\n : []),\n ].join(\"\\n\\n\"),\n };\n }\n }\n\n // Adjudicated against the whole base, excluded only after: a record kept out\n // of the block still supersedes, so the replacement it names stays right.\n const adjudicated = adjudicate(bundle, bundle).filter((hit) =>\n matchesTags(hit.record, { excludeTags }),\n );\n const lines = adjudicated\n .filter((hit) => hit.standing !== \"superseded\")\n .map((hit) => renderIndexLine(hit.record));\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(\n (hit) =>\n `- \\`${hit.record.conceptId}\\` → superseded by ${hit.heads.map((head) => `\\`${head.conceptId}\\``).join(\", \") || \"(missing replacement)\"}`,\n );\n return {\n path,\n absolutePath,\n mode: \"index\",\n body: [...lines, ...superseded].join(\"\\n\"),\n ...(degradedFrom ? { degradedFrom } : {}),\n };\n}\n\n/**\n * Builds the block, or a refusal that lists the bases — never a truncation. A\n * truncated index is indistinguishable from a complete one, so a reader would\n * take a slice for the whole, which is `load`'s argument one layer up.\n */\nexport async function buildContext(\n store: KbStore,\n workspaceDir: string,\n options: KbContextOptions = {},\n): Promise<KbContextResult> {\n const builtin = options.profile\n ? (CONTEXT_PROFILES[options.profile] ?? {})\n : {};\n let budgetTokens =\n options.budgetTokens ?? builtin.budgetTokens ?? DEFAULT_CONTEXT_BUDGET;\n let fullUnderTokens = options.fullUnderTokens ?? builtin.fullUnderTokens ?? 0;\n\n // All three manifest layers, merged — nearest wins. The reader skips a\n // malformed layer rather than throwing: this runs from hooks at every\n // session start, and one broken personal file must not silence the team's\n // pins. `pin`/`unpin` are what surface the broken layer, loudly.\n const merged = await readMergedPins(workspaceDir);\n\n // The workspace's own numbers, from the manifests — above the built-ins,\n // below anything passed explicitly.\n const fromManifest = mergedContextBudgets(merged, options.profile);\n budgetTokens =\n options.budgetTokens ??\n fromManifest.budgetTokens ??\n builtin.budgetTokens ??\n DEFAULT_CONTEXT_BUDGET;\n fullUnderTokens =\n options.fullUnderTokens ??\n fromManifest.fullUnderTokens ??\n builtin.fullUnderTokens ??\n 0;\n const excludeTags =\n options.excludeTags ??\n fromManifest.excludeTags ??\n builtin.excludeTags ??\n [];\n\n // A pin scoped to named profiles surfaces only in those; unscoped pins\n // surface everywhere, and a run without a profile sees everything — the\n // explicit full view.\n const pins = merged.pins.filter(\n (pin) =>\n !pin.profiles?.length ||\n !options.profile ||\n pin.profiles.includes(options.profile),\n );\n if (pins.length === 0) {\n return {\n block: \"\",\n refused: false,\n approxTokens: 0,\n budgetTokens,\n bases: [],\n };\n }\n\n const sections = await Promise.all(\n pins.map(async (pin) => ({\n section: await renderBase(\n store,\n pin.path,\n pin.absolutePath,\n fullUnderTokens,\n pin.mode,\n budgetTokens,\n excludeTags,\n ),\n frozen: pin.frozen === true,\n })),\n );\n\n const modeLabel = {\n index: \"index only — record bodies are not here\",\n full: \"full records — this base arrives whole\",\n empty: \"empty\",\n } as const;\n\n // A full pin that could not fit is loudly labelled, in the block and in the\n // log: the reader asked for the whole base and must know it is not looking\n // at it, and the operator must see the budget pressure without reading\n // injected context.\n for (const { section } of sections) {\n if (section.degradedFrom) {\n options.warn?.({\n operation: \"kb.context.full-pin-degraded\",\n path: section.path,\n approxTokens: section.degradedFrom.approxTokens,\n budgetTokens,\n });\n }\n }\n\n const rendered = sections.map(({ section, frozen }) => {\n const label = section.degradedFrom\n ? `index only — pinned \\`mode: full\\`, but its ~${section.degradedFrom.approxTokens} tokens exceed this block's ${budgetTokens}-token budget; kb_load it directly (load's budget is separate), or raise this profile's budget`\n : modeLabel[section.mode];\n return [\n `### ${section.path} (${label}${frozen ? \" · frozen, read-only\" : \"\"})`,\n \"\",\n `bundlePath: \\`${section.absolutePath}\\``,\n \"\",\n section.body,\n ].join(\"\\n\");\n });\n\n const block = [preamble(), \"\", rendered.join(\"\\n\\n\"), \"\"].join(\"\\n\");\n const bases = sections.map(({ section }) => ({\n path: section.path,\n absolutePath: section.absolutePath,\n approxTokens: approxTokens(section.body),\n }));\n const total = approxTokens(block);\n\n if (total > budgetTokens) {\n options.warn?.({\n operation: \"kb.context.refused\",\n approxTokens: total,\n budgetTokens,\n bases: bases.map((base) => base.path),\n });\n // A refusal, not a lock: the budget guards what is injected at every\n // context birth, never a deliberate read. So the refusal carries both\n // moves — read what the question needs right now, and shrink the\n // recurring block so the next session does not land here.\n const refusal = [\n HEADING,\n \"\",\n `The pinned index runs to ~${total} tokens, past the ${budgetTokens}-token`,\n \"budget, and was not emitted — a truncated index is indistinguishable\",\n \"from a complete one. The pinned bases:\",\n \"\",\n ...bases.map(\n (base) =>\n `- ${base.path} — ~${base.approxTokens} tokens (bundlePath: \\`${base.absolutePath}\\`)`,\n ),\n \"\",\n \"For the question at hand, read what you need now — `kb_load` a base\",\n \"(its own budget is separate), or `kb_index` for one base's shape.\",\n \"\",\n \"To bring this block back under budget, in order of preference:\",\n \"- supersede or resolve stale records — the base shrinks, the knowledge keeps\",\n \"- force a large base to index lines: `strauss-kb pin <path> --mode index`\",\n \"- scope a pin to the profiles that need it: `strauss-kb pin <path> --profiles session-start`\",\n \"- raise this profile's budget under `context` in .strauss/kb-pins.json\",\n \"- unpin what no session actually needs\",\n \"\",\n ].join(\"\\n\");\n return {\n block: refusal,\n refused: true,\n approxTokens: total,\n budgetTokens,\n bases,\n };\n }\n\n return { block, refused: false, approxTokens: total, budgetTokens, bases };\n}\n\n/**\n * The same block in the envelope hook protocols that demand strict JSON on\n * stdout require:\n * those protocols treat non-JSON stdout as a violation, where Claude Code and\n * Codex take plain text. One canonical writer for the block; this is wrapping.\n */\nexport function toHookJson(block: string, event: string): string {\n return JSON.stringify({\n hookSpecificOutput: {\n hookEventName: event,\n additionalContext: block,\n },\n });\n}\n\nexport const CONTEXT_BEGIN = \"<!-- strauss-kb:begin -->\";\nexport const CONTEXT_END = \"<!-- strauss-kb:end -->\";\n\nexport type KbSyncResult = {\n file: string;\n action: \"created\" | \"replaced\" | \"appended\" | \"removed\" | \"unchanged\";\n};\n\n/**\n * Idempotently plants the block between sentinels in an instruction file\n * (AGENTS.md, CLAUDE.md). This is how a runtime without a reliable\n * post-compact hook keeps a refreshable index: the file is re-read where the\n * conversation is not. Everything outside the sentinels is left alone.\n */\nexport async function syncInstructions(\n file: string,\n block: string,\n): Promise<KbSyncResult> {\n const existing = await readFile(file, \"utf8\").catch(() => null);\n const region = block\n ? `${CONTEXT_BEGIN}\\n${block.trim()}\\n${CONTEXT_END}`\n : null;\n\n if (existing === null) {\n if (!region) return { file, action: \"unchanged\" };\n await writeFile(file, `${region}\\n`, \"utf8\");\n return { file, action: \"created\" };\n }\n\n const begin = existing.indexOf(CONTEXT_BEGIN);\n const end = existing.indexOf(CONTEXT_END);\n if (begin !== -1 && end !== -1 && end >= begin) {\n const before = existing.slice(0, begin);\n const after = existing.slice(end + CONTEXT_END.length);\n const next = region\n ? `${before}${region}${after}`\n : `${before.replace(/\\n+$/, \"\\n\")}${after.replace(/^\\n+/, \"\\n\")}`;\n if (next === existing) return { file, action: \"unchanged\" };\n await writeFile(file, next, \"utf8\");\n return { file, action: region ? \"replaced\" : \"removed\" };\n }\n\n if (!region) return { file, action: \"unchanged\" };\n await writeFile(\n file,\n `${existing.replace(/\\n*$/, \"\\n\\n\")}${region}\\n`,\n \"utf8\",\n );\n return { file, action: \"appended\" };\n}\n","import type { KbRecord } from \"./kb-record.schema.js\";\n\nexport const INDEX_FILE = \"INDEX.md\";\n\nconst HEADING = \"# KB Index\";\n\n/**\n * `INDEX.md` is a projection — every byte recomputable from record frontmatter.\n *\n * That is what lets parallel writers regenerate it without a lock: they compute\n * the same function of the same records, so two concurrent regenerations differ\n * only in how recent each writer's scan was, and the next read settles it. The\n * file is therefore eventually correct rather than always correct, which is the\n * right trade for something nothing reads transactionally.\n *\n * Lines carry `description`, not just a title. A reader consults the index to\n * decide what is worth opening, and a list of titles does not answer that.\n */\nexport function renderIndex(records: KbRecord[]): string {\n const lines = [...records]\n .sort((left, right) => left.conceptId.localeCompare(right.conceptId))\n .map(renderIndexLine);\n\n return `${HEADING}\\n\\n${lines.join(\"\\n\")}\\n`;\n}\n\n/**\n * One record's index line. The single writer of this shape — `context` emits\n * the same line rather than growing a second index renderer that would drift\n * from this one.\n */\nexport function renderIndexLine(record: KbRecord): string {\n const { frontmatter: fm } = record;\n const parts = [fm.type, fm.strauss_status];\n if (fm.tags?.length) parts.push(`tags: ${fm.tags.join(\", \")}`);\n if (fm.description) parts.push(fm.description);\n return `- [${fm.title ?? record.conceptId}](${record.conceptId}.md) — ${parts.join(\" · \")}`;\n}\n\n/** Whether the stored projection still matches the records it claims to index. */\nexport function indexIsStale(stored: string | null, expected: string): boolean {\n return stored !== expected;\n}\n","import { z } from \"zod\";\nimport { adjudicate } from \"../adjudicate.js\";\nimport {\n movedSearch,\n reassessPacket,\n type KbReassessPacket,\n} from \"../drift/index.js\";\nimport {\n doctor,\n DEFAULT_AGING_DAYS,\n DEFAULT_EXPIRING_DAYS,\n DEFAULT_UNVERIFIED_DAYS,\n type KbDoctorReport,\n} from \"../doctor.js\";\nimport { renderReassess } from \"./reassess.js\";\nimport { grammarHints } from \"../grammars/index.js\";\nimport { argvFlag, bundlePath, define, REPO_ROOT } from \"./model.js\";\n\nexport type KbDoctorCommandResult = KbDoctorReport & {\n bundlePath: string;\n checkedAt: string;\n /**\n * One per drifted record that still needs a reading, present only under\n * `--drifted`. Records whose every drifted anchor was `moved` or `cosmetic`\n * produce no packet — that is the classification earning its keep.\n */\n packets?: KbReassessPacket[];\n /**\n * Records carrying an anchor whose code turned up unchanged elsewhere.\n * `doctor` never writes, so it names them and stops; `kb_reassess <id>` is\n * the verb that moves the anchor.\n */\n rebaselinable?: string[];\n /** What to do about a grammar this run could not obtain. */\n hints?: string[];\n};\n\nconst days = (what: string, fallback: number) =>\n z\n .number()\n .int()\n .positive()\n .optional()\n .describe(`${what} Defaults to ${fallback}.`);\n\nexport const doctorCommand = define({\n name: \"doctor\",\n tool: \"kb_doctor\",\n usage:\n \"doctor [--expiring-days N] [--unverified-days N] [--aging-days N] [--repo-root PATH] [--offline] [--strict] [--drifted [--with-diff]]\",\n description:\n \"Read-only health sweep: expired, expiring, unverified, aging, orphaned, broken-supersession, superseded-but-cited, drifted and unchecked anchors. Every group is reported even when empty; nothing is written or re-stamped. `drifted` narrows it to a reassessment packet per drifted record, `with_diff` adding each anchor's old-vs-new span.\",\n input: z.object({\n bundlePath,\n repoRoot: REPO_ROOT,\n expiringDays: days(\n \"How far ahead `expiring` looks, in days.\",\n DEFAULT_EXPIRING_DAYS,\n ),\n unverifiedDays: days(\n \"How old an unconfirmed record must be before `unverified` reports it, in days.\",\n DEFAULT_UNVERIFIED_DAYS,\n ),\n agingDays: days(\n \"How long a record may stay `open` or `proposed` before `aging` reports it, in days.\",\n DEFAULT_AGING_DAYS,\n ),\n offline: z\n .boolean()\n .optional()\n .describe(\n \"Read foreign anchors from the local repo cache only, never fetching.\",\n ),\n strict: z\n .boolean()\n .optional()\n .describe(\n \"Turn an expired record into a non-zero exit for the CLI. No effect on the report itself.\",\n ),\n drifted: z\n .boolean()\n .optional()\n .describe(\n \"Report only drift, as a reassessment packet per record: claim, per-anchor class, and what depends on it.\",\n ),\n withDiff: z\n .boolean()\n .optional()\n .describe(\n \"With `drifted`: recover each anchor's committed span and render the old-vs-new diff. Reads git history.\",\n ),\n }),\n // Presence, not truthiness: `--expiring-days \"\"` is a caller who meant\n // something and mistyped it, and a falsy test would answer by quietly\n // sweeping at the default. Passed through as given, the schema rejects it\n // and says which field.\n fromArgv: (argv, path) => {\n const expiring = argvFlag(argv, \"--expiring-days\");\n const unverified = argvFlag(argv, \"--unverified-days\");\n const agingDays = argvFlag(argv, \"--aging-days\");\n const repoRoot = argvFlag(argv, \"--repo-root\");\n return {\n bundlePath: path,\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n ...(expiring !== undefined ? { expiringDays: Number(expiring) } : {}),\n ...(unverified !== undefined\n ? { unverifiedDays: Number(unverified) }\n : {}),\n ...(agingDays !== undefined ? { agingDays: Number(agingDays) } : {}),\n ...(argv.includes(\"--offline\") ? { offline: true } : {}),\n ...(argv.includes(\"--strict\") ? { strict: true } : {}),\n ...(argv.includes(\"--drifted\") ? { drifted: true } : {}),\n ...(argv.includes(\"--with-diff\") ? { withDiff: true } : {}),\n };\n },\n run: async (\n { store, now },\n {\n bundlePath: path,\n expiringDays,\n unverifiedDays,\n agingDays,\n repoRoot,\n offline,\n drifted,\n withDiff,\n },\n ) => {\n const checkedAt = now();\n const records = await store.list(path);\n // Read-only, like every other check here: the sweep names the drifted\n // anchors and leaves the re-stamp to `anchor-resolve`, which is the verb\n // that writes.\n const anchorDrift = await store.detectDrift(records, repoRoot, {\n offline: offline === true,\n });\n const report = doctor(records, {\n ...(expiringDays !== undefined ? { expiringDays } : {}),\n ...(unverifiedDays !== undefined ? { unverifiedDays } : {}),\n ...(agingDays !== undefined ? { agingDays } : {}),\n ...(anchorDrift !== undefined ? { anchorDrift } : {}),\n now: new Date(checkedAt),\n });\n const hints = grammarHints();\n if (!drifted) {\n return {\n bundlePath: path,\n checkedAt,\n ...report,\n ...(hints.length ? { hints } : {}),\n };\n }\n\n // Read-only, like the rest of the sweep: packets are built, `moved`\n // anchors are named, and not one anchor is rewritten.\n const standings = new Map(\n adjudicate(records, records, new Date(checkedAt)).map((hit) => [\n hit.record.conceptId,\n hit.standing,\n ]),\n );\n const packets: KbReassessPacket[] = [];\n const rebaselinable: string[] = [];\n // One search for the whole sweep: the repository is listed once, and a\n // candidate file is parsed once however many records anchor into it.\n const search = movedSearch(repoRoot ?? process.cwd());\n for (const found of report.groups.find((g) => g.check === \"drifted\")\n ?.findings ?? []) {\n const record = records.find(\n (entry) => entry.conceptId === found.conceptId,\n );\n if (!record) continue;\n const standing = standings.get(record.conceptId);\n const built = await reassessPacket(\n repoRoot ?? process.cwd(),\n record,\n anchorDrift?.get(record.conceptId) ?? [],\n {\n ...(withDiff ? { withDiff: true } : {}),\n impact: await store.impact(path, record.conceptId),\n ...(standing ? { standing } : {}),\n search,\n },\n );\n if (built.packet) packets.push(built.packet);\n if (built.classified.some((entry) => entry.class === \"moved\")) {\n rebaselinable.push(record.conceptId);\n }\n }\n return {\n bundlePath: path,\n checkedAt,\n ...report,\n packets,\n rebaselinable,\n ...(hints.length ? { hints } : {}),\n };\n },\n render: (result) => render(result as KbDoctorCommandResult),\n // Only expiry, and only under --strict. The other seven checks report debt a\n // reader decides about; an expired record is the base asserting something it\n // already said it would stop standing behind, which is the one finding a\n // pipeline can act on without a judgment call. Drift has its own gate —\n // `anchor-resolve` exits non-zero on it, against a repo root the caller\n // named, which is the run a CI pipeline should be making anyway.\n failsWhen: (result, input) =>\n input.strict === true &&\n (result as KbDoctorCommandResult).counts.expired > 0,\n});\n\n/**\n * The summary table first, then only the groups that found something.\n *\n * The table carries every check including the empty ones — that is what makes\n * \"checked and clean\" legible — while the detail below stays as short as the\n * base's actual health.\n */\nfunction render(result: KbDoctorCommandResult): string {\n if (result.packets) return renderPackets(result);\n const { thresholds } = result;\n const lines = [\n `# KB Doctor — ${result.bundlePath}`,\n `records: ${result.recordCount}`,\n `thresholds: expiring within ${thresholds.expiringDays}d, unverified over ${thresholds.unverifiedDays}d, aging over ${thresholds.agingDays}d`,\n `checked: ${result.checkedAt}`,\n ...(result.anchorResolvers.total\n ? [\n `anchors: ${result.anchorResolvers.total} hashed — ${result.anchorResolvers.treeSitter} tree-sitter, ${result.anchorResolvers.regex} regex`,\n ]\n : []),\n \"\",\n ];\n\n const width = Math.max(...result.groups.map((group) => group.check.length));\n for (const group of result.groups) {\n lines.push(\n ` ${group.check.padEnd(width)} ${String(group.count).padStart(3)} ${group.headline}`,\n );\n }\n\n for (const group of result.groups) {\n if (!group.count) continue;\n lines.push(\"\", `## ${group.check} (${group.count})`);\n for (const found of group.findings) {\n lines.push(\n `- ${found.conceptId}${found.title ? ` — ${found.title}` : \"\"}: ${found.note}`,\n );\n }\n }\n\n for (const hint of result.hints ?? []) lines.push(\"\", hint);\n\n lines.push(\n \"\",\n result.healthy\n ? \"Nothing to repair.\"\n : `${result.findingCount} finding${result.findingCount === 1 ? \"\" : \"s\"} across ${\n result.groups.filter((group) => group.count).length\n } of ${result.groups.length} checks.`,\n );\n\n return lines.join(\"\\n\");\n}\n\n/**\n * `--drifted` answers a different question from the sweep, so it prints a\n * different report: not \"what is wrong with this base\" but \"here is what to\n * read, and what the code did\".\n */\nfunction renderPackets(result: KbDoctorCommandResult): string {\n const packets = result.packets ?? [];\n const lines = [\n `# KB Drift — ${result.bundlePath}`,\n `checked: ${result.checkedAt}`,\n `${packets.length} record${packets.length === 1 ? \"\" : \"s\"} need a reading; ${\n result.counts.drifted\n } drifted in all.`,\n ];\n if (result.rebaselinable?.length) {\n lines.push(\n `moved, rebaseline with \\`kb_reassess\\`: ${result.rebaselinable.join(\", \")}`,\n );\n }\n for (const packet of packets) {\n lines.push(\n renderReassess({\n conceptId: packet.conceptId,\n packet,\n rebaselined: [],\n cosmetic: 0,\n }),\n );\n }\n return lines.join(\"\\n\");\n}\n","import { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { filePathIsSafe, refShapeIsSafe } from \"../remote-repo/validate.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/**\n * Reading a committed file, for the one thing a working tree cannot answer:\n * what the anchored code looked like when the record was written.\n *\n * `ref` and `file` come off an anchor, which is a `.md` file the reader did not\n * write. An argv array stops a shell; it does not stop git's own option\n * parsing, so every positional that derives from bundle data goes after\n * `--end-of-options` and is shape-checked before a subprocess exists. Nothing\n * here fetches — a rev this checkout does not have is a finding, never a\n * network call.\n *\n * The shape checks themselves are `remote-repo/validate.ts`'s: one definition\n * of what a `ref` and a `file` may be, whichever read path asks.\n */\n\n/** Output cap. A recovered file is source, and source this large is not. */\nexport const MAX_GIT_OUTPUT_BYTES = 1_048_576;\n\nconst GIT_TIMEOUT_MS = 5_000;\n\ntype GitResult = { ok: true; stdout: string } | { ok: false };\n\n/**\n * `GIT_DIR`, `GIT_WORK_TREE` and `GIT_INDEX_FILE` are stripped from the child:\n * a caller's environment must not be able to redirect a read that `-C` already\n * addressed.\n */\nasync function git(cwd: string, args: string[]): Promise<GitResult> {\n const env = { ...process.env };\n delete env[\"GIT_DIR\"];\n delete env[\"GIT_WORK_TREE\"];\n delete env[\"GIT_INDEX_FILE\"];\n try {\n const { stdout } = await execFileAsync(\"git\", [\"-C\", cwd, ...args], {\n timeout: GIT_TIMEOUT_MS,\n maxBuffer: MAX_GIT_OUTPUT_BYTES,\n env,\n });\n return { ok: true, stdout };\n } catch {\n return { ok: false };\n }\n}\n\n/** Repository-relative paths, for the `moved` search. Empty when git fails. */\nexport async function listRepoFiles(repoRoot: string): Promise<string[]> {\n const result = await git(repoRoot, [\"ls-files\", \"-z\", \"--cached\"]);\n if (!result.ok) return [];\n return result.stdout.split(\"\\0\").filter(Boolean);\n}\n\n/** Where a recovered file came from, so a packet can say how far back it looked. */\nexport type OldSourceOrigin =\n /** `git show <anchor.ref>:<file>` — the rev the record itself named. */\n | { kind: \"ref\"; ref: string }\n /** The last commit touching the path before `resolved_at`. */\n | { kind: \"history\"; ref: string };\n\nexport type OldSource =\n | { ok: true; source: string; origin: OldSourceOrigin }\n /**\n * No committed text to diff against: no usable `ref`, no history before\n * `resolved_at`, or the path did not exist at the rev that was found.\n */\n | { ok: false; reason: \"unrecoverable\" };\n\n/**\n * The anchored file as it was, `ref` first and the record's own timestamp\n * second.\n *\n * `ref` is what the record asserted the evidence was taken at, so it is tried\n * before anything inferred. Falling back to `git log --before=<resolved_at>`\n * recovers the far commoner case of an anchor that was stamped but never\n * pinned; it is weaker — the last commit before a timestamp is a guess about\n * which tree the reader had — which is why the origin travels with the text.\n */\nexport async function readOldSource(\n repoRoot: string,\n anchor: { file: string; ref?: string; resolved_at?: string },\n): Promise<OldSource> {\n if (!filePathIsSafe(anchor.file))\n return { ok: false, reason: \"unrecoverable\" };\n\n if (anchor.ref && refShapeIsSafe(anchor.ref)) {\n const shown = await showFile(repoRoot, anchor.ref, anchor.file);\n if (shown !== null) {\n return {\n ok: true,\n source: shown,\n origin: { kind: \"ref\", ref: anchor.ref },\n };\n }\n }\n\n const at = anchor.resolved_at;\n if (!at || Number.isNaN(Date.parse(at))) {\n return { ok: false, reason: \"unrecoverable\" };\n }\n // `--before` is a git-parsed value, not a path or a rev, and it is passed as\n // one `--before=<date>` token so it can never be read as two arguments.\n const found = await git(repoRoot, [\n \"log\",\n \"-1\",\n \"--format=%H\",\n `--before=${at}`,\n \"--end-of-options\",\n \"HEAD\",\n \"--\",\n anchor.file,\n ]);\n const sha = found.ok ? found.stdout.trim() : \"\";\n if (!sha || !refShapeIsSafe(sha))\n return { ok: false, reason: \"unrecoverable\" };\n\n const shown = await showFile(repoRoot, sha, anchor.file);\n if (shown === null) return { ok: false, reason: \"unrecoverable\" };\n return { ok: true, source: shown, origin: { kind: \"history\", ref: sha } };\n}\n\n/** `<rev>:<path>` is one positional, so both halves are validated together. */\nasync function showFile(\n repoRoot: string,\n ref: string,\n file: string,\n): Promise<string | null> {\n const path = file.replace(/^\\.\\//, \"\");\n const result = await git(repoRoot, [\n \"show\",\n \"--end-of-options\",\n `${ref}:${path}`,\n ]);\n return result.ok ? result.stdout : null;\n}\n","import { stat } from \"node:fs/promises\";\nimport {\n anchorFilePath,\n anchorFileReader,\n hashAnchorText,\n type AnchorFileReader,\n type KbDriftMovedTo,\n} from \"../anchor-resolver/index.js\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"../concurrency.js\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport {\n languageForFile,\n TreeSitterResolver,\n} from \"../tree-sitter-resolver/index.js\";\nimport { listRepoFiles } from \"./git.js\";\n\n/**\n * Did this exact code turn up somewhere else?\n *\n * The one drift question a machine can close on its own. A file renamed, a\n * function lifted into a new module, a block reordered — the bytes are\n * identical, so the record still describes them, and asking a reader to\n * re-read what they already read would train them to skip the ones that\n * matter.\n *\n * Identity is the stored hash, never a similarity score: \"nearly the same\n * code\" is exactly the case a reader has to judge.\n */\n\n/**\n * How many repository files one search may parse.\n *\n * The search runs on a reassessment path a person is waiting on, and a\n * repository is not bounded. Past the cap the answer is \"not found\", which is\n * the same answer the reader gets today.\n */\nexport const MAX_MOVED_SEARCH_FILES = 2_000;\n\n/**\n * How many candidates are dispatched before the result is checked.\n *\n * The batch is the unit of wasted work: a hit in the first file still costs a\n * whole batch of reads, and a miss in the whole repository costs one round of\n * latency per batch. Large enough that the pool stays fed, small enough that\n * an early hit does not read a repository to find it.\n */\nconst SEARCH_BATCH = 64;\n\nexport type MovedSearch = {\n /**\n * Where this anchor's stored hash turned up, or `undefined`.\n *\n * Shared across every anchor of a run: one `git ls-files`, one parse cache,\n * one set of loaded grammars. A `doctor --drifted` sweep over a base whose\n * records anchor into the same few languages parses each candidate once, not\n * once per drifted anchor.\n */\n find(anchor: KbAnchor): Promise<KbDriftMovedTo | undefined>;\n};\n\nexport type MovedSearchOptions = {\n /** Test seam: replaces the disk reader. */\n reader?: AnchorFileReader;\n /** Test seam: a candidate's byte size, or `null` when it cannot be known. */\n sizeOf?: (file: string) => Promise<number | null>;\n};\n\n/**\n * Repository-wide through tree-sitter, same-file-only without it.\n *\n * The fallback is narrow on purpose. Without a parser there are no definition\n * boundaries, so the only honest search is a sliding window of the recorded\n * line count over one file — which finds a block that moved within its file\n * and nothing else. Widening that to the repository would be a hash collision\n * hunt across every line offset of every file, for an answer no more certain.\n */\nexport function movedSearch(\n repoRoot: string,\n options: MovedSearchOptions = {},\n): MovedSearch {\n const read = options.reader ?? anchorFileReader(repoRoot);\n const sizeOf = options.sizeOf ?? diskSize(repoRoot);\n const resolver = new TreeSitterResolver();\n let repoFiles: Promise<string[]> | undefined;\n const prepared = new Set<string>();\n\n const filesForLanguage = async (language: string): Promise<string[]> => {\n repoFiles ??= listRepoFiles(repoRoot);\n return (await repoFiles)\n .filter((file) => languageForFile(file) === language)\n .slice(0, MAX_MOVED_SEARCH_FILES);\n };\n\n return {\n async find(anchor) {\n const stored = anchor.hash;\n if (!stored) return undefined;\n\n const language = languageForFile(anchor.file);\n // No grammar means no token stream, and an `ast` hash can only be\n // compared against one. Comparing it to a raw hash would be comparing\n // two different measurements and calling a mismatch a move.\n if (!language) return sameFileWindow(anchor, read, stored);\n\n const candidates = await filesForLanguage(language);\n if (!prepared.has(language)) {\n await resolver.prepare(candidates.length ? candidates : [anchor.file]);\n prepared.add(language);\n }\n // A file smaller than the span cannot contain it. One `stat` is far\n // cheaper than a read and a parse, and in a repository of small modules\n // it is most of the candidates.\n const floor = anchor.lines ?? 0;\n\n for (let at = 0; at < candidates.length; at += SEARCH_BATCH) {\n const batch = candidates.slice(at, at + SEARCH_BATCH);\n const hits = await mapLimit(\n batch,\n DEFAULT_IO_CONCURRENCY,\n async (file) => {\n const size = await sizeOf(file);\n // One byte per line is the floor a file of that many lines cannot\n // go under. `null` is \"unknown\", which reads rather than skips.\n if (size !== null && size < floor) return undefined;\n return matchIn(resolver, read, anchor, stored, file);\n },\n );\n // Index order, not completion order: the same repository must always\n // report the same destination.\n const found = hits.find((hit) => hit !== undefined);\n if (found) return found;\n }\n return undefined;\n },\n };\n}\n\n/** The stored hash at some definition in `file`, or `undefined`. */\nasync function matchIn(\n resolver: TreeSitterResolver,\n read: AnchorFileReader,\n anchor: KbAnchor,\n stored: string,\n file: string,\n): Promise<KbDriftMovedTo | undefined> {\n const source = await read(file);\n if (!source.ok) return undefined;\n const normalized = source.source.replace(/\\r\\n/g, \"\\n\");\n\n for (const found of resolver.spans(normalized, file)) {\n // Hashed the way the anchor was stamped: an `ast` hash is only ever\n // compared against a token stream, a raw hash only against raw text.\n const text =\n anchor.hash_kind === \"ast\"\n ? resolver.normalize(found.span.text, file)\n : found.span.text;\n if (text === null || hashAnchorText(text) !== stored) continue;\n // The anchor's own place is where it already looked; finding the hash\n // there would mean it never drifted.\n if (file === anchor.file && found.symbol === anchor.symbol) continue;\n return {\n file,\n symbol: found.symbol,\n startLine: found.span.startLine,\n endLine: found.span.endLine,\n };\n }\n return undefined;\n}\n\n/** `stat` under the repository root; `null` for anything it cannot size. */\nfunction diskSize(repoRoot: string): (file: string) => Promise<number | null> {\n return async (file) => {\n const path = anchorFilePath(repoRoot, file);\n if (path === null) return null;\n try {\n return (await stat(path)).size;\n } catch {\n return null;\n }\n };\n}\n\n/** A block of the recorded line count, at some other offset in the same file. */\nasync function sameFileWindow(\n anchor: KbAnchor,\n read: AnchorFileReader,\n stored: string,\n): Promise<KbDriftMovedTo | undefined> {\n const height = anchor.lines;\n // Without a recorded line count there is no window to slide, and guessing\n // one would make the search's negative answer meaningless. An `ast` hash is\n // over a token stream, which has no line offsets to slide over at all.\n if (!height || anchor.hash_kind === \"ast\") return undefined;\n\n const source = await read(anchor.file);\n if (!source.ok) return undefined;\n const lines = source.source.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n\n for (let at = 0; at + height <= lines.length; at++) {\n if (hashAnchorText(lines.slice(at, at + height).join(\"\\n\")) !== stored) {\n continue;\n }\n return {\n file: anchor.file,\n ...(anchor.symbol ? { symbol: anchor.symbol } : {}),\n startLine: at + 1,\n endLine: at + height,\n };\n }\n return undefined;\n}\n","import {\n anchorFileReader,\n prepareResolvers,\n regexResolver,\n resolveAnchorSpan,\n type AnchorFileReader,\n type AnchorResolver,\n type KbAnchorDriftEntry,\n type KbDriftClass,\n} from \"../anchor-resolver/index.js\";\nimport type { KbAnchor, KbRecord } from \"../kb-record.schema.js\";\nimport { isUncheckedReason } from \"../remote-repo/index.js\";\nimport { TreeSitterResolver } from \"../tree-sitter-resolver/index.js\";\nimport { readOldSource, type OldSourceOrigin } from \"./git.js\";\nimport { movedSearch, type MovedSearch } from \"./moved.js\";\n\n/**\n * Turning \"the bytes changed\" into one of four answers, two of which end the\n * matter.\n *\n * The order is not arbitrary: `moved` is asked first because it is the only\n * class that needs no history at all, and `cosmetic` second because it is the\n * only one that needs the old text. What survives both is what a reader has to\n * read — and the whole point of asking the cheap questions first is that most\n * drift never reaches them.\n *\n * Everything here is read-only. Rebaselining a `moved` anchor is a write, and\n * writes belong to the verb the caller named.\n */\n\nexport type ClassifiedAnchor = {\n anchor: KbAnchor;\n entry: KbAnchorDriftEntry;\n /** Resolved class. Never `undefined` — every reported anchor gets one. */\n class: KbDriftClass;\n /** The anchored text as it stands now. Absent when the class is `gone`. */\n newText?: string;\n /** The anchored text as it was, when history could produce it. */\n oldText?: string;\n oldOrigin?: OldSourceOrigin;\n};\n\nexport type ClassifyOptions = {\n /** Test seam: replaces the disk reader. */\n reader?: AnchorFileReader;\n /** Skip the history read. `cosmetic` cannot be reached without it. */\n withHistory?: boolean;\n /**\n * The run's shared `moved` search. A sweep classifying many records passes\n * one, so the repository is listed once and each candidate file is parsed\n * once for the whole sweep rather than once per record.\n */\n search?: MovedSearch;\n};\n\n/**\n * Refines one record's drift entries. Anchors that matched, or that name\n * another repository, are not drift and never appear.\n */\nexport async function classifyDrift(\n repoRoot: string,\n record: KbRecord,\n entries: readonly KbAnchorDriftEntry[],\n options: ClassifyOptions = {},\n): Promise<ClassifiedAnchor[]> {\n // `detectAnchorDrift` walks the hash-carrying anchors in frontmatter order\n // and emits one entry each, so index is identity here.\n const anchors = (record.frontmatter.strauss_anchors ?? []).filter(\n (anchor) => anchor.hash,\n );\n const reader = options.reader ?? anchorFileReader(repoRoot);\n const treeSitter = new TreeSitterResolver();\n const resolvers: AnchorResolver[] = [treeSitter, regexResolver];\n const search =\n options.search ??\n movedSearch(repoRoot, { ...(options.reader ? { reader } : {}) });\n\n const wanted: { anchor: KbAnchor; entry: KbAnchorDriftEntry }[] = [];\n entries.forEach((entry, at) => {\n const anchor = anchors[at];\n if (!anchor) return;\n if (entry.state === \"match\" || isUncheckedReason(entry.reason)) return;\n wanted.push({ anchor, entry });\n });\n if (!wanted.length) return [];\n\n await prepareResolvers(\n resolvers,\n wanted.map(({ anchor }) => anchor.file),\n );\n\n const out: ClassifiedAnchor[] = [];\n for (const { anchor, entry } of wanted) {\n const movedTo = await search.find(anchor);\n if (movedTo) {\n out.push({\n anchor,\n entry: { ...entry, class: \"moved\", movedTo },\n class: \"moved\",\n });\n continue;\n }\n\n const newText = await currentText(reader, anchor, resolvers);\n const old =\n options.withHistory === false\n ? { ok: false as const, reason: \"unrecoverable\" as const }\n : await readOldSource(repoRoot, anchor);\n const oldText = old.ok ? spanIn(old.source, anchor, resolvers) : undefined;\n\n const settled: KbDriftClass =\n newText !== undefined &&\n oldText !== undefined &&\n sameTokens(treeSitter, anchor.file, oldText, newText)\n ? \"cosmetic\"\n : (entry.class ?? \"changed\");\n\n out.push({\n anchor,\n entry: { ...entry, class: settled },\n class: settled,\n ...(newText !== undefined ? { newText } : {}),\n ...(oldText !== undefined ? { oldText } : {}),\n ...(old.ok ? { oldOrigin: old.origin } : {}),\n });\n }\n return out;\n}\n\n/**\n * Only a parser can say two spellings are one program. Without one — a file\n * with no grammar, or text that will not parse — the answer is no, which\n * leaves the class where it was rather than inventing a reassurance.\n */\nfunction sameTokens(\n resolver: TreeSitterResolver,\n file: string,\n before: string,\n after: string,\n): boolean {\n if (before === after) return false;\n const left = resolver.normalize(before, file);\n const right = resolver.normalize(after, file);\n return left !== null && left === right;\n}\n\nasync function currentText(\n reader: AnchorFileReader,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n): Promise<string | undefined> {\n const read = await reader(anchor.file);\n if (!read.ok) return undefined;\n return spanIn(read.source, anchor, resolvers);\n}\n\n/** The anchor's span within some version of its file, current or committed. */\nfunction spanIn(\n source: string,\n anchor: KbAnchor,\n resolvers: readonly AnchorResolver[],\n): string | undefined {\n const outcome = resolveAnchorSpan(source, anchor, resolvers);\n return outcome.ok ? outcome.span.text : undefined;\n}\n","/**\n * A unified diff of two spans, bounded on purpose.\n *\n * The packet exists so a reader can judge without opening the repository, and\n * a diff that has to be scrolled past defeats that as surely as no diff at all.\n * Both caps below are line counts rather than bytes, because what a reader\n * runs out of is attention.\n */\n\n/** Never more than this from one anchor, whatever the record's shape. */\nexport const MAX_ANCHOR_DIFF_LINES = 200;\n\n/**\n * Shared across a record's anchors, so a ten-anchor record stays as readable as\n * a one-anchor record is. `kb_reassess`'s size ceiling is a whole-packet\n * number, and only a whole-packet budget can hold it.\n */\nexport const PACKET_DIFF_LINE_BUDGET = 200;\n\n/** Below this an anchor is better dropped than shown as a stub. */\nexport const MIN_ANCHOR_DIFF_LINES = 12;\n\n/** Each anchor's share of the budget, never above the per-anchor cap. */\nexport function diffBudget(anchors: number): number {\n if (anchors <= 0) return MAX_ANCHOR_DIFF_LINES;\n return Math.min(\n MAX_ANCHOR_DIFF_LINES,\n Math.max(\n MIN_ANCHOR_DIFF_LINES,\n Math.floor(PACKET_DIFF_LINE_BUDGET / anchors),\n ),\n );\n}\n\nexport type UnifiedDiff = {\n /** `-`/`+`/` ` prefixed lines, with a `@@` header. */\n text: string;\n added: number;\n removed: number;\n /** Whether the cap cut it short. */\n truncated: boolean;\n};\n\n/**\n * One hunk, no context trimming: the two sides are already a symbol's span,\n * so the whole of both is the context a reader wants.\n *\n * The common subsequence is computed over line *hashes* through a simple\n * O(n·m) table. Spans are bounded by the anchor file cap, and a smarter\n * algorithm would be a second thing to be wrong about for a saving nobody can\n * measure at this size.\n */\nexport function unifiedDiff(\n before: string,\n after: string,\n options: { maxLines?: number; oldLabel?: string; newLabel?: string } = {},\n): UnifiedDiff {\n const max = options.maxLines ?? MAX_ANCHOR_DIFF_LINES;\n const left = before.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n const right = after.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n\n const body: string[] = [];\n let added = 0;\n let removed = 0;\n for (const edit of edits(left, right)) {\n if (edit.kind === \"same\") body.push(` ${edit.line}`);\n else if (edit.kind === \"remove\") {\n body.push(`-${edit.line}`);\n removed += 1;\n } else {\n body.push(`+${edit.line}`);\n added += 1;\n }\n }\n\n const truncated = body.length > max;\n const shown = truncated ? body.slice(0, max) : body;\n const header = `@@ -1,${left.length} +1,${right.length} @@${\n options.oldLabel\n ? ` ${options.oldLabel} → ${options.newLabel ?? \"\"}`.trimEnd()\n : \"\"\n }`;\n const lines = [header, ...shown];\n if (truncated) lines.push(`… ${body.length - max} more diff lines`);\n\n return { text: lines.join(\"\\n\"), added, removed, truncated };\n}\n\ntype Edit = { kind: \"same\" | \"remove\" | \"add\"; line: string };\n\n/** Longest-common-subsequence backtrack, emitted in source order. */\nfunction edits(left: string[], right: string[]): Edit[] {\n const rows = left.length;\n const cols = right.length;\n const table: number[][] = Array.from({ length: rows + 1 }, () =>\n new Array<number>(cols + 1).fill(0),\n );\n for (let row = rows - 1; row >= 0; row--) {\n for (let col = cols - 1; col >= 0; col--) {\n (table[row] as number[])[col] =\n left[row] === right[col]\n ? ((table[row + 1] as number[])[col + 1] as number) + 1\n : Math.max(\n (table[row + 1] as number[])[col] as number,\n (table[row] as number[])[col + 1] as number,\n );\n }\n }\n\n const out: Edit[] = [];\n let row = 0;\n let col = 0;\n while (row < rows && col < cols) {\n if (left[row] === right[col]) {\n out.push({ kind: \"same\", line: left[row] as string });\n row += 1;\n col += 1;\n } else if (\n ((table[row + 1] as number[])[col] as number) >=\n ((table[row] as number[])[col + 1] as number)\n ) {\n out.push({ kind: \"remove\", line: left[row] as string });\n row += 1;\n } else {\n out.push({ kind: \"add\", line: right[col] as string });\n col += 1;\n }\n }\n for (; row < rows; row++)\n out.push({ kind: \"remove\", line: left[row] as string });\n for (; col < cols; col++)\n out.push({ kind: \"add\", line: right[col] as string });\n return out;\n}\n","import type { KbStanding } from \"../adjudicate.js\";\nimport type {\n KbAnchorDriftEntry,\n KbDriftClass,\n KbDriftMovedTo,\n} from \"../anchor-resolver/index.js\";\nimport type { KbRecord, KbRecordType } from \"../kb-record.schema.js\";\nimport type { KbImpactResult } from \"../kb-links/index.js\";\nimport { isKbRecordType, RECORD_TYPES } from \"../record-types.js\";\nimport {\n classifyDrift,\n type ClassifiedAnchor,\n type ClassifyOptions,\n} from \"./classify.js\";\nimport { diffBudget, unifiedDiff } from \"./diff.js\";\n\n/**\n * What a reader needs in order to decide whether a record still holds, without\n * opening the repository.\n *\n * A drift finding today says two hashes disagree, which is not a thing anyone\n * can judge. The packet is the same finding with the three pieces judgment\n * actually takes: what the record claims, what the code did, and what depends\n * on the answer. It stops there — the reading itself is the reader's, and\n * every default below is a starting point the protocol expects to be argued\n * with.\n */\n\nexport type KbReassessDiff =\n | {\n status: \"ok\";\n /** `ref` when the anchor pinned one, `history` when it was inferred. */\n source: \"ref\" | \"history\";\n /** The rev the old side was read at. */\n ref: string;\n unified: string;\n added: number;\n removed: number;\n truncated: boolean;\n }\n /** No committed text to diff against; see `readOldSource`. */\n | { status: \"unrecoverable\" };\n\nexport type KbReassessAnchor = {\n file: string;\n symbol?: string;\n class: KbDriftClass;\n reason?: string;\n storedHash: string;\n currentHash?: string;\n diffSize: number | null;\n movedTo?: KbDriftMovedTo;\n diff?: KbReassessDiff;\n};\n\n/**\n * What the type says about a record whose code changed under it.\n *\n * A `fact` is a claim about the world that the code was the evidence for, so\n * changed evidence presumptively unmakes it. A `decision` is a claim about a\n * choice, and the reasoning for a choice routinely outlives the code that\n * implemented it. Neither is a verdict — they are which way to lean while\n * reading, and naming the lean is what keeps it arguable.\n */\nexport type KbReassessDefault =\n \"presumed-invalidated\" | \"rationale-may-survive\" | \"review\";\n\nconst PRESUMED_INVALID: readonly KbRecordType[] = [\n \"fact\",\n \"constraint\",\n \"contract\",\n];\nconst RATIONALE_SURVIVES: readonly KbRecordType[] = [\"decision\", \"risk\"];\n\nconst DEFAULT_NOTES: Record<KbReassessDefault, string> = {\n \"presumed-invalidated\":\n \"the code this claim was taken from changed; presume it no longer holds until re-read\",\n \"rationale-may-survive\":\n \"the reasoning may outlive the code that implemented it; check whether it does\",\n review: \"re-read the record against the new code\",\n};\n\nexport type KbReassessPacket = {\n conceptId: string;\n title: string | null;\n type: string;\n standing: KbStanding;\n /** What breaks if this record is wrong — the record's `why`, stored as `description`. */\n why: string | null;\n /** The type's claim section — the sentence being reassessed. */\n claim: { section: string; text: string } | null;\n anchors: KbReassessAnchor[];\n /**\n * The record's dependants. A fact that stopped holding did not stop holding\n * alone, and a reader deciding about it is deciding about these too.\n */\n impact: {\n conceptId: string;\n title: string | null;\n standing: KbStanding;\n depth: number;\n }[];\n impactTruncated: boolean;\n default: KbReassessDefault;\n defaultNote: string;\n};\n\nexport type PacketOptions = ClassifyOptions & {\n /** Recover and render the old-vs-new span diff. Off by default: it reads git. */\n withDiff?: boolean;\n impact?: KbImpactResult;\n standing?: KbStanding;\n};\n\n/**\n * One record's packet, or `null` when nothing survived classification.\n *\n * A record whose every drifted anchor turned out to be `moved` or `cosmetic`\n * is a record with no reassessment work, and emitting an empty packet for it\n * would put it back in front of the reader the classification just cleared it\n * from.\n */\nexport async function reassessPacket(\n repoRoot: string,\n record: KbRecord,\n entries: readonly KbAnchorDriftEntry[],\n options: PacketOptions = {},\n): Promise<{\n packet: KbReassessPacket | null;\n classified: ClassifiedAnchor[];\n}> {\n const classified = await classifyDrift(repoRoot, record, entries, {\n ...(options.reader ? { reader: options.reader } : {}),\n ...(options.search ? { search: options.search } : {}),\n withHistory: options.withDiff !== false,\n });\n\n const open = classified.filter(\n (found) => found.class === \"changed\" || found.class === \"gone\",\n );\n if (!open.length) return { packet: null, classified };\n\n const budget = diffBudget(open.length);\n const anchors = open.map((found) =>\n anchorPacket(found, options.withDiff === true, budget),\n );\n\n const type = record.frontmatter.type;\n const fallback: KbReassessDefault = isKbRecordType(type)\n ? PRESUMED_INVALID.includes(type)\n ? \"presumed-invalidated\"\n : RATIONALE_SURVIVES.includes(type)\n ? \"rationale-may-survive\"\n : \"review\"\n : \"review\";\n\n return {\n classified,\n packet: {\n conceptId: record.conceptId,\n title: record.frontmatter.title ?? null,\n type,\n standing: options.standing ?? \"unsettled\",\n why: record.frontmatter.description ?? null,\n claim: claimOf(record),\n anchors,\n impact: (options.impact?.impacted ?? []).map((entry) => ({\n conceptId: entry.conceptId,\n title: entry.title,\n standing: entry.standing,\n depth: entry.depth,\n })),\n impactTruncated: options.impact?.truncated ?? false,\n default: fallback,\n defaultNote: DEFAULT_NOTES[fallback],\n },\n };\n}\n\nfunction anchorPacket(\n found: ClassifiedAnchor,\n withDiff: boolean,\n maxLines: number,\n): KbReassessAnchor {\n const { entry } = found;\n const base: KbReassessAnchor = {\n file: entry.file,\n ...(entry.symbol ? { symbol: entry.symbol } : {}),\n class: found.class,\n ...(entry.reason ? { reason: entry.reason } : {}),\n storedHash: entry.storedHash,\n ...(entry.currentHash ? { currentHash: entry.currentHash } : {}),\n diffSize: entry.diffSize,\n ...(entry.movedTo ? { movedTo: entry.movedTo } : {}),\n };\n if (!withDiff) return base;\n\n if (found.oldText === undefined || !found.oldOrigin) {\n return { ...base, diff: { status: \"unrecoverable\" } };\n }\n // A `gone` anchor has no new side; the diff is the whole old span removed,\n // which is exactly what the reader has to weigh.\n const rendered = unifiedDiff(found.oldText, found.newText ?? \"\", {\n maxLines,\n });\n return {\n ...base,\n diff: {\n status: \"ok\",\n source: found.oldOrigin.kind,\n ref: found.oldOrigin.ref,\n unified: rendered.text,\n added: rendered.added,\n removed: rendered.removed,\n truncated: rendered.truncated,\n },\n };\n}\n\n/**\n * The first section of the record's type — its central claim, per the type\n * table — pulled out of the body so the packet carries the sentence being\n * judged rather than the whole record.\n */\nfunction claimOf(record: KbRecord): { section: string; text: string } | null {\n const type = record.frontmatter.type;\n const section = isKbRecordType(type)\n ? RECORD_TYPES[type].sections[0]\n : undefined;\n if (!section) return null;\n\n const lines = record.body.replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\n const start = lines.findIndex(\n (line) => line.trim().toLowerCase() === `## ${section}`.toLowerCase(),\n );\n if (start < 0) return null;\n const rest = lines.slice(start + 1);\n const end = rest.findIndex((line) => line.startsWith(\"## \"));\n const text = (end < 0 ? rest : rest.slice(0, end)).join(\"\\n\").trim();\n return text ? { section, text } : null;\n}\n","import { KB_CONCEPT_ID_PATTERN, type KbRecord } from \"./kb-record.schema.js\";\nimport { KB_LINK_RELS } from \"./record-types.js\";\n\n/**\n * The edges between records in one bundle, defined once.\n *\n * Both walks — `trace` and `pack` — consume this module, so they cannot drift\n * into disagreeing about what makes two records neighbours, and a diagnostic\n * pass over the graph can reuse the same definition.\n *\n * There is no separate `related` kind: compose.ts renders `relatedConceptIds`\n * as body links (`Relates to [id](id.md).`), so in stored form a related edge\n * IS a body link, and a distinct kind would count the same markdown twice.\n *\n * `typed-link` is not that case, despite compose.ts also rendering a sentence\n * per link. The edge is `strauss_links` in the frontmatter — the authoritative,\n * typed form — and the sentence is its rendering for a reader that only knows\n * OKF. A record can carry the frontmatter without the prose (hand-written, or\n * from a producer we did not write), so reading only the body would miss it.\n * A pair connected both ways comes back with both kinds in `via`, which is the\n * honest answer: it was declared, and it was written about.\n *\n * `body-link` and `typed-link` are DIRECTED — the edges a record itself makes,\n * read off its own body or frontmatter. `supersession`, `anchor` and `source`\n * are symmetric: they hold between two records because both name the same\n * thing, so either end sees the other. Callers wanting the inbound half of a\n * typed edge use `kb-links/` (`kb_backlinks`, `kb_impact`) rather than this\n * module, which answers \"what does this record point at\".\n */\nexport const KB_EDGE_KINDS = [\n \"body-link\",\n \"typed-link\",\n \"supersession\",\n \"anchor\",\n \"source\",\n] as const;\n\nexport type KbEdgeKind = (typeof KB_EDGE_KINDS)[number];\n\nexport type KbNeighbour = {\n record: KbRecord;\n /** Every edge kind that connects it to the record asked about. */\n via: KbEdgeKind[];\n};\n\n// The target of any markdown link whose href is a record filename:\n// `](<concept-id>.md)`. Built from the id pattern with its anchors stripped so\n// the id can be matched mid-body.\nconst BODY_LINK_TARGET = new RegExp(\n `\\\\]\\\\((${KB_CONCEPT_ID_PATTERN.source.replace(/^\\^|\\$$/g, \"\")})\\\\.md\\\\)`,\n \"g\",\n);\n\n/**\n * Which rels a `typed-link` walk may follow.\n *\n * Defaults to the whole known vocabulary — including `related_to`, since a\n * neighbourhood is the one place a bibliography belongs. It never includes an\n * unknown rel: a rel outside the vocabulary is not a claim any walk can\n * interpret, so no walk traverses it anywhere, and `kb_validate` reports it as\n * an error rather than a walk quietly acting on it.\n */\nexport const DEFAULT_TYPED_LINK_RELS: readonly string[] = KB_LINK_RELS;\n\n/**\n * Every record `from` touches, each carrying the full set of edge kinds that\n * connect the pair. Order is deterministic: bundle order per kind, kinds in\n * the order given.\n */\nexport function neighbours(\n from: KbRecord,\n bundle: KbRecord[],\n kinds: readonly KbEdgeKind[] = KB_EDGE_KINDS,\n linkRels: readonly string[] = DEFAULT_TYPED_LINK_RELS,\n): KbNeighbour[] {\n const found = new Map<string, KbNeighbour>();\n for (const kind of kinds) {\n for (const record of edgeNeighbours(from, bundle, kind, linkRels)) {\n const existing = found.get(record.conceptId);\n if (existing) {\n if (!existing.via.includes(kind)) existing.via.push(kind);\n continue;\n }\n found.set(record.conceptId, { record, via: [kind] });\n }\n }\n return [...found.values()];\n}\n\n/**\n * The records one edge kind connects `from` to, in bundle order.\n *\n * `linkRels` narrows the `typed-link` kind and is ignored by the others —\n * `trace` passes the causal rels, `pack` takes the default.\n */\nexport function edgeNeighbours(\n from: KbRecord,\n bundle: KbRecord[],\n kind: KbEdgeKind,\n linkRels: readonly string[] = DEFAULT_TYPED_LINK_RELS,\n): KbRecord[] {\n switch (kind) {\n // A link whose target is not in the bundle is legal per compose.ts —\n // records are routinely written before the ones they point at exist — so\n // missing targets are skipped, never an error.\n case \"body-link\": {\n const targets = new Set(\n [...from.body.matchAll(BODY_LINK_TARGET)].map((match) => match[1]),\n );\n if (!targets.size) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n targets.has(candidate.conceptId),\n );\n }\n\n // Outbound only, like `body-link`, and for the same reason: this is what\n // the record declares about itself. A missing target is legal — the walk\n // skips it, and `kb_validate` is what reports it as a warning. A rel\n // outside `linkRels` is skipped too, which is how an unknown rel stays\n // untraversable everywhere rather than one walk at a time.\n case \"typed-link\": {\n const allowed = new Set(linkRels);\n const targets = new Set(\n (from.frontmatter.strauss_links ?? [])\n .filter((link) => allowed.has(link.rel))\n .map((link) => link.target),\n );\n if (!targets.size) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n targets.has(candidate.conceptId),\n );\n }\n\n // Both directions and both pointers: `supersede()` writes the pair, but a\n // hand-edit can leave one side behind, and a walk trusting one pointer\n // would miss a replacement the bundle openly declares.\n case \"supersession\":\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n (candidate.conceptId === from.frontmatter.strauss_superseded_by ||\n from.frontmatter.strauss_supersedes?.includes(\n candidate.conceptId,\n ) ||\n candidate.frontmatter.strauss_superseded_by === from.conceptId ||\n candidate.frontmatter.strauss_supersedes?.includes(from.conceptId)),\n );\n\n // The edge that answers \"why is this code shaped this way\": every record\n // attached to the same file or symbol, whatever its standing.\n case \"anchor\": {\n const mine = from.frontmatter.strauss_anchors ?? [];\n if (!mine.length) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n (candidate.frontmatter.strauss_anchors ?? []).some((theirs) =>\n mine.some((ours) => anchorsTouch(ours, theirs)),\n ),\n );\n }\n\n case \"source\": {\n const mine = new Set((from.frontmatter.sources ?? []).map((s) => s.id));\n if (!mine.size) return [];\n return bundle.filter(\n (candidate) =>\n candidate.conceptId !== from.conceptId &&\n (candidate.frontmatter.sources ?? []).some((source) =>\n mine.has(source.id),\n ),\n );\n }\n }\n}\n\n/**\n * Two anchors touch when they name the same file and do not name different\n * symbols within it.\n *\n * An anchor without a symbol means \"this record is about this file\", so it\n * relates to everything anchored inside it. Requiring an exact match instead\n * would hide the file-level record from every symbol-level walk, which is the\n * direction a reviewer actually reads.\n */\nfunction anchorsTouch(\n left: { file: string; symbol?: string },\n right: { file: string; symbol?: string },\n): boolean {\n if (left.file !== right.file) return false;\n if (!left.symbol || !right.symbol) return true;\n return left.symbol === right.symbol;\n}\n","import { isCanonicalRepoUrl } from \"./anchor-resolver/index.js\";\nimport { KB_CONCEPT_ID_PATTERN, type KbRecord } from \"./kb-record.schema.js\";\nimport { isKbLinkRel, isKbRecordType, KB_LINK_RELS } from \"./record-types.js\";\n\n/** `error` fails the check; `warning` does not. */\nexport type KbValidationSeverity = \"error\" | \"warning\";\n\nexport type KbValidationProblem = {\n check: string;\n conceptId: string;\n note: string;\n severity: KbValidationSeverity;\n};\n\n/**\n * Checks that only hold across the whole bundle: whether one record's pointers\n * agree with another's. Per-record shape is the schema's job, enforced on every\n * read, so nothing here re-states it.\n */\nexport function validateBundle(records: KbRecord[]): KbValidationProblem[] {\n const byId = new Map(records.map((record) => [record.conceptId, record]));\n const problems: KbValidationProblem[] = [];\n const report = (\n check: string,\n conceptId: string,\n note: string,\n severity: KbValidationSeverity = \"error\",\n ) => problems.push({ check, conceptId, note, severity });\n\n for (const record of records) {\n const { conceptId, frontmatter: fm } = record;\n\n // OKF permits any `type`, so an unrecognised one is a note, not a failure:\n // another producer may legitimately be writing into this bundle.\n if (!isKbRecordType(fm.type)) {\n report(\"type\", conceptId, `unrecognised type \"${fm.type}\"`);\n }\n\n if (fm.strauss_status === \"superseded\") {\n const by = fm.strauss_superseded_by;\n if (!by) {\n report(\"superseded_by\", conceptId, \"superseded with no replacement\");\n } else if (!byId.has(by)) {\n report(\"superseded_by\", conceptId, `replacement ${by} is missing`);\n } else if (\n !byId.get(by)?.frontmatter.strauss_supersedes?.includes(conceptId)\n ) {\n report(\"backlink\", by, `does not list ${conceptId} in supersedes`);\n }\n }\n\n for (const old of fm.strauss_supersedes ?? []) {\n const previous = byId.get(old);\n if (!previous) {\n report(\"supersedes\", conceptId, `target ${old} is missing`);\n } else if (previous.frontmatter.strauss_status !== \"superseded\") {\n report(\"supersedes\", conceptId, `${old} is not marked superseded`);\n }\n }\n\n for (const link of fm.strauss_links ?? []) {\n // The vocabulary is closed, and this is where that is enforced. An\n // unknown rel is not a record another producer wrote in good faith the\n // way an unknown `type` is — `rel` is this package's own extension, so\n // there is no spec under which a foreign spelling is legitimate, and\n // every walk over the graph would silently skip it.\n if (!isKbLinkRel(link.rel)) {\n report(\n \"link_rel\",\n conceptId,\n `unknown rel \"${link.rel}\" on link to ${link.target} — expected one of ${KB_LINK_RELS.join(\", \")}`,\n );\n }\n\n // A target is an error or a warning depending on whether time can fix\n // it. An id that does not match the concept-id pattern can never name a\n // record — no write could produce that filename — so it is a defect\n // now and forever. A well-formed id that is simply absent is the\n // ordinary state of a base being written, and the same tolerance body\n // links already have.\n if (!KB_CONCEPT_ID_PATTERN.test(link.target)) {\n report(\n \"link_target\",\n conceptId,\n `target \"${link.target}\" is not a valid concept id — expected <type>.<slug>, both kebab-case`,\n );\n } else if (link.target === conceptId) {\n // The composer refuses this outright; reaching it means a hand-edit,\n // and a self-link is inert rather than wrong — nothing traverses it.\n report(\n \"link_target\",\n conceptId,\n `links to itself (${link.rel})`,\n \"warning\",\n );\n } else if (!byId.has(link.target)) {\n report(\n \"link_target\",\n conceptId,\n `target ${link.target} is not in the bundle`,\n \"warning\",\n );\n }\n }\n\n // A short `repo` names a repository without saying where it lives, so a\n // foreign anchor carrying one can never be fetched. A warning, not an\n // error: it still matches this root's own origin, and records are never\n // rewritten under an author.\n for (const anchor of fm.strauss_anchors ?? []) {\n if (anchor.repo && !isCanonicalRepoUrl(anchor.repo)) {\n report(\n \"anchor_repo\",\n conceptId,\n `anchor repo \"${anchor.repo}\" is not a full remote URL, so it cannot be resolved against a remote`,\n \"warning\",\n );\n }\n }\n\n // An assumption with sources is a fact that forgot to change its mind.\n if (fm.strauss_assumption && fm.sources?.length) {\n report(\"assumption\", conceptId, \"marked an assumption but cites sources\");\n }\n }\n\n return problems;\n}\n","import {\n adjudicate,\n type KbStanding,\n type KbWarning,\n type KbWarningAnchor,\n} from \"./adjudicate.js\";\nimport type { KbAnchorDriftEntry } from \"./anchor-resolver/index.js\";\nimport { edgeNeighbours } from \"./kb-edges.js\";\nimport type { KbRecord, KbRecordStatus } from \"./kb-record.schema.js\";\nimport { validateBundle } from \"./validate.js\";\n\n/**\n * A health sweep over a whole base — read-only, and never a mutation.\n *\n * Every other read answers a question a caller already had. This one asks the\n * questions nobody thinks to: which records the calendar has already retired,\n * which nobody ever confirmed, which have been open long enough that \"open\" is\n * now the answer, and which the graph has quietly dropped on the floor. Those\n * decay silently, because a stale record reads exactly like a live one and a\n * question nobody answered reads exactly like one nobody asked.\n *\n * Grouped and counted rather than merged into one list: the eight checks are\n * eight different repairs — re-verify, re-date, answer, link, supersede, or\n * re-anchor — and a flat list of \"problems\" would leave the reader sorting\n * them again.\n *\n * Every group is emitted even when empty. A check that found nothing and a\n * check that never ran look identical in a report that only lists findings,\n * and the difference is the whole value of a sweep.\n */\n\nexport const DEFAULT_EXPIRING_DAYS = 30;\nexport const DEFAULT_UNVERIFIED_DAYS = 90;\nexport const DEFAULT_AGING_DAYS = 90;\n\nexport const KB_DOCTOR_CHECKS = [\n \"expired\",\n \"expiring\",\n \"unverified\",\n \"aging\",\n \"orphaned\",\n \"broken-supersession\",\n \"superseded-but-cited\",\n \"drifted\",\n \"unchecked\",\n] as const;\n\nexport type KbDoctorCheck = (typeof KB_DOCTOR_CHECKS)[number];\n\n/** What each check looks for, in the words the report prints. */\nconst CHECK_HEADLINES: Record<KbDoctorCheck, string> = {\n expired: \"past its stale_after date\",\n expiring: \"stale_after falls within the window\",\n unverified: \"nobody has ever confirmed it, and it is old enough to matter\",\n aging: \"still open or still proposed long after it was written\",\n orphaned: \"no other record links to it\",\n \"broken-supersession\": \"the supersession pointers do not resolve\",\n \"superseded-but-cited\":\n \"a live record's body links to one that no longer holds\",\n drifted: \"the code an anchor points at moved out from under its hash\",\n unchecked: \"an anchor in another repository nothing could reach\",\n};\n\nexport type KbDoctorFinding = {\n conceptId: string;\n title: string | null;\n status: KbRecordStatus;\n /** Why this record is in this group, in one phrase a reader can act on. */\n note: string;\n};\n\nexport type KbDoctorGroup = {\n check: KbDoctorCheck;\n /** What the check looks for, so a zero count still says something. */\n headline: string;\n count: number;\n findings: KbDoctorFinding[];\n};\n\nexport type KbDoctorThresholds = {\n expiringDays: number;\n unverifiedDays: number;\n agingDays: number;\n};\n\nexport type KbDoctorReport = {\n recordCount: number;\n thresholds: KbDoctorThresholds;\n counts: Record<KbDoctorCheck, number>;\n /** All eight, in `KB_DOCTOR_CHECKS` order, empty ones included. */\n groups: KbDoctorGroup[];\n findingCount: number;\n healthy: boolean;\n /**\n * Anchors carrying a hash, by the resolver that produced it. A heuristic\n * span is weaker evidence than a parsed one, so a base still leaning on the\n * regex resolver is worth re-resolving. Not a finding: a regex-stamped\n * anchor is not broken.\n */\n anchorResolvers: KbAnchorResolverCounts;\n};\n\nexport type KbAnchorResolverCounts = {\n total: number;\n treeSitter: number;\n /** Includes anchors stamped before resolvers were named. */\n regex: number;\n};\n\nexport type KbDoctorOptions = {\n /** How far ahead `expiring` looks. */\n expiringDays?: number;\n /** How old an unconfirmed record must be before `unverified` reports it. */\n unverifiedDays?: number;\n /** How long `open` or `proposed` may stand before `aging` reports it. */\n agingDays?: number;\n now?: Date;\n /**\n * Anchor drift, precomputed by the caller. `doctor` stays pure and sync for\n * the same reason `adjudicate` does — the filesystem work of re-resolving\n * anchors belongs to `detectAnchorDrift`, and a sweep with no map simply\n * reports the `drifted` check as clean rather than half-running it.\n */\n anchorDrift?: Map<string, KbAnchorDriftEntry[]>;\n};\n\nconst DAY_MS = 86_400_000;\n\n/** A whole-file anchor names no resolver, so only symbol anchors are counted. */\nfunction anchorResolverCounts(bundle: KbRecord[]): KbAnchorResolverCounts {\n let treeSitter = 0;\n let regex = 0;\n for (const record of bundle) {\n for (const anchor of record.frontmatter.strauss_anchors ?? []) {\n if (!anchor.hash || !anchor.symbol) continue;\n if (anchor.resolver === \"tree-sitter\") treeSitter += 1;\n else regex += 1;\n }\n }\n return { total: treeSitter + regex, treeSitter, regex };\n}\n\nexport function doctor(\n bundle: KbRecord[],\n options: KbDoctorOptions = {},\n): KbDoctorReport {\n const thresholds: KbDoctorThresholds = {\n expiringDays: options.expiringDays ?? DEFAULT_EXPIRING_DAYS,\n unverifiedDays: options.unverifiedDays ?? DEFAULT_UNVERIFIED_DAYS,\n agingDays: options.agingDays ?? DEFAULT_AGING_DAYS,\n };\n const now = options.now ?? new Date();\n\n const adjudicated = adjudicate(bundle, bundle, now, options.anchorDrift);\n const standings = new Map<string, KbStanding>(\n adjudicated.map((hit) => [hit.record.conceptId, hit.standing]),\n );\n // Superseded and rejected records are already out of force: a replaced\n // record whose date has passed needs no repair, and reporting one would\n // bury the records that do.\n const inForce = adjudicated.filter(\n (hit) => hit.standing !== \"superseded\" && hit.standing !== \"rejected\",\n );\n\n const groups: KbDoctorGroup[] = [\n group(\"expired\", expired(inForce, now)),\n group(\"expiring\", expiring(inForce, now, thresholds.expiringDays)),\n group(\"unverified\", unverified(inForce, now, thresholds.unverifiedDays)),\n group(\"aging\", aging(inForce, now, thresholds.agingDays)),\n group(\"orphaned\", orphaned(bundle)),\n group(\"broken-supersession\", brokenSupersession(bundle, adjudicated)),\n group(\"superseded-but-cited\", supersededButCited(bundle, standings)),\n group(\"drifted\", drifted(inForce)),\n group(\"unchecked\", unchecked(inForce)),\n ];\n\n const counts = Object.fromEntries(\n groups.map((entry) => [entry.check, entry.count]),\n ) as Record<KbDoctorCheck, number>;\n const findingCount = groups.reduce((total, entry) => total + entry.count, 0);\n\n return {\n recordCount: bundle.length,\n thresholds,\n counts,\n groups,\n findingCount,\n anchorResolvers: anchorResolverCounts(bundle),\n healthy: findingCount === 0,\n };\n}\n\nfunction group(\n check: KbDoctorCheck,\n findings: KbDoctorFinding[],\n): KbDoctorGroup {\n return {\n check,\n headline: CHECK_HEADLINES[check],\n count: findings.length,\n findings,\n };\n}\n\n/**\n * An unreadable `stale_after` counts as expired rather than being skipped.\n * A date nobody can parse is a date nobody can trust, and treating it as\n * absent would silently exempt the record from the only check that ages it.\n *\n * `stale_after` is written date-only, which `Date.parse` reads as UTC\n * midnight — so a record goes stale at the start of its date, and a sweep run\n * at 00:00:00Z on that very date still counts it as expiring rather than\n * expired. That is `adjudicate`'s comparison, not a second one: two readings\n * of the same field disagreeing about the day would be worse than either.\n */\nfunction expired(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const raw = hit.record.frontmatter.stale_after;\n if (!raw) continue;\n const at = Date.parse(raw);\n if (Number.isNaN(at)) {\n findings.push(\n finding(hit.record, `stale_after \"${raw}\" is not a readable date`),\n );\n continue;\n }\n if (at < now.getTime()) {\n findings.push(\n finding(\n hit.record,\n `stale since ${raw} (${daysBetween(at, now.getTime())} days ago)`,\n ),\n );\n }\n }\n return findings;\n}\n\nfunction expiring(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n withinDays: number,\n): KbDoctorFinding[] {\n const horizon = now.getTime() + withinDays * DAY_MS;\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const raw = hit.record.frontmatter.stale_after;\n if (!raw) continue;\n const at = Date.parse(raw);\n if (Number.isNaN(at) || at < now.getTime() || at > horizon) continue;\n findings.push(\n finding(\n hit.record,\n `goes stale ${raw} (in ${daysBetween(now.getTime(), at)} days)`,\n ),\n );\n }\n return findings;\n}\n\n/**\n * Age is read from `generated.at`, so a record carrying no timestamp is not\n * reported: this check is about how long something has gone unconfirmed, and\n * without a start there is no duration. `kb_query` still warns `unverified` on\n * every such record at read time, which is where the timeless case belongs.\n */\nfunction unverified(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n olderThanDays: number,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n if (hit.record.frontmatter.verified?.length) continue;\n const age = ageInDays(hit.record, now);\n if (age === null || age <= olderThanDays) continue;\n findings.push(\n finding(hit.record, `never verified, written ${age} days ago`),\n );\n }\n return findings;\n}\n\n/**\n * One group for both spellings of the same decay. An `open` question and a\n * `proposed` decision are the same debt — something was raised and never\n * settled — and splitting them would make the reader check two places for one\n * repair.\n */\nfunction aging(\n hits: ReturnType<typeof adjudicate>,\n now: Date,\n olderThanDays: number,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const status = hit.record.frontmatter.strauss_status;\n if (status !== \"open\" && status !== \"proposed\") continue;\n const age = ageInDays(hit.record, now);\n if (age === null || age <= olderThanDays) continue;\n findings.push(\n finding(\n hit.record,\n status === \"open\"\n ? `open for ${age} days`\n : `proposed ${age} days ago and still unsettled`,\n ),\n );\n }\n return findings.sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n}\n\n/**\n * Incoming edges only, and over every record whatever its standing.\n *\n * \"Links to\" is directional: a record that cites five others and is cited by\n * none is precisely the island this names — reachable if you already know it\n * exists, which is the thing nobody does. Standing is not a filter here\n * because the question is about the graph, not about force: a rejected record\n * nothing points at is as lost as a current one.\n *\n * Supersession is read in one direction only — the replacement references what\n * it replaced, never the other way. `kb-edges` deliberately reports the pair\n * symmetrically, which is right for a walk and wrong here: taken symmetrically,\n * a dead record vouches for its own replacement, so an old→new pair nothing\n * else touches would rescue itself and never report. Read one way, the\n * replaced record stays reachable through its history and the replacement has\n * to earn its own inbound link.\n */\nfunction orphaned(bundle: KbRecord[]): KbDoctorFinding[] {\n const present = new Set(bundle.map((record) => record.conceptId));\n const referenced = new Set<string>();\n for (const record of bundle) {\n for (const neighbour of edgeNeighbours(record, bundle, \"body-link\")) {\n referenced.add(neighbour.conceptId);\n }\n // Both spellings of one statement — \"X replaced R\" — whichever side of the\n // pair stores it. Either way it is X that references R.\n for (const replaced of record.frontmatter.strauss_supersedes ?? []) {\n referenced.add(replaced);\n }\n const replacement = record.frontmatter.strauss_superseded_by;\n if (replacement && present.has(replacement)) {\n referenced.add(record.conceptId);\n }\n }\n return bundle\n .filter((record) => !referenced.has(record.conceptId))\n .map((record) => finding(record, \"no other record links to it\"));\n}\n\n/**\n * The cross-record supersession checks `validate` already owns, plus the two\n * shapes only a chain walk can see: a cycle, and a fork where two records both\n * claim to replace one. Re-deriving the first set here would give the two\n * commands room to disagree about what a broken chain is.\n *\n * \"Superseded with nothing surviving\" is not a third clause: a chain ends\n * empty only when a pointer is absent, missing, or cyclic, and all three are\n * already reported above — a second phrasing of the same defect would read as\n * two problems to repair.\n */\nconst SUPERSESSION_CHECKS = new Set([\n \"superseded_by\",\n \"supersedes\",\n \"backlink\",\n]);\n\nfunction brokenSupersession(\n bundle: KbRecord[],\n adjudicated: ReturnType<typeof adjudicate>,\n): KbDoctorFinding[] {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const findings: KbDoctorFinding[] = [];\n const seen = new Set<string>();\n const add = (record: KbRecord, note: string) => {\n const key = `${record.conceptId}\\u0000${note}`;\n if (seen.has(key)) return;\n seen.add(key);\n findings.push(finding(record, note));\n };\n\n for (const problem of validateBundle(bundle)) {\n if (!SUPERSESSION_CHECKS.has(problem.check)) continue;\n const record = byId.get(problem.conceptId);\n if (record) add(record, problem.note);\n }\n\n // Both `validate` and the chain walk below reach a `strauss_superseded_by`\n // only through a record whose status is already `superseded` — so a record\n // left `accepted` while pointing at a replacement is invisible to both, and\n // adjudication reads it as current no matter what the pointer says. That is\n // precisely the hand-edit this check exists for: the store writes the status\n // and the pointer in one mutation, so the two can only disagree off-tool.\n for (const record of bundle) {\n const replacement = record.frontmatter.strauss_superseded_by;\n if (!replacement) continue;\n if (!byId.has(replacement)) {\n add(record, `replacement ${replacement} is missing`);\n } else if (record.frontmatter.strauss_status !== \"superseded\") {\n add(\n record,\n `names ${replacement} as its replacement but is not marked superseded`,\n );\n }\n }\n\n for (const hit of adjudicated) {\n for (const warning of hit.warnings) {\n if (warning.kind === \"broken-chain\") {\n add(hit.record, `replacement ${warning.missing} is missing`);\n } else if (warning.kind === \"chain-cycle\") {\n add(\n hit.record,\n `supersession chain cycles through ${warning.through.join(\" → \")}`,\n );\n } else if (warning.kind === \"forked-chain\") {\n add(\n hit.record,\n `two records claim to replace it: ${warning.heads.join(\", \")}`,\n );\n }\n }\n }\n\n return findings.sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n}\n\n/**\n * A live record whose body points at a record that no longer holds.\n *\n * The most quietly wrong state in a base: the citing record is current, so a\n * reader trusts it, and the link reads as support for a claim its target has\n * already stopped making. One finding per pair, because each is its own edit.\n *\n * Rejected targets count as well as superseded ones. The check's name is for\n * the common case, but the failure is \"cites something that no longer holds\",\n * and a live record citing a rejected one is the worse half — a superseded\n * record at least names its replacement, while a rejected one is a well-formed\n * assertion of what someone decided *not* to do.\n *\n * A record citing the very record it replaced is exempt. That link is the\n * history working as designed — `relatedConceptIds` on a superseding write\n * renders as exactly this edge — and reporting it would put a finding on every\n * correctly performed supersession.\n */\nfunction supersededButCited(\n bundle: KbRecord[],\n standings: Map<string, KbStanding>,\n): KbDoctorFinding[] {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const findings: KbDoctorFinding[] = [];\n for (const record of bundle) {\n const standing = standings.get(record.conceptId);\n if (standing === \"superseded\" || standing === \"rejected\") continue;\n for (const target of edgeNeighbours(record, bundle, \"body-link\")) {\n const targetStanding = standings.get(target.conceptId);\n if (targetStanding !== \"superseded\" && targetStanding !== \"rejected\") {\n continue;\n }\n if (replaces(record, target)) continue;\n const replacement = target.frontmatter.strauss_superseded_by;\n findings.push(\n finding(\n record,\n `cites ${targetStanding} ${target.conceptId}${\n targetStanding === \"superseded\" &&\n replacement &&\n byId.has(replacement)\n ? ` — replaced by ${replacement}`\n : \"\"\n }`,\n ),\n );\n }\n }\n return findings;\n}\n\n/**\n * Records whose anchors no longer resolve to the code they were hashed\n * against — read off the `drifted` warning `adjudicate` already attaches, so\n * the sweep and every read path agree about what drift is. Recomputing the\n * comparison here would give the two room to disagree.\n *\n * In-force records only. A superseded record anchoring code that has since\n * moved is the expected outcome of it being replaced, not a repair.\n *\n * Unresolvable anchors ride in this group rather than a check of their own:\n * the repair is the same edit, and the note says which happened.\n */\nfunction drifted(hits: ReturnType<typeof adjudicate>): KbDoctorFinding[] {\n return anchorFindings(hits, \"drifted\", (count) =>\n count === 1 ? \"anchor no longer matches\" : \"anchors no longer match\",\n );\n}\n\n/**\n * Anchors in another repository that nothing could read — unreachable, refused,\n * or offline. Its own group because the repair is not an edit to the record:\n * a reader who cannot tell \"unchecked\" from \"clean\" trusts a base nobody\n * checked.\n */\nfunction unchecked(hits: ReturnType<typeof adjudicate>): KbDoctorFinding[] {\n return anchorFindings(hits, \"unchecked\", (count) =>\n count === 1 ? \"anchor was not checked\" : \"anchors were not checked\",\n );\n}\n\n/** Anchor findings grouped by repository, so one unreachable remote reads as one cause. */\nfunction anchorFindings(\n hits: ReturnType<typeof adjudicate>,\n kind: \"drifted\" | \"unchecked\",\n headline: (count: number) => string,\n): KbDoctorFinding[] {\n const findings: KbDoctorFinding[] = [];\n for (const hit of hits) {\n const warning = hit.warnings.find(\n (entry): entry is Extract<KbWarning, { anchors: KbWarningAnchor[] }> =>\n entry.kind === kind,\n );\n if (!warning) continue;\n const byRepo = new Map<string, string[]>();\n for (const anchor of warning.anchors) {\n const repo = anchor.repo ?? \"\";\n byRepo.set(repo, [...(byRepo.get(repo) ?? []), describeAnchor(anchor)]);\n }\n const detail = [...byRepo.entries()].map(([repo, entries]) =>\n repo ? `${repo}: ${entries.join(\", \")}` : entries.join(\", \"),\n );\n findings.push(\n finding(\n hit.record,\n `${warning.anchors.length} ${headline(warning.anchors.length)}: ${detail.join(\"; \")}`,\n ),\n );\n }\n return findings.sort((left, right) =>\n left.conceptId.localeCompare(right.conceptId),\n );\n}\n\nfunction describeAnchor(anchor: KbWarningAnchor): string {\n const at = anchor.symbol ? `${anchor.file}:${anchor.symbol}` : anchor.file;\n if (anchor.class === \"gone\") {\n return `${at} gone${anchor.reason ? ` (${anchor.reason})` : \"\"}`;\n }\n if (anchor.reason) return `${at} (${anchor.reason})`;\n if (anchor.remoteState === \"drifted-on-default\") {\n return `${at} (matches ref, moved on the default branch)`;\n }\n if (anchor.diffSize === null) return `${at} (changed, size unrecorded)`;\n // A same-size rewrite is the drift most worth naming plainly:\n // \"0 lines apart\" reads as \"nothing happened\".\n return anchor.diffSize === 0\n ? `${at} (content changed, same line count)`\n : `${at} (${anchor.diffSize} line${anchor.diffSize === 1 ? \"\" : \"s\"} apart)`;\n}\n\n/** Either pointer saying `later` is what stands in `earlier`'s place. */\nfunction replaces(later: KbRecord, earlier: KbRecord): boolean {\n return (\n (later.frontmatter.strauss_supersedes ?? []).includes(earlier.conceptId) ||\n earlier.frontmatter.strauss_superseded_by === later.conceptId\n );\n}\n\nfunction finding(record: KbRecord, note: string): KbDoctorFinding {\n return {\n conceptId: record.conceptId,\n title: record.frontmatter.title ?? null,\n status: record.frontmatter.strauss_status,\n note,\n };\n}\n\n/** Whole days between two instants, never negative. */\nfunction daysBetween(from: number, to: number): number {\n return Math.max(0, Math.floor((to - from) / DAY_MS));\n}\n\nfunction ageInDays(record: KbRecord, now: Date): number | null {\n const at = record.frontmatter.generated?.at;\n if (!at) return null;\n const written = Date.parse(at);\n if (Number.isNaN(written)) return null;\n return daysBetween(written, now.getTime());\n}\n","import { z } from \"zod\";\nimport { adjudicate } from \"../adjudicate.js\";\nimport { reassessPacket, type KbReassessPacket } from \"../drift/index.js\";\nimport { KbRecordNotFoundError } from \"../kb-errors.js\";\nimport { assertBaseNotFrozen, KbBaseFrozenError } from \"../kb-pins/index.js\";\nimport type { KbAnchor } from \"../kb-record.schema.js\";\nimport { argvFlag, bundlePath, conceptId, define, REPO_ROOT } from \"./model.js\";\n\n/** One anchor whose code turned up unchanged elsewhere, and where. */\nexport type KbRebaselinedAnchor = {\n file: string;\n symbol?: string;\n toFile: string;\n toSymbol?: string;\n};\n\nexport type KbReassessResult = {\n conceptId: string;\n /** `null` when nothing survived classification — the record needs no reading. */\n packet: KbReassessPacket | null;\n rebaselined: KbRebaselinedAnchor[];\n /** Anchors whose only change was formatting. Reported, never read. */\n cosmetic: number;\n frozen?: true;\n note?: string;\n};\n\nexport const reassessCommand = define({\n name: \"reassess\",\n tool: \"kb_reassess\",\n usage: \"reassess <concept-id> [--repo-root <path>] [--with-diff]\",\n description:\n \"One drifted record, as something to judge: its claim, each anchor's drift class, the old-vs-new span diff, and the records that depend on it. Formatting-only drift is dropped. Empty when there is nothing to reassess. Writes: relocates moved anchors, keeping their hash; never verifies, supersedes, or changes standing.\",\n input: z.object({\n bundlePath,\n conceptId,\n repoRoot: REPO_ROOT,\n withDiff: z\n .boolean()\n .optional()\n .describe(\n \"Recover each anchor's committed span and render the diff. Reads git history.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const repoRoot = argvFlag(argv, \"--repo-root\");\n return {\n bundlePath: path,\n conceptId: argv[1],\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n ...(argv.includes(\"--with-diff\") ? { withDiff: true } : {}),\n };\n },\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, repoRoot, withDiff },\n ): Promise<KbReassessResult> => {\n const root = repoRoot ?? process.cwd();\n const bundle = await store.list(path);\n const record = bundle.find((entry) => entry.conceptId === id);\n if (!record) throw new KbRecordNotFoundError(id);\n\n const drift = await store.detectDrift([record], repoRoot);\n const entries = drift?.get(id) ?? [];\n if (!entries.some((entry) => entry.state !== \"match\")) {\n return { conceptId: id, packet: null, rebaselined: [], cosmetic: 0 };\n }\n\n const standing = adjudicate(bundle, bundle).find(\n (hit) => hit.record.conceptId === id,\n )?.standing;\n // Only asked for once there is drift: the dependants of a record that\n // still holds are not part of this question.\n const impact = await store.impact(path, id);\n\n const { packet, classified } = await reassessPacket(root, record, entries, {\n ...(withDiff ? { withDiff: true } : {}),\n impact,\n ...(standing ? { standing } : {}),\n });\n\n // `moved` is the one class this command settles rather than reports: the\n // bytes are identical, so the record still describes them and only the\n // address was wrong. The hash is kept exactly as it was — nothing here\n // re-baselines *content*, which would be accepting an edit nobody read.\n const moves = classified.filter((found) => found.class === \"moved\");\n let frozen = false;\n const rebaselined: KbRebaselinedAnchor[] = [];\n if (moves.length) {\n const relocated = new Map<KbAnchor, KbAnchor>();\n for (const found of moves) {\n const to = found.entry.movedTo;\n if (!to) continue;\n relocated.set(found.anchor, {\n ...found.anchor,\n file: to.file,\n ...(to.symbol ? { symbol: to.symbol } : {}),\n });\n rebaselined.push({\n file: found.anchor.file,\n ...(found.anchor.symbol ? { symbol: found.anchor.symbol } : {}),\n toFile: to.file,\n ...(to.symbol ? { toSymbol: to.symbol } : {}),\n });\n }\n try {\n await assertBaseNotFrozen(process.cwd(), path);\n } catch (error) {\n if (!(error instanceof KbBaseFrozenError)) throw error;\n frozen = true;\n }\n if (!frozen) {\n await store.updateAnchors(\n path,\n id,\n (record.frontmatter.strauss_anchors ?? []).map(\n (anchor) => relocated.get(anchor) ?? anchor,\n ),\n actor,\n );\n }\n }\n\n return {\n conceptId: id,\n packet,\n rebaselined: frozen ? [] : rebaselined,\n cosmetic: classified.filter((found) => found.class === \"cosmetic\").length,\n ...(frozen\n ? {\n frozen: true as const,\n note: \"base is frozen: nothing was rebaselined\",\n }\n : {}),\n };\n },\n render: (result) => renderReassess(result as KbReassessResult),\n});\n\n/**\n * The packet as prose, because it is read rather than parsed. `--json` is the\n * machine shape; everything below exists so a reader can answer without\n * opening the repository.\n */\nexport function renderReassess(result: KbReassessResult): string {\n const lines: string[] = [];\n for (const move of result.rebaselined) {\n lines.push(\n `rebaselined: ${at(move.file, move.symbol)} → ${at(move.toFile, move.toSymbol)} (same code, new address)`,\n );\n }\n if (result.cosmetic) {\n lines.push(\n `${result.cosmetic} anchor${result.cosmetic === 1 ? \"\" : \"s\"} changed formatting only.`,\n );\n }\n if (result.note) lines.push(result.note);\n\n const packet = result.packet;\n if (!packet) {\n lines.push(`${result.conceptId}: nothing to reassess.`);\n return lines.join(\"\\n\");\n }\n\n lines.push(\n \"\",\n `# ${packet.conceptId}${packet.title ? ` — ${packet.title}` : \"\"}`,\n `type: ${packet.type} standing: ${packet.standing}`,\n ...(packet.why ? [`why: ${packet.why}`] : []),\n ...(packet.claim\n ? [\"\", `## ${packet.claim.section}`, packet.claim.text]\n : []),\n \"\",\n `## Anchors (${packet.anchors.length})`,\n );\n\n for (const anchor of packet.anchors) {\n lines.push(\n `- ${at(anchor.file, anchor.symbol)} — ${anchor.class}${anchor.reason ? ` (${anchor.reason})` : \"\"}`,\n );\n if (!anchor.diff) continue;\n if (anchor.diff.status === \"unrecoverable\") {\n lines.push(\n \" diff: unrecoverable — no committed span to compare against\",\n );\n continue;\n }\n lines.push(\n ` diff vs ${anchor.diff.ref} (${anchor.diff.source}): +${anchor.diff.added} −${anchor.diff.removed}`,\n ...anchor.diff.unified.split(\"\\n\").map((line) => ` ${line}`),\n );\n }\n\n if (packet.impact.length) {\n lines.push(\"\", `## Impact (${packet.impact.length})`);\n for (const entry of packet.impact) {\n lines.push(\n `- ${entry.conceptId} [${entry.standing}]${entry.title ? ` — ${entry.title}` : \"\"}`,\n );\n }\n if (packet.impactTruncated) lines.push(\"- … walk truncated\");\n }\n\n lines.push(\"\", `Default: ${packet.default} — ${packet.defaultNote}.`);\n return lines.join(\"\\n\");\n}\n\nfunction at(file: string, symbol?: string): string {\n return symbol ? `${file}:${symbol}` : file;\n}\n","import { z } from \"zod\";\nimport { KB_CAUSAL_LINK_RELS } from \"../record-types.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\nexport const impactCommand = define({\n name: \"impact\",\n tool: \"kb_impact\",\n usage: \"impact <concept-id> [--depth N] [--rels a,b]\",\n description:\n \"What breaks if this record changes: its transitive set of dependants, each with its standing. Each rel declares which of its ends depends on the other, and the walk follows each rel in its own direction. Naming `related_to` or an unknown rel in `rels` is an error. kb_backlinks gives one flat hop.\",\n input: z.object({\n bundlePath,\n conceptId,\n depth: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Hops out from the record. Unbounded when omitted; a walk this cuts reports truncated: true.\",\n ),\n rels: z\n .array(z.enum(KB_CAUSAL_LINK_RELS))\n .optional()\n .describe(\n \"Narrow which rels the walk follows. Defaults to every rel that carries a dependence — all but related_to.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const depth = argvFlag(argv, \"--depth\");\n const rels = argvFlag(argv, \"--rels\");\n return {\n bundlePath: path,\n conceptId: argv[1],\n ...(depth ? { depth: Number(depth) } : {}),\n ...(rels ? { rels: rels.split(\",\").filter(Boolean) } : {}),\n };\n },\n run: async ({ store }, { bundlePath: path, conceptId: id, depth, rels }) =>\n store.impact(path, id, {\n ...(depth !== undefined ? { depth } : {}),\n ...(rels?.length ? { rels } : {}),\n }),\n});\n","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport {\n argvFlags,\n argvPositional,\n bundlePath,\n define,\n TAGS,\n} from \"./model.js\";\n\nexport const listCommand = define({\n name: \"list\",\n tool: \"kb_list\",\n usage: \"list [type] [--tag T]...\",\n description:\n \"Every record, optionally one type or tag. For enumerating; use kb_query for a question.\",\n input: z.object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES).optional(),\n tags: TAGS,\n }),\n fromArgv: (argv, path) => {\n const tags = argvFlags(argv, \"--tag\");\n // The type is the first positional, in either order: a flag in the slot is\n // a flag, and `list --tag review decision` still narrows by type.\n const type = argvPositional(argv, \"--tag\");\n return {\n bundlePath: path,\n ...(type ? { type } : {}),\n ...(tags.length ? { tags } : {}),\n };\n },\n run: async ({ store }, { bundlePath: path, type, tags }) =>\n (await store.list(path, type, { ...(tags ? { tags } : {}) })).map(\n (record) => ({\n conceptId: record.conceptId,\n title: record.frontmatter.title ?? null,\n description: record.frontmatter.description ?? null,\n status: record.frontmatter.strauss_status,\n anchors: record.frontmatter.strauss_anchors ?? [],\n }),\n ),\n});\n","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport { argvFlag, bundlePath, define, REPO_ROOT } from \"./model.js\";\n\nexport const loadCommand = define({\n name: \"load\",\n tool: \"kb_load\",\n usage: \"load [type] [--budget N | --all] [--repo-root PATH]\",\n description:\n \"Load the whole base, each record with its standing — call it first, at the point of use, since compaction drops it. Superseded records arrive as stubs; kb_trace has the history. Over budget it refuses: kb_catalog, then kb_pack, or narrow with `type`; `all` bypasses. Never read record files directly — only kb_* tools resolve supersession. `digest` stamps the base's content, so hooks know when to reload.\",\n input: z\n .object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES).optional(),\n budgetTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Approximate token ceiling. Defaults to 25000.\"),\n all: z\n .boolean()\n .optional()\n .describe(\n \"Loads the entire base regardless of size, bypassing the token budget; mutually exclusive with budgetTokens.\",\n ),\n repoRoot: REPO_ROOT,\n })\n .refine((value) => !(value.all && value.budgetTokens !== undefined), {\n message:\n \"all is mutually exclusive with budgetTokens: pass a ceiling or none, not both.\",\n }),\n fromArgv: (argv, path) => {\n const budget = argvFlag(argv, \"--budget\");\n const repoRoot = argvFlag(argv, \"--repo-root\");\n return {\n bundlePath: path,\n ...(argv[1] && !argv[1].startsWith(\"--\") ? { type: argv[1] } : {}),\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(argv.includes(\"--all\") ? { all: true } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n };\n },\n run: async (\n { store },\n { bundlePath: path, type, budgetTokens, all, repoRoot },\n ) => {\n const result = await store.load(path, {\n ...(type ? { type } : {}),\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(all ? { all } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n });\n if (!result.loaded) return result;\n return {\n ...result,\n records: result.records.map((hit) => ({\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n warnings: hit.warnings,\n anchors: hit.record.frontmatter.strauss_anchors ?? [],\n body: hit.record.body,\n })),\n };\n },\n});\n","import { z } from \"zod\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const logCommand = define({\n name: \"log\",\n tool: \"kb_log\",\n usage: \"log\",\n description:\n \"Who touched what, and when. Append-only; malformed lines are reported, never repaired.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: ({ store }, { bundlePath: path }) => store.readLog(path),\n});\n","import { z } from \"zod\";\nimport { composeNoDecisionRecord } from \"../decision-record.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const noDecisionCommand = define({\n name: \"no-decision\",\n tool: \"kb_no_decision\",\n usage: \"no-decision <reason...>\",\n description:\n \"Record in one sentence that a piece of work had nothing to decide. Idempotent.\",\n input: z.object({ bundlePath, reason: z.string().min(1) }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n reason: argv.slice(1).join(\" \").trim(),\n }),\n run: async ({ store, actor, now }, { bundlePath: path, reason }) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.write(\n path,\n { ...composeNoDecisionRecord(reason, actor, now()), overwrite: true },\n actor,\n );\n return { conceptId: record.conceptId };\n },\n});\n","import { z } from \"zod\";\nimport type { KbWarning } from \"../adjudicate.js\";\nimport type { KbPackResult } from \"../pack.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\nexport const packCommand = define({\n name: \"pack\",\n tool: \"kb_pack\",\n usage: \"pack <conceptId> [--hops N] [--max-nodes N] [--budget N]\",\n description:\n \"Bounded neighbourhood around one record: within `hops`, ranked, cut to `maxNodes`, with every cut record named under Excluded. Use when the base is over kb_load's budget and the work centres on a record you can name. Refuses over budget rather than truncating. Everything below the header is byte-stable across runs. Resolves supersession like kb_load.\",\n input: z.object({\n bundlePath,\n conceptId,\n hops: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"How far from the root the walk may reach. Defaults to 2.\"),\n maxNodes: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"How many records the pack may hold, root included. Defaults to 20.\",\n ),\n budgetTokens: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\n \"Approximate token ceiling over what is actually emitted. Defaults to 25000.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const hops = argvFlag(argv, \"--hops\");\n const maxNodes = argvFlag(argv, \"--max-nodes\");\n const budget = argvFlag(argv, \"--budget\");\n return {\n bundlePath: path,\n conceptId: argv[1],\n ...(hops ? { hops: Number(hops) } : {}),\n ...(maxNodes ? { maxNodes: Number(maxNodes) } : {}),\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n };\n },\n run: async (\n { store, now },\n { bundlePath: path, conceptId: root, hops, maxNodes, budgetTokens },\n ) => {\n const result = await store.pack(path, root, {\n ...(hops !== undefined ? { hops } : {}),\n ...(maxNodes !== undefined ? { maxNodes } : {}),\n ...(budgetTokens !== undefined ? { budgetTokens } : {}),\n });\n return render(result, path, now());\n },\n});\n\n/**\n * The timestamp is the header's last line and appears nowhere else, so a\n * caller can drop everything through that line and diff two packs of the same\n * base byte for byte.\n */\nfunction render(result: KbPackResult, bundle: string, at: string): string {\n const lines = [\n `# KB Pack — ${result.root}`,\n `bundle: ${bundle}`,\n `budget: ~${result.tokensLoaded} of ${result.budgetTokens} tokens, ${result.recordCount} records`,\n `packed: ${at}`,\n \"\",\n `## Records (${result.records.length})`,\n ];\n\n for (const record of result.records) {\n lines.push(\n \"\",\n `### ${record.conceptId}${record.title ? ` — ${record.title}` : \"\"} [${record.standing}]`,\n );\n if (record.warnings.length) {\n lines.push(`warnings: ${record.warnings.map(warningLabel).join(\"; \")}`);\n }\n if (record.anchors.length) {\n lines.push(\n `anchors: ${record.anchors\n .map((anchor) =>\n anchor.symbol ? `${anchor.file}#${anchor.symbol}` : anchor.file,\n )\n .join(\", \")}`,\n );\n }\n lines.push(\"\", record.body.trimEnd());\n }\n\n if (result.superseded.length) {\n lines.push(\"\", `## Superseded (${result.superseded.length})`);\n for (const entry of result.superseded) {\n lines.push(\n `- ${entry.conceptId} → ${\n entry.supersededBy.join(\", \") || \"(no surviving head)\"\n }${entry.at ? ` (${entry.at})` : \"\"}`,\n );\n }\n }\n\n if (result.excluded.length) {\n lines.push(\"\", `## Excluded (${result.excluded.length})`);\n for (const cut of result.excluded) lines.push(`- ${cut}`);\n }\n\n return lines.join(\"\\n\");\n}\n\nfunction warningLabel(warning: KbWarning): string {\n switch (warning.kind) {\n case \"superseded\":\n return `superseded by ${warning.by.join(\", \")}`;\n case \"unsettled\":\n return `unsettled (${warning.status})`;\n case \"broken-chain\":\n return `broken chain — ${warning.missing} is not in the bundle`;\n case \"chain-cycle\":\n return `chain cycle through ${warning.through.join(\" → \")}`;\n case \"forked-chain\":\n return `forked chain — heads ${warning.heads.join(\", \")}`;\n case \"stale\":\n return `stale since ${warning.staleAfter}`;\n case \"unresolved-question\":\n return \"unresolved question\";\n default:\n return warning.kind;\n }\n}\n","import { z } from \"zod\";\nimport { pinBase } from \"../kb-pins/index.js\";\nimport { argvFlag, bundlePath, define } from \"./model.js\";\n\nexport const pinCommand = define({\n name: \"pin\",\n tool: \"kb_pin\",\n usage:\n \"pin [bundle-path] [--mode full|index] [--profiles a,b] [--local|--user] [--frozen|--unfreeze]\",\n description:\n \"Pin a base into a workspace manifest so kb_context surfaces it. Layers, nearest wins: project `.strauss/kb-pins.json` (default), `--local` (personal, gitignored), `--user` (`~/.strauss`). Idempotent; `--mode full|index`, `--profiles`, `--frozen`/`--unfreeze` update only those fields. A path with no records pins with a warning. Never touches the base itself.\",\n input: z.object({\n bundlePath,\n mode: z\n .enum([\"full\", \"index\"])\n .optional()\n .describe(\n \"full: always emit this base's records whole (still under the block budget); index: never upgrade. Absent: the profile's full-under threshold decides.\",\n ),\n profiles: z\n .array(z.string())\n .optional()\n .describe(\"Context profiles this pin surfaces in. Absent: all of them.\"),\n layer: z\n .enum([\"project\", \"local\", \"user\"])\n .optional()\n .describe(\n \"Which manifest to write: project (committed, default), local (personal, gitignored), user (~/.strauss, every workspace).\",\n ),\n frozen: z\n .boolean()\n .optional()\n .describe(\n \"true: the base is concluded — writes against it refuse while pinned. false: lift a freeze.\",\n ),\n }),\n fromArgv: (argv, path) => {\n const positional = argv[1] && !argv[1].startsWith(\"--\") ? argv[1] : path;\n const mode = argvFlag(argv, \"--mode\");\n const profiles = argvFlag(argv, \"--profiles\");\n const layer = argv.includes(\"--user\")\n ? \"user\"\n : argv.includes(\"--local\")\n ? \"local\"\n : undefined;\n const frozen = argv.includes(\"--frozen\")\n ? true\n : argv.includes(\"--unfreeze\")\n ? false\n : undefined;\n return {\n bundlePath: positional,\n ...(mode ? { mode } : {}),\n ...(profiles\n ? {\n profiles: profiles\n .split(\",\")\n .map((p) => p.trim())\n .filter(Boolean),\n }\n : {}),\n ...(layer ? { layer } : {}),\n ...(frozen !== undefined ? { frozen } : {}),\n };\n },\n run: ({ store, now }, { bundlePath: path, mode, profiles, layer, frozen }) =>\n pinBase(store, process.cwd(), path, now(), {\n ...(mode ? { mode } : {}),\n ...(profiles ? { profiles } : {}),\n ...(layer ? { layer } : {}),\n ...(frozen !== undefined ? { frozen } : {}),\n }),\n});\n","import { z } from \"zod\";\nimport { listPins } from \"../kb-pins/index.js\";\nimport { define } from \"./model.js\";\n\nexport const pinsCommand = define({\n name: \"pins\",\n tool: \"kb_pins\",\n usage: \"pins\",\n description:\n \"Every pinned base across the manifest layers, with its layer and whether it resolves to records. Takes no bundlePath.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: ({ store }) => listPins(store, process.cwd()),\n});\n","import { z } from \"zod\";\nimport { KB_RECORD_TYPES } from \"../kb-record.schema.js\";\nimport {\n argvFlag,\n argvFlags,\n argvWithout,\n bundlePath,\n define,\n REPO_ROOT,\n TAGS,\n} from \"./model.js\";\n\nexport const queryCommand = define({\n name: \"query\",\n tool: \"kb_query\",\n usage: \"query <text...> [--tag T]... [--repo-root PATH]\",\n description:\n \"Search; every hit carries its standing. Flagged, never filtered: a superseded hit returns with its replacement, a rejected one is marked. Prefer kb_load when the base fits its budget — a full read beats search. Results are volatile: place them at the tail, not the cached prefix. Never read record files directly.\",\n input: z.object({\n bundlePath,\n text: z.string().optional(),\n type: z.enum(KB_RECORD_TYPES).optional(),\n includeNonCurrent: z.boolean().optional(),\n tags: TAGS,\n repoRoot: REPO_ROOT,\n }),\n // Both are flags, so neither's value may fall into the search text.\n fromArgv: (argv, path) => {\n const repoRoot = argvFlag(argv, \"--repo-root\");\n const tags = argvFlags(argv, \"--tag\");\n const words = argvWithout(argv.slice(1), \"--repo-root\", \"--tag\");\n return {\n bundlePath: path,\n text: words.join(\" \").trim(),\n includeNonCurrent: true,\n ...(tags.length ? { tags } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n };\n },\n run: async (\n { store },\n { bundlePath: path, text, type, includeNonCurrent, tags, repoRoot },\n ) =>\n (\n await store.query(path, text ?? \"\", {\n ...(type ? { type } : {}),\n includeNonCurrent: includeNonCurrent === true,\n ...(tags ? { tags } : {}),\n ...(repoRoot !== undefined ? { repoRoot } : {}),\n })\n ).map((hit) => ({\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n description: hit.record.frontmatter.description ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n warnings: hit.warnings,\n body: hit.record.body,\n })),\n});\n","import { z } from \"zod\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const readIndexCommand = define({\n name: \"index\",\n tool: \"kb_index\",\n usage: \"index\",\n description:\n \"The index — title, type, status, description per record — rebuilt if stale. Cheapest re-orientation after compaction: call it (or kb_context) first, then kb_load or fetch by id.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: ({ store }, { bundlePath: path }) => store.readIndex(path),\n});\n","import { z } from \"zod\";\nimport { kbJsonSchemas } from \"../json-schema.js\";\nimport { define } from \"./model.js\";\n\nexport const schemaCommand = define({\n name: \"schema\",\n tool: \"kb_schema\",\n usage: \"schema\",\n description:\n \"JSON Schema for frontmatter, write input, and log entries, generated from the enforcing code.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: () => Promise.resolve(kbJsonSchemas()),\n});\n","import { z } from \"zod\";\nimport { composeInputSchema } from \"./compose.js\";\nimport { kbLogEntrySchema } from \"./kb-log.js\";\nimport { kbRecordFrontmatterSchema } from \"./kb-record.schema.js\";\n\n/**\n * The frontmatter contract, emitted rather than restated.\n *\n * Prose describing a schema drifts from the code that enforces it; a generated\n * artifact cannot. Documentation points at this, a YAML language server\n * validates hand-edited records against it, and a consumer that is not\n * TypeScript has something to check.\n *\n * `io: 'input'` on purpose. `strauss_status` carries a default, so the output\n * type marks it required while the *document* may legitimately omit it — and\n * the document is what this schema is used to validate.\n */\nexport function kbJsonSchemas(): Record<string, unknown> {\n return {\n recordFrontmatter: z.toJSONSchema(kbRecordFrontmatterSchema, {\n io: \"input\",\n }),\n composeInput: z.toJSONSchema(composeInputSchema, { io: \"input\" }),\n logEntry: z.toJSONSchema(kbLogEntrySchema, { io: \"input\" }),\n };\n}\n","import { z } from \"zod\";\n\nexport const LOG_FILE = \"log.jsonl\";\n\nexport const kbLogEntrySchema = z\n .object({\n // Validated, not just `min(1)`: `at` is a sort key (see `parseLog`\n // below), and a value that isn't actually chronological — a Unix\n // timestamp, a human-typed date, garbage — would sort wrong without\n // ever failing to parse. `z.iso.datetime()` accepts exactly what\n // `record()` writes (`Date#toISOString()`: full precision, `Z` offset)\n // and rejects everything else, including a non-`Z` offset — so a\n // malformed `at` is reported the same way a malformed line already is,\n // rather than silently sorting into the wrong place.\n at: z.iso.datetime(),\n by: z.string().min(1),\n operation: z.string().min(1),\n conceptId: z.string().min(1),\n /** Second concept id, where the operation relates two — supersession. */\n target: z.string().min(1).optional(),\n })\n .strict();\n\nexport type KbLogEntry = z.infer<typeof kbLogEntrySchema>;\n\n/**\n * The log is the bundle's only primary artifact, and the reason it is handled\n * unlike `INDEX.md`.\n *\n * The index is derived: lose it and the records rebuild it. The log records\n * events — which agent wrote what, and when — that leave no trace in the record\n * set, so it cannot be regenerated from anything. Repair therefore means detect\n * and report, never rewrite: rewriting an append-only log destroys the only\n * copy of what it holds.\n *\n * JSONL rather than a markdown list. An earlier version rendered entries as\n * `- <at> · <by> · <op> · <id>` and parsed them by splitting on the separator —\n * a hand-written parser for a format invented here, which fails the first time\n * a value contains the separator. JSON needs no parser and the schema below\n * needs no separator to be unambiguous. Humans read the log through\n * `strauss-kb log`, as they read everything else.\n *\n * One line per entry, appended with `O_APPEND`: POSIX makes the offset update\n * atomic, and writes this size do not interleave on a local filesystem.\n */\nexport function renderLogEntry(entry: KbLogEntry): string {\n return `${JSON.stringify(kbLogEntrySchema.parse(entry))}\\n`;\n}\n\nexport type KbLogReadResult = {\n entries: KbLogEntry[];\n /** Lines that did not parse, with their 1-based position. Never rewritten. */\n malformed: { line: number; text: string }[];\n};\n\nexport function parseLog(raw: string): KbLogReadResult {\n const entries: KbLogEntry[] = [];\n const malformed: { line: number; text: string }[] = [];\n const seen = new Set<string>();\n\n raw.split(\"\\n\").forEach((text, index) => {\n if (!text.trim()) return;\n let value: unknown;\n try {\n value = JSON.parse(text) as unknown;\n } catch {\n malformed.push({ line: index + 1, text });\n return;\n }\n const parsed = kbLogEntrySchema.safeParse(value);\n if (!parsed.success) {\n malformed.push({ line: index + 1, text });\n return;\n }\n\n // A union merge keeps both sides' lines even when a line appears on\n // both — a cherry-pick or rebase that carried one worktree's entry into\n // the other's history before the merge produces two byte-identical\n // lines for what was genuinely one event. Dropping the repeat is the\n // right read here: two writers independently logging the *same*\n // `at`/`by`/`operation`/`conceptId`/`target` is not a real scenario\n // `record()` can produce (each call mints its own `at`), so an exact\n // duplicate is merge residue, not two events that happen to coincide.\n // A near-duplicate (same fields but a different `at`) is left alone —\n // that is two genuine events and both stay.\n const key = JSON.stringify(parsed.data);\n if (seen.has(key)) return;\n seen.add(key);\n\n entries.push(parsed.data);\n });\n\n // A union merge (see `kb-gitattributes.ts`) interleaves two worktrees'\n // appends by whatever order git's merge happened to visit them in, not by\n // when each entry was actually written. Sorting on `at` here means line\n // order in the file is never load-bearing — only the timestamp is. `at` is\n // `Date#toISOString`, so lexicographic order is chronological order; the\n // sort is stable, so entries that share a timestamp keep their file order.\n entries.sort((left, right) =>\n left.at < right.at ? -1 : left.at > right.at ? 1 : 0,\n );\n\n return { entries, malformed };\n}\n","import { readFile } from \"node:fs/promises\";\nimport { z } from \"zod\";\nimport {\n KbStampBaselineError,\n KbStampDigestBaselineError,\n} from \"../kb-errors.js\";\nimport { readMergedPins } from \"../kb-pins/index.js\";\nimport type { KbStampResult } from \"../kb-store.js\";\nimport { argvFlag, define } from \"./model.js\";\n\n/** One base's stamp, plus which records moved when a baseline was given. */\ntype KbStampReport = KbStampResult & {\n /** Changed, added or removed ids; null when the baseline was a digest. */\n changed: string[] | null;\n};\n\nconst DIGEST = /^[0-9a-f]{64}$/;\n\nexport const stampCommand = define({\n name: \"stamp\",\n tool: \"kb_stamp\",\n usage: \"stamp [--bundle PATH] [--since DIGEST|FILE]\",\n description:\n \"Content stamp of a base — `load`'s digest, record counts, per-record digests, how many records have drifted anchors — without any bodies. Takes no bundlePath to stamp every pinned base. With `since`, reports only the bases that moved, naming the changed ids. Reads, never writes.\",\n input: z.object({\n bundlePath: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Absolute path to one knowledge base. Omit to stamp every pinned base.\",\n ),\n since: z\n .string()\n .min(1)\n .optional()\n .describe(\n \"Prior digest, or path to a prior `stamp --json`; only moved bases return, with changed ids when the baseline is a file.\",\n ),\n }),\n fromArgv: (argv, path, _stdin, bundleExplicit) => {\n const since = argvFlag(argv, \"--since\");\n return {\n ...(bundleExplicit ? { bundlePath: path } : {}),\n ...(since !== undefined ? { since } : {}),\n };\n },\n run: async ({ store }, { bundlePath, since }) => {\n const targets = bundlePath\n ? [bundlePath]\n : (await readMergedPins(process.cwd())).pins.map(\n (pin) => pin.absolutePath,\n );\n\n // A digest baseline only answers equality, and equality against which\n // base is ambiguous once more than one is in play — a file baseline\n // carries a digest per base and has no such limit.\n if (since !== undefined && DIGEST.test(since) && targets.length > 1) {\n throw new KbStampDigestBaselineError(since);\n }\n\n const stamps = await Promise.all(\n targets.map((target) => store.stamp(target)),\n );\n if (since === undefined) {\n return stamps.map((stamp) => ({ ...stamp, changed: null }));\n }\n\n const baseline = await readBaseline(since);\n const reports: KbStampReport[] = [];\n for (const stamp of stamps) {\n const before = baseline.byPath.get(stamp.path);\n if (baseline.digest !== null) {\n if (baseline.digest === stamp.digest) continue;\n reports.push({ ...stamp, changed: null });\n continue;\n }\n // A base absent from the baseline was never injected — reported whole,\n // the same as a base whose every record is new.\n if (before && before.digest === stamp.digest) continue;\n reports.push({ ...stamp, changed: changedIds(before?.records, stamp) });\n }\n return reports;\n },\n render: (result) =>\n (result as KbStampReport[])\n .map((report) => {\n const counts = `${report.recordCount} record(s), ${report.superseded} superseded${\n report.drifted ? `, ${report.drifted} drifted` : \"\"\n }`;\n const head = `${report.path} ${report.digest} ${counts}${\n report.newestAt ? ` newest ${report.newestAt}` : \"\"\n }`;\n return report.changed?.length\n ? `${head}\\n changed: ${report.changed.join(\", \")}`\n : head;\n })\n .join(\"\\n\"),\n});\n\nfunction changedIds(\n before: Map<string, string> | undefined,\n stamp: KbStampResult,\n): string[] {\n const now = new Map(\n stamp.records.map((record) => [record.conceptId, record.digest]),\n );\n const ids = new Set<string>();\n for (const [conceptId, digest] of now) {\n if (before?.get(conceptId) !== digest) ids.add(conceptId);\n }\n for (const conceptId of before?.keys() ?? []) {\n if (!now.has(conceptId)) ids.add(conceptId);\n }\n return [...ids].sort();\n}\n\n/**\n * `--since` is either a digest — an equality answer, no ids to name — or a\n * path to a prior `stamp --json` (equally, a hook's session state file), which\n * carries the per-record digests a changed-id list needs.\n */\nasync function readBaseline(since: string): Promise<{\n digest: string | null;\n byPath: Map<string, { digest: string; records: Map<string, string> }>;\n}> {\n if (DIGEST.test(since)) return { digest: since, byPath: new Map() };\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(await readFile(since, \"utf8\"));\n } catch {\n throw new KbStampBaselineError(since);\n }\n\n // Either a `stamp --json` array, or a hook's session state file, which\n // carries the same entries under `stamps` beside the git head it saw.\n const entries = Array.isArray(parsed)\n ? parsed\n : ((parsed as { stamps?: unknown[] })?.stamps ?? []);\n const byPath = new Map<\n string,\n { digest: string; records: Map<string, string> }\n >();\n for (const entry of entries as {\n path?: string;\n digest?: string;\n records?: { conceptId: string; digest: string }[];\n }[]) {\n if (typeof entry?.path !== \"string\" || typeof entry?.digest !== \"string\") {\n continue;\n }\n byPath.set(entry.path, {\n digest: entry.digest,\n records: new Map(\n (entry.records ?? []).map((record) => [\n record.conceptId,\n record.digest,\n ]),\n ),\n });\n }\n return { digest: null, byPath };\n}\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { KB_RECORD_STATUSES } from \"../kb-record.schema.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const statusCommand = define({\n name: \"status\",\n tool: \"kb_status\",\n usage: \"status <concept-id> <status>\",\n description:\n \"Move a record's status. Compare-and-swap: a concurrent change fails instead of being overwritten.\",\n input: z.object({\n bundlePath,\n conceptId,\n status: z.enum(KB_RECORD_STATUSES),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n status: argv[2],\n }),\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, status },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.setStatus(path, id, status, actor);\n return { conceptId: record.conceptId, status };\n },\n});\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const supersedeCommand = define({\n name: \"supersede\",\n tool: \"kb_supersede\",\n usage: \"supersede <concept-id> <replacement-id>\",\n description:\n \"Mark a record superseded by another, linked in both directions. Use instead of editing a record whose meaning changed.\",\n input: z.object({ bundlePath, conceptId, replacementId: conceptId }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n replacementId: argv[2],\n }),\n run: async (\n { store, actor },\n { bundlePath: path, conceptId: id, replacementId },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n await store.supersede(path, id, replacementId, actor);\n return { superseded: id, replacedBy: replacementId };\n },\n});\n","import { z } from \"zod\";\nimport { buildContext, syncInstructions } from \"../kb-context.js\";\nimport { argvFlag, define } from \"./model.js\";\n\nexport const syncInstructionsCommand = define({\n name: \"sync-instructions\",\n usage:\n \"sync-instructions <file> [--profile NAME] [--budget N] [--full-under N]\",\n description:\n \"CLI-only: plant the kb_context block between sentinel comments in AGENTS.md or CLAUDE.md, idempotently.\",\n input: z.object({\n file: z.string().min(1).describe(\"The instruction file to edit in place.\"),\n budgetTokens: z.number().int().positive().optional(),\n fullUnderTokens: z.number().int().positive().optional(),\n profile: z.string().optional(),\n }),\n fromArgv: (argv) => {\n const budget = argvFlag(argv, \"--budget\");\n const fullUnder = argvFlag(argv, \"--full-under\");\n const profile = argvFlag(argv, \"--profile\");\n return {\n file: argv[1],\n ...(budget ? { budgetTokens: Number(budget) } : {}),\n ...(fullUnder ? { fullUnderTokens: Number(fullUnder) } : {}),\n ...(profile ? { profile } : {}),\n };\n },\n run: async ({ store }, { file, budgetTokens, fullUnderTokens, profile }) => {\n const result = await buildContext(store, process.cwd(), {\n ...(budgetTokens ? { budgetTokens } : {}),\n ...(fullUnderTokens ? { fullUnderTokens } : {}),\n ...(profile ? { profile } : {}),\n warn: (entry) => process.stderr.write(`${JSON.stringify(entry)}\\n`),\n });\n return syncInstructions(file, result.block);\n },\n});\n","import { z } from \"zod\";\nimport { TRACE_EDGES } from \"../trace.js\";\nimport { bundlePath, conceptId, define } from \"./model.js\";\n\nexport const traceCommand = define({\n name: \"trace\",\n tool: \"kb_trace\",\n usage: \"trace <concept-id> [edges...]\",\n description:\n 'Timeline of how a position was reached, ordered by write time, following supersession, shared anchors and shared sources. Includes rejected, draft and superseded records — in a history they are the content. For \"why is it like this\"; kb_load answers \"what holds now\".',\n input: z.object({\n bundlePath,\n conceptId,\n edges: z.array(z.enum(TRACE_EDGES)).optional(),\n depth: z.number().int().positive().optional(),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n edges: argv\n .slice(2)\n .filter((edge) => (TRACE_EDGES as readonly string[]).includes(edge)),\n }),\n run: async ({ store }, { bundlePath: path, conceptId: id, edges, depth }) =>\n (\n await store.trace(path, id, {\n ...(edges?.length ? { edges } : {}),\n ...(depth ? { depth } : {}),\n })\n ).map((step) => ({\n conceptId: step.record.conceptId,\n at: step.record.frontmatter.generated?.at ?? null,\n status: step.record.frontmatter.strauss_status,\n title: step.record.frontmatter.title ?? null,\n depth: step.depth,\n via: step.via,\n body: step.record.body,\n })),\n});\n","import { edgeNeighbours } from \"./kb-edges.js\";\nimport type { KbRecord } from \"./kb-record.schema.js\";\nimport { KB_CAUSAL_LINK_RELS } from \"./record-types.js\";\n\n/**\n * Edges a trace may follow — the shared kb-edges.ts definitions, minus\n * `body-link`: body links can reach most of a bundle from anywhere, which\n * suits a bounded pack but floods a timeline. Also absent by design:\n * `strauss_answered` carries no target id, so a question's resolution lives\n * in its own body rather than in another record.\n *\n * `typed-link` is in, where `body-link` is out, because the two differ in how\n * cheaply they are made. A body link is any markdown a writer happened to\n * type; a `strauss_links` entry is a deliberate claim from a closed vocabulary\n * about what this record depends on. That is exactly the kind of edge a\n * timeline should follow — \"we chose this because of that\" is the history.\n *\n * Only the causal rels, though. `related_to` asserts no dependence and reaches\n * whatever a writer thought worth mentioning, which is the same flooding\n * `body-link` is excluded for; a bibliography is a neighbourhood's business\n * (`pack`), not a history's.\n */\nexport const TRACE_EDGES = [\n \"typed-link\",\n \"supersession\",\n \"anchor\",\n \"source\",\n] as const;\nexport type KbTraceEdge = (typeof TRACE_EDGES)[number];\n\nexport type KbTraceStep = {\n record: KbRecord;\n /** Hops from the seed. 0 is the seed itself. */\n depth: number;\n /** Why this record was reached. Empty for the seed. */\n via: KbTraceEdge[];\n};\n\nexport type KbTraceOptions = {\n edges?: readonly KbTraceEdge[];\n /** Body links alone can reach the whole bundle, so a trace is always bounded. */\n depth?: number;\n};\n\n/**\n * How a position was arrived at, as a timeline.\n *\n * The inverse of a point query, and the reason the two cannot be one call with\n * a flag: there, a `rejected` record is the most dangerous thing retrievable —\n * here it is the content. A trace that drops the rejected alternatives and the\n * superseded earlier understanding has removed the answer and kept the\n * conclusion, which is what reading a diff already gives you.\n *\n * Ordered by `generated.at` rather than by relevance. Ranking a history is\n * meaningless when the sequence is the point.\n */\nexport function trace(\n seedId: string,\n bundle: KbRecord[],\n options: KbTraceOptions = {},\n): KbTraceStep[] {\n const edges = options.edges?.length ? options.edges : TRACE_EDGES;\n const maxDepth = options.depth ?? 3;\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const seed = byId.get(seedId);\n if (!seed) return [];\n\n const reached = new Map<string, KbTraceStep>([\n [seedId, { record: seed, depth: 0, via: [] }],\n ]);\n let frontier: KbRecord[] = [seed];\n\n for (let depth = 1; depth <= maxDepth && frontier.length; depth += 1) {\n const next: KbRecord[] = [];\n for (const from of frontier) {\n for (const edge of edges) {\n for (const record of edgeNeighbours(\n from,\n bundle,\n edge,\n KB_CAUSAL_LINK_RELS,\n )) {\n const existing = reached.get(record.conceptId);\n if (existing) {\n // Reached twice by different edges: keep the shorter path, but\n // record both reasons — \"shares an anchor and replaces it\" is more\n // informative than either alone. The seed keeps an empty `via`,\n // since it was not reached by anything.\n if (existing.depth > 0 && !existing.via.includes(edge)) {\n existing.via.push(edge);\n }\n continue;\n }\n reached.set(record.conceptId, { record, depth, via: [edge] });\n next.push(record);\n }\n }\n }\n frontier = next;\n }\n\n return [...reached.values()].sort(byGeneratedAt);\n}\n\nfunction byGeneratedAt(left: KbTraceStep, right: KbTraceStep): number {\n const at = (step: KbTraceStep) => step.record.frontmatter.generated?.at ?? \"\";\n return at(left).localeCompare(at(right)) || left.depth - right.depth;\n}\n","import { z } from \"zod\";\nimport { RECORD_TYPES } from \"../record-types.js\";\nimport { define } from \"./model.js\";\n\nexport const typesCommand = define({\n name: \"types\",\n tool: \"kb_types\",\n usage: \"types\",\n description:\n \"The twelve record types with their purpose, body sections, and starting status. Read this before writing rather than guessing headings — a section the type does not define is rejected.\",\n input: z.object({}),\n fromArgv: () => ({}),\n run: () => Promise.resolve(RECORD_TYPES),\n});\n","import { z } from \"zod\";\nimport { unpinBase } from \"../kb-pins/index.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const unpinCommand = define({\n name: \"unpin\",\n tool: \"kb_unpin\",\n usage: \"unpin [bundle-path]\",\n description:\n \"Remove a base from every manifest layer that holds it. Reports the layers touched.\",\n input: z.object({ bundlePath }),\n fromArgv: (argv, path) => ({ bundlePath: argv[1] ?? path }),\n run: (_ctx, { bundlePath: path }) => unpinBase(process.cwd(), path),\n});\n","import { z } from \"zod\";\nimport { validateBundle, type KbValidationProblem } from \"../validate.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const validateCommand = define({\n name: \"validate\",\n tool: \"kb_validate\",\n usage: \"validate\",\n description:\n \"Check pointers no single record can see: supersession links that disagree between the two records, typed causal links, and assumptions that cite sources. Each finding carries a severity: errors fail the exit code, warnings do not.\",\n input: z.object({ bundlePath }),\n fromArgv: (_argv, path) => ({ bundlePath: path }),\n run: async ({ store }, { bundlePath: path }) =>\n validateBundle(await store.list(path)),\n // Warnings never fail the exit code; every other severity does.\n failsWhen: (result) =>\n Array.isArray(result) &&\n (result as KbValidationProblem[]).some(\n (problem) => problem.severity !== \"warning\",\n ),\n});\n","import { z } from \"zod\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { argvFlag, bundlePath, conceptId, define } from \"./model.js\";\n\nexport const verifyCommand = define({\n name: \"verify\",\n tool: \"kb_verify\",\n usage: \"verify <concept-id> --note <text>\",\n description:\n \"Append a verified[] event: who checked, when, and what was found. Append-only. A record's own generator is refused unless the actor is `human:`-prefixed.\",\n input: z.object({\n bundlePath,\n conceptId,\n note: z.string().refine((s) => s.trim().length > 0, {\n message: \"note must say what the check found\",\n }),\n }),\n fromArgv: (argv, path) => ({\n bundlePath: path,\n conceptId: argv[1],\n note: argvFlag(argv, \"--note\"),\n }),\n run: async (\n { store, actor, now },\n { bundlePath: path, conceptId: id, note },\n ) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.verify(path, id, note, actor, now());\n return {\n conceptId: record.conceptId,\n verified: record.frontmatter.verified?.length ?? 0,\n };\n },\n});\n","import { z } from \"zod\";\nimport { composeInputSchema, composeRecord } from \"../compose.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { KB_RECORD_TYPES, type KbRecordType } from \"../kb-record.schema.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const writeCommand = define({\n name: \"write\",\n tool: \"kb_write\",\n usage: \"write <type> < record.json\",\n description:\n \"Write one record. Search first — a duplicate concept id is rejected, not overwritten; kb_types lists each type's sections. An unsourced claim is an `assumption` with assumption: true, never a vague `fact`. Conflicting records get a `risk`, `open-question`, or superseding `decision`. Prefer a new short record over overloading one. Never delete; supersede.\",\n input: z.object({\n bundlePath,\n type: z.enum(KB_RECORD_TYPES),\n input: composeInputSchema,\n }),\n fromArgv: async (argv, path, stdin) => ({\n bundlePath: path,\n type: argv[1],\n input: JSON.parse(await stdin()) as unknown,\n }),\n run: async ({ store, actor, now }, { bundlePath: path, type, input }) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.write(\n path,\n composeRecord(type as KbRecordType, input, actor, now()),\n actor,\n );\n return {\n conceptId: record.conceptId,\n action: record.action,\n supersededIds: record.supersededIds,\n };\n },\n});\n","import { z } from \"zod\";\nimport {\n composeDecisionRecord,\n decisionInputSchema,\n} from \"../decision-record.js\";\nimport { assertBaseNotFrozen } from \"../kb-pins/index.js\";\nimport { bundlePath, define } from \"./model.js\";\n\nexport const writeDecisionCommand = define({\n name: \"write-decision\",\n tool: \"kb_write_decision\",\n usage: \"write-decision < decision.json\",\n description:\n \"Write a decision, with `alternative` (what was rejected and why) and `impact` as fields. Record one when a later reader would otherwise simplify the constraint away; skip when the diff already answers it. `sources` for material read, `anchors` for code, `relatedConceptIds` for records.\",\n input: z.object({ bundlePath, input: decisionInputSchema }),\n fromArgv: async (_argv, path, stdin) => ({\n bundlePath: path,\n input: JSON.parse(await stdin()) as unknown,\n }),\n run: async ({ store, actor, now }, { bundlePath: path, input }) => {\n await assertBaseNotFrozen(process.cwd(), path);\n const record = await store.write(\n path,\n composeDecisionRecord(input, actor, now()),\n actor,\n );\n return {\n conceptId: record.conceptId,\n action: record.action,\n supersededIds: record.supersededIds,\n };\n },\n});\n","/**\n * The command table, assembled from one file per command.\n *\n * Order is the CLI usage listing's order: the write path, the read path,\n * base housekeeping, the format, and the workspace pin verbs.\n */\nimport { DECISION_TYPE } from \"../decision-record.js\";\nimport { anchorResolveCommand } from \"./anchor-resolve.js\";\nimport { answerCommand } from \"./answer.js\";\nimport { backlinksCommand } from \"./backlinks.js\";\nimport { catalogCommand } from \"./catalog.js\";\nimport { contextCommand } from \"./context.js\";\nimport { doctorCommand } from \"./doctor.js\";\nimport { impactCommand } from \"./impact.js\";\nimport { listCommand } from \"./list.js\";\nimport { loadCommand } from \"./load.js\";\nimport { logCommand } from \"./log.js\";\nimport { noDecisionCommand } from \"./no-decision.js\";\nimport { packCommand } from \"./pack.js\";\nimport { pinCommand } from \"./pin.js\";\nimport { pinsCommand } from \"./pins.js\";\nimport { queryCommand } from \"./query.js\";\nimport { readIndexCommand } from \"./read-index.js\";\nimport { reassessCommand } from \"./reassess.js\";\nimport { schemaCommand } from \"./schema.js\";\nimport { stampCommand } from \"./stamp.js\";\nimport { statusCommand } from \"./status.js\";\nimport { supersedeCommand } from \"./supersede.js\";\nimport { syncInstructionsCommand } from \"./sync-instructions.js\";\nimport { traceCommand } from \"./trace.js\";\nimport { typesCommand } from \"./types.js\";\nimport { unpinCommand } from \"./unpin.js\";\nimport { validateCommand } from \"./validate.js\";\nimport { verifyCommand } from \"./verify.js\";\nimport { writeCommand } from \"./write.js\";\nimport { writeDecisionCommand } from \"./write-decision.js\";\nimport type { KbCommand } from \"./model.js\";\n\nexport const KB_COMMANDS: KbCommand[] = [\n writeCommand,\n writeDecisionCommand,\n noDecisionCommand,\n statusCommand,\n supersedeCommand,\n answerCommand,\n verifyCommand,\n anchorResolveCommand,\n reassessCommand,\n loadCommand,\n catalogCommand,\n packCommand,\n queryCommand,\n traceCommand,\n impactCommand,\n backlinksCommand,\n listCommand,\n readIndexCommand,\n logCommand,\n stampCommand,\n validateCommand,\n doctorCommand,\n schemaCommand,\n pinCommand,\n unpinCommand,\n pinsCommand,\n contextCommand,\n syncInstructionsCommand,\n typesCommand,\n];\n\nexport const KB_COMMANDS_BY_NAME = new Map(\n KB_COMMANDS.map((command) => [command.name, command]),\n);\n\nexport { DECISION_TYPE };\nexport type { KbCommand, KbCommandContext } from \"./model.js\";\n","import {\n appendFile,\n link,\n mkdir,\n readdir,\n readFile,\n rename,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { join, resolve, sep } from \"node:path\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"./concurrency.js\";\nimport {\n parseMarkdownWithFrontmatter,\n stringifyMarkdownWithFrontmatter,\n} from \"./markdown.js\";\nimport {\n kbRecordFrontmatterSchema,\n kbVerifiedEventSchema,\n KB_SLUG_PATTERN,\n type KbAnchor,\n type KbRecord,\n type KbRecordFrontmatter,\n type KbRecordStatus,\n} from \"./kb-record.schema.js\";\nimport {\n KbInvalidConceptIdError,\n KbRecordAlreadyExistsError,\n KbRecordNotFoundError,\n KbSelfVerificationError,\n KbWriteConflictError,\n} from \"./kb-errors.js\";\nimport { INDEX_FILE, indexIsStale, renderIndex } from \"./kb-index.js\";\nimport { adjudicate, type KbAdjudicated } from \"./adjudicate.js\";\nimport {\n bundleDigest,\n bundleStamp,\n sha256 as digest,\n type KbRecordStamp,\n} from \"./kb-stamp.js\";\nimport {\n detectAnchorDrift,\n looksLikeWrongRepoRoot,\n type KbAnchorDriftEntry,\n} from \"./anchor-resolver/index.js\";\nimport { isUncheckedReason } from \"./remote-repo/index.js\";\nimport { resolveHits, searchBase, SEARCH_INDEX_FILE } from \"./search-index.js\";\nimport { trace, type KbTraceOptions, type KbTraceStep } from \"./trace.js\";\nimport { pack, type KbPackOptions, type KbPackResult } from \"./pack.js\";\nimport { catalog, type KbCatalogResult } from \"./catalog.js\";\nimport { matchesTags, type KbTagFilter } from \"./kb-tags.js\";\nimport {\n backlinks,\n impact,\n type KbBacklinksResult,\n type KbImpactOptions,\n type KbImpactResult,\n} from \"./kb-links/index.js\";\nimport {\n LOG_FILE,\n parseLog,\n renderLogEntry,\n type KbLogEntry,\n} from \"./kb-log.js\";\nimport {\n appendUnionMergeLine,\n GITATTRIBUTES_FILE,\n hasMergeDeclaration,\n} from \"./kb-gitattributes.js\";\n\n/**\n * Default bundle, relative to the working directory. A scratch base lives here\n * and is meant to be gitignored; a base worth keeping is written to a committed\n * path instead, passed explicitly. Nothing promotes one to the other.\n */\nexport const KB_DIR = join(\".strauss\", \"kb\");\n\nconst STORE_OWNED = new Set([INDEX_FILE, LOG_FILE, SEARCH_INDEX_FILE]);\n\nexport type KbLogger = {\n info?(entry: Record<string, unknown>): void;\n warn?(entry: Record<string, unknown>): void;\n};\n\n/** Roughly an eighth of a large context window — generous, and overridable. */\nexport const DEFAULT_LOAD_BUDGET = 25_000;\n\n/**\n * A superseded record, named but not spelled out.\n *\n * Standing is a qualifier on a body, and over a long session the body outlives\n * the qualifier — the reader keeps what the record said and loses that it no\n * longer holds. A stub has nothing left to act on, so the failure cannot occur,\n * and `trace` still reaches the content through the id.\n */\nexport type KbSupersededStub = {\n conceptId: string;\n title: string | null;\n supersededBy: string[];\n at: string | null;\n};\n\nexport type KbLoadResult =\n | {\n loaded: true;\n records: KbAdjudicated[];\n /** Named only. Their bodies are reachable through `trace`. */\n superseded: KbSupersededStub[];\n recordCount: number;\n tokensLoaded: number;\n /** `null` when loaded via `all`: no ceiling was applied. */\n budgetTokens: number | null;\n /**\n * Sha256 over every record's content and standing, sorted by concept\n * id. Flips when a body, frontmatter, or standing changes; it's the\n * base's content stamp, compared by hooks and `kb_stamp` (SAA-719).\n */\n digest: string;\n }\n | {\n loaded: false;\n recordCount: number;\n approxTokens: number;\n budgetTokens: number;\n /** The refusal in words, naming the budget and what to call next. */\n message: string;\n /**\n * Same digest a successful load would carry, computed over what would\n * have been handed back. Cheap here — adjudication already ran before\n * the refusal — and it lets a caller notice a refused bundle's content\n * changed (say, after a narrower `type` filter) without loading it.\n */\n digest: string;\n };\n\n/** What `stamp` reports for one base. See `kb-stamp.ts`. */\nexport type KbStampResult = {\n path: string;\n digest: string;\n recordCount: number;\n superseded: number;\n /** Newest `generated.at` across the base, or null when none carries one. */\n newestAt: string | null;\n records: KbRecordStamp[];\n /**\n * Records with at least one anchor whose code no longer matches its hash.\n *\n * Outside the digest, and deliberately: drift is a fact about the working\n * tree, not about the base's content, and folding it in would make a stamp\n * change every time someone checked out a branch. `null` when the drift pass\n * could not run — an unknown count, which is not zero.\n */\n drifted: number | null;\n};\n\nexport type KbWriteInput = {\n type: string;\n slug: string;\n frontmatter: Omit<KbRecordFrontmatter, \"type\">;\n body: string;\n /** Replace an existing record rather than failing on the collision. */\n overwrite?: boolean;\n};\n\nexport type KbWriteResult = KbRecord & {\n /** Whether this write also marked prior records superseded. */\n action: \"created\" | \"superseded-prior\";\n /** `frontmatter.strauss_supersedes` ids that were actually marked. */\n supersededIds: string[];\n};\n\n/**\n * Reads and writes a knowledge bundle.\n *\n * One record per file, deliberately. Several agents run in parallel against the\n * same bundle, and a shared file would need merging — a file-per-record store\n * has no write conflict to resolve, only distinct filenames to choose.\n *\n * The bundle is addressed by path rather than fixed to one directory. A base\n * belongs to whatever prompted it — a worktree, an investigation, a document —\n * and one hardcoded location cannot be all of those.\n *\n * Framework-free on purpose. The consumers are a library caller, a CLI an agent\n * shells out to, and an MCP server; the store takes a logger rather than\n * reaching for one, because only some of those have anything to reach into.\n */\nexport class KbStore {\n constructor(private readonly logger: KbLogger = {}) {}\n\n /**\n * Writes one record. `type` and `slug` compose both the filename and the\n * concept id, so a caller cannot produce a file whose identity disagrees with\n * its contents.\n */\n async write(\n bundlePath: string,\n input: KbWriteInput,\n actor = \"unknown\",\n ): Promise<KbWriteResult> {\n if (!KB_SLUG_PATTERN.test(input.slug)) {\n throw new KbInvalidConceptIdError(\"slug must be kebab-case\", {\n slug: input.slug,\n });\n }\n if (!KB_SLUG_PATTERN.test(input.type)) {\n throw new KbInvalidConceptIdError(\"type must be kebab-case\", {\n type: input.type,\n });\n }\n\n const frontmatter = kbRecordFrontmatterSchema.parse({\n ...input.frontmatter,\n type: input.type,\n });\n const conceptId = `${input.type}.${input.slug}`;\n const root = this.root(bundlePath);\n const target = this.recordPath(bundlePath, conceptId);\n\n await mkdir(root, { recursive: true });\n await this.publish(\n target,\n stringifyMarkdownWithFrontmatter(input.body, frontmatter),\n input.overwrite ?? false,\n conceptId,\n );\n\n await this.record(root, {\n operation: input.overwrite ? \"overwrite\" : \"write\",\n conceptId,\n by: actor,\n });\n\n // The new record is published and logged first, then each prior record it\n // supersedes is marked. A crash between the two leaves an old\n // record with no backlink — exactly what kb_validate already reports as\n // \"<old> is not marked superseded\", never a silent drift.\n //\n // Naming itself is a no-op, not an error — the record is already itself.\n // Duplicates collapse through the Set, so a repeated id marks once.\n const targets = new Set(frontmatter.strauss_supersedes ?? []);\n targets.delete(conceptId);\n\n // Targets are marked sequentially, in order: targets are 1-3 in practice,\n // and marking them concurrently made log.jsonl entry order depend on\n // which retry finished first rather than on strauss_supersedes order.\n const supersededIds: string[] = [];\n for (const old of targets) {\n if (\n await this.markSupersededRetrying(bundlePath, old, conceptId, actor)\n ) {\n supersededIds.push(old);\n }\n }\n\n this.logger.info?.({\n operation: \"kb.write\",\n bundlePath: root,\n conceptId,\n anchors: frontmatter.strauss_anchors?.length ?? 0,\n });\n\n return {\n conceptId,\n frontmatter,\n body: input.body,\n action: supersededIds.length ? \"superseded-prior\" : \"created\",\n supersededIds,\n };\n }\n\n /** One record by concept id, or null when it does not exist. */\n async read(bundlePath: string, conceptId: string): Promise<KbRecord | null> {\n // Resolved outside the try: the `catch` exists to turn a missing file into\n // `null`, and must not also swallow the concept-id validation below it.\n const target = this.recordPath(bundlePath, conceptId);\n let raw: string;\n try {\n raw = await readFile(target, \"utf8\");\n } catch {\n return null;\n }\n return this.parse(conceptId, raw);\n }\n\n /**\n * Every record in the bundle, optionally narrowed to one type and to the\n * records carrying every tag in `filter.tags`. Selection only — `excludeTags`\n * is not taken here, because `query`, `catalog` and `load` read through this\n * and must adjudicate over the whole base.\n *\n * A file that fails to parse is skipped and logged rather than thrown: one\n * malformed record — hand-edited, or written by a producer we don't know —\n * must not make the whole bundle unreadable.\n */\n async list(\n bundlePath: string,\n type?: string,\n filter: { tags?: string[] } = {},\n ): Promise<KbRecord[]> {\n const root = this.root(bundlePath);\n let names: string[];\n try {\n names = await readdir(root);\n } catch {\n return [];\n }\n\n // The type filter runs on the filename, so a narrowed list never opens a\n // record it is going to discard. What remains is read concurrently: the\n // cost here is per-file syscall latency, not CPU.\n const wanted = names\n .sort()\n // Both store-owned files are markdown and neither is a record; without\n // this they parse to null and are dropped, but not before logging a\n // warning that says the bundle contains a malformed record.\n .filter((name) => name.endsWith(\".md\") && !STORE_OWNED.has(name))\n .map((name) => ({ name, conceptId: name.slice(0, -\".md\".length) }))\n .filter(({ conceptId }) => !type || conceptId.startsWith(`${type}.`));\n\n const records = await mapLimit(\n wanted,\n DEFAULT_IO_CONCURRENCY,\n async ({ name, conceptId }) =>\n this.parse(conceptId, await readFile(join(root, name), \"utf8\")),\n );\n return records.filter(\n (record): record is KbRecord =>\n record !== null && matchesTags(record, filter),\n );\n }\n\n /**\n * Moves a record's status, preserving everything else.\n *\n * Read-modify-write on one file is the one place two agents genuinely race,\n * and the fix is a compare-and-swap rather than a lock: hash on read, verify\n * the file is unchanged immediately before writing, fail if it moved. A lock\n * would buy the same guarantee and add a stale-lock failure mode — a writer\n * killed mid-hold blocks every later one until someone reasons about\n * timeouts.\n */\n async setStatus(\n bundlePath: string,\n conceptId: string,\n status: KbRecordStatus,\n actor = \"unknown\",\n ): Promise<KbRecord> {\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({ ...frontmatter, strauss_status: status }),\n { operation: `status:${status}`, by: actor },\n );\n }\n\n /**\n * Replaces a record's anchors wholesale, preserving everything else.\n *\n * Wholesale rather than merged: the caller just resolved the anchors it is\n * writing, so it holds the complete current set, and a merge would keep\n * stale entries the resolution pass deliberately dropped.\n */\n async updateAnchors(\n bundlePath: string,\n conceptId: string,\n anchors: KbAnchor[],\n actor = \"unknown\",\n ): Promise<KbRecord> {\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({ ...frontmatter, strauss_anchors: anchors }),\n { operation: \"anchor-resolve\", by: actor },\n );\n }\n\n /**\n * Appends one `verified[]` event: who checked the record, when, and what the\n * check found. Append-only — prior events are history, and are spread into\n * the new array untouched rather than reshaped through the write schema.\n *\n * A record's generator cannot verify its own record unless the actor is\n * human: the generator re-reading its own output is not an independent\n * check. The rule runs before the mutation so a refusal never publishes,\n * and the refusal is logged under its own operation name — `mutate` only\n * logs what it publishes.\n */\n async verify(\n bundlePath: string,\n conceptId: string,\n note: string,\n actor = \"unknown\",\n at = new Date().toISOString(),\n ): Promise<KbRecord> {\n const event = kbVerifiedEventSchema.parse({ by: actor, at, note });\n\n const existing = await this.read(bundlePath, conceptId);\n if (!existing) throw new KbRecordNotFoundError(conceptId);\n\n // The equality test compares whole actors case-insensitively: case drift\n // (`agent:Claude` vs `agent:claude`) must not mint a distinct verifier\n // identity. Only the `human:` exemption keeps the prefix-only\n // normalization.\n const generatedBy = existing.frontmatter.generated?.by;\n if (\n generatedBy !== undefined &&\n actor.toLowerCase() === generatedBy.toLowerCase() &&\n !normalizeActor(actor).startsWith(\"human:\")\n ) {\n await this.record(this.root(bundlePath), {\n operation: \"verify:refused\",\n conceptId,\n by: actor,\n });\n throw new KbSelfVerificationError(conceptId, actor, generatedBy);\n }\n\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({\n ...frontmatter,\n verified: [...(frontmatter.verified ?? []), event],\n }),\n { operation: \"verify\", by: actor },\n );\n }\n\n /**\n * Marks `conceptId` superseded by `replacementId`, and links both directions.\n *\n * Writing one side and letting a validator notice the other is missing was\n * the previous arrangement; doing both here means the backlink cannot drift\n * in normal use, and validation drops to catching hand-edits.\n */\n async supersede(\n bundlePath: string,\n conceptId: string,\n replacementId: string,\n actor = \"unknown\",\n ): Promise<KbRecord> {\n const replacement = await this.read(bundlePath, replacementId);\n if (!replacement) throw new KbRecordNotFoundError(replacementId);\n\n const superseded = await this.markSuperseded(\n bundlePath,\n conceptId,\n replacementId,\n actor,\n );\n\n await this.mutate(\n bundlePath,\n replacementId,\n (frontmatter) => ({\n ...frontmatter,\n strauss_supersedes: [\n ...new Set([...(frontmatter.strauss_supersedes ?? []), conceptId]),\n ],\n }),\n { operation: \"supersedes\", by: actor, target: conceptId },\n );\n\n return superseded;\n }\n\n /** Resolves an open question, stamping who answered and when. */\n async answer(\n bundlePath: string,\n conceptId: string,\n answer: string,\n actor = \"unknown\",\n at = new Date().toISOString(),\n ): Promise<KbRecord> {\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({\n ...frontmatter,\n strauss_status: \"resolved\" as const,\n strauss_answered: { by: actor, at },\n }),\n { operation: \"answer\", by: actor },\n (body) => `${body.trimEnd()}\\n\\n## Answer\\n\\n${answer}\\n`,\n );\n }\n\n /**\n * Records matching a text query, each carrying its standing.\n *\n * Relevance comes from qmd's BM25 where an index is available and from a\n * substring scan where it is not. What never moves to the ranker is the\n * adjudication below it: a ranker answers relevance, and relevance is not\n * standing — a superseded record is the older, longer, more general one, so\n * ranking alone prefers what is no longer true.\n *\n * The fallback is deliberate. A search index is an optimisation, so losing it\n * degrades recall and must never change the answer's shape or fail the call.\n */\n async query(\n bundlePath: string,\n text: string,\n options: {\n type?: string;\n includeNonCurrent?: boolean;\n repoRoot?: string;\n } & KbTagFilter = {},\n ): Promise<KbAdjudicated[]> {\n const bundle = await this.list(bundlePath);\n const needle = text.trim();\n const hits = needle ? await this.rank(bundlePath, needle, bundle) : bundle;\n const narrowed = options.type\n ? hits.filter((r) => r.frontmatter.type === options.type)\n : hits;\n const adjudicated = adjudicate(\n narrowed,\n bundle,\n new Date(),\n await this.detectDrift(narrowed, options.repoRoot),\n );\n\n // Tags cut after adjudication: a tag narrows what is returned, never what\n // anything's standing is or which record replaced it.\n const kept = adjudicated.filter((hit) => matchesTags(hit.record, options));\n\n if (options.includeNonCurrent) return kept;\n // Superseded records are dropped only once their replacement is in the\n // result too — otherwise the caller loses the thread entirely rather than\n // being handed a newer version of it. Over `kept`, so a replacement the\n // tag filter cut cannot silence the record it replaced.\n const present = new Set(kept.map((hit) => hit.record.conceptId));\n return kept.filter(\n (hit) =>\n hit.standing !== \"superseded\" ||\n !hit.heads.some((head) => present.has(head.conceptId)),\n );\n }\n\n private async rank(\n bundlePath: string,\n needle: string,\n bundle: KbRecord[],\n ): Promise<KbRecord[]> {\n const ranked = await searchBase(this.root(bundlePath), needle, {\n logger: this.logger,\n });\n if (ranked) {\n const found = resolveHits(ranked, bundle);\n if (found.length) return found;\n }\n const lowered = needle.toLowerCase();\n return bundle.filter((record) => matches(record, lowered));\n }\n\n /**\n * Anchor drift over the records about to be handed back. Like the search\n * index, this is an enrichment: a filesystem failure degrades to \"no drift\n * reported\" rather than failing the read. Anchors without a stored hash are\n * skipped inside `detectAnchorDrift`, so a base nobody has stamped pays no\n * fs cost here. `repoRoot` defaults to the working directory — the CLI runs\n * at the repo root, and the MCP server's cwd is the workspace.\n *\n * Public because `doctor` needs the same map with the same degradation: a\n * sweep that failed to read the tree should report no drift, not fail — and\n * `offline: false` there, because a sweep is worth a fetch.\n *\n * When no root was given and not one anchored file was found, the finding is\n * discarded. A base read from somewhere other than the tree it describes\n * misses every file at once, and that shape is far likelier to be a wrong\n * default root than a repository where every anchored file was deleted on\n * the same day. Reporting it would put a drift warning on every record in\n * the base, which teaches a reader to ignore the warning — the one outcome\n * worse than not having it. One file found anywhere makes the root\n * plausible, and the misses become findings again; an explicit `repoRoot` is\n * taken at its word either way.\n */\n async detectDrift(\n records: KbRecord[],\n repoRoot?: string,\n options: { offline?: boolean } = {},\n ): Promise<Map<string, KbAnchorDriftEntry[]> | undefined> {\n try {\n const drift = await detectAnchorDrift(records, {\n repoRoot: repoRoot ?? process.cwd(),\n // Offline by default: a read path must never spend a network fetch per\n // call. `doctor` and `anchor-resolve` are the verbs that go get it.\n remote: { offline: options.offline !== false },\n });\n if (repoRoot === undefined && looksLikeWrongRepoRoot(drift)) {\n this.logger.warn?.({\n operation: \"kb.anchor-drift\",\n outcome: \"skipped\",\n reason: \"no anchored file found under the default repo root\",\n });\n return undefined;\n }\n return drift;\n } catch (error) {\n this.logger.warn?.({\n operation: \"kb.anchor-drift\",\n outcome: \"skipped\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n return undefined;\n }\n }\n\n /**\n * The whole base, adjudicated, when it is small enough to hand over.\n *\n * At the sizes these reach — twenty records is about three thousand tokens —\n * loading everything beats searching it, and measurably: on nine questions\n * whose wording appears in no record, a reader holding the base answered\n * eight against an embedding search's four. Two of those differences are\n * structural. A reader can say no record answers the question; vector search\n * returns its nearest neighbour whatever the distance. And a reader picks the\n * record that answers the question rather than the one nearest the topic.\n * See the README's retrieval section for the measurements.\n *\n * Load it for a question, not for a session — a base read into a long\n * conversation is summarised away by the end of it.\n *\n * Refuses rather than truncates when the base is too large. A truncated base\n * is indistinguishable from a complete one, so a caller would answer \"that\n * was never decided\" from a slice it did not know was a slice.\n *\n * A token budget decides that, measured over what is actually handed back.\n * The refusal names the estimate and the budget, because a caller told only\n * \"too big\" cannot tell whether to narrow the type filter, raise the budget,\n * or stop loading the base whole altogether. Past the budget the answer is\n * the catalog and then a pack, which is what the refusal says.\n *\n * That refusal is the default guardrail. `all` bypasses the budget outright\n * and always hands back the whole bundle: an explicit, never-accidental\n * escape hatch for an operator who has the budget to spend, not a wider\n * default.\n */\n async load(\n bundlePath: string,\n options: {\n budgetTokens?: number;\n type?: string;\n all?: boolean;\n repoRoot?: string;\n /** Records carrying any of these are left out. See `kb-tags.ts`. */\n excludeTags?: string[];\n } = {},\n ): Promise<KbLoadResult> {\n const budgetTokens = options.budgetTokens ?? DEFAULT_LOAD_BUDGET;\n const bundle = await this.list(bundlePath);\n const wanted = options.type\n ? bundle.filter((record) => record.frontmatter.type === options.type)\n : bundle;\n\n // Adjudicated against the whole base, not the filtered slice: a record's\n // replacement may be of another type.\n const adjudicated = adjudicate(\n wanted,\n bundle,\n new Date(),\n await this.detectDrift(wanted, options.repoRoot),\n );\n // Excluded tags cut after adjudication, so nothing's standing moves and\n // the estimate below still measures exactly what is handed back.\n const kept = adjudicated.filter((hit) =>\n matchesTags(hit.record, { excludeTags: options.excludeTags }),\n );\n const records = kept.filter((hit) => hit.standing !== \"superseded\");\n const superseded = kept\n .filter((hit) => hit.standing === \"superseded\")\n .map(stub);\n\n // Measured over what is actually handed back. Costing the full bodies would\n // refuse bases that fit comfortably once the superseded ones are stubs.\n const approxTokens =\n records.reduce((total, hit) => total + estimateTokens(hit.record), 0) +\n superseded.reduce((total, entry) => total + estimateStubTokens(entry), 0);\n\n // Adjudication has already run either way, so this costs nothing extra —\n // computed once and carried on whichever branch returns.\n const bundleDigestValue = bundleDigest(records, superseded);\n\n if (!options.all && approxTokens > budgetTokens) {\n return {\n loaded: false,\n recordCount: kept.length,\n approxTokens,\n budgetTokens,\n message: refusalMessage({\n approxTokens,\n budgetTokens,\n type: options.type,\n }),\n digest: bundleDigestValue,\n };\n }\n\n return {\n loaded: true,\n recordCount: kept.length,\n tokensLoaded: approxTokens,\n budgetTokens: options.all ? null : budgetTokens,\n records,\n superseded,\n digest: bundleDigestValue,\n };\n }\n\n /**\n * `load`'s digest without `load`'s bodies — the same records, adjudicated\n * the same way, handed back as a stamp.\n *\n * Drift is counted but kept out of the digest, which is what lets the reload\n * hook ask one question and get two answers: whether the base moved, and\n * whether the code under it did. A `load` and a `stamp` of the same base\n * still agree on the digest, because no warning has ever reached it.\n */\n async stamp(\n bundlePath: string,\n options: { repoRoot?: string } = {},\n ): Promise<KbStampResult> {\n const bundle = await this.list(bundlePath);\n const adjudicated = adjudicate(bundle, bundle, new Date());\n const current = adjudicated.filter((hit) => hit.standing !== \"superseded\");\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(stub);\n\n const stamped = bundleStamp(current, superseded);\n const dates = bundle\n .map((record) => record.frontmatter.generated?.at ?? null)\n .filter((at): at is string => typeof at === \"string\")\n .sort();\n\n // Counted after the digest, so a failed or suppressed drift pass can only\n // cost the count, never the stamp.\n //\n // Deliberately the shallow pass: `detectAnchorDrift` compares hashes and\n // stops, so this reads each anchored file once and never lists or parses\n // the repository. `moved` and `cosmetic` would need both, and a count does\n // not want them — a reload hook runs this after ordinary git commands, and\n // it asks how many records need a look, not which of them are relocatable.\n // That question belongs to `reassess` and `doctor --drifted`. Anchors\n // naming another repository are read from the local cache only — never\n // fetched — and an unchecked one is never counted.\n const drift = await this.detectDrift(bundle, options.repoRoot);\n const drifted =\n drift === undefined\n ? null\n : [...drift.values()].filter((entries) =>\n entries.some(\n (entry) =>\n entry.state !== \"match\" && !isUncheckedReason(entry.reason),\n ),\n ).length;\n\n return {\n path: bundlePath,\n digest: stamped.digest,\n recordCount: bundle.length,\n superseded: superseded.length,\n newestAt: dates.at(-1) ?? null,\n records: stamped.records,\n drifted,\n };\n }\n\n /** How a position was arrived at, as a timeline. See `trace.ts`. */\n async trace(\n bundlePath: string,\n seedId: string,\n options: KbTraceOptions = {},\n ): Promise<KbTraceStep[]> {\n return trace(seedId, await this.list(bundlePath), options);\n }\n\n /** Every record named in one line each. See `catalog.ts`. */\n async catalog(\n bundlePath: string,\n options: { type?: string; now?: Date } & KbTagFilter = {},\n ): Promise<KbCatalogResult> {\n return catalog(await this.list(bundlePath), options);\n }\n\n /** A bounded neighbourhood around one record. See `pack.ts`. */\n async pack(\n bundlePath: string,\n rootId: string,\n options: KbPackOptions = {},\n ): Promise<KbPackResult> {\n return pack(await this.list(bundlePath), rootId, options);\n }\n\n /** What breaks if this record changes. See `kb-links/impact.ts`. */\n async impact(\n bundlePath: string,\n targetId: string,\n options: KbImpactOptions = {},\n ): Promise<KbImpactResult> {\n return impact(targetId, await this.list(bundlePath), options);\n }\n\n /** Who points at this record, one hop. See `kb-links/backlinks.ts`. */\n async backlinks(\n bundlePath: string,\n targetId: string,\n ): Promise<KbBacklinksResult> {\n return backlinks(targetId, await this.list(bundlePath));\n }\n\n /**\n * The stored index, rebuilt if it disagrees with the records.\n *\n * Repair on read is what makes the lock-free write path safe: a writer whose\n * scan predated another writer's record publishes a momentarily stale index,\n * and the next reader through here settles it.\n */\n async readIndex(bundlePath: string): Promise<string> {\n const root = this.root(bundlePath);\n const expected = renderIndex(await this.list(bundlePath));\n const stored = await readFile(join(root, INDEX_FILE), \"utf8\").catch(\n () => null,\n );\n\n if (indexIsStale(stored, expected)) {\n await this.publish(join(root, INDEX_FILE), expected, true, INDEX_FILE);\n this.logger.info?.({\n operation: \"kb.index.repair\",\n bundlePath: root,\n reason: stored === null ? \"missing\" : \"stale\",\n });\n }\n return expected;\n }\n\n /**\n * The log, with unparseable lines reported rather than repaired.\n *\n * The log is the bundle's only artifact that cannot be reconstructed — the\n * records rebuild the index, and the code outlives both, but nothing else\n * knows which agent touched what. So a bad line is surfaced and left alone.\n */\n async readLog(bundlePath: string): Promise<ReturnType<typeof parseLog>> {\n const raw = await readFile(\n join(this.root(bundlePath), LOG_FILE),\n \"utf8\",\n ).catch(() => \"\");\n const result = parseLog(raw);\n for (const bad of result.malformed) {\n this.logger.warn?.({\n operation: \"kb.log.parse\",\n line: bad.line,\n outcome: \"skipped\",\n });\n }\n return result;\n }\n\n /**\n * `markSuperseded`, tolerant of the two ways it legitimately doesn't land:\n * a missing target (a broken link, legal per compose.ts) or a CAS conflict\n * from a concurrent writer touching the same target. A conflict is retried\n * a bounded number of times — each attempt re-reads the target fresh — and\n * on the last, `false` reports \"not marked\" rather than throwing: the\n * caller's own record is already published, so failing here would leave\n * that publish unreported instead of undone. kb_validate's existing\n * \"not marked superseded\" check is what surfaces the residue.\n */\n private async markSupersededRetrying(\n bundlePath: string,\n conceptId: string,\n replacementId: string,\n actor: string,\n retries = 3,\n ): Promise<boolean> {\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n await this.markSuperseded(bundlePath, conceptId, replacementId, actor);\n return true;\n } catch (error) {\n if (error instanceof KbRecordNotFoundError) return false;\n if (!(error instanceof KbWriteConflictError)) throw error;\n if (attempt === retries) return false;\n }\n }\n return false;\n }\n\n /** The one-directional half of `supersede`: marks `conceptId` superseded. */\n private async markSuperseded(\n bundlePath: string,\n conceptId: string,\n replacementId: string,\n actor: string,\n ): Promise<KbRecord> {\n return this.mutate(\n bundlePath,\n conceptId,\n (frontmatter) => ({\n ...frontmatter,\n strauss_status: \"superseded\" as const,\n strauss_superseded_by: replacementId,\n }),\n { operation: \"supersede\", by: actor, target: replacementId },\n );\n }\n\n private async mutate(\n bundlePath: string,\n conceptId: string,\n change: (frontmatter: KbRecordFrontmatter) => KbRecordFrontmatter,\n entry: Omit<KbLogEntry, \"at\" | \"conceptId\"> & { target?: string },\n changeBody: (body: string) => string = (body) => body,\n ): Promise<KbRecord> {\n const target = this.recordPath(bundlePath, conceptId);\n const before = await readFile(target, \"utf8\").catch(() => null);\n if (before === null) throw new KbRecordNotFoundError(conceptId);\n\n const parsed = this.parse(conceptId, before);\n if (!parsed) throw new KbRecordNotFoundError(conceptId);\n\n const frontmatter = change(parsed.frontmatter);\n const body = changeBody(parsed.body);\n const contents = stringifyMarkdownWithFrontmatter(body, frontmatter);\n\n // Optimistic check, not a hard guarantee: a writer landing between this\n // read and the publish below still wins silently. It narrows the window\n // from \"the whole compose\" to two adjacent syscalls, which is as far as a\n // filesystem goes without a lock — and a lock's stale-hold failure mode is\n // worse than the residue.\n const witness = await readFile(target, \"utf8\").catch(() => null);\n if (witness === null || digest(witness) !== digest(before)) {\n throw new KbWriteConflictError(conceptId);\n }\n await this.publish(target, contents, true, conceptId);\n await this.record(this.root(bundlePath), { ...entry, conceptId });\n\n return { conceptId, frontmatter, body };\n }\n\n /**\n * Two guarantees, both about writers running in parallel.\n *\n * The record is written to a staging file and only then published, so a\n * concurrent reader sees the whole record or no record — never half of one. A\n * plain write is not atomic, and `list()` skips what it cannot parse, so a\n * torn read would be silently reported as a malformed record.\n *\n * Publishing uses `link` rather than `rename` unless the caller asked to\n * overwrite: `link` fails with EEXIST instead of replacing, which turns \"two\n * writers chose the same concept id\" from silent data loss into a collision\n * the caller has to answer. Both are atomic; only `rename` clobbers.\n *\n * The staging name deliberately does not end in `.md` — `list()` would\n * otherwise try to read it mid-write.\n */\n private async publish(\n target: string,\n contents: string,\n overwrite: boolean,\n conceptId: string,\n ): Promise<void> {\n const staging = `${target}.${process.pid}.tmp`;\n await writeFile(staging, contents, \"utf8\");\n\n try {\n if (overwrite) {\n await rename(staging, target);\n return;\n }\n await link(staging, target);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") {\n throw new KbRecordAlreadyExistsError(conceptId);\n }\n throw error;\n } finally {\n // `rename` consumed the staging file; `link` left it behind.\n await unlink(staging).catch(() => undefined);\n }\n }\n\n /**\n * Declares union merge for the log, so two worktrees writing the same\n * bundle interleave their `log.jsonl` lines on merge rather than one\n * side's appends silently losing to git's ordinary line-level merge.\n *\n * Called from `record` — every path that appends a log line, not just\n * `write` — so a bundle only ever mutated through `setStatus`/`verify`/\n * `supersede` still gets it. There is no cheaper reliable signal for\n * \"first write\" than checking the file itself, and after the first call\n * the check is a no-op `readFile`.\n *\n * A missing `.gitattributes` is created outright, with `wx` (exclusive\n * create) rather than a plain write: if another process's `write()` won a\n * race and created the file between the `readFile` below and this call,\n * `wx` fails instead of truncating what that writer just wrote, and the\n * failure is swallowed by the catch below same as any other best-effort\n * miss. A file that exists but declares no merge strategy for the log\n * gets the line appended, never a wholesale rewrite; one that already\n * declares any merge strategy — this one or a user's own — is left alone\n * entirely (see `hasMergeDeclaration`).\n *\n * `readFile` failing is `existing === null` only for `ENOENT` — genuinely\n * missing. Any other error (a permission problem, a transient `EMFILE`,\n * the path being a directory) is *not* \"missing\" and must not fall into\n * the create branch, which would truncate whatever is actually there with\n * just the union-merge line: that is the file-destroying bug this\n * function exists to avoid, not commit. An unreadable existing file is\n * therefore left untouched and reported as a failure like any other.\n *\n * Two processes racing the append branch — both read a file without the\n * line, both append it — is possible and left unguarded: `appendFile` is\n * `O_APPEND`, so the result is two copies of the same line rather than a\n * torn write, and `hasMergeDeclaration` sees a duplicate declaration as\n * \"already declared\" on the next call. A cheap-to-detect, harmless-to-\n * leave residue, not a reason to add a cross-process lock (see\n * `ARCHITECTURE.md`'s rejection of one for the same trade on records).\n *\n * Best-effort, like the log append it precedes: failing to write this\n * file must not fail the mutation it guards.\n */\n private async ensureGitattributes(root: string): Promise<void> {\n const target = join(root, GITATTRIBUTES_FILE);\n try {\n let existing: string | null;\n try {\n existing = await readFile(target, \"utf8\");\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error;\n existing = null;\n }\n\n if (existing === null) {\n try {\n await writeFile(target, appendUnionMergeLine(\"\"), {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n } catch (error) {\n // Another writer created the same file with the same content\n // between our read and our write — a win for them counts as a win\n // for us, not a failure.\n if ((error as NodeJS.ErrnoException).code !== \"EEXIST\") throw error;\n this.logger.info?.({\n operation: \"kb.gitattributes.ensure\",\n bundlePath: root,\n outcome: \"exists\",\n });\n return;\n }\n this.logger.info?.({\n operation: \"kb.gitattributes.ensure\",\n bundlePath: root,\n outcome: \"created\",\n });\n return;\n }\n if (!hasMergeDeclaration(existing)) {\n await appendFile(target, appendUnionMergeLine(existing), \"utf8\");\n this.logger.info?.({\n operation: \"kb.gitattributes.ensure\",\n bundlePath: root,\n outcome: \"appended\",\n });\n }\n } catch (error) {\n this.logger.warn?.({\n operation: \"kb.gitattributes.ensure\",\n outcome: \"failed\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n }\n }\n\n /** Appends one log line. Failing to log must not fail the mutation. */\n private async record(\n root: string,\n entry: Omit<KbLogEntry, \"at\"> & { at?: string },\n ): Promise<void> {\n await this.ensureGitattributes(root);\n const line = renderLogEntry({ at: new Date().toISOString(), ...entry });\n await appendFile(join(root, LOG_FILE), line, \"utf8\").catch((error) => {\n this.logger.warn?.({\n operation: \"kb.log.append\",\n outcome: \"failed\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n });\n }\n\n private parse(conceptId: string, raw: string): KbRecord | null {\n const parsed = parseMarkdownWithFrontmatter(raw, kbRecordFrontmatterSchema);\n if (!parsed.frontmatter.success) {\n this.logger.warn?.({\n operation: \"kb.parse\",\n conceptId,\n outcome: \"skipped\",\n error: parsed.frontmatter.error.issues[0]?.message ?? \"invalid\",\n });\n return null;\n }\n return {\n conceptId,\n frontmatter: parsed.frontmatter.data,\n body: parsed.content,\n };\n }\n\n private root(bundlePath: string): string {\n return resolve(bundlePath);\n }\n\n // Concept ids are `<type>.<slug>` and map to a single file directly under the\n // bundle root; anything carrying a separator would escape it.\n private recordPath(bundlePath: string, conceptId: string): string {\n if (conceptId.includes(sep) || conceptId.includes(\"/\")) {\n throw new KbInvalidConceptIdError(\n \"concept id must not contain a path separator\",\n { conceptId },\n );\n }\n return join(this.root(bundlePath), `${conceptId}.md`);\n }\n}\n\n/**\n * Deliberately crude, and labelled `approx` everywhere it surfaces. A real\n * tokeniser would be a dependency carried to decide whether to avoid carrying\n * dependencies, and four characters per token is close enough to choose\n * between \"hand it over\" and \"do not\".\n *\n * Exported (with `estimateStubTokens` and `stub`) so `pack` costs and stubs\n * records exactly as `load` does — two accountings would drift.\n */\nexport function estimateTokens(record: KbRecord): number {\n return Math.ceil(\n (record.body.length + JSON.stringify(record.frontmatter).length) / 4,\n );\n}\n\nexport function estimateStubTokens(entry: KbSupersededStub): number {\n return Math.ceil(JSON.stringify(entry).length / 4);\n}\n\n/** What a refused load says: what tripped the budget, and what to call next. */\nfunction refusalMessage(refusal: {\n approxTokens: number;\n budgetTokens: number;\n type?: string;\n}): string {\n const scope = refusal.type ? ` of type ${refusal.type}` : \"\";\n\n return [\n `Refusing to load this base whole: ~${refusal.approxTokens} tokens is past the ${refusal.budgetTokens}-token budget.`,\n `Call kb_catalog for one line per record${scope} (id, type, title, standing), then kb_pack on the record that matters; kb_query works for a lookup by wording.`,\n `To load anyway: raise budgetTokens (currently ${refusal.budgetTokens}), or all=true to bypass the budget.`,\n ].join(\" \");\n}\n\n/**\n * `heads` is where the supersession chain ends, which is what a reader needs:\n * pointing at an intermediate record that is itself superseded would answer\n * \"what replaced this\" with something else that no longer holds. A broken or\n * forked chain resolves to no head, and the warning that says so travels with\n * the head record rather than here.\n */\nexport function stub(hit: KbAdjudicated): KbSupersededStub {\n return {\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n supersededBy: hit.heads.map((head) => head.conceptId),\n at: hit.record.frontmatter.generated?.at ?? null,\n };\n}\n\nfunction matches(record: KbRecord, needle: string): boolean {\n const { title, description } = record.frontmatter;\n // The concept id is searched too: a slug is chosen to describe the record, so\n // a base where `decision.cursor-v2` does not answer \"cursor\" is surprising in\n // a way no caller would think to work around.\n return [record.conceptId, title, description, record.body].some((field) =>\n field?.toLowerCase().includes(needle),\n );\n}\n\n/**\n * Case-normalizes only the kind prefix — the segment up to and including the\n * first `:` — so `Human:alice` and `human:alice` name the same kind of actor\n * while the identity after the colon keeps its case. An id with no colon is\n * all prefix, and is lowercased whole.\n */\nfunction normalizeActor(id: string): string {\n const colon = id.indexOf(\":\");\n if (colon === -1) return id.toLowerCase();\n return id.slice(0, colon + 1).toLowerCase() + id.slice(colon + 1);\n}\n","import matter from \"gray-matter\";\nimport type { z } from \"zod\";\n\n/**\n * Frontmatter round-tripping, thin over gray-matter.\n *\n * Thin on purpose. A record is a YAML block and a markdown body, and every\n * hand-rolled reader of that shape eventually meets a nested map — an OKF\n * `generated`, a `sources[]`, a `verified[]` — and misreads it. The parser is\n * therefore borrowed and the only thing added is the schema gate below.\n */\nexport function stringifyMarkdownWithFrontmatter(\n content: string,\n frontmatter: Record<string, unknown>,\n): string {\n return matter.stringify(content, frontmatter);\n}\n\nexport function splitMarkdownFrontmatter(text: string): {\n content: string;\n prefix: string;\n raw: Record<string, unknown>;\n} {\n const file = matter(text);\n\n return {\n content: file.content,\n // Everything gray-matter consumed: the fences, the YAML, and the blank line\n // after them. Kept so a caller can rewrite a body without touching the head.\n prefix: text.slice(0, text.length - file.content.length),\n raw: file.data as Record<string, unknown>,\n };\n}\n\n/**\n * Splits, then validates the frontmatter against a schema.\n *\n * The result is a `safeParse` outcome rather than a throw: one malformed record\n * must not make a whole directory unreadable, so the caller decides whether to\n * skip it or fail.\n */\nexport function parseMarkdownWithFrontmatter<S extends z.ZodType>(\n text: string,\n schema: S,\n): {\n content: string;\n prefix: string;\n raw: Record<string, unknown>;\n frontmatter: ReturnType<S[\"safeParse\"]>;\n} {\n const { content, prefix, raw } = splitMarkdownFrontmatter(text);\n\n return {\n content,\n prefix,\n raw,\n frontmatter: schema.safeParse(raw) as ReturnType<S[\"safeParse\"]>,\n };\n}\n","/**\n * A base's content stamp: `load`'s digest, and the per-record digests it is\n * built from.\n *\n * The aggregate answers \"did anything change\"; the per-record entries answer\n * \"which records\", which is what a reload notice has to name. One pass\n * produces both, so `load` and `stamp` cannot disagree.\n */\nimport { createHash } from \"node:crypto\";\nimport { stringifyMarkdownWithFrontmatter } from \"./markdown.js\";\nimport type { KbAdjudicated } from \"./adjudicate.js\";\nimport type { KbSupersededStub } from \"./kb-store.js\";\n\nexport type KbRecordStamp = { conceptId: string; digest: string };\n\nexport type KbBundleStamp = { digest: string; records: KbRecordStamp[] };\n\nexport function sha256(contents: string): string {\n return createHash(\"sha256\").update(contents).digest(\"hex\");\n}\n\n/**\n * Entries are sorted by concept id, so the digest never depends on listing\n * order; each is hashed over its record's canonical recomposed form, not the\n * on-disk bytes; superseded stubs are included, so a standing flip changes the\n * digest even when the body did not.\n */\nexport function bundleStamp(\n records: KbAdjudicated[],\n superseded: KbSupersededStub[],\n): KbBundleStamp {\n const entries: KbRecordStamp[] = [\n ...records.map((hit) => ({\n conceptId: hit.record.conceptId,\n digest: `current:${sha256(\n stringifyMarkdownWithFrontmatter(\n hit.record.body,\n hit.record.frontmatter,\n ),\n )}`,\n })),\n ...superseded.map((entry) => ({\n conceptId: entry.conceptId,\n digest: `superseded:${sha256(JSON.stringify(entry))}`,\n })),\n ].sort((a, b) => (a.conceptId < b.conceptId ? -1 : 1));\n\n return {\n digest: sha256(\n entries.map((entry) => `${entry.conceptId}:${entry.digest}`).join(\"\\n\"),\n ),\n records: entries,\n };\n}\n\nexport function bundleDigest(\n records: KbAdjudicated[],\n superseded: KbSupersededStub[],\n): string {\n return bundleStamp(records, superseded).digest;\n}\n","import { stat } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { DEFAULT_IO_CONCURRENCY, mapLimit } from \"./concurrency.js\";\nimport { INDEX_FILE } from \"./kb-index.js\";\nimport { LOG_FILE } from \"./kb-log.js\";\n\nexport const SEARCH_INDEX_FILE = \".index.sqlite\";\n\nconst COLLECTION = \"kb\";\n\n/**\n * BM25 over one knowledge base, via qmd's SDK.\n *\n * Reached only when a base is too large to hand over whole — see `load()`,\n * which is the first thing a reader should try.\n *\n * Lexical only. `searchLex` is BM25 and needs no model. Measured against the\n * substring scan it replaces it wins on word forms and little else: `pages`\n * finds a record saying only `page`, and eight of nine probe queries returned\n * exactly what substring returned.\n *\n * The vector tier does close the semantic gap — \"why not just use a mutex\"\n * finds the record about compare-and-swap, which no lexical match can. It stays\n * off because its scores do not separate right from wrong: a wrong hit scored\n * 0.318 against a correct one at 0.295, and a query about a subject absent from\n * the base still returns its nearest record rather than nothing.\n *\n * The index is derived and disposable — one file per base, gitignored, deleted\n * and rebuilt at will. That is only true because a base is self-contained: an\n * index covering exactly one directory can always be rebuilt from it.\n *\n * qmd is used as a **library**, and is an optional peer dependency: with it\n * absent every path here still answers, `searchBase` returns null, and the\n * store falls back to a substring scan. Its own MCP server would let an agent\n * reach a base without passing the store, and its default markdown glob would\n * return `INDEX.md` as a search hit — the case `list()` already excludes,\n * reintroduced by a reader this package does not control. Hence the explicit\n * `ignore` below.\n */\n/**\n * A hit as qmd reports it — by its own normalised path, not by our identity.\n *\n * qmd rewrites `decision.cursor-keyset.md` to `decision-cursor-keyset.md`,\n * which destroys the separator between a record's type and its slug and cannot\n * be undone from the string alone: `decision-cursor-keyset` could be the type\n * `decision` or a type `decision-cursor`. The caller maps these back through\n * the records it already holds rather than parsing them.\n */\nexport type SearchHit = { displayPath: string; score: number };\n\ntype QmdStore = {\n searchLex(\n query: string,\n options?: { limit?: number; collection?: string },\n ): Promise<{ displayPath?: string; filepath?: string; score?: number }[]>;\n addCollection(\n name: string,\n opts: { path: string; pattern?: string; ignore?: string[] },\n ): Promise<void>;\n listCollections(): Promise<unknown[]>;\n update(options?: { collections?: string[] }): Promise<unknown>;\n close(): Promise<void>;\n};\n\nexport type KbSearchLogger = {\n warn?(entry: Record<string, unknown>): void;\n};\n\n/** What this module needs of qmd, which is all it is allowed to assume. */\nexport type QmdModule = { createStore(options: unknown): Promise<unknown> };\n\nexport type SearchOptions = {\n limit?: number;\n logger?: KbSearchLogger;\n /**\n * The backend, supplied rather than imported. Production passes nothing and\n * gets the dynamic import below; a caller that already holds qmd — or a test\n * covering the present-backend branch on a machine where the optional peer is\n * not installed — passes it here.\n */\n qmd?: QmdModule;\n};\n\n/**\n * Opens (or creates) the base's index and answers a query against it.\n *\n * Re-indexes when the index is older than the newest record rather than on a\n * schedule or a write hook: the same repair-on-read rule `INDEX.md` follows,\n * and for the same reason — a derived artifact that can rebuild itself does not\n * need anyone to remember to rebuild it.\n */\nexport async function searchBase(\n bundlePath: string,\n query: string,\n options: SearchOptions = {},\n): Promise<SearchHit[] | null> {\n const qmd = options.qmd ?? (await loadQmd(options.logger));\n if (!qmd) return null;\n\n let store: QmdStore | null = null;\n try {\n store = (await qmd.createStore({\n dbPath: join(bundlePath, SEARCH_INDEX_FILE),\n config: {\n collections: {\n [COLLECTION]: {\n path: bundlePath,\n pattern: \"**/*.md\",\n // Both store-owned files are markdown and neither is a record.\n ignore: [INDEX_FILE, LOG_FILE],\n },\n },\n },\n })) as QmdStore;\n\n if (await isStale(bundlePath)) {\n await store.update({ collections: [COLLECTION] });\n }\n\n const hits = await store.searchLex(query, {\n collection: COLLECTION,\n ...(options.limit ? { limit: options.limit } : {}),\n });\n return hits\n .map((hit) => ({\n displayPath: hit.displayPath ?? hit.filepath ?? \"\",\n score: hit.score ?? 0,\n }))\n .filter((hit) => hit.displayPath.length > 0);\n } catch (error) {\n // A search index is an optimisation. Losing it must degrade recall, never\n // the answer — `query()` falls back to substring rather than failing.\n options.logger?.warn?.({\n operation: \"kb.search\",\n outcome: \"unavailable\",\n error: error instanceof Error ? error.message : \"unknown\",\n });\n return null;\n } finally {\n await store?.close().catch(() => undefined);\n }\n}\n\n/**\n * Whether any record is newer than the index.\n *\n * Stats run through a bounded pool rather than one at a time; once one record\n * has answered \"newer\", the workers still queued skip their `stat` entirely.\n */\nasync function isStale(bundlePath: string): Promise<boolean> {\n const indexAt = await stat(join(bundlePath, SEARCH_INDEX_FILE))\n .then((s) => s.mtimeMs)\n .catch(() => 0);\n if (!indexAt) return true;\n\n const { readdir } = await import(\"node:fs/promises\");\n const names = (await readdir(bundlePath).catch(() => [] as string[])).filter(\n (name) => name.endsWith(\".md\") && name !== INDEX_FILE,\n );\n\n let stale = false;\n await mapLimit(names, DEFAULT_IO_CONCURRENCY, async (name) => {\n if (stale) return;\n const at = await stat(join(bundlePath, name))\n .then((s) => s.mtimeMs)\n .catch(() => 0);\n if (at > indexAt) stale = true;\n });\n return stale;\n}\n\n/**\n * Maps qmd's normalised paths back onto real records.\n *\n * Comparing on the same normalisation rather than trying to invert it: a dot in\n * a concept id and a dash in a slug are indistinguishable once qmd has rewritten\n * the name, so the only reliable direction is forwards, from ids we hold.\n */\nexport function resolveHits<T extends { conceptId: string }>(\n hits: SearchHit[],\n records: T[],\n): T[] {\n const byName = new Map<string, T>();\n for (const record of records) {\n const name = flatten(record.conceptId);\n // A collision would make the mapping a guess; drop both rather than pick.\n if (byName.has(name)) byName.delete(name);\n else byName.set(name, record);\n }\n\n const resolved: T[] = [];\n for (const hit of hits) {\n const file = hit.displayPath.split(\"/\").pop() ?? \"\";\n const name = file.endsWith(\".md\") ? file.slice(0, -\".md\".length) : file;\n const record = byName.get(flatten(name));\n if (record) resolved.push(record);\n }\n return resolved;\n}\n\nfunction flatten(value: string): string {\n return value.replace(/[.]/g, \"-\").toLowerCase();\n}\n\n/**\n * Held in a variable rather than written inline. qmd is not a dependency of\n * this package, so a literal specifier sends the compiler looking for types\n * that are not installed; the indirection keeps the import dynamic at runtime\n * and invisible at build time, which is what an optional engine needs.\n */\nconst QMD_MODULE = \"@tobilu/qmd\";\n\n/**\n * Loaded on demand so a caller that never searches pays nothing for a\n * dependency that pulls in native SQLite bindings and a llama runtime — and\n * returns null rather than throwing when it is not installed at all, which is\n * the normal case for an optional peer.\n */\nexport async function loadQmd(\n logger?: KbSearchLogger,\n): Promise<QmdModule | null> {\n try {\n return (await import(QMD_MODULE)) as unknown as QmdModule;\n } catch {\n logger?.warn?.({ operation: \"kb.search\", outcome: \"qmd-unavailable\" });\n return null;\n }\n}\n","import { adjudicate, type KbStanding, type KbWarning } from \"./adjudicate.js\";\nimport { neighbours } from \"./kb-edges.js\";\nimport {\n KbPackBudgetExceededError,\n KbRecordNotFoundError,\n} from \"./kb-errors.js\";\nimport {\n KB_RECORD_TYPES,\n type KbAnchor,\n type KbRecord,\n} from \"./kb-record.schema.js\";\nimport {\n DEFAULT_LOAD_BUDGET,\n estimateStubTokens,\n estimateTokens,\n stub,\n type KbSupersededStub,\n} from \"./kb-store.js\";\n\nexport const DEFAULT_PACK_HOPS = 2;\nexport const DEFAULT_PACK_MAX_NODES = 20;\n\nexport type KbPackOptions = {\n /** How far from the root the walk may reach. */\n hops?: number;\n /** How many records the pack may hold, root included. */\n maxNodes?: number;\n /** Approximate token ceiling over what is actually emitted. */\n budgetTokens?: number;\n};\n\n/** One record as the pack emits it — the same mapping `kb_load` hands back. */\nexport type KbPackedRecord = {\n conceptId: string;\n title: string | null;\n standing: KbStanding;\n supersededBy: string[];\n warnings: KbWarning[];\n anchors: KbAnchor[];\n body: string;\n};\n\n/**\n * Deliberately timestamp-free: the same bundle and root must produce the same\n * bytes on every run, so a caller can diff two packs and trust that a changed\n * byte means changed knowledge.\n */\nexport type KbPackResult = {\n root: string;\n records: KbPackedRecord[];\n /** Named only, exactly as `load` stubs them. Bodies reachable via trace. */\n superseded: KbSupersededStub[];\n /** Every reachable record the hop and node limits cut, never summarized. */\n excluded: string[];\n recordCount: number;\n tokensLoaded: number;\n budgetTokens: number;\n};\n\n// What a reader wants first when the walk has to cut: what was settled\n// (decision), then what binds (constraint, requirement), then the rest in\n// their declared order.\nconst TYPE_PRIORITY: readonly string[] = [\n \"decision\",\n \"constraint\",\n \"requirement\",\n ...KB_RECORD_TYPES.filter(\n (type) => ![\"decision\", \"constraint\", \"requirement\"].includes(type),\n ),\n];\n\ntype Reached = { record: KbRecord; depth: number };\n\n/**\n * A bounded, progressively disclosed neighbourhood around one record.\n *\n * Where `load` hands over a whole base and `trace` a timeline, a pack is the\n * subgraph a reader needs to act near one record: everything within `hops`\n * of the root, cut to `maxNodes` by ranking, with every cut id listed —\n * a named gap is knowable, a silent one is not.\n *\n * Adjudication runs against the whole bundle, not the reached slice, so a\n * record's standing cannot depend on whether its replacement happened to be\n * within reach. Superseded records become the same stubs `load` emits, costed\n * as stubs, and the budget is a refusal rather than a truncation: a partial\n * pack looks complete to its reader.\n */\nexport function pack(\n bundle: KbRecord[],\n rootId: string,\n options: KbPackOptions = {},\n): KbPackResult {\n const hops = options.hops ?? DEFAULT_PACK_HOPS;\n const maxNodes = options.maxNodes ?? DEFAULT_PACK_MAX_NODES;\n const budgetTokens = options.budgetTokens ?? DEFAULT_LOAD_BUDGET;\n\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n const root = byId.get(rootId);\n if (!root) throw new KbRecordNotFoundError(rootId);\n\n // The whole reachable component is walked, not just the first `hops` rings:\n // the bundle is already in memory, and knowing what lies past the bound is\n // what lets the excluded list name records instead of waving at them.\n const reached: Reached[] = [{ record: root, depth: 0 }];\n const seen = new Set([rootId]);\n let frontier: KbRecord[] = [root];\n for (let depth = 1; frontier.length; depth += 1) {\n const next: KbRecord[] = [];\n for (const from of frontier) {\n for (const { record } of neighbours(from, bundle)) {\n if (seen.has(record.conceptId)) continue;\n seen.add(record.conceptId);\n reached.push({ record, depth });\n next.push(record);\n }\n }\n frontier = next;\n }\n\n reached.sort(byRank);\n const within = reached.filter((entry) => entry.depth <= hops);\n const kept = within.slice(0, maxNodes);\n const excluded = [\n ...within.slice(maxNodes),\n ...reached.filter((entry) => entry.depth > hops),\n ]\n .map((entry) => entry.record.conceptId)\n .sort();\n\n const adjudicated = adjudicate(\n kept.map((entry) => entry.record),\n bundle,\n );\n const superseded = adjudicated\n .filter((hit) => hit.standing === \"superseded\")\n .map(stub);\n const whole = adjudicated.filter((hit) => hit.standing !== \"superseded\");\n\n const tokensLoaded =\n whole.reduce((total, hit) => total + estimateTokens(hit.record), 0) +\n superseded.reduce((total, entry) => total + estimateStubTokens(entry), 0);\n const recordCount = adjudicated.length;\n\n if (tokensLoaded > budgetTokens) {\n throw new KbPackBudgetExceededError(\n recordCount,\n tokensLoaded,\n budgetTokens,\n excluded,\n );\n }\n\n return {\n root: rootId,\n records: whole.map((hit) => ({\n conceptId: hit.record.conceptId,\n title: hit.record.frontmatter.title ?? null,\n standing: hit.standing,\n supersededBy: hit.heads.map((head) => head.conceptId),\n warnings: hit.warnings,\n anchors: hit.record.frontmatter.strauss_anchors ?? [],\n body: hit.record.body,\n })),\n superseded,\n excluded,\n recordCount,\n tokensLoaded,\n budgetTokens,\n };\n}\n\nfunction byRank(left: Reached, right: Reached): number {\n return (\n left.depth - right.depth ||\n typeRank(left.record) - typeRank(right.record) ||\n (left.record.frontmatter.title ?? \"\").localeCompare(\n right.record.frontmatter.title ?? \"\",\n ) ||\n left.record.conceptId.localeCompare(right.record.conceptId)\n );\n}\n\n// A foreign type — legal under OKF — ranks after every known one.\nfunction typeRank(record: KbRecord): number {\n const index = TYPE_PRIORITY.indexOf(record.frontmatter.type);\n return index === -1 ? TYPE_PRIORITY.length : index;\n}\n","import type { KbRecord } from \"../kb-record.schema.js\";\nimport type { KbInboundEdge } from \"./model.js\";\n\n/**\n * The whole bundle's typed edges, indexed by target — built once per call, so a\n * walk stays linear in the bundle rather than quadratic. Order is `list()`'s\n * own, then each record's declared link order, so repeated runs agree.\n */\nexport function inboundIndex(bundle: KbRecord[]): Map<string, KbInboundEdge[]> {\n const byTarget = new Map<string, KbInboundEdge[]>();\n\n for (const record of bundle) {\n for (const link of record.frontmatter.strauss_links ?? []) {\n // A record naming itself is a no-op, not an error, for the same reason\n // `supersedes` treats it that way: the claim is already true.\n if (link.target === record.conceptId) continue;\n\n const edges = byTarget.get(link.target) ?? [];\n // The same pair stated twice says nothing twice.\n if (\n edges.some(\n (edge) => edge.from === record.conceptId && edge.rel === link.rel,\n )\n ) {\n continue;\n }\n edges.push({ from: record.conceptId, rel: link.rel });\n byTarget.set(link.target, edges);\n }\n }\n\n return byTarget;\n}\n","import { adjudicate } from \"../adjudicate.js\";\nimport { KbRecordNotFoundError } from \"../kb-errors.js\";\nimport type { KbRecord } from \"../kb-record.schema.js\";\nimport { inboundIndex } from \"./inbound.js\";\nimport type { KbBacklink, KbBacklinksResult } from \"./model.js\";\n\n/**\n * Every edge the bundle holds against this id: one hop, every rel including\n * `related_to`, each row carrying the standing of the record that made it.\n * Flat and factual, where `impact` answers the causal, transitive question.\n */\nexport function backlinks(\n targetId: string,\n bundle: KbRecord[],\n): KbBacklinksResult {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n if (!byId.has(targetId)) throw new KbRecordNotFoundError(targetId);\n\n const standingOf = new Map(\n adjudicate(bundle, bundle).map((hit) => [hit.record.conceptId, hit]),\n );\n\n const rows: KbBacklink[] = [];\n for (const edge of inboundIndex(bundle).get(targetId) ?? []) {\n const record = byId.get(edge.from);\n if (!record) continue;\n const hit = standingOf.get(edge.from);\n rows.push({\n ...edge,\n title: record.frontmatter.title ?? null,\n standing: hit?.standing ?? \"unsettled\",\n warnings: hit?.warnings ?? [],\n });\n }\n\n return {\n target: targetId,\n backlinks: rows.sort(\n (left, right) =>\n left.from.localeCompare(right.from) ||\n left.rel.localeCompare(right.rel),\n ),\n };\n}\n","import { adjudicate, type KbAdjudicated } from \"../adjudicate.js\";\nimport { KbRecordNotFoundError, KbUnknownLinkRelError } from \"../kb-errors.js\";\nimport type { KbRecord } from \"../kb-record.schema.js\";\nimport {\n isKbLinkRel,\n KB_CAUSAL_LINK_RELS,\n LINK_RELS,\n} from \"../record-types.js\";\nimport { inboundIndex } from \"./inbound.js\";\nimport type {\n KbImpactOptions,\n KbImpactResult,\n KbImpactedRecord,\n KbLinkEdge,\n} from \"./model.js\";\n\n/**\n * The transitive set of *dependants*, not the set of inbound edges: each rel is\n * followed in its own direction of dependence. `related_to` and unknown rels\n * propagate nothing. A superseded or rejected record is reported, then not\n * walked through. A record expands once, so cycles terminate.\n */\nexport function impact(\n targetId: string,\n bundle: KbRecord[],\n options: KbImpactOptions = {},\n): KbImpactResult {\n const byId = new Map(bundle.map((record) => [record.conceptId, record]));\n if (!byId.has(targetId)) throw new KbRecordNotFoundError(targetId);\n\n const rels = resolveRels(options.rels);\n const maxDepth = options.depth ?? Number.POSITIVE_INFINITY;\n const inbound = inboundIndex(bundle);\n\n // Adjudicated once over the whole bundle: standing must not depend on\n // whether a record's replacement happened to be within the walk.\n const standingOf = new Map<string, KbAdjudicated>(\n adjudicate(bundle, bundle).map((hit) => [hit.record.conceptId, hit]),\n );\n\n const reached = new Map<string, KbImpactedRecord>();\n const stopped: string[] = [];\n let frontier = [targetId];\n let depth = 0;\n\n while (frontier.length && depth < maxDepth) {\n depth += 1;\n const next: string[] = [];\n\n const consider = (dependantId: string, edge: KbLinkEdge) => {\n // The root is the question, not an answer to it.\n if (dependantId === targetId) return;\n\n const existing = reached.get(dependantId);\n if (existing) {\n if (!hasEdge(existing.via, edge)) existing.via.push(edge);\n return;\n }\n\n const record = byId.get(dependantId);\n // An edge naming a record that is not in the bundle is routine — records\n // are written before the ones they point at — and `kb_validate` is what\n // reports it. Nothing to report as impacted, so nothing is invented.\n if (!record) return;\n\n const hit = standingOf.get(dependantId);\n const entry: KbImpactedRecord = {\n conceptId: dependantId,\n title: record.frontmatter.title ?? null,\n standing: hit?.standing ?? \"unsettled\",\n warnings: hit?.warnings ?? [],\n depth,\n via: [edge],\n };\n reached.set(dependantId, entry);\n\n if (entry.standing === \"superseded\" || entry.standing === \"rejected\") {\n stopped.push(dependantId);\n return;\n }\n next.push(dependantId);\n };\n\n for (const id of frontier) {\n // Inbound: someone points at me with a rel whose dependant is the source.\n for (const edge of inbound.get(id) ?? []) {\n if (!rels.has(edge.rel)) continue;\n if (dependantEnd(edge.rel) !== \"source\") continue;\n consider(edge.from, { source: edge.from, target: id, rel: edge.rel });\n }\n\n // Outbound: I point at someone with a rel whose dependant is the target.\n for (const link of byId.get(id)?.frontmatter.strauss_links ?? []) {\n if (!rels.has(link.rel)) continue;\n if (dependantEnd(link.rel) !== \"target\") continue;\n if (link.target === id) continue;\n consider(link.target, {\n source: id,\n target: link.target,\n rel: link.rel,\n });\n }\n }\n\n frontier = next;\n }\n\n return {\n root: targetId,\n impacted: [...reached.values()].sort(\n (left, right) =>\n left.depth - right.depth ||\n left.conceptId.localeCompare(right.conceptId),\n ),\n stopped: stopped.sort(),\n truncated: frontier.length > 0,\n unexpanded: [...frontier].sort(),\n };\n}\n\n/**\n * The caller's `rels`, checked at the library boundary.\n *\n * A rel the walk cannot follow is an error, not an empty result: the two are\n * indistinguishable to a caller, and \"nothing breaks\" is the most dangerous\n * answer this function can return.\n */\nfunction resolveRels(rels: readonly string[] | undefined): Set<string> {\n if (!rels?.length) return new Set<string>(KB_CAUSAL_LINK_RELS);\n for (const rel of rels) {\n if (!isKbLinkRel(rel) || LINK_RELS[rel].dependant === null) {\n throw new KbUnknownLinkRelError(rel, KB_CAUSAL_LINK_RELS);\n }\n }\n return new Set(rels);\n}\n\n/** Which end of a stored rel depends on the other. `null` for anything inert. */\nfunction dependantEnd(rel: string): \"source\" | \"target\" | null {\n return isKbLinkRel(rel) ? LINK_RELS[rel].dependant : null;\n}\n\nfunction hasEdge(edges: KbLinkEdge[], edge: KbLinkEdge): boolean {\n return edges.some(\n (existing) =>\n existing.source === edge.source &&\n existing.target === edge.target &&\n existing.rel === edge.rel,\n );\n}\n","import { LOG_FILE } from \"./kb-log.js\";\n\nexport const GITATTRIBUTES_FILE = \".gitattributes\";\n\n/**\n * Declares the log's merge driver, plus line endings.\n *\n * `merge=union` interleaves both sides' lines instead of the ordinary\n * line-level merge, which can drop one side's appends outright. The log is\n * append-only JSONL and two worktrees against the same bundle is the normal\n * case, not an edge case — `kb_log`'s reader sorts on `at` and dedupes exact\n * repeats (`kb-log.ts`), so interleaved line order — or a line a union merge\n * happened to keep twice — coming out of a merge is exactly as readable as a\n * single writer's log.\n *\n * `text eol=lf` pins line endings to `\\n` regardless of a checkout's\n * `core.autocrlf`. Without it, Windows with `autocrlf=true` normalizes the\n * file to CRLF on checkout while every append after that (`O_APPEND`, raw\n * `\\n`) keeps writing LF — a file with mixed endings, which is exactly the\n * kind of divergence a merge driver can't paper over.\n */\nexport const UNION_MERGE_LINE = `${LOG_FILE} text eol=lf merge=union`;\n\n/**\n * One parsed `.gitattributes` line: the pattern and its whitespace-separated\n * attributes. `null` for a blank line or a `#` comment — gitattributes\n * ignores both.\n */\nfunction parseLine(line: string): { pattern: string; attrs: string[] } | null {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"#\")) return null;\n const [pattern, ...attrs] = trimmed.split(/\\s+/);\n return pattern === undefined ? null : { pattern, attrs };\n}\n\n/**\n * Whether `contents` already assigns *any* `merge` attribute to the log\n * file — our own `merge=union`, a plain `merge` (the default driver), an\n * explicit `-merge` (merging disabled), or a user's own choice such as\n * `merge=ours`.\n *\n * Exact-string matching against `UNION_MERGE_LINE` was the first cut, and it\n * both under- and over-reaches: a line with a tab or doubled space between\n * tokens, or one that also sets an unrelated attribute alongside `merge`,\n * would not match and get a harmless-looking but wrong second line appended\n * — and it can never see a deliberate `merge=ours` as \"already decided\",\n * which is the one case where appending anything at all would be wrong.\n * Whitespace-tokenizing the pattern and attributes separately answers the\n * question this function actually needs answered: does *some* line already\n * give `log.jsonl` a merge strategy, whatever it is — and if so, that\n * strategy is left alone rather than layered under a second, possibly\n * conflicting one. gitattributes itself resolves multiple matching lines by\n * \"last one wins\", so appending a second `merge=` line for the same pattern\n * would silently override a user's `merge=ours` with `merge=union` — the\n * opposite of respecting what they set.\n */\nexport function hasMergeDeclaration(contents: string): boolean {\n return contents.split(\"\\n\").some((line) => {\n const parsed = parseLine(line);\n if (!parsed || parsed.pattern !== LOG_FILE) return false;\n return parsed.attrs.some(\n (attr) =>\n attr === \"merge\" || attr === \"-merge\" || attr.startsWith(\"merge=\"),\n );\n });\n}\n\n/**\n * The bytes to append to a `.gitattributes` that does not yet declare a\n * merge strategy for the log — a newline first, unless `contents` already\n * ends in one, so the line lands on its own rather than tacked onto the\n * file's last line.\n */\nexport function appendUnionMergeLine(contents: string): string {\n const separator =\n contents.length === 0 || contents.endsWith(\"\\n\") ? \"\" : \"\\n\";\n return `${separator}${UNION_MERGE_LINE}\\n`;\n}\n","/**\n * The package version, injected at build time by tsup's `define`.\n *\n * Hardcoding it here would be a second copy of `package.json`'s version, and a\n * copy that only a human comparing two numbers would ever catch: it reaches\n * users as `serverInfo.version`, which is the one thing a client can ask a\n * running server about itself. It sat at 0.1.0 through five releases.\n *\n * `typeof` rather than a bare reference so this also works unbuilt — under\n * Vitest the identifier is never defined, and reading an undeclared name would\n * throw where reading its type does not.\n */\ndeclare const __STRAUSS_KB_VERSION__: string | undefined;\n\nexport const VERSION: string =\n typeof __STRAUSS_KB_VERSION__ === \"string\"\n ? __STRAUSS_KB_VERSION__\n : \"0.0.0-dev\";\n","#!/usr/bin/env node\nimport { runKbMcpServer } from \"./mcp.js\";\n\nrunKbMcpServer().catch((error: unknown) => {\n process.stderr.write(\n `${error instanceof Error ? error.message : String(error)}\\n`,\n );\n process.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,IAAM,mBAAmB,MACvB,OAAO,aAAa,cAChB,IAAI,IAAI,QAAQ,UAAU,EAAE,EAAE,OAC7B,SAAS,iBAAiB,SAAS,cAAc,QAAQ,YAAY,MAAM,WAC1E,SAAS,cAAc,MACvB,IAAI,IAAI,WAAW,SAAS,OAAO,EAAE;AAEtC,IAAM,gBAAgC,iCAAiB;;;ACZ9D,iBAA0B;AAC1B,mBAAqC;;;ACDrC,IAAAA,cAAkB;;;ACAlB,IAAAC,cAAkB;;;ACAlB,iBAAkB;AAqBX,IAAM,iBAAiB,aAC3B,OAAO;AAAA,EACN,IAAI,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,UAAU,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC1B,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAClC,QAAQ,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACnC,eAAe,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAC5C,CAAC,EACA,YAAY;AAGR,IAAM,qBAAqB,aAC/B,OAAO;AAAA,EACN,IAAI,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,IAAI,aAAE,OAAO,EAAE,IAAI,CAAC;AACtB,CAAC,EACA,YAAY;AAQR,IAAM,wBAAwB,mBAAmB,OAAO;AAAA,EAC7D,MAAM,aAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG;AAAA,IAClD,SAAS;AAAA,EACX,CAAC;AACH,CAAC;AAsBM,IAAM,iBAAiB,aAC3B,OAAO;AAAA,EACN,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,QAAQ,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUnC,MAAM,aAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQxC,KAAK,aAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACvC,MAAM,aACH,OAAO,EACP,MAAM,yBAAyB;AAAA,IAC9B,SAAS;AAAA,EACX,CAAC,EACA,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQZ,WAAW,aAAE,KAAK,CAAC,OAAO,KAAK,CAAC,EAAE,SAAS;AAAA;AAAA,EAE3C,aAAa,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAExC,OAAO,aAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM5C,UAAU,aAAE,KAAK,CAAC,eAAe,OAAO,CAAC,EAAE,SAAS;AACtD,CAAC,EACA,OAAO;AAcH,IAAM,eAAe,aACzB,OAAO;AAAA,EACN,QAAQ,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACxB,KAAK,aAAE,OAAO,EAAE,IAAI,CAAC;AACvB,CAAC,EACA,YAAY;AAER,IAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,kBAAkB;AACxB,IAAM,wBACX;AAOK,IAAM,oBAAoB,aAAE,OAAO,EAAE,MAAM,uBAAuB;AAAA,EACvE,SAAS;AACX,CAAC;AAUM,IAAM,qBAAqB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,IAAM,mBAAmB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AACF;AACO,IAAM,iBAAiB,CAAC,OAAO,UAAU,MAAM;AAE/C,IAAM,4BAA4B,aACtC,OAAO;AAAA;AAAA;AAAA,EAGN,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAGtB,OAAO,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAClC,aAAa,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACxC,UAAU,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACrC,MAAM,aAAE,MAAM,aAAE,OAAO,CAAC,EAAE,SAAS;AAAA;AAAA,EAGnC,SAAS,aAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAC1C,WAAW,mBAAmB,SAAS;AAAA,EACvC,UAAU,aAAE,MAAM,kBAAkB,EAAE,SAAS;AAAA,EAC/C,aAAa,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA,EAGxC,iBAAiB,aAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAClD,gBAAgB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,EAKpD,eAAe,aAAE,MAAM,YAAY,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO9C,gBAAgB,aAAE,KAAK,kBAAkB,EAAE,QAAQ,OAAO;AAAA,EAC1D,oBAAoB,aAAE,MAAM,aAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EACxD,uBAAuB,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAClD,kBAAkB,mBAAmB,SAAS;AAAA,EAC9C,qBAAqB,aAAE,KAAK,gBAAgB,EAAE,SAAS;AAAA,EACvD,oBAAoB,aAAE,KAAK,cAAc,EAAE,SAAS;AAAA,EACpD,eAAe,aAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA,EAK1C,oBAAoB,aAAE,QAAQ,EAAE,SAAS;AAC3C,CAAC,EAIA,YAAY;;;AC9NR,IAAM,eAAiE;AAAA,EAC5E,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,UAAU,CAAC,SAAS,YAAY,aAAa;AAAA,IAC7C,eAAe;AAAA,EACjB;AAAA,EACA,aAAa;AAAA,IACX,SAAS;AAAA,IACT,UAAU,CAAC,SAAS,YAAY,aAAa;AAAA,IAC7C,eAAe;AAAA,EACjB;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,UAAU,CAAC,SAAS,YAAY,aAAa;AAAA,IAC7C,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,UAAU,CAAC,YAAY,aAAa,YAAY,QAAQ;AAAA,IACxD,eAAe;AAAA,EACjB;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,UAAU,CAAC,SAAS,mBAAmB,uBAAuB;AAAA,IAC9D,eAAe;AAAA,EACjB;AAAA,EACA,iBAAiB;AAAA,IACf,SAAS;AAAA,IACT,UAAU,CAAC,YAAY,kBAAkB,oBAAoB;AAAA,IAC7D,eAAe;AAAA,EACjB;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,UAAU,CAAC,QAAQ,kBAAkB,cAAc,cAAc;AAAA,IACjE,eAAe;AAAA,EACjB;AAAA,EACA,UAAU;AAAA,IACR,SAAS;AAAA,IACT,UAAU,CAAC,YAAY,YAAY,YAAY,eAAe;AAAA,IAC9D,eAAe;AAAA,EACjB;AAAA,EACA,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,UAAU,CAAC,QAAQ,WAAW,SAAS,eAAe;AAAA,IACtD,eAAe;AAAA,EACjB;AAAA,EACA,mBAAmB;AAAA,IACjB,SAAS;AAAA,IACT,UAAU,CAAC,UAAU,sBAAsB,cAAc;AAAA,IACzD,eAAe;AAAA,EACjB;AAAA,EACA,mBAAmB;AAAA,IACjB,SAAS;AAAA,IACT,UAAU,CAAC,cAAc,kBAAkB,eAAe;AAAA,IAC1D,eAAe;AAAA,EACjB;AAAA,EACA,eAAe;AAAA,IACb,SAAS;AAAA,IACT,UAAU,CAAC,QAAQ,oBAAoB;AAAA,IACvC,eAAe;AAAA,EACjB;AACF;AAEO,SAAS,eAAe,OAAsC;AACnE,SAAO,OAAO,UAAU,eAAe,KAAK,cAAc,KAAK;AACjE;AA4BO,IAAM,eAAe;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAIO,IAAM,YAAwD;AAAA,EACnE,YAAY;AAAA,IACV,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,YAAY;AAAA,IACV,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,SAAS;AAAA,IACP,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,QAAQ;AAAA,IACN,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,aAAa;AAAA,IACX,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,aAAa;AAAA,IACX,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,WAAW;AAAA,IACT,SACE;AAAA,IACF,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AAAA,EACA,YAAY;AAAA,IACV,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,WAAW;AAAA,EACb;AACF;AAWO,IAAM,sBAAsB,aAAa;AAAA,EAC9C,CAAC,QAAQ,UAAU,GAAG,EAAE,cAAc;AACxC;AAEO,SAAS,YAAY,OAAmC;AAC7D,SAAO,OAAO,UAAU,eAAe,KAAK,WAAW,KAAK;AAC9D;;;AF9KO,IAAM,oBAAoB,cAC9B,OAAO;AAAA,EACN,QAAQ;AAAA,EACR,KAAK,cAAE,KAAK,YAAY;AAC1B,CAAC,EACA,OAAO;AAIH,IAAM,qBAAqB,cAC/B,OAAO;AAAA,EACN,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEtB,OAAO,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAEvB,KAAK,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAErB,UAAU,cAAE,OAAO,cAAE,OAAO,GAAG,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EAC3D,SAAS,cAAE,MAAM,cAAc,EAAE,SAAS;AAAA,EAC1C,SAAS,cAAE,MAAM,cAAc,EAAE,SAAS;AAAA;AAAA,EAE1C,YAAY,cAAE,QAAQ,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMjC,aAAa,cACV,OAAO,EACP,MAAM,uBAAuB;AAAA,IAC5B,SAAS;AAAA,EACX,CAAC,EACA,OAAO,CAAC,SAAS,CAAC,OAAO,MAAM,KAAK,MAAM,IAAI,CAAC,GAAG;AAAA,IACjD,SAAS;AAAA,EACX,CAAC,EACA,SAAS;AAAA,EACZ,QAAQ,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA,EAC5C,MAAM,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EAAE,SAAS;AAAA;AAAA,EAE1C,mBAAmB,cAAE,MAAM,iBAAiB,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQvD,OAAO,cACJ,MAAM,iBAAiB,EACvB,IAAI,EAAE,EACN,SAAS,EACT;AAAA,IACC,4GAAkG,aAAa;AAAA,MAC7G,CAAC,QAAQ,GAAG,GAAG,KAAK,UAAU,GAAG,EAAE,OAAO;AAAA,IAC5C,EAAE,KAAK,IAAI,CAAC;AAAA,EACd;AAAA;AAAA,EAEF,YAAY,cAAE,MAAM,iBAAiB,EAAE,IAAI,EAAE,EAAE,SAAS;AAAA,EACxD,aAAa,cAAE,KAAK,gBAAgB,EAAE,SAAS;AAAA,EAC/C,YAAY,cAAE,KAAK,cAAc,EAAE,SAAS;AAAA,EAC5C,OAAO,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACpC,CAAC,EACA,OAAO;AAoBH,SAAS,cACd,MACA,OACA,WACA,WACgB;AAIhB,QAAM,SAAS,mBAAmB,MAAM,KAAK;AAC7C,QAAM,OAAO,aAAa,IAAI;AAC9B,QAAM,WAAW,OAAO,YAAY,CAAC;AAErC,QAAM,UAAU,OAAO,KAAK,QAAQ,EAAE;AAAA,IACpC,CAAC,YAAY,CAAC,KAAK,SAAS,SAAS,OAAO;AAAA,EAC9C;AACA,MAAI,QAAQ,QAAQ;AAClB,UAAM,IAAI;AAAA,MACR,OAAO,IAAI,mBAAmB,QAAQ,KAAK,IAAI,CAAC,2BAAsB,KAAK,SAAS,KAAK,IAAI,CAAC;AAAA,IAChG;AAAA,EACF;AAEA,QAAM,cAAiD;AAAA,IACrD,OAAO,OAAO;AAAA,IACd,aAAa,OAAO;AAAA,IACpB,WAAW,EAAE,IAAI,WAAW,IAAI,UAAU;AAAA;AAAA;AAAA;AAAA,IAI1C,UAAU,CAAC;AAAA,IACX,gBAAgB,KAAK;AAAA,EACvB;AACA,MAAI,OAAO,YAAa,aAAY,cAAc,OAAO;AACzD,MAAI,OAAO,SAAS,OAAQ,aAAY,kBAAkB,OAAO;AACjE,MAAI,OAAO,QAAQ,OAAQ,aAAY,iBAAiB,OAAO;AAC/D,MAAI,OAAO,MAAM,OAAQ,aAAY,OAAO,OAAO;AACnD,MAAI,OAAO,SAAS,OAAQ,aAAY,UAAU,OAAO;AACzD,MAAI,OAAO,WAAY,aAAY,qBAAqB;AACxD,MAAI,OAAO,YAAa,aAAY,sBAAsB,OAAO;AACjE,MAAI,OAAO,WAAY,aAAY,qBAAqB,OAAO;AAC/D,MAAI,OAAO,MAAO,aAAY,gBAAgB,OAAO;AACrD,MAAI,OAAO,YAAY;AACrB,gBAAY,qBAAqB,OAAO;AAK1C,QAAM,WAAW,OAAO,OAAO;AAAA,IAC7B,CAACC,UAASA,MAAK,WAAW,GAAG,IAAI,IAAI,OAAO,IAAI;AAAA,EAClD;AACA,MAAI,UAAU;AACZ,UAAM,IAAI;AAAA,MACR,OAAO,IAAI,IAAI,OAAO,IAAI,WAAW,SAAS,GAAG;AAAA,IACnD;AAAA,EACF;AACA,MAAI,OAAO,OAAO,OAAQ,aAAY,gBAAgB,OAAO;AAE7D,QAAM,SAAmB,CAAC;AAC1B,aAAW,WAAW,KAAK,UAAU;AACnC,UAAM,OAAO,SAAS,OAAO;AAG7B,QAAI,KAAM,QAAO,KAAK,MAAM,OAAO;AAAA;AAAA,EAAO,IAAI,EAAE;AAAA,EAClD;AACA,MAAI,CAAC,OAAO,OAAQ,QAAO,KAAK,OAAO,GAAG;AAE1C,aAAW,WAAW,OAAO,qBAAqB,CAAC,GAAG;AACpD,WAAO,KAAK,eAAe,OAAO,KAAK,OAAO,OAAO;AAAA,EACvD;AAOA,aAAWA,SAAQ,OAAO,SAAS,CAAC,GAAG;AACrC,WAAO;AAAA,MACL,GAAG,UAAUA,MAAK,GAAG,EAAE,MAAM,KAAKA,MAAK,MAAM,KAAKA,MAAK,MAAM;AAAA,IAC/D;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,QAAQ;AAC1B,WAAO;AAAA,MACL,OAAO,QACJ,IAAI,CAAC,WAAW,KAAK,OAAO,EAAE,MAAM,OAAO,SAAS,OAAO,QAAQ,EAAE,EACrE,KAAK,IAAI;AAAA,IACd;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,MAAM,OAAO;AAAA,IACb;AAAA,IACA,MAAM,GAAG,OAAO,KAAK,MAAM,CAAC;AAAA;AAAA,EAC9B;AACF;;;ADnLO,IAAM,gBAAgB;AAWtB,IAAM,mBAAmB;AAQzB,IAAM,sBAAsB,mBAChC,KAAK,EAAE,UAAU,KAAK,CAAC,EACvB,OAAO;AAAA,EACN,aAAa,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACxC,QAAQ,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACrC,CAAC,EACA,OAAO;AAIH,SAAS,sBACd,OACA,WACA,WACgB;AAChB,QAAM,EAAE,aAAa,QAAAC,SAAQ,GAAG,KAAK,IAAI;AACzC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,UAAU;AAAA,QACR,UAAU,MAAM;AAAA,QAChB,WAAW,MAAM;AAAA,QACjB,GAAI,cAAc,EAAE,UAAU,YAAY,IAAI,CAAC;AAAA,QAC/C,GAAIA,UAAS,EAAE,QAAQA,QAAO,IAAI,CAAC;AAAA,MACrC;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAGO,SAAS,wBACd,QACA,WACA,WACgB;AAChB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,MACL,UAAU,EAAE,UAAU,OAAO;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AItFA,IAAAC,cAAkB;;;ACQX,IAAM,yBAAyB;AAQtC,eAAsB,SACpB,OACA,OACA,IACc;AACd,MAAI,CAAC,OAAO,UAAU,KAAK,KAAK,QAAQ,GAAG;AACzC,UAAM,IAAI;AAAA,MACR,qDAAqD,KAAK;AAAA,IAC5D;AAAA,EACF;AACA,QAAM,MAAM,IAAI,MAAS,MAAM,MAAM;AACrC,MAAI,OAAO;AACX,MAAI,SAAS;AACb,QAAM,UAAU,MAAM;AAAA,IACpB,EAAE,QAAQ,KAAK,IAAI,OAAO,MAAM,MAAM,EAAE;AAAA,IACxC,YAAY;AACV,aAAO,CAAC,UAAU,OAAO,MAAM,QAAQ;AACrC,cAAMC,MAAK;AACX,YAAI;AACF,cAAIA,GAAE,IAAI,MAAM,GAAG,MAAMA,GAAE,GAAQA,GAAE;AAAA,QACvC,SAAS,OAAO;AACd,mBAAS;AACT,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,QAAM,QAAQ,IAAI,OAAO;AACzB,SAAO;AACT;;;AC7CA,qBAAwB;AACxB,uBAAqB;;;ACDrB,gCAAyB;AACzB,uBAA0B;AAG1B,IAAM,oBAAgB,4BAAU,kCAAQ;AAajC,SAAS,iBAAiB,OAAuB;AACtD,MAAI,MAAM,MAAM,KAAK,EAAE,QAAQ,UAAU,EAAE;AAE3C,QAAM,MAAM,2BAA2B,KAAK,GAAG;AAC/C,MAAI,IAAK,OAAM,WAAW,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AAC1C,QAAM,IAAI,QAAQ,yBAAyB,UAAU;AAIrD,QAAM,oBAAoB,GAAG;AAC7B,MAAI,IAAI,SAAS,MAAM,EAAG,OAAM,IAAI,MAAM,GAAG,EAAE;AAC/C,SAAO,oBAAoB,GAAG,EAAE,YAAY;AAC9C;AAEA,SAAS,oBAAoB,OAAuB;AAClD,MAAI,MAAM,MAAM;AAChB,SAAO,MAAM,KAAK,MAAM,MAAM,CAAC,MAAM,IAAK,QAAO;AACjD,SAAO,MAAM,MAAM,GAAG,GAAG;AAC3B;AAQO,SAAS,mBAAmB,OAAwB;AACzD,SAAO,qBAAqB,KAAK,iBAAiB,KAAK,CAAC;AAC1D;AAGA,SAAS,SAAS,YAA4B;AAC5C,QAAM,gBAAgB,WAAW,QAAQ,sBAAsB,EAAE;AACjE,QAAM,WAAW,cAAc,MAAM,GAAG,EAAE,OAAO,OAAO;AACxD,SAAO,SAAS,SAAS,IAAI,SAAS,MAAM,CAAC,EAAE,KAAK,GAAG,IAAI;AAC7D;AAWO,SAAS,eACd,UACA,WACS;AACT,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,SAAS,iBAAiB,SAAS;AACzC,QAAM,OAAO,iBAAiB,QAAQ;AACtC,MAAI,CAAC,QAAQ,CAAC,OAAQ,QAAO;AAC7B,MAAI,SAAS,OAAQ,QAAO;AAE5B,QAAM,OAAO,SAAS,MAAM;AAC5B,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,SAAS,QAAQ,UAAU,KAAK,MAAM,GAAG,EAAE,IAAI,KAAK;AAC7D;AAWA,eAAsB,cAAc,UAA0C;AAC5E,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM;AAAA,MACvB;AAAA,MACA,CAAC,MAAM,UAAU,UAAU,SAAS,mBAAmB;AAAA,MACvD,EAAE,SAAS,IAAM;AAAA,IACnB;AACA,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,IAAM,aAAN,MAAiB;AAAA,EAItB,YAA6B,UAAkB;AAAlB;AAAA,EAAmB;AAAA,EAAnB;AAAA,EAHrB,MAAqB;AAAA,EACrB,QAAQ;AAAA;AAAA,EAKhB,MAAM,QAAuB;AAC3B,QAAI,KAAK,MAAO;AAChB,SAAK,MAAM,MAAM,cAAc,KAAK,QAAQ;AAC5C,SAAK,QAAQ;AAAA,EACf;AAAA;AAAA,EAGA,UAAU,QAA2B;AACnC,QAAI,CAAC,OAAO,KAAM,QAAO;AACzB,WAAO,CAAC,eAAe,OAAO,MAAM,KAAK,GAAG;AAAA,EAC9C;AAAA,EAEA,MAAM,QAAQ,QAAoC;AAChD,QAAI,CAAC,OAAO,KAAM,QAAO;AACzB,UAAM,KAAK,MAAM;AACjB,WAAO,KAAK,UAAU,MAAM;AAAA,EAC9B;AACF;;;AD3HO,SAAS,aAAa,UAA2B;AACtD,SACE,YACA,QAAQ,IAAI,uBAAuB,SACnC,2BAAK,wBAAQ,GAAG,YAAY,YAAY;AAE5C;AAGO,IAAM,2BAA2B;AAEjC,SAAS,eAAe,UAA2B;AACxD,MAAI,aAAa,OAAW,QAAO;AACnC,QAAM,UAAU,OAAO,QAAQ,IAAI,6BAA6B,CAAC;AACjE,SAAO,OAAO,SAAS,OAAO,KAAK,UAAU,IACzC,UACA;AACN;AAQO,SAAS,aAAa,MAAc,UAAiC;AAC1E,QAAM,aAAa,iBAAiB,IAAI;AACxC,QAAM,SAAS,qBAAqB,KAAK,UAAU;AACnD,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,WAAW,WACd,MAAM,OAAO,CAAC,EAAE,MAAM,EACtB,MAAM,GAAG,EACT,OAAO,OAAO,EACd,IAAI,CAAC,YAAoB,YAAY,OAAO,CAAC;AAChD,MAAI,SAAS,SAAS,KAAK,SAAS,KAAK,CAAC,YAAY,YAAY,IAAI,GAAG;AACvE,WAAO;AAAA,EACT;AACA,QAAM,OAAO;AACb,aAAO,uBAAK,UAAU,GAAG,KAAK,MAAM,GAAG,EAAE,GAAG,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,MAAM;AAC5E;AAQA,SAAS,YAAY,OAA8B;AACjD,SAAO,UAAU,OAAO,UAAU,QAAQ,MAAM,SAAS,IAAI,IACzD,OACA,MAAM,QAAQ,WAAW,GAAG;AAClC;AAMO,SAAS,OAAO,KAAqB;AAE1C,QAAM,OAAO,IAAI,QAAQ,mBAAmB,GAAG,EAAE,MAAM,GAAG,EAAE;AAC5D,MAAI,OAAO;AACX,WAASC,MAAK,GAAGA,MAAK,IAAI,QAAQA,OAAM;AACtC,YAAS,OAAO,KAAM,IAAI,WAAWA,GAAE,OAAO;AAAA,EAChD;AACA,SAAO,gBAAgB,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;AAClD;;;AE9CO,IAAM,oBAAuD;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,kBACd,QACS;AACT,SACE,WAAW,UACX,kBAAkB,SAAS,MAAgC;AAE/D;AAGO,SAAS,QACd,MACA,KACA,MACQ;AACR,SAAO,GAAG,IAAI,KAAS,OAAO,EAAE,KAAS,IAAI;AAC/C;;;AC9CA,sBAAsB;;;ACAtB,IAAAC,6BAAyB;AACzB,IAAAC,oBAA0B;;;ACkGnB,IAAM,wBAAwB;;;AD5FrC,IAAMC,qBAAgB,6BAAU,mCAAQ;AAmBxC,SAAS,WAA8B;AACrC,QAAM,MAAyB,EAAE,GAAG,QAAQ,KAAK,qBAAqB,IAAI;AAC1E,aAAW,QAAQ,CAAC,WAAW,iBAAiB,gBAAgB,GAAG;AACjE,WAAO,IAAI,IAAI;AAAA,EACjB;AACA,SAAO;AACT;AAMA,eAAsB,IACpB,MACA,UAAmE,CAAC,GACnD;AACjB,MAAI;AACF,UAAM,EAAE,QAAQ,OAAO,IAAI,MAAMA,eAAc,OAAO,MAAM;AAAA,MAC1D,GAAI,QAAQ,MAAM,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC;AAAA,MAC1C,SAAS,QAAQ,aAAa;AAAA,MAC9B,WAAW,QAAQ,YAAY;AAAA,MAC/B,UAAU;AAAA,MACV,aAAa;AAAA,MACb,KAAK,SAAS;AAAA,IAChB,CAAC;AACD,WAAO,EAAE,IAAI,MAAM,QAAQ,QAAQ,YAAY,MAAM;AAAA,EACvD,SAAS,OAAO;AACd,UAAM,UAAU;AAKhB,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,QAAQ,QAAQ,UAAU;AAAA,MAC1B,QAAQ,QAAQ,UAAU;AAAA,MAC1B,YAAY,QAAQ,SAAS;AAAA,IAC/B;AAAA,EACF;AACF;AAOO,SAAS,gBAAgB,QAAwC;AACtE,QAAM,OAAO,OAAO,YAAY;AAChC,MACE,KAAK,SAAS,uBAAuB,KACrC,KAAK,SAAS,mBAAmB,KACjC,KAAK,SAAS,yBAAyB,KACvC,KAAK,SAAS,eAAe,KAC7B,KAAK,SAAS,eAAe,GAC7B;AACA,WAAO;AAAA,EACT;AACA,MACE,KAAK,SAAS,0BAA0B,KACxC,KAAK,SAAS,qBAAqB,KACnC,KAAK,SAAS,aAAa,GAC3B;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;;;AE9EA,IAAM,iBAAiB;AAOvB,IAAM,YAAY;AAGX,SAAS,eAAe,KAAsB;AACnD,MAAI,CAAC,OAAO,IAAI,SAAS,eAAgB,QAAO;AAEhD,MAAI,IAAI,SAAS,IAAI,EAAG,QAAO;AAC/B,SAAO,UAAU,KAAK,GAAG;AAC3B;AAMA,eAAsB,gBAAgB,KAA+B;AACnE,MAAI,CAAC,eAAe,GAAG,EAAG,QAAO;AACjC,QAAM,UAAU,MAAM,IAAI,CAAC,oBAAoB,oBAAoB,GAAG,CAAC;AACvE,SAAO,QAAQ;AACjB;AAMO,SAAS,eAAe,MAAuB;AACpD,QAAM,OAAO,KAAK,QAAQ,SAAS,EAAE;AACrC,MAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,KAAK,KAAK,SAAS,IAAI,EAAG,QAAO;AACjE,SAAO,CAAC,KAAK,MAAM,GAAG,EAAE,SAAS,IAAI;AACvC;AAGA,IAAM,oBAAoB,CAAC,SAAS,OAAO,KAAK;AAOzC,SAAS,mBAA6B;AAC3C,QAAM,MAAM,QAAQ,IAAI,2BAA2B;AACnD,MAAI,QAAQ,OAAW,QAAO,CAAC,GAAG,iBAAiB;AACnD,QAAM,SAAS,IACZ,MAAM,GAAG,EACT,IAAI,CAAC,UAAU,MAAM,KAAK,EAAE,YAAY,CAAC,EACzC,OAAO,OAAO;AACjB,SAAO,OAAO,SAAS,SAAS,CAAC,GAAG,iBAAiB;AACvD;AAOO,SAAS,gBAAgB,MAAuB;AACrD,SAAO,0CAA0C,KAAK,KAAK,KAAK,CAAC;AACnE;AAGA,IAAM,WAAW;AAEjB,IAAM,aAAa;AAGnB,IAAM,gBAAgB;AAGf,SAAS,cAAc,MAAuB;AACnD,QAAM,MAAM,KAAK,KAAK;AACtB,MAAI,CAAC,OAAO,IAAI,WAAW,GAAG,KAAK,cAAc,KAAK,GAAG,EAAG,QAAO;AAEnE,QAAM,UAAU,iBAAiB;AACjC,MAAI,SAAS,KAAK,GAAG,EAAG,QAAO,QAAQ,SAAS,KAAK;AAErD,QAAM,SAAS,WAAW,KAAK,GAAG;AAElC,MAAI,CAAC,SAAS,CAAC,EAAG,QAAO;AACzB,MAAI,CAAC,QAAQ,SAAS,OAAO,CAAC,EAAE,YAAY,CAAC,EAAG,QAAO;AAIvD,QAAM,YAAY,IAAI,MAAM,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,GAAG,EAAE,CAAC,KAAK;AAC/D,QAAMC,MAAK,UAAU,YAAY,GAAG;AACpC,SAAOA,MAAK,KAAK,CAAC,UAAU,MAAM,GAAGA,GAAE,EAAE,SAAS,GAAG;AACvD;AAMO,SAAS,eAAyB;AACvC,QAAM,UAAU,iBAAiB;AACjC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,uBAAuB,QAAQ,SAAS,MAAM,IAAI,SAAS,OAAO;AAAA,EACpE;AACF;;;AH/FA,IAAM,2BAA2B;AAGjC,IAAM,gBAAgB;AAStB,eAAsB,kBACpB,OACA,UAAyB,CAAC,GACQ;AAClC,QAAM,MAAM,oBAAI,IAAwB;AACxC,MAAI,CAAC,MAAM,OAAQ,QAAO;AAE1B,QAAM,WAAW,aAAa,QAAQ,QAAQ;AAC9C,QAAM,YAAY,eAAe,QAAQ,cAAc;AACvD,QAAM,SAAS,oBAAI,IAAkD;AACrE,aAAW,QAAQ,OAAO;AACxB,UAAM,MAAM,iBAAiB,KAAK,IAAI;AACtC,UAAMC,SAAQ,OAAO,IAAI,GAAG,KAAK,EAAE,KAAK,KAAK,KAAK,KAAK,GAAG,OAAO,CAAC,EAAE;AACpE,IAAAA,OAAM,MAAM,KAAK,IAAI;AACrB,WAAO,IAAI,KAAKA,MAAK;AAAA,EACvB;AAEA,QAAM,SAAS,CAAC,GAAG,OAAO,QAAQ,CAAC;AACnC,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,IACA,KAAK,IAAI,GAAG,QAAQ,eAAe,wBAAwB;AAAA,IAC3D,CAAC,CAAC,MAAMA,MAAK,MACX,YAAY,MAAMA,OAAM,KAAKA,OAAM,OAAO;AAAA,MACxC;AAAA,MACA;AAAA,MACA,SAAS,QAAQ,YAAY;AAAA,IAC/B,CAAC;AAAA,EACL;AACA,aAAW,UAAU,SAAS;AAC5B,eAAW,CAAC,KAAK,IAAI,KAAK,OAAQ,KAAI,IAAI,KAAK,IAAI;AAAA,EACrD;AACA,SAAO;AACT;AAIA,eAAe,YACb,MACA,KACA,UACA,SACkC;AAClC,MAAI,QAA+B;AACnC,QAAM,MAAM,CAAC,SACX,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,MAAM,KAAK,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC,CAAC;AAIzE,MAAI,gBAAgB,GAAG,GAAG;AACxB,WAAO,IAAI,EAAE,IAAI,OAAO,QAAQ,qBAAqB,CAAC;AAAA,EACxD;AAGA,MAAI,CAAC,cAAc,GAAG,EAAG,QAAO,IAAI,EAAE,IAAI,OAAO,QAAQ,eAAe,CAAC;AAEzE,QAAM,QAAQ,aAAa,MAAM,QAAQ,QAAQ;AACjD,MAAI,CAAC,MAAO,QAAO,IAAI,EAAE,IAAI,OAAO,QAAQ,qBAAqB,CAAC;AAIlE,QAAMC,YAAW,oBAAI,IAAwB;AAC7C,QAAM,SAAuB,CAAC;AAC9B,aAAW,QAAQ,OAAO;AACxB,UAAM,SAAS,WAAW,IAAI;AAC9B,QAAI;AACF,MAAAA,UAAS,IAAI,QAAQ,MAAM,KAAK,KAAK,KAAK,IAAI,GAAG,EAAE,IAAI,OAAO,OAAO,CAAC;AAAA,QACnE,QAAO,KAAK,IAAI;AAAA,EACvB;AACA,MAAI,CAAC,OAAO,OAAQ,QAAOA;AAC3B,UAAQ;AAER,QAAM,SAAS,MAAM,UAAU,OAAO,KAAK,OAAO;AAClD,MAAI,OAAQ,QAAO,IAAI,IAAI,CAAC,GAAGA,WAAU,GAAG,IAAI,MAAM,CAAC,CAAC;AAExD,QAAM,eAAe,MAAM,KAAK,CAAC,SAAS,KAAK,QAAQ,MAAS;AAChE,QAAM,SAAiB,eACnB,MAAM,cAAc,OAAO,OAAO,IAClC,CAAC;AAIL,QAAM,OAAO,oBAAI,IAAoC;AACrD,aAAW,OAAO,aAAa,OAAO,OAAO,IAAI,GAAG;AAClD,SAAK;AAAA,MACH;AAAA,MACC,MAAM,gBAAgB,GAAG,IACtB,MAAM,UAAU,OAAO,KAAK,OAAO,IACnC,EAAE,IAAI,OAAO,QAAQ,cAAc;AAAA,IACzC;AAAA,EACF;AAEA,QAAM,QAAQ,MAAM;AAAA,IAClB;AAAA,IACA;AAAA,IACA,OAAO,SAA8B;AACnC,YAAM,MAAM,KAAK,OAAO,OAAO;AAC/B,UAAI,QAAQ,QAAW;AACrB,eAAO;AAAA,UACL,IAAI;AAAA,UACJ,QAAQ,OAAO,UAAU;AAAA,QAC3B;AAAA,MACF;AACA,YAAM,SAAS,KAAK,IAAI,GAAG;AAC3B,UAAI,OAAQ,QAAO;AACnB,aAAO,SAAS,OAAO,KAAK,KAAK,MAAM,OAAO;AAAA,IAChD;AAAA,EACF;AACA,SAAO,IAAI,IAAI;AAAA,IACb,GAAGA;AAAA,IACH,GAAG,MAAM;AAAA,MACP,CAAC,MAAMC,QACL,CAAC,QAAQ,MAAM,KAAK,KAAK,KAAK,IAAI,GAAG,MAAMA,GAAE,CAAe;AAAA,IAChE;AAAA,EACF,CAAC;AACH;AAQA,SAAS,WAAW,MAAsD;AACxE,MAAI,KAAK,QAAQ,UAAa,CAAC,eAAe,KAAK,GAAG,EAAG,QAAO;AAChE,SAAO,eAAe,KAAK,IAAI,IAAI,SAAY;AACjD;AAEA,SAAS,aACP,OACA,QACU;AACV,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,QAAQ,OAAW,MAAK,IAAI,KAAK,GAAG;AAAA,aACpC,OAAQ,MAAK,IAAI,MAAM;AAAA,EAClC;AACA,SAAO,CAAC,GAAG,IAAI;AACjB;AAGA,eAAe,UACb,OACA,KACA,SACiC;AACjC,MAAI;AACF,cAAM,uBAAM,OAAO,EAAE,WAAW,KAAK,CAAC;AAAA,EACxC,QAAQ;AACN,WAAO,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAAA,EACnD;AACA,QAAM,OAAO,MAAM,IAAI,CAAC,QAAQ,UAAU,WAAW,KAAK,GAAG;AAAA,IAC3D,WAAW,QAAQ;AAAA,EACrB,CAAC;AACD,MAAI,CAAC,KAAK,GAAI,QAAO,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAK/D,QAAM,SAAS,MAAM,IAAI,CAAC,UAAU,qBAAqB,GAAG,GAAG;AAAA,IAC7D,KAAK;AAAA,IACL,WAAW,QAAQ;AAAA,EACrB,CAAC;AACD,SAAO,OAAO,KAAK,SAAY,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAC3E;AAQA,eAAe,cACb,OACA,SACiB;AACjB,MAAI,CAAC,QAAQ,SAAS;AACpB,UAAM,SAAS,MAAM;AAAA,MACnB,CAAC,GAAG,aAAa,GAAG,aAAa,YAAY,UAAU,MAAM;AAAA,MAC7D;AAAA,QACE,KAAK;AAAA,QACL,WAAW,QAAQ;AAAA,MACrB;AAAA,IACF;AACA,UAAM,QAAQ,sCAAsC,KAAK,OAAO,MAAM;AACtE,QAAI,OAAO,MAAM,QAAQ,CAAC,GAAG;AAC3B,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,IAAI,CAAC,UAAU,yBAAyB,IAAI,GAAG,EAAE,KAAK,MAAM,CAAC;AACnE,aAAO,EAAE,KAAK;AAAA,IAChB;AACA,QAAI,CAAC,OAAO,IAAI;AACd,YAAM,SAAS,gBAAgB,OAAO,MAAM;AAC5C,UAAI,WAAW,iBAAiB;AAC9B,cAAMC,UAAS,MAAM,aAAa,KAAK;AACvC,eAAOA,UAAS,EAAE,MAAMA,QAAO,IAAI,EAAE,OAAO;AAAA,MAC9C;AAAA,IACF;AAAA,EACF;AACA,QAAMA,UAAS,MAAM,aAAa,KAAK;AACvC,MAAIA,QAAQ,QAAO,EAAE,MAAMA,QAAO;AAGlC,SAAO;AAAA,IACL,QAAQ,QAAQ,UAAU,uBAAuB;AAAA,EACnD;AACF;AAEA,eAAe,aAAa,OAA4C;AACtE,QAAM,SAAS,MAAM,IAAI,CAAC,UAAU,SAAS,uBAAuB,GAAG;AAAA,IACrE,KAAK;AAAA,EACP,CAAC;AACD,MAAI,OAAO,MAAM,OAAO,OAAO,KAAK,EAAG,QAAO,OAAO,OAAO,KAAK;AACjE,QAAM,OAAO,MAAM;AAAA,IACjB,CAAC,gBAAgB,WAAW,0BAA0B;AAAA,IACtD;AAAA,MACE,KAAK;AAAA,IACP;AAAA,EACF;AACA,QAAM,OAAO,KAAK,OAAO,KAAK,EAAE,QAAQ,aAAa,EAAE;AACvD,SAAO,KAAK,MAAM,OAAO,OAAO;AAClC;AASA,eAAe,UACb,OACA,KACA,SACiC;AACjC,QAAM,MAAM,OAAO,GAAG;AACtB,QAAM,OAAO,MAAM;AAAA,IACjB,CAAC,aAAa,YAAY,WAAW,GAAG,GAAG,WAAW;AAAA,IACtD;AAAA,MACE,KAAK;AAAA,IACP;AAAA,EACF;AACA,QAAMA,UAAS,KAAK,MAAM,KAAK,OAAO,KAAK,EAAE,SAAS;AACtD,MAAIA,YAAW,QAAQ,WAAW,cAAc,KAAK,GAAG,GAAI,QAAO;AACnE,MAAI,QAAQ,QAAS,QAAO,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAKtE,QAAM,UAAU,MAAM;AAAA,IACpB;AAAA,MACE,GAAG,aAAa;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,EAAE,KAAK,OAAO,WAAW,QAAQ,UAAU;AAAA,EAC7C;AACA,MAAI,CAAC,QAAQ,IAAI;AAGf,UAAM,SAAS,gBAAgB,QAAQ,MAAM;AAC7C,QAAIA,WAAU,WAAW,gBAAiB,QAAO;AACjD,WAAO,EAAE,IAAI,OAAO,OAAO;AAAA,EAC7B;AACA,QAAM,OAAO,MAAM,IAAI,CAAC,aAAa,YAAY,GAAG,EAAE,KAAK,MAAM,CAAC;AAClE,QAAM,MAAM,KAAK,OAAO,KAAK;AAC7B,MAAI,CAAC,KAAK,MAAM,CAAC,IAAK,QAAO,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AACvE,QAAM,UAAU,MAAM,IAAI,CAAC,cAAc,KAAK,GAAG,GAAG,EAAE,KAAK,MAAM,CAAC;AAClE,SAAO,QAAQ,KAAK,SAAY,EAAE,IAAI,OAAO,QAAQ,qBAAqB;AAC5E;AAGA,eAAe,SACb,OACA,KACA,MACA,SACqB;AACrB,QAAM,OAAO,KAAK,QAAQ,SAAS,EAAE;AACrC,QAAM,OAAO,MAAM;AAAA,IACjB,CAAC,YAAY,QAAQ,oBAAoB,GAAG,OAAO,GAAG,CAAC,IAAI,IAAI,EAAE;AAAA,IACjE;AAAA,MACE,KAAK;AAAA,MACL,WAAW,QAAQ;AAAA,IACrB;AAAA,EACF;AACA,MAAI,KAAK,GAAI,QAAO,EAAE,IAAI,MAAM,QAAQ,KAAK,OAAO;AACpD,MAAI,KAAK,WAAY,QAAO,EAAE,IAAI,OAAO,QAAQ,iBAAiB;AAClE,QAAM,OAAO,KAAK,OAAO,YAAY;AACrC,SAAO,KAAK,SAAS,gBAAgB,KAAK,KAAK,SAAS,oBAAoB,IACxE,EAAE,IAAI,OAAO,QAAQ,eAAe,IACpC,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAC7C;;;AIxUA,IAAAC,mBAAyC;AACzC,IAAAC,oBAAmD;AAkB5C,SAAS,eAAe,UAAkB,MAA6B;AAE5E,QAAM,WAAO,2BAAQ,UAAU,KAAK,QAAQ,SAAS,EAAE,CAAC;AACxD,QAAM,UAAM,gCAAS,2BAAQ,QAAQ,GAAG,IAAI;AAC5C,MACE,QAAQ,MACR,QAAQ,QACR,IAAI,WAAW,KAAK,qBAAG,EAAE,SACzB,8BAAW,GAAG,GACd;AACA,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,SAAS,MAAc,MAAuB;AACrD,QAAM,UAAM,4BAAS,MAAM,IAAI;AAC/B,SACE,QAAQ,MACR,QAAQ,QACR,CAAC,IAAI,WAAW,KAAK,qBAAG,EAAE,KAC1B,KAAC,8BAAW,GAAG;AAEnB;AAEA,SAAS,UAAU,OAAoC;AACrD,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,UAAU,QAC5D,OAAQ,MAA4B,IAAI,IACxC;AACN;AAGO,SAAS,iBAAiB,UAAoC;AACnE,MAAI;AACJ,QAAM,WAAW,MAAuB;AACtC,qBAAa,+BAAS,2BAAQ,QAAQ,CAAC,EAAE,MAAM,CAAC,UAAmB;AAKjE,iBAAW;AACX,YAAM;AAAA,IACR,CAAC;AACD,WAAO;AAAA,EACT;AACA,SAAO,CAAC,SAAS,uBAAuB,UAAU,MAAM,QAAQ;AAClE;AAiBA,eAAe,uBACb,UACA,MACA,UACqB;AACrB,QAAM,UAAU,eAAe,UAAU,IAAI;AAC7C,MAAI,YAAY,KAAM,QAAO,EAAE,IAAI,OAAO,QAAQ,eAAe;AAEjE,MAAI;AACJ,MAAI;AACJ,MAAI;AACF,WAAO,MAAM,SAAS;AACtB,WAAO,UAAM,2BAAS,OAAO;AAAA,EAC/B,SAAS,OAAO;AACd,UAAM,OAAO,UAAU,KAAK;AAC5B,QAAI,SAAS,YAAY,SAAS,WAAW;AAC3C,aAAO,EAAE,IAAI,OAAO,QAAQ,eAAe;AAAA,IAC7C;AACA,WAAO,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAAA,EAChD;AACA,MAAI,CAAC,SAAS,MAAM,IAAI,EAAG,QAAO,EAAE,IAAI,OAAO,QAAQ,eAAe;AAEtE,MAAI;AACF,UAAM,QAAQ,UAAM,uBAAK,IAAI;AAC7B,QAAI,CAAC,MAAM,OAAO,EAAG,QAAO,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAGnE,QAAI,MAAM,OAAO,uBAAuB;AACtC,aAAO,EAAE,IAAI,OAAO,QAAQ,iBAAiB;AAAA,IAC/C;AACA,WAAO,EAAE,IAAI,MAAM,QAAQ,UAAM,2BAAS,MAAM,MAAM,EAAE;AAAA,EAC1D,SAAS,OAAO;AACd,UAAM,OAAO,UAAU,KAAK;AAC5B,QAAI,SAAS,YAAY,SAAS,WAAW;AAC3C,aAAO,EAAE,IAAI,OAAO,QAAQ,eAAe;AAAA,IAC7C;AACA,WAAO,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAAA,EAChD;AACF;AAWO,SAAS,uBACd,OACS;AACT,MAAI,UAAU;AACd,aAAW,WAAW,MAAM,OAAO,GAAG;AACpC,eAAW,SAAS,SAAS;AAK3B,UAAI,MAAM,SAAS,OAAW;AAC9B,iBAAW;AACX,UAAI,MAAM,UAAU,gBAAgB,MAAM,WAAW,gBAAgB;AACnE,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACA,SAAO,UAAU;AACnB;AAOA,eAAsB,gBACpB,OACA,MACA,cAAsB,wBACY;AAClC,MAAI,CAAC,OAAO,UAAU,WAAW,KAAK,cAAc,GAAG;AACrD,UAAM,IAAI;AAAA,MACR,yEAAyE,WAAW;AAAA,IACtF;AAAA,EACF;AACA,QAAM,SAAS,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AACjC,QAAM,UAAU,MAAM,SAAS,QAAQ,aAAa,OAAO,SAAS;AAClE,QAAI;AACF,aAAO,MAAM,KAAK,IAAI;AAAA,IACxB,QAAQ;AACN,aAAO,EAAE,IAAI,OAAO,QAAQ,kBAAkB;AAAA,IAChD;AAAA,EACF,CAAC;AACD,SAAO,IAAI,IAAI,OAAO,IAAI,CAAC,MAAMC,QAAO,CAAC,MAAM,QAAQA,GAAE,CAAe,CAAC,CAAC;AAC5E;;;AC/KA,IAAAC,sBAA2B;;;ACA3B,IAAAC,oBAAwB;;;ACAxB,IAAAC,mBAAyB;;;ACAzB,yBAAwC;AACxC,IAAAC,mBAAuD;AACvD,IAAAC,kBAAwB;AACxB,IAAAC,oBAA8B;AAIvB,SAAS,kBAAkB,UAA2B;AAC3D,SACE,YACA,QAAQ,IAAI,yBAAyB,SACrC,4BAAK,yBAAQ,GAAG,YAAY,UAAU;AAE1C;AAOO,SAAS,iBACd,MACA,UACAC,SACA,YAA4B,QACpB;AACR,aAAO,wBAAK,MAAM,UAAU,GAAGA,QAAO,MAAM,GAAG,EAAE,CAAC,IAAI,SAAS,EAAE;AACnE;AAEO,SAAS,OAAO,OAA2B;AAChD,aAAO,+BAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK;AACxD;AAEO,SAAS,QAAQ,OAAmB,OAAwB;AACjE,MAAI,MAAM,UAAU,UAAa,MAAM,eAAe,MAAM;AAC1D,WAAO;AACT,SAAO,OAAO,KAAK,MAAM,MAAM;AACjC;AAOA,eAAsB,aACpB,MACA,OACkB;AAClB,MAAI;AACJ,MAAI;AACF,YAAQ,UAAM,2BAAS,IAAI;AAAA,EAC7B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,MAAI,QAAQ,OAAO,KAAK,EAAG,QAAO;AAClC,YAAM,qBAAG,MAAM,EAAE,OAAO,KAAK,CAAC;AAC9B,SAAO;AACT;AAMA,eAAsB,YACpB,MACA,OACe;AACf,YAAM,4BAAM,2BAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,QAAM,YAAY,GAAG,IAAI,IAAI,QAAQ,GAAG,QAAI,gCAAY,CAAC,EAAE,SAAS,KAAK,CAAC;AAC1E,MAAI;AACF,cAAM,4BAAU,WAAW,KAAK;AAChC,cAAM,yBAAO,WAAW,IAAI;AAAA,EAC9B,SAAS,OAAO;AACd,cAAM,qBAAG,WAAW,EAAE,OAAO,KAAK,CAAC;AACnC,UAAM;AAAA,EACR;AACF;;;ACvEA,IAAM,WAAW;AACjB,IAAM,aAAa;AAOZ,SAAS,WAAW,KAAa,UAA2B;AACjE,QAAMC,QAAO,gBAAgB,QAAQ;AACrC,MAAI,CAACA,MAAM,QAAO;AAClB,MAAI,OAAOA;AACX,SAAO,KAAK,SAAS,GAAG,EAAG,QAAO,KAAK,MAAM,GAAG,EAAE;AAClD,QAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,SAAO,GAAG,IAAI,GAAG,OAAO,QAAQ,GAAG,OAAO,MAAM;AAClD;AAEO,SAAS,gBAAgB,UAAuC;AACrE,SAAO,YAAY,QAAQ,IAAI,yBAAyB;AAC1D;AAWA,eAAsB,aACpB,KACA,MACA,OACA,UAA0B,CAAC,GACR;AACnB,QAAM,MACJ,QAAQ,QAAQ,CAAC,SAAiB,KAAK,QAAQ,OAAO,MAAM,IAAI;AAClE,QAAM,SACJ,MAAM,UAAU,SAAY,KAAK,KAAK,KAAK,MAAM,KAAK,CAAC;AACzD,MAAI,2BAA2B,IAAI,GAAG,MAAM,SAAS,GAAG;AAAA,CAAI;AAE5D,MAAI,QAAQ;AACZ,WAAS,UAAU,GAAG,WAAW,UAAU,WAAW;AACpD,UAAM,UAAU,MAAM,gBAAgB,KAAK,OAAO,QAAQ,cAAc;AACxE,QAAI,WAAW,QAAS,QAAO;AAC/B,YAAQ,QAAQ;AAChB;AAAA,MACE,eAAe,IAAI,YAAY,OAAO,IAAI,QAAQ,YAAY,KAAK;AAAA;AAAA,IACrE;AACA,QAAI,CAAC,QAAQ,MAAO;AACpB,QAAI,UAAU,SAAU,OAAM,MAAM,aAAa,OAAO;AAAA,EAC1D;AACA,MAAI,eAAe,IAAI,oBAAoB,KAAK;AAAA,CAAI;AACpD,SAAO,EAAE,MAAM;AACjB;AAEA,eAAe,gBACb,KACA,OACA,WACoE;AACpE,MAAI;AACF,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ,YAAY,QAAQ,eAAe,SAAS,CAAC;AAAA,IACvD,CAAC;AACD,QAAI,CAAC,SAAS,IAAI;AAChB,aAAO;AAAA,QACL,OAAO,QAAQ,SAAS,MAAM;AAAA,QAC9B,OAAO,SAAS,UAAU,OAAO,SAAS,WAAW;AAAA,MACvD;AAAA,IACF;AACA,UAAM,QAAQ,IAAI,WAAW,MAAM,SAAS,YAAY,CAAC;AACzD,QAAI,CAAC,QAAQ,OAAO,KAAK;AACvB,aAAO,EAAE,OAAO,mBAAmB,OAAO,MAAM;AAClD,WAAO,EAAE,MAAM;AAAA,EACjB,SAAS,OAAO;AACd,UAAM,WACJ,iBAAiB,UAChB,MAAM,SAAS,kBAAkB,MAAM,SAAS;AACnD,WAAO,EAAE,OAAO,WAAW,YAAY,iBAAiB,OAAO,KAAK;AAAA,EACtE;AACF;AAGA,SAAS,KAAK,OAAuB;AACnC,SAAO,SAAS,OAAO,OACnB,IAAI,SAAS,OAAO,OAAO,QAAQ,CAAC,CAAC,QACrC,GAAG,KAAK,MAAM,QAAQ,IAAI,CAAC;AACjC;AAEA,SAAS,MAAM,IAA2B;AACxC,SAAO,IAAI,QAAQ,CAACC,aAAY,WAAWA,UAAS,EAAE,CAAC;AACzD;;;AClGA,qBAAyC;AACzC,IAAAC,oBAA8B;AAC9B,sBAA8B;;;ACF9B,IAAAC,cAAkB;AAElB,IAAMC,UAAS,cAAE,OAAO,EAAE,MAAM,gBAAgB;AAOzC,IAAM,oBAAoB,cAAE,OAAO;AAAA,EACxC,KAAK,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACrB,QAAAA;AAAA,EACA,OAAO,cAAE,OAAO,EAAE,IAAI,EAAE,SAAS;AACnC,CAAC;AAMM,IAAM,oBAAoB,cAAE,OAAO,EAAE,KAAK,cAAE,OAAO,EAAE,IAAI,CAAC,GAAG,QAAAA,QAAO,CAAC;AAOrE,IAAM,oBAAoB,cAAE,OAAO;AAAA,EACxC,SAAS,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACzB,MAAM;AAAA,EACN,MAAM,cAAE,MAAM,iBAAiB;AAAA,EAC/B,SAAS,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACzB,YAAY,cAAE,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC;AACvC,CAAC;AAEM,IAAM,wBAAwB,cAAE,OAAO;AAAA;AAAA,EAE5C,eAAe,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC/B,UAAU,cAAE,OAAO,EAAE,KAAK,cAAE,OAAO,EAAE,IAAI,CAAC,GAAG,QAAQ,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,EACxE,OAAO,cAAE,OAAO,cAAE,OAAO,EAAE,IAAI,CAAC,GAAG,iBAAiB;AACtD,CAAC;;;ADlCD,IAAI;AAMG,SAAS,kBAAmC;AACjD,aAAW,sBAAsB;AAAA,IAC/B,KAAK,UAAM,6BAAa,iBAAiB,eAAe,GAAG,MAAM,CAAC;AAAA,EACpE;AACA,SAAO;AACT;AAiBO,SAAS,oBAAoB,UAA4B;AAC9D,MAAI,UAAM,+BAAQ,+BAAc,aAAe,CAAC;AAChD,WAAS,KAAK,GAAG,KAAK,GAAG,MAAM;AAC7B,UAAM,gBAAY,wBAAK,KAAK,UAAU;AACtC,YAAI,+BAAW,wBAAK,WAAW,eAAe,CAAC;AAC7C,iBAAO,wBAAK,WAAW,GAAG,QAAQ;AACpC,cAAM,2BAAQ,GAAG;AAAA,EACnB;AACA,QAAM,IAAI,MAAM,oDAAoD;AACtE;;;AHfA,IAAM,WAAW,oBAAI,IAAqC;AAG1D,IAAM,UAAU,oBAAI,IAAiD;AAGrE,IAAM,eAAe,oBAAI,IAAoB;AAG7C,IAAM,WAAW,oBAAI,IAAoB;AAGlC,SAAS,2BAAoC;AAClD,SAAO,QAAQ,IAAI,qBAAqB,MAAM;AAChD;AAOA,eAAsB,cACpB,UACA,UAA0B,CAAC,GACF;AACzB,QAAMC,QAAO,gBAAgB,EAAE,MAAM,QAAQ;AAC7C,MAAI,CAACA,MAAM,QAAO;AAElB,QAAM,OAAO,kBAAkB,QAAQ,SAAS;AAChD,QAAM,OAAO,iBAAiB,MAAM,UAAUA,MAAK,KAAK,MAAM;AAG9D,QAAM,MAAM,GAAG,IAAI,IAAI,gBAAgB,QAAQ,OAAO,KAAK,EAAE;AAC7D,QAAM,WAAW,SAAS,IAAI,GAAG;AACjC,MAAI,SAAU,QAAO;AAErB,QAAM,WAAW,YAAY;AAC3B,UAAM,UAAU,MAAM;AAAA,MACpB;AAAA,MACA,eAAe,QAAQ;AAAA,MACvBA,MAAK;AAAA,MACL;AAAA,IACF;AACA,QAAI,YAAY;AACd,aAAO,KAAK,UAAU,uBAAuB,QAAQ,IAAI,OAAO;AAElE,UAAM,QAAkB,CAAC;AACzB,UAAM,QAAQA,MAAK,KAAK;AACxB,eAAW,CAACC,KAAI,IAAI,KAAKD,MAAK,KAAK,QAAQ,GAAG;AAC5C,YAAM,OAAO,GAAG,QAAQ,QAAQ,QAAQ,IAAI,SAASC,MAAK,CAAC,IAAI,KAAK,KAAK,EAAE;AAC3E,YAAM,OAAO,iBAAiB,MAAM,UAAU,KAAK,QAAQ,KAAK;AAChE,YAAM,OAAO,MAAM,WAAW,MAAM,MAAM,MAAM,OAAO;AACvD,UAAI,SAAS,KAAM,QAAO,KAAK,UAAU,MAAM,IAAI;AACnD,YAAM,KAAK,KAAK,KAAK,GAAG;AAAA,EAAK,GAAG,UAAM,2BAAS,MAAM,MAAM,CAAC,CAAC,EAAE;AAAA,IACjE;AAEA,YAAQ,OAAO,QAAQ;AACvB,WAAO,EAAE,MAAM,OAAO,QAAQ,MAAM,KAAK,IAAI,IAAI,OAAU;AAAA,EAC7D,GAAG;AACH,WAAS,IAAI,KAAK,OAAO;AACzB,QAAM,SAAS,MAAM;AACrB,MAAI,WAAW,KAAM,UAAS,OAAO,GAAG;AACxC,SAAO;AACT;AAGA,eAAe,WACb,MACA,MACA,OACA,SACoC;AACpC,MAAI,MAAM,aAAa,MAAM,KAAK,EAAG,QAAO;AAC5C,MAAI,QAAQ,YAAY,QAAQ,yBAAyB,EAAG,QAAO,CAAC;AACpE,QAAM,WAAW,MAAM;AAAA,IACrB,WAAW,MAAM,KAAK,QAAQ,OAAO;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,MAAI,WAAW,SAAU,QAAO,EAAE,OAAO,SAAS,MAAM;AACxD,QAAM,YAAY,MAAM,SAAS,KAAK,EAAE,MAAM,MAAM,IAAI;AACxD,SAAO;AACT;AAGA,SAAS,KACP,UACA,SACA,SACM;AACN,UAAQ,IAAI,UAAU,EAAE,SAAS,GAAG,QAAQ,CAAC;AAC7C,SAAO;AACT;AAGA,SAAS,GAAG,MAAsB;AAChC,SAAO,KAAK,QAAQ,SAAS,IAAI;AACnC;AAMO,SAAS,sBAAsB,UAAkB,OAAqB;AAC3E,eAAa,IAAI,UAAU,KAAK;AAClC;AAOO,SAAS,oBAAoB,UAAkB,OAAqB;AACzE,WAAS,IAAI,UAAU,KAAK;AAC9B;AAMO,SAAS,eAAyB;AACvC,QAAM,WAAW,gBAAgB;AACjC,QAAM,QAAQ,SAAS;AACvB,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,CAAC,UAAU,EAAE,SAAS,MAAM,CAAC,KAAK;AAC3C,UAAM;AAAA,MACJ;AAAA,MACA,GAAG,OAAO,cAAc,QAAQ,KAAK,KAAK,MAAM,EAAE;AAAA,IACpD;AACF,aAAW,CAAC,UAAU,KAAK,KAAK;AAC9B,UAAM;AAAA,MACJ;AAAA,MACA,GAAG,MAAM,QAAQ,GAAG,WAAW,eAAe,QAAQ,EAAE,gCAAgC,SAAS,aAAa,GAAG,QAAQ,KAAK,KAAK,KAAK,EAAE,mCAAmC,QAAQ;AAAA,IACvL;AACF,aAAW,CAAC,UAAU,KAAK,KAAK;AAC9B,UAAM;AAAA,MACJ;AAAA,MACA,kBAAkB,QAAQ,6BAA6B,MAAM,QAAQ,GAAG,WAAW,eAAe,QAAQ,EAAE,KAAK,KAAK,mCAAmC,QAAQ;AAAA,IACnK;AACF,SAAO,CAAC,GAAG,KAAK,EACb,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EACrC,IAAI,CAAC,CAAC,EAAE,IAAI,MAAM,IAAI;AAC3B;;;AD/JA,IAAI;AAGJ,SAAS,iBAAyC;AAChD,QAAM,WAAW,gBAAgB;AACjC,MAAI,OAAO,OAAO;AAChB,YAAQ;AAAA,MACN,IAAI;AAAA,MACJ,YAAY,OAAO;AAAA,QACjB,OAAO,QAAQ,SAAS,KAAK,EAAE;AAAA,UAAQ,CAAC,CAAC,UAAUC,KAAI,MACrDA,MAAK,WAAW,IAAI,CAAC,cAAc,CAAC,WAAW,QAAQ,CAAC;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AACF,SAAO,MAAM;AACf;AAGA,SAAS,SAAS,UAA2B;AAC3C,UAAQ,gBAAgB,EAAE,MAAM,QAAQ,GAAG,KAAK,UAAU,KAAK;AACjE;AAOO,SAAS,gBAAgB,MAAkC;AAChE,QAAM,WAAW,eAAe,MAAE,2BAAQ,IAAI,EAAE,YAAY,CAAC;AAC7D,SAAO,YAAY,SAAS,QAAQ,IAAI,WAAW;AACrD;;;AMzCA,IAAAC,sBAA2B;AAC3B,6BAAmD;;;ACQnD,IAAM,aAAa;AAuBZ,SAAS,MAAM,MAAY,OAA0B;AAC1D,QAAM,SAAS,oBAAI,IAAwB;AAE3C,aAAW,SAAS,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAChD,UAAM,WAAW,MAAM,SAAS,KAAK,CAAC,YAAY,QAAQ,SAAS,MAAM;AACzE,UAAM,UAAU,MAAM,SAAS;AAAA,MAC7B,CAAC,YACC,QAAQ,KAAK,WAAW,aAAa,KAAK,QAAQ,SAAS;AAAA,IAC/D;AACA,QAAI,CAAC,YAAY,CAAC,QAAS;AAE3B,UAAM,YAAwB;AAAA,MAC5B,MAAM,QAAQ;AAAA,MACd,MAAM,SAAS,KAAK;AAAA,MACpB,QAAQ,QAAQ,SAAS;AAAA,IAC3B;AACA,UAAM,WAAW,OAAO,IAAI,SAAS,KAAK,EAAE;AAC5C,QAAI,YAAY,MAAM,SAAS,IAAI,KAAK,MAAM,UAAU,IAAI,EAAG;AAC/D,WAAO,IAAI,SAAS,KAAK,IAAI,SAAS;AAAA,EACxC;AAEA,QAAM,cAAc,CAAC,GAAG,OAAO,OAAO,CAAC;AACvC,SAAO;AAAA,IACL;AAAA,IACA,UAAU,IAAI;AAAA,MACZ,YAAY,IAAI,CAAC,eAAe,CAAC,WAAW,KAAK,IAAI,UAAU,CAAC;AAAA,IAClE;AAAA,IACA;AAAA,EACF;AACF;AAOO,SAAS,OACd,QACA,QACc;AACd,QAAMC,WAAU,OAAO,YAAY;AAAA,IACjC,CAAC,eACC,WAAW,UACX,SAAS,QAAQ,YAAY,OAAO,QAAQ,GAAG,MAAM;AAAA,EACzD;AACA,MAAIA,SAAQ,SAAS,EAAG,QAAOA;AAC/B,QAAM,SAASA,SAAQ;AAAA,IACrB,CAAC,eAAe,WAAW,KAAK,kBAAkB,MAAM,MAAM;AAAA,EAChE;AACA,SAAO,OAAO,WAAW,IAAI,SAASA;AACxC;AASO,SAAS,QACd,YACA,UACU;AACV,QAAM,QAAQ,CAAC,WAAW,IAAI;AAE9B,QAAM,WAAW,WAAW,KAAK,kBAAkB,UAAU;AAC7D,QAAM,OAAO,YAAY,WAAW,QAAQ;AAC5C,MAAI,KAAM,OAAM,QAAQ,IAAI;AAE5B,WAAS,OAAO,WAAW,KAAK,QAAQ,MAAM,OAAO,KAAK,QAAQ;AAChE,UAAM,YAAY,SAAS,IAAI,KAAK,EAAE;AACtC,QAAI,aAAa,UAAU,SAAS,WAAW;AAC7C,YAAM,QAAQ,UAAU,IAAI;AAAA,EAChC;AACA,SAAO;AACT;AAGA,SAAS,WAAW,UAAoC;AACtD,QAAM,QAAgB,CAAC,QAAQ;AAC/B,SAAO,MAAM,QAAQ;AACnB,UAAM,OAAO,MAAM,IAAI;AACvB,QAAI,KAAK,SAAS,kBAAmB,QAAO,KAAK;AACjD,aAASC,MAAK,GAAGA,MAAK,KAAK,YAAYA,OAAM;AAC3C,YAAM,QAAQ,KAAK,MAAMA,GAAE;AAC3B,UAAI,MAAO,OAAM,KAAK,KAAK;AAAA,IAC7B;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,SAAS,OAAiB,QAAoC;AACrE,MAAI,OAAO,SAAS,MAAM,OAAQ,QAAO;AACzC,QAAM,SAAS,MAAM,SAAS,OAAO;AACrC,SAAO,OAAO,MAAM,CAAC,SAASA,QAAO,MAAM,SAASA,GAAE,MAAM,OAAO;AACrE;AAEA,SAAS,MAAM,MAAoB;AACjC,SAAO,KAAK,WAAW,KAAK;AAC9B;AAMO,SAAS,OAAO,YAAwB,QAAgC;AAC7E,MAAI,QAAQ,WAAW;AACvB,MAAI,MAAM,WAAW;AAErB,WACM,UAAU,MAAM,iBACpB,SAAS,SAAS,aAClB,UAAU,QAAQ,iBAClB;AACA,YAAQ;AAAA,EACV;AAEA,QAAM,SAAS,IAAI;AACnB,MACE,QAAQ,SAAS,sBACjB,OAAO,kBAAkB,aAAa,GAAG,OAAO,IAAI,IACpD;AACA,YAAQ;AACR,UAAM;AAAA,EACR;AAEA,QAAM,QAAQ,OAAO,MAAM,IAAI;AAC/B,QAAM,YAAY,MAAM,cAAc;AAEtC,QAAM,UACJ,IAAI,YAAY,WAAW,KAAK,IAAI,YAAY,MAAM,YAClD,IAAI,YAAY,MAAM,IACtB,IAAI,YAAY;AAEtB,SAAO;AAAA,IACL,MAAM,MAAM,MAAM,WAAW,UAAU,CAAC,EAAE,KAAK,IAAI;AAAA,IACnD,WAAW,YAAY;AAAA,IACvB,SAAS,UAAU;AAAA,EACrB;AACF;;;ACnKO,SAAS,OAAO,MAAsB;AAC3C,QAAM,MAAgB,CAAC;AACvB,QAAM,QAAgB,CAAC,IAAI;AAC3B,SAAO,MAAM,QAAQ;AACnB,UAAM,OAAO,MAAM,IAAI;AACvB,QAAI,KAAK,KAAK,SAAS,SAAS,EAAG;AACnC,QAAI,KAAK,eAAe,GAAG;AACzB,YAAM,OAAO,KAAK,KAAK,KAAK;AAC5B,UAAI,KAAM,KAAI,KAAK,IAAI;AACvB;AAAA,IACF;AACA,aAASC,MAAK,KAAK,aAAa,GAAGA,OAAM,GAAGA,OAAM;AAChD,YAAM,QAAQ,KAAK,MAAMA,GAAE;AAC3B,UAAI,MAAO,OAAM,KAAK,KAAK;AAAA,IAC7B;AAAA,EACF;AACA,SAAO;AACT;;;AFSA,IAAM,mBAAmB;AASlB,IAAM,qBAAN,MAAmD;AAAA,EAC/C,OAAO;AAAA,EAEC;AAAA,EACA,SAAS,oBAAI,IAA2B;AAAA,EACxC,QAAQ,oBAAI,IAAwB;AAAA,EAC7C;AAAA,EACA,cAAc;AAAA;AAAA,EAGb,QAAyB,EAAE,QAAQ,GAAG,WAAW,EAAE;AAAA,EAE5D,YAAY,UAA6B,CAAC,GAAG;AAC3C,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQ,OAAyC;AACrD,UAAM,SAAS,oBAAI,IAAY;AAC/B,eAAW,QAAQ,OAAO;AACxB,YAAM,WAAW,gBAAgB,IAAI;AACrC,UAAI,YAAY,CAAC,KAAK,OAAO,IAAI,QAAQ,EAAG,QAAO,IAAI,QAAQ;AAAA,IACjE;AACA,QAAI,CAAC,OAAO,KAAM;AAElB,QAAI,CAAC,KAAK,aAAa;AACrB,UAAI;AACF,cAAM,8BAAO,KAAK;AAClB,aAAK,SAAS,IAAI,8BAAO;AACzB,aAAK,cAAc;AAAA,MACrB,QAAQ;AACN,mBAAW,YAAY,OAAQ,MAAK,OAAO,IAAI,UAAU,IAAI;AAC7D;AAAA,MACF;AAAA,IACF;AAIA,UAAM,YAAY,CAAC,GAAG,MAAM;AAC5B,UAAM,SAAS,MAAM;AAAA,MACnB;AAAA,MACA,KAAK,IAAI,wBAAwB,UAAU,MAAM;AAAA,MACjD,CAAC,aAAa,KAAK,KAAK,QAAQ;AAAA,IAClC;AACA,cAAU;AAAA,MAAQ,CAAC,UAAUC,QAC3B,KAAK,OAAO,IAAI,UAAU,OAAOA,GAAE,KAAK,IAAI;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,KAAK,UAA0C;AAC3D,QAAIC;AACJ,QAAI;AACF,MAAAA,QAAO,MAAM,cAAc,UAAU,KAAK,QAAQ;AAAA,IACpD,QAAQ;AACN,aAAO;AAAA,IACT;AACA,QAAI,CAACA,OAAM,MAAO,QAAO;AAEzB,QAAI;AACJ,QAAI;AACF,gBAAU,MAAM,gCAAS,KAAKA,MAAK,IAAI;AAAA,IACzC,SAAS,OAAO;AACd,0BAAoB,UAAU,IAAI,KAAK,CAAC;AACxC,aAAO;AAAA,IACT;AACA,QAAI;AACF,aAAO,EAAE,UAAU,SAAS,OAAO,IAAI,6BAAM,SAASA,MAAK,KAAK,EAAE;AAAA,IACpE,SAAS,OAAO;AACd,4BAAsB,UAAU,IAAI,KAAK,CAAC;AAC1C,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAQ,QAAgB,QAAgB,MAAgC;AACtE,UAAM,WAAW,OAAO,gBAAgB,IAAI,IAAI;AAChD,QAAI,CAAC,SAAU,QAAO,EAAE,MAAM,UAAU;AACxC,QAAI,CAAC,KAAK,OAAO,IAAI,QAAQ,EAAG,QAAO,EAAE,MAAM,UAAU;AACzD,UAAM,SAAS,KAAK,OAAO,IAAI,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,cAAc,QAAQ,uBAAuB;AAEzE,UAAM,SAAS,KAAK,MAAM,UAAU,QAAQ,MAAM;AAClD,QAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,cAAc,QAAQ,uBAAuB;AAEzE,UAAM,SAAS,OAAO,MAAM,GAAG,EAAE,OAAO,OAAO;AAC/C,QAAI,CAAC,OAAO;AACV,aAAO,EAAE,MAAM,cAAc,QAAQ,mBAAmB;AAE1D,UAAMC,WAAU,OAAO,QAAQ,MAAM;AACrC,QAAI,CAACA,SAAQ;AACX,aAAO,EAAE,MAAM,cAAc,QAAQ,mBAAmB;AAC1D,QAAIA,SAAQ,SAAS;AACnB,aAAO,EAAE,MAAM,cAAc,QAAQ,mBAAmB;AAC1D,WAAO,EAAE,MAAM,YAAY,MAAM,OAAOA,SAAQ,CAAC,GAAiB,MAAM,EAAE;AAAA,EAC5E;AAAA,EAEA,QACE,QACA,QACA,MACuB;AACvB,UAAM,UAAU,KAAK,QAAQ,QAAQ,QAAQ,IAAI;AACjD,WAAO,QAAQ,SAAS,aAAa,QAAQ,OAAO;AAAA,EACtD;AAAA;AAAA,EAGQ,MACN,UACA,QACA,QACmB;AACnB,UAAM,MAAM,GAAG,QAAQ,QAAI,gCAAW,QAAQ,EAAE,OAAO,MAAM,EAAE,OAAO,KAAK,CAAC;AAC5E,UAAMC,UAAS,KAAK,MAAM,IAAI,GAAG;AACjC,QAAIA,SAAQ;AACV,WAAK,MAAM,aAAa;AACxB,aAAOA;AAAA,IACT;AAEA,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAQ,QAAO;AACpB,QAAI;AACJ,QAAI;AACF,aAAO,YAAY,OAAO,QAAQ;AAClC,YAAM,OAAO,OAAO,MAAM,MAAM;AAChC,UAAI,CAAC,KAAM,QAAO;AAClB,eAAS,MAAM,MAAM,OAAO,KAAK;AAAA,IACnC,QAAQ;AACN,aAAO;AAAA,IACT;AACA,SAAK,MAAM,UAAU;AAErB,QAAI,KAAK,MAAM,QAAQ,kBAAkB;AACvC,YAAM,SAAS,KAAK,MAAM,KAAK,EAAE,KAAK;AACtC,UAAI,CAAC,OAAO,MAAM;AAChB,aAAK,MAAM,IAAI,OAAO,KAAK,GAAG,KAAK,OAAO;AAC1C,aAAK,MAAM,OAAO,OAAO,KAAK;AAAA,MAChC;AAAA,IACF;AACA,SAAK,MAAM,IAAI,KAAK,MAAM;AAC1B,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MACE,QACA,MAC4C;AAC5C,UAAM,WAAW,gBAAgB,IAAI;AACrC,QAAI,CAAC,SAAU,QAAO,CAAC;AACvB,UAAM,SAAS,KAAK,OAAO,IAAI,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO,CAAC;AACrB,UAAM,SAAS,KAAK,MAAM,UAAU,QAAQ,MAAM;AAClD,QAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,WAAO,OAAO,YACX,OAAO,CAAC,eAAe,WAAW,MAAM,EACxC,IAAI,CAAC,gBAAgB;AAAA,MACpB,QAAQ,QAAQ,YAAY,OAAO,QAAQ,EAAE,KAAK,GAAG;AAAA,MACrD,MAAM,OAAO,YAAY,MAAM;AAAA,IACjC,EAAE;AAAA,EACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,UAAU,MAAc,MAA8B;AACpD,UAAM,WAAW,OAAO,gBAAgB,IAAI,IAAI;AAChD,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,SAAS,KAAK,OAAO,IAAI,QAAQ;AACvC,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,SAAS,KAAK;AACpB,QAAI,CAAC,OAAQ,QAAO;AACpB,QAAI;AACJ,QAAI;AACF,aAAO,YAAY,OAAO,QAAQ;AAClC,aAAO,OAAO,MAAM,IAAI;AAAA,IAC1B,QAAQ;AACN,aAAO;AAAA,IACT;AACA,QAAI,CAAC,KAAM,QAAO;AAClB,QAAI;AACF,aAAO,OAAO,KAAK,QAAQ,EAAE,KAAK,GAAG;AAAA,IACvC,UAAE;AACA,WAAK,OAAO;AAAA,IACd;AAAA,EACF;AAAA;AAAA,EAGA,QAAc;AACZ,eAAW,UAAU,KAAK,MAAM,OAAO,EAAG,QAAO,KAAK,OAAO;AAC7D,SAAK,MAAM,MAAM;AACjB,SAAK,MAAM,SAAS;AACpB,SAAK,MAAM,YAAY;AAAA,EACzB;AACF;AAGA,SAAS,IAAI,OAAwB;AACnC,QAAM,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAClE,SAAO,QAAQ;AACjB;;;AP7PA,IAAM,qBAAqB;AAQ3B,IAAM,cAAyB,EAAE,cAAc,OAAO,UAAU,MAAM;AAatE,SAAS,UACP,MACA,OACoC;AACpC,MAAI,MAAM;AACV,MAAIC,SAAQ;AACZ,MAAI,EAAE,cAAc,SAAS,IAAI;AAEjC,SAAOA,SAAQ,KAAK,QAAQ;AAC1B,UAAM,OAAO,KAAKA,MAAK;AACvB,UAAM,OAAO,KAAKA,SAAQ,CAAC;AAE3B,QAAI,cAAc;AAChB,UAAI,SAAS,OAAO,SAAS,KAAK;AAChC,uBAAe;AACf,QAAAA,UAAS;AACT;AAAA,MACF;AACA,MAAAA,UAAS;AACT;AAAA,IACF;AAIA,QAAI,UAAU;AACZ,UAAI,SAAS,MAAM;AACjB,QAAAA,UAAS;AACT;AAAA,MACF;AACA,UAAI,SAAS,IAAK,YAAW;AAC7B,MAAAA,UAAS;AACT;AAAA,IACF;AAEA,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,qBAAe;AACf,MAAAA,UAAS;AACT;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,IAAK;AAClC,QAAI,SAAS,KAAK;AAChB,iBAAW;AACX,MAAAA,UAAS;AACT;AAAA,IACF;AACA,QAAI,SAAS,OAAO,SAAS,KAAK;AAChC,YAAM,QAAQ;AACd,MAAAA,UAAS;AACT,aAAOA,SAAQ,KAAK,QAAQ;AAC1B,YAAI,KAAKA,MAAK,MAAM,MAAM;AACxB,UAAAA,UAAS;AACT;AAAA,QACF;AACA,YAAI,KAAKA,MAAK,MAAM,OAAO;AACzB,UAAAA,UAAS;AACT;AAAA,QACF;AACA,QAAAA,UAAS;AAAA,MACX;AACA;AAAA,IACF;AAEA,WAAO;AACP,IAAAA,UAAS;AAAA,EACX;AAEA,SAAO,EAAE,MAAM,KAAK,OAAO,EAAE,cAAc,SAAS,EAAE;AACxD;AAMA,SAAS,KAAK,OAAiB,MAAc,IAA4B;AACvE,SAAO;AAAA,IACL,MAAM,MAAM,MAAM,MAAM,KAAK,CAAC,EAAE,KAAK,IAAI;AAAA,IACzC,WAAW,OAAO;AAAA,IAClB,SAAS,KAAK;AAAA,EAChB;AACF;AAUA,SAAS,kBACP,OACA,WACuB;AACvB,MAAI,QAAQ;AACZ,MAAI,SAAS;AACb,MAAI,QAAQ;AAEZ,WAASA,SAAQ,WAAWA,SAAQ,MAAM,QAAQA,UAAS;AACzD,UAAM,WAAW,UAAU,MAAMA,MAAK,KAAK,IAAI,KAAK;AACpD,YAAQ,SAAS;AAEjB,eAAW,QAAQ,SAAS,MAAM;AAChC,UAAI,SAAS,KAAK;AAChB,iBAAS;AACT,iBAAS;AAAA,MACX,WAAW,SAAS,KAAK;AACvB,gBAAQ,KAAK,IAAI,GAAG,QAAQ,CAAC;AAAA,MAC/B,WAAW,SAAS,OAAO,CAAC,QAAQ;AAClC,eAAO,KAAK,OAAO,WAAWA,MAAK;AAAA,MACrC;AAAA,IACF;AAEA,QAAI,UAAU,UAAU,EAAG,QAAO,KAAK,OAAO,WAAWA,MAAK;AAAA,EAChE;AAEA,SAAO;AACT;AAGA,IAAM,gBAAgB;AAUtB,SAAS,qBACP,OACA,WACuB;AACvB,QAAM,SAAS,MAAM,SAAS,KAAK;AACnC,QAAM,SAAS,OAAO,SAAS,OAAO,UAAU,EAAE;AAElD,MAAI,YAAY;AAChB,WACMA,SAAQ,WACZA,SAAQ,MAAM,UAAUA,UAAS,YAAY,IAC7CA,UACA;AACA,UAAM,OAAO,UAAU,MAAMA,MAAK,KAAK,IAAI,WAAW,EAAE,KAAK,QAAQ;AACrE,QAAI,KAAK,SAAS,GAAG,GAAG;AACtB,kBAAYA;AACZ;AAAA,IACF;AAEA,QAAI,KAAK,SAAS,GAAG,EAAG,QAAO,KAAK,OAAO,WAAWA,MAAK;AAAA,EAC7D;AACA,MAAI,cAAc,GAAI,QAAO;AAE7B,MAAI,MAAM;AACV,WAASA,SAAQ,YAAY,GAAGA,SAAQ,MAAM,QAAQA,UAAS;AAC7D,UAAM,OAAO,MAAMA,MAAK,KAAK;AAC7B,QAAI,KAAK,KAAK,MAAM,GAAI;AACxB,UAAM,aAAa,KAAK,SAAS,KAAK,UAAU,EAAE;AAClD,QAAI,cAAc,OAAQ;AAC1B,UAAMA;AAAA,EACR;AAGA,SAAO,QAAQ,YAAY,OAAO,KAAK,OAAO,WAAW,GAAG;AAC9D;AAYA,IAAM,QAAsC;AAAA,EAC1C,CAAC,SACC,IAAI;AAAA,IACF,+DAA+D,IAAI;AAAA,EACrE;AAAA,EACF,CAAC,SAAS,IAAI,OAAO,MAAM,IAAI,UAAU;AAAA,EACzC,CAAC,SAAS,IAAI,OAAO,MAAM,IAAI,SAAS;AAAA,EACxC,CAAC,SAAS,IAAI,OAAO,MAAM,IAAI,KAAK;AACtC;AAYO,IAAM,gBAAgC;AAAA,EAC3C,MAAM;AAAA,EACN,QAAQ,QAAQ,QAAQ;AACtB,UAAM,WAAW,OAAO,MAAM,GAAG;AACjC,UAAM,OAAO,SAAS,SAAS,SAAS,CAAC;AACzC,QAAI,CAAC,KAAM,QAAO;AAClB,UAAM,SACJ,SAAS,SAAS,IAAI,SAAS,SAAS,SAAS,CAAC,IAAI;AAExD,UAAM,UAAU,aAAa,IAAI;AACjC,UAAM,gBAAgB,SAClB,IAAI,OAAO,MAAM,aAAa,MAAM,CAAC,KAAK,IAC1C;AACJ,UAAM,QAAQ,OAAO,MAAM,IAAI;AAE/B,eAAW,QAAQ,OAAO;AACxB,YAAM,UAAU,KAAK,OAAO;AAC5B,UAAI,aAAa,MACd,IAAI,CAAC,MAAMA,YAAW,EAAE,MAAM,OAAAA,OAAM,EAAE,EACtC,OAAO,CAAC,UAAU,QAAQ,KAAK,MAAM,IAAI,CAAC,EAC1C,IAAI,CAAC,UAAU,MAAM,KAAK;AAC7B,UAAI,CAAC,WAAW,OAAQ;AAKxB,UAAI,iBAAiB,WAAW,SAAS,GAAG;AAC1C,cAAM,YAAY,WAAW;AAAA,UAAI,CAACA,WAChC,iBAAiB,OAAOA,QAAO,aAAa;AAAA,QAC9C;AACA,cAAM,UAAU,KAAK,IAAI,GAAG,SAAS;AACrC,YAAI,OAAO,SAAS,OAAO,GAAG;AAC5B,uBAAa,WAAW,OAAO,CAAC,GAAGC,QAAO,UAAUA,GAAE,MAAM,OAAO;AAAA,QACrE;AAAA,MACF;AAIA,UAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,YAAM,YAAY,WAAW,CAAC;AAC9B,aAAO,cAAc,KAAK,MAAM,SAAS,KAAK,EAAE,IAC5C,qBAAqB,OAAO,SAAS,IACrC,kBAAkB,OAAO,SAAS;AAAA,IACxC;AAEA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aAAa,OAAuB;AAC3C,SAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;AAGA,SAAS,iBACP,OACAD,QACA,QACQ;AACR,QAAM,QAAQ,KAAK,IAAI,GAAGA,SAAQ,kBAAkB;AACpD,WAASC,MAAKD,QAAOC,OAAM,OAAOA,OAAM;AACtC,QAAI,OAAO,KAAK,MAAMA,GAAE,KAAK,EAAE,EAAG,QAAOD,SAAQC;AAAA,EACnD;AACA,SAAO,OAAO;AAChB;AAGO,SAAS,eAAe,MAAsB;AACnD,SAAO,cAAU,gCAAW,QAAQ,EACjC,OAAO,KAAK,QAAQ,SAAS,IAAI,CAAC,EAClC,OAAO,KAAK,CAAC;AAClB;AA6BO,SAAS,kBACd,QACA,QACA,YAAuC,CAAC,aAAa,GACnC;AAClB,QAAM,aAAa,OAAO,QAAQ,SAAS,IAAI;AAC/C,MAAI,CAAC,OAAO,QAAQ;AAClB,UAAM,QAAQ,WAAW,MAAM,IAAI;AACnC,QAAI,MAAM,SAAS,KAAK,MAAM,MAAM,SAAS,CAAC,MAAM,GAAI,OAAM,IAAI;AAClE,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,WAAW;AAAA,QACX,SAAS,KAAK,IAAI,GAAG,MAAM,MAAM;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAEA,aAAW,YAAY,WAAW;AAChC,UAAM,UAAU,SAAS,UACrB,SAAS,QAAQ,YAAY,OAAO,QAAQ,OAAO,IAAI,IACvD,YAAY,UAAU,YAAY,OAAO,QAAQ,OAAO,IAAI;AAChE,QAAI,QAAQ,SAAS,UAAW;AAChC,QAAI,QAAQ,SAAS,cAAc;AACjC,UAAI,QAAQ,WAAW,mBAAoB;AAC3C,aAAO,EAAE,IAAI,OAAO,QAAQ,QAAQ,OAAO;AAAA,IAC7C;AACA,UAAMC,UAAS,SAAS,YAAY,QAAQ,KAAK,MAAM,OAAO,IAAI;AAClE,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,MAAM,QAAQ;AAAA,MACd,GAAI,eAAe,SAAS,IAAI,IAAI,EAAE,UAAU,SAAS,KAAK,IAAI,CAAC;AAAA,MACnE,GAAIA,UAAS,EAAE,YAAYA,QAAO,IAAI,CAAC;AAAA,IACzC;AAAA,EACF;AACA,SAAO,EAAE,IAAI,OAAO,QAAQ,mBAAmB;AACjD;AAGA,SAAS,YACP,UACA,QACA,QACA,MACiB;AACjB,QAAMC,QAAO,SAAS,QAAQ,QAAQ,QAAQ,IAAI;AAClD,SAAOA,QACH,EAAE,MAAM,YAAY,MAAAA,MAAK,IACzB,EAAE,MAAM,cAAc,QAAQ,mBAAmB;AACvD;AAEA,SAAS,eAAe,MAA0C;AAChE,SAAO,SAAS,iBAAiB,SAAS;AAC5C;AAGA,eAAsB,iBACpB,WACA,OACe;AACf,aAAW,YAAY,UAAW,OAAM,SAAS,UAAU,KAAK;AAClE;AAQO,SAAS,uBACd,WAA2B,CAAC,GACV;AAClB,SAAO,CAAC,IAAI,mBAAmB,QAAQ,GAAG,aAAa;AACzD;AASO,SAAS,gBACd,QACA,QACA,UACS;AACT,QAAM,WAAW,OAAO,YAAY;AACpC,MAAI,CAAC,YAAY,CAAC,OAAO,UAAU,aAAa,SAAU,QAAO;AACjE,MAAI,aAAa,QAAS,QAAO;AACjC,QAAM,SAAS,cAAc;AAAA,IAC3B,OAAO,QAAQ,SAAS,IAAI;AAAA,IAC5B,OAAO;AAAA,EACT;AACA,SAAO,WAAW,QAAQ,eAAe,OAAO,IAAI,MAAM,OAAO;AACnE;AAWO,SAAS,aACd,QACA,SACwC;AACxC,QAAM,SAAS,OAAO,OAAQ,OAAO,aAAa,QAAS;AAC3D,QAAM,SAAS,WAAW,QAAQ,aAAa,QAAQ;AACvD,SAAO,WAAW,SAAS,QAAQ,aAC/B,EAAE,MAAM,eAAe,QAAQ,UAAU,GAAG,MAAM,MAAM,IACxD,EAAE,MAAM,eAAe,QAAQ,KAAK,IAAI,GAAG,MAAM,MAAM;AAC7D;;;AUhZA,eAAsB,kBACpB,SACA,UAA8B,CAAC,GACa;AAC5C,QAAM,WAAW,QAAQ,YAAY,QAAQ,IAAI;AACjD,QAAM,YACJ,QAAQ,cACP,QAAQ,WACL,CAAC,QAAQ,QAAQ,IACjB,uBAAuB;AAAA,IACrB,SAAS,QAAQ,QAAQ,YAAY;AAAA,EACvC,CAAC;AACP,QAAM,SAAS,IAAI,WAAW,QAAQ;AAEtC,QAAM,UAAU,oBAAI,IAAuB;AAC3C,MAAI,eAAe;AACnB,aAAW,UAAU,SAAS;AAC5B,UAAM,WAAW,OAAO,YAAY,mBAAmB,CAAC,GAAG;AAAA,MACzD,CAAC,WAAW,OAAO;AAAA,IACrB;AACA,QAAI,CAAC,QAAQ,OAAQ;AACrB,QAAI,QAAQ,KAAK,CAAC,WAAW,OAAO,IAAI,EAAG,gBAAe;AAC1D,YAAQ;AAAA,MACN,OAAO;AAAA,MACP,QAAQ,IAAI,CAAC,YAAY,EAAE,QAAQ,SAAS,MAAM,EAAE;AAAA,IACtD;AAAA,EACF;AACA,MAAI,cAAc;AAChB,UAAM,OAAO,MAAM;AACnB,eAAW,WAAW,QAAQ,OAAO,GAAG;AACtC,iBAAW,SAAS;AAClB,cAAM,UAAU,OAAO,UAAU,MAAM,MAAM;AAAA,IACjD;AAAA,EACF;AAEA,QAAM,QAAkB,CAAC;AACzB,QAAM,QAAsB,CAAC;AAC7B,aAAW,WAAW,QAAQ,OAAO,GAAG;AACtC,eAAW,EAAE,QAAQ,QAAQ,KAAK,SAAS;AACzC,UAAI,CAAC,QAAS,OAAM,KAAK,OAAO,IAAI;AAAA,UAC/B,OAAM,KAAK,GAAG,YAAY,MAAM,CAAC;AAAA,IACxC;AAAA,EACF;AAGA,QAAM,CAAC,OAAO,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IACxC;AAAA,MACE;AAAA,MACA,QAAQ,UAAU,iBAAiB,QAAQ;AAAA,MAC3C,QAAQ,eAAe;AAAA,IACzB;AAAA,KACC,QAAQ,cAAc,mBAAmB,OAAO,QAAQ,UAAU,CAAC,CAAC;AAAA,EACvE,CAAC;AACD,QAAM,iBAAiB,WAAW;AAAA,IAChC,GAAG;AAAA,IACH,GAAG,MAAM,IAAI,CAAC,SAAS,KAAK,IAAI;AAAA,EAClC,CAAC;AAED,QAAM,QAAQ,oBAAI,IAAkC;AACpD,aAAW,UAAU,SAAS;AAC5B,UAAM,UAAgC,CAAC;AACvC,eAAW,EAAE,QAAQ,QAAQ,KAAK,QAAQ,IAAI,OAAO,SAAS,KAAK,CAAC,GAAG;AACrE,cAAQ;AAAA,QACN,UACI,YAAY,QAAQ,QAAQ,SAAS,IACrC,WAAW,QAAQ,MAAM,IAAI,OAAO,IAAI,GAAiB,SAAS;AAAA,MACxE;AAAA,IACF;AACA,QAAI,QAAQ,OAAQ,OAAM,IAAI,OAAO,WAAW,OAAO;AAAA,EACzD;AACA,SAAO;AACT;AAMO,SAAS,YAAY,QAAgC;AAC1D,QAAM,OAAO,OAAO;AACpB,QAAM,QAAsB,CAAC,EAAE,MAAM,MAAM,OAAO,KAAK,CAAC;AACxD,MAAI,OAAO,IAAK,OAAM,QAAQ,EAAE,MAAM,KAAK,OAAO,KAAK,MAAM,OAAO,KAAK,CAAC;AAC1E,SAAO;AACT;AAEA,SAAS,KACP,QAC4D;AAC5D,SAAO;AAAA,IACL,MAAM,OAAO;AAAA,IACb,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,IACjD,YAAY,OAAO;AAAA,EACrB;AACF;AAEA,SAAS,WACP,QACA,QACA,MACoB;AACpB,SAAO;AAAA,IACL,GAAG,KAAK,MAAM;AAAA,IACd,OAAO;AAAA,IACP,UAAU;AAAA,IACV,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3B,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACvB,GAAG,QAAQ,MAAM;AAAA,EACnB;AACF;AAUO,SAAS,sBACd,OAC0B;AAC1B,MAAI,MAAM,UAAU,cAAc;AAChC,WAAO,MAAM,WAAW,kBACtB,MAAM,WAAW,qBACf,SACA;AAAA,EACN;AACA,SAAO,MAAM,UAAU,YAAY,YAAY;AACjD;AAGA,SAAS,QAAQ,QAEf;AACA,QAAM,UAAU,sBAAsB,EAAE,OAAO,cAAc,OAAO,CAAC;AACrE,SAAO,UAAU,EAAE,OAAO,QAAQ,IAAI,CAAC;AACzC;AAUA,SAAS,OACP,QACA,QACA,WAGsD;AACtD,QAAM,UAAU,kBAAkB,QAAQ,QAAQ,SAAS;AAC3D,MAAI,CAAC,QAAQ,GAAI,QAAO,EAAE,IAAI,OAAO,QAAQ,QAAQ,OAAO;AAC5D,QAAM,EAAE,MAAM,KAAK,IAAI,aAAa,QAAQ,OAAO;AACnD,SAAO;AAAA,IACL,IAAI;AAAA,IACJ,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA,OAAO,QAAQ,KAAK,UAAU,QAAQ,KAAK,YAAY;AAAA,MACvD,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,IAC3D;AAAA,EACF;AACF;AASA,SAAS,eACP,QACA,QACA,SAC6B;AAC7B,SAAO;AAAA,IACL,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,IACzD,GAAI,QAAQ,SAAS,OAAO,QAC5B,gBAAgB,QAAQ,QAAQ,QAAQ,QAAQ,IAC5C,EAAE,QAAQ,mBAA4B,IACtC,CAAC;AAAA,EACP;AACF;AAEA,SAAS,SACP,QACA,SACA,QAAqC,CAAC,GAClB;AACpB,QAAM,UAAU,QAAQ,SAAS,OAAO;AACxC,SAAO;AAAA,IACL,GAAG,KAAK,MAAM;AAAA,IACd,OAAO,UAAU,UAAU;AAAA,IAC3B,aAAa,QAAQ;AAAA,IACrB,UAAU,QAAQ;AAAA,IAClB,UACE,OAAO,UAAU,SACb,OACA,KAAK,IAAI,QAAQ,QAAQ,OAAO,KAAK;AAAA,IAC3C,GAAI,UAAU,CAAC,IAAI,EAAE,OAAO,UAAmB;AAAA,IAC/C,GAAG;AAAA,EACL;AACF;AAEA,SAAS,WACP,QACA,MACA,WACoB;AACpB,MAAI,CAAC,KAAK,GAAI,QAAO,WAAW,QAAQ,KAAK,MAAM;AACnD,QAAM,QAAQ,OAAO,KAAK,QAAQ,QAAQ,SAAS;AACnD,MAAI,CAAC,MAAM,GAAI,QAAO,WAAW,QAAQ,MAAM,MAAM;AACrD,SAAO;AAAA,IACL;AAAA,IACA,MAAM;AAAA,IACN,eAAe,KAAK,QAAQ,QAAQ,MAAM,OAAO;AAAA,EACnD;AACF;AAUA,SAAS,YACP,QACA,QACA,WACoB;AACpB,QAAM,OAAO,OAAO;AACpB,QAAM,MAAM,iBAAiB,IAAI;AACjC,QAAM,YAAY,OAAO,IAAI,QAAQ,KAAK,QAAW,OAAO,IAAI,CAAC;AACjE,QAAM,UAAU,OAAO,MACnB,OAAO,IAAI,QAAQ,KAAK,OAAO,KAAK,OAAO,IAAI,CAAC,IAChD;AAEJ,MAAI,CAAC,QAAS,QAAO,WAAW,QAAQ,sBAAsB,IAAI;AAClE,MAAI,CAAC,QAAQ,GAAI,QAAO,WAAW,QAAQ,QAAQ,QAAQ,IAAI;AAE/D,QAAM,QAAQ,OAAO,QAAQ,QAAQ,QAAQ,SAAS;AACtD,MAAI,CAAC,MAAM,GAAI,QAAO,WAAW,QAAQ,MAAM,QAAQ,IAAI;AAC3D,QAAM,UAAU,MAAM;AACtB,QAAM,SAAS,eAAe,QAAQ,QAAQ,QAAQ,OAAO;AAC7D,MAAI,CAAC,OAAO,IAAK,QAAO,SAAS,QAAQ,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;AACrE,MAAI,QAAQ,SAAS,OAAO,MAAM;AAChC,WAAO,SAAS,QAAQ,SAAS;AAAA,MAC/B;AAAA,MACA,GAAG;AAAA,MACH,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAEA,QAAM,OAAO,WAAW,KACpB,OAAO,UAAU,QAAQ,QAAQ,SAAS,IAC1C;AACJ,SAAO,MAAM,MAAM,KAAK,QAAQ,SAAS,OAAO,OAC5C;AAAA,IACE,GAAG,SAAS,QAAQ,KAAK,SAAS;AAAA,MAChC;AAAA,MACA,GAAI,KAAK,QAAQ,WAAW,EAAE,UAAU,KAAK,QAAQ,SAAS,IAAI,CAAC;AAAA,IACrE,CAAC;AAAA,IACD,OAAO;AAAA,IACP,aAAa;AAAA,EACf,IACA,SAAS,QAAQ,SAAS;AAAA,IACxB;AAAA,IACA,GAAG;AAAA,IACH,aAAa;AAAA,EACf,CAAC;AACP;;;AC1RO,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA,YAAY,OAAmB;AAC7B,UAAM,MAAM,OAAO;AACnB,SAAK,OAAO,MAAM,QAAQ,KAAK,YAAY;AAC3C,SAAK,OAAO,MAAM,QAAQ;AAC1B,SAAK,YAAY,MAAM;AACvB,SAAK,QAAQ,MAAM;AACnB,SAAK,YAAY,MAAM,aAAa;AACpC,SAAK,eAAe,MAAM,gBAAgB;AAC1C,SAAK,UAAU,MAAM;AAAA,EACvB;AACF;;;AC7DO,IAAM,6BAAN,cAAyC,UAAU;AAAA,EACxD,YAAqBC,YAAmB;AACtC,UAAM;AAAA,MACJ,SAAS,OAAOA,UAAS;AAAA,MACzB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,WAAAA,YAAW,QAAQ,UAAU;AAAA,IAC1C,CAAC;AATkB,qBAAAA;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAEO,IAAM,wBAAN,cAAoC,UAAU;AAAA,EACnD,YAAqBA,YAAmB;AACtC,UAAM;AAAA,MACJ,SAAS,OAAOA,UAAS;AAAA,MACzB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,WAAAA,WAAU;AAAA,IACvB,CAAC;AATkB,qBAAAA;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAGO,IAAM,uBAAN,cAAmC,UAAU;AAAA,EAClD,YAAqBA,YAAmB;AACtC,UAAM;AAAA,MACJ,SAAS,OAAOA,UAAS;AAAA,MACzB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,WAAAA,WAAU;AAAA,IACvB,CAAC;AATkB,qBAAAA;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAGO,IAAM,0BAAN,cAAsC,UAAU;AAAA,EACrD,YACWA,YACA,OACA,aACT;AACA,UAAM;AAAA,MACJ,SAAS,OAAOA,UAAS,qBAAqB,WAAW;AAAA,MACzD;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,WAAAA,YAAW,OAAO,aAAa,QAAQ,UAAU;AAAA,IAC9D,CAAC;AAZQ,qBAAAA;AACA;AACA;AAAA,EAWX;AAAA,EAbW;AAAA,EACA;AAAA,EACA;AAYb;AASO,IAAM,4BAAN,cAAwC,UAAU;AAAA,EACvD,YACW,aACAC,eACA,cACA,UACT;AACA,UAAM;AAAA,MACJ,SAAS,iBAAiB,WAAW,gBAAgBA,aAAY,+BAA+B,YAAY;AAAA,MAC5G;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,aAAa,cAAAA,eAAc,cAAc,SAAS;AAAA,IAC/D,CAAC;AAbQ;AACA,wBAAAA;AACA;AACA;AAAA,EAWX;AAAA,EAdW;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAYb;AAUO,IAAM,wBAAN,cAAoC,UAAU;AAAA,EACnD,YACW,KACA,UACT;AACA,UAAM;AAAA,MACJ,SAAS,OAAO,GAAG,0DAAqD,SAAS,KAAK,IAAI,CAAC;AAAA,MAC3F;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,KAAK,UAAU,SAAS,KAAK,IAAI,EAAE;AAAA,IAChD,CAAC;AAXQ;AACA;AAAA,EAWX;AAAA,EAZW;AAAA,EACA;AAYb;AAUO,IAAM,0BAAN,cAAsC,UAAU;AAAA,EACrD,YAAqB,MAAc;AACjC,UAAM;AAAA,MACJ,SAAS,OAAO,IAAI,8BAAyB,IAAI,eAAe,IAAI;AAAA,MACpE;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,KAAK;AAAA,IAClB,CAAC;AATkB;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAEO,IAAM,0BAAN,cAAsC,UAAU;AAAA,EACrD,YAAY,SAAiB,SAAiC;AAC5D,UAAM;AAAA,MACJ,SAAS,OAAO,OAAO;AAAA,MACvB;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAGO,IAAM,uBAAN,cAAmC,UAAU;AAAA,EAClD,YAAqB,OAAe;AAClC,UAAM;AAAA,MACJ,SAAS,eAAe,KAAK;AAAA,MAC7B;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,MAAM;AAAA,IACnB,CAAC;AATkB;AAAA,EAUrB;AAAA,EAVqB;AAWvB;AAGO,IAAM,6BAAN,cAAyC,UAAU;AAAA,EACxD,YAAqB,OAAe;AAClC,UAAM;AAAA,MACJ,SAAS,eAAe,KAAK;AAAA,MAC7B;AAAA,MACA,MAAM;AAAA,MACN;AAAA,MACA,WAAW;AAAA,MACX,cAAc;AAAA,MACd,SAAS,EAAE,MAAM;AAAA,IACnB,CAAC;AATkB;AAAA,EAUrB;AAAA,EAVqB;AAWvB;;;AClLA,SAAS,UAAU,OAAkC;AACnD,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,CAAC;AACzD,QAAMC,SAAQ;AACd,QAAM,OAAO,CAAC,KAAa,QAAgB;AACzC,UAAMC,OAAMD,OAAM,GAAG;AACrB,WAAO,OAAOC,SAAQ,YAAY,OAAO,UAAUA,IAAG,KAAKA,QAAO,MAC9DA,OACA;AAAA,EACN;AACA,QAAM,eAAe,KAAK,gBAAgB,CAAC;AAE3C,QAAM,kBAAkB,KAAK,mBAAmB,CAAC;AAEjD,QAAM,MAAMD,OAAM,aAAa;AAC/B,QAAM,cAAc,MAAM,QAAQ,GAAG,IACjC,IAAI,OAAO,CAAC,QAAuB,OAAO,QAAQ,YAAY,QAAQ,EAAE,IACxE;AACJ,SAAO;AAAA,IACL,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,IACvC,GAAI,oBAAoB,SAAY,EAAE,gBAAgB,IAAI,CAAC;AAAA,IAC3D,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA,EACvC;AACF;AAOO,SAAS,sBACd,UACA,SACkB;AAClB,QAAMA,SAAQ,SAAS;AACvB,MAAIA,WAAU,QAAQ,OAAOA,WAAU,SAAU,QAAO,CAAC;AACzD,QAAM,UAAUA;AAChB,SAAO;AAAA,IACL,GAAG,UAAU,QAAQ,SAAS,CAAC;AAAA,IAC/B,GAAI,UAAU,UAAU,QAAQ,OAAO,CAAC,IAAI,CAAC;AAAA,EAC/C;AACF;AAOO,SAAS,qBACd,QACA,SACkB;AAClB,QAAM,UAAW,CAAC,QAAQ,SAAS,SAAS,EAAY,IAAI,CAAC,UAAU;AACrE,UAAM,WAAW,OAAO,UAAU,KAAK;AACvC,WAAO,WAAW,sBAAsB,UAAU,OAAO,IAAI,CAAC;AAAA,EAChE,CAAC;AACD,SAAO,EAAE,GAAG,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,GAAG,GAAG,QAAQ,CAAC,EAAE;AACvD;;;AC7DO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAC9C,YAAY,MAAc,OAAe;AACvC,UAAM,gBAAgB,IAAI,qBAAqB,KAAK,2BAAsB;AAC1E,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,oBAAN,cAAgC,MAAM;AAAA,EAC3C,YAAYE,aAAoB,OAAmB;AACjD;AAAA,MACE,GAAGA,WAAU,8CAA8C,KAAK;AAAA,IAClE;AACA,SAAK,OAAO;AAAA,EACd;AACF;;;AChBA,IAAAC,oBAAwB;;;ACAxB,IAAAC,mBAA2C;AAC3C,IAAAC,kBAAwB;AACxB,IAAAC,oBAAkE;;;ACFlE,IAAAC,oBAAqB;AACrB,IAAAC,cAAkB;AAuBX,IAAM,gBAAY,wBAAK,YAAY,cAAc;AACjD,IAAM,sBAAkB,wBAAK,YAAY,oBAAoB;AAE7D,IAAM,aAAa,CAAC,WAAW,SAAS,MAAM;AAS9C,IAAM,YAAY,cACtB,OAAO;AAAA;AAAA,EAEN,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACtB,UAAU,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUrC,MAAM,cAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,MAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ1D,UAAU,cAAE,MAAM,cAAE,OAAO,CAAC,EAAE,SAAS,EAAE,MAAM,MAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOxD,QAAQ,cAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,MAAS;AAChD,CAAC,EACA,YAAY;AAER,IAAM,qBAAqB,cAC/B,OAAO;AAAA,EACN,MAAM,cAAE,MAAM,SAAS,EAAE,QAAQ,CAAC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASnC,SAAS,cAAE,QAAQ,EAAE,SAAS;AAChC,CAAC,EACA,YAAY;;;ADnEf,SAAS,WAAmB;AAC1B,SAAO,QAAQ,IAAI,4BAAwB,yBAAQ;AACrD;AAGO,SAAS,UAAU,cAAsB,OAA2B;AACzE,SAAO,UAAU,SAAS,SAAS,QAAI,2BAAQ,YAAY;AAC7D;AAEA,SAAS,UAAU,cAAsB,OAA2B;AAClE,aAAO;AAAA,IACL,UAAU,cAAc,KAAK;AAAA,IAC7B,UAAU,UAAU,kBAAkB;AAAA,EACxC;AACF;AAWA,eAAsB,cACpB,cACA,OACyB;AACzB,QAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,MAAI;AACJ,MAAI;AACF,UAAM,UAAM,2BAAS,MAAM,MAAM;AAAA,EACnC,QAAQ;AACN,WAAO,EAAE,MAAM,CAAC,EAAE;AAAA,EACpB;AAEA,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,GAAG;AAAA,EACzB,SAAS,OAAO;AACd,UAAM,IAAI;AAAA,MACR;AAAA,MACA,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAC3C;AAAA,EACF;AACA,QAAM,WAAW,mBAAmB,UAAU,MAAM;AACpD,MAAI,CAAC,SAAS,SAAS;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,MACA,SAAS,MAAM,OAAO,CAAC,GAAG,WAAW;AAAA,IACvC;AAAA,EACF;AACA,SAAO,SAAS;AAClB;AAEA,eAAsB,eACpB,cACA,OACA,UACe;AACf,QAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,YAAM,4BAAM,2BAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,YAAM,4BAAU,MAAM,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,GAAM,MAAM;AACxE;AAGO,SAAS,eAAe,SAAiB,MAAsB;AACpE,aAAO,8BAAW,IAAI,QAClB,2BAAQ,IAAI,QACZ,2BAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,KAAK,qBAAG,CAAC;AAChD;AAGO,SAAS,aAAa,SAAiBC,aAA4B;AACxE,QAAM,UAAM,gCAAS,2BAAQ,OAAO,OAAG,2BAAQA,WAAU,CAAC;AAC1D,UAAQ,QAAQ,KAAK,MAAM,KAAK,MAAM,qBAAG,EAAE,KAAK,GAAG;AACrD;AAQA,eAAsB,eACpB,cACuB;AACvB,QAAM,YAAyD,CAAC;AAChE,QAAM,OAAsB,CAAC;AAC7B,QAAM,OAAO,oBAAI,IAAY;AAE7B,aAAW,SAAS,YAAY;AAC9B,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,cAAc,cAAc,KAAK;AAAA,IACpD,QAAQ;AACN;AAAA,IACF;AACA,cAAU,KAAK,IAAI;AACnB,UAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,eAAW,SAAS,SAAS,MAAM;AACjC,YAAM,eAAe,eAAe,MAAM,MAAM,IAAI;AACpD,UAAI,KAAK,IAAI,YAAY,EAAG;AAC5B,WAAK,IAAI,YAAY;AACrB,WAAK,KAAK,EAAE,GAAG,OAAO,OAAO,aAAa,CAAC;AAAA,IAC7C;AAAA,EACF;AACA,SAAO,EAAE,MAAM,UAAU;AAC3B;;;ADlHA,eAAsB,oBACpB,cACAC,aACe;AACf,QAAM,SAAS,MAAM,eAAe,YAAY;AAChD,QAAM,eAAW,2BAAQA,WAAU;AACnC,QAAM,MAAM,OAAO,KAAK,KAAK,CAAC,UAAU,MAAM,iBAAiB,QAAQ;AACvE,MAAI,KAAK,WAAW,MAAM;AACxB,UAAM,IAAI,kBAAkB,IAAI,MAAM,IAAI,KAAK;AAAA,EACjD;AACF;;;AGfA,eAAsB,SACpB,OACA,cACwB;AACxB,QAAM,SAAS,MAAM,eAAe,YAAY;AAChD,SAAO,QAAQ;AAAA,IACb,OAAO,KAAK,IAAI,OAAO,UAAU;AAC/B,YAAM,UAAU,MAAM,MAAM,KAAK,MAAM,YAAY;AACnD,aAAO;AAAA,QACL,MAAM,MAAM;AAAA,QACZ,OAAO,MAAM;AAAA,QACb,UAAU,MAAM,YAAY;AAAA,QAC5B,cAAc,MAAM;AAAA,QACpB,OAAO,QAAQ,SAAS;AAAA,QACxB,aAAa,QAAQ;AAAA,QACrB,MAAM,MAAM,QAAQ;AAAA,QACpB,UAAU,MAAM,YAAY;AAAA,QAC5B,QAAQ,MAAM,WAAW;AAAA,MAC3B;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACRA,eAAsB,QACpB,OACA,cACAC,aACAC,KACA,UAAwB,CAAC,GACH;AACtB,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,QAAM,WAAW,MAAM,cAAc,cAAc,KAAK;AACxD,QAAM,WAAW,eAAe,MAAM,aAAa,MAAMD,WAAU,CAAC;AAEpE,QAAM,WAAW,SAAS,KAAK;AAAA,IAC7B,CAACE,WAAU,eAAe,MAAMA,OAAM,IAAI,MAAM;AAAA,EAClD;AACA,QAAM,UAAU,MAAM,MAAM,KAAK,QAAQ;AACzC,QAAM,UACJ,QAAQ,WAAW,IACf,uBAAuB,QAAQ,gFAC/B;AAEN,QAAM,SAAS;AAAA,IACb,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,IAC7C,GAAI,QAAQ,UAAU,SAAS,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,IACjE,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,EACnE;AAEA,MAAI,UAAU;AACZ,UAAM,UAAiB,EAAE,GAAG,UAAU,GAAG,OAAO;AAChD,QAAI,OAAO,KAAK,MAAM,EAAE,QAAQ;AAC9B,YAAM,eAAe,cAAc,OAAO;AAAA,QACxC,GAAG;AAAA,QACH,MAAM,SAAS,KAAK;AAAA,UAAI,CAACA,WACvBA,WAAU,WAAW,UAAUA;AAAA,QACjC;AAAA,MACF,CAAC;AAAA,IACH;AACA,WAAO;AAAA,MACL,MAAM,SAAS;AAAA,MACf;AAAA,MACA,UAAU,SAAS,YAAYD;AAAA,MAC/B,eAAe;AAAA,MACf,GAAI,QAAQ,OAAO,EAAE,MAAM,QAAQ,KAAK,IAAI,CAAC;AAAA,MAC7C,GAAI,QAAQ,WAAW,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,MACzD,GAAI,QAAQ,WAAW,SAAY,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,MACjE,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,QAAe;AAAA,IACnB,MAAM,aAAa,MAAMD,WAAU;AAAA,IACnC,UAAUC;AAAA,IACV,GAAG;AAAA,EACL;AACA,QAAM,eAAe,cAAc,OAAO;AAAA,IACxC,GAAG;AAAA,IACH,MAAM,CAAC,GAAG,SAAS,MAAM,KAAK;AAAA,EAChC,CAAC;AACD,SAAO;AAAA,IACL,MAAM,MAAM;AAAA,IACZ;AAAA,IACA,UAAUA;AAAA,IACV,eAAe;AAAA,IACf,GAAG;AAAA,IACH,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,EAC/B;AACF;;;ACpFA,IAAAE,oBAAwB;AAgBxB,eAAsB,UACpB,cACAC,aACmE;AACnE,QAAM,SAAuB,CAAC;AAC9B,aAAW,SAAS,YAAY;AAC9B,UAAM,OAAO,UAAU,cAAc,KAAK;AAC1C,QAAI;AACJ,QAAI;AACF,iBAAW,MAAM,cAAc,cAAc,KAAK;AAAA,IACpD,QAAQ;AACN;AAAA,IACF;AACA,UAAM,WAAW,eAAe,MAAM,aAAa,MAAMA,WAAU,CAAC;AACpE,UAAM,OAAO,SAAS,KAAK;AAAA,MACzB,CAAC,UAAU,eAAe,MAAM,MAAM,IAAI,MAAM;AAAA,IAClD;AACA,QAAI,KAAK,WAAW,SAAS,KAAK,QAAQ;AACxC,YAAM,eAAe,cAAc,OAAO,EAAE,GAAG,UAAU,MAAM,KAAK,CAAC;AACrE,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,iBAAa,2BAAQ,YAAY,GAAGA,WAAU;AAAA,IACpD,SAAS,OAAO,SAAS;AAAA,IACzB;AAAA,EACF;AACF;;;AC3CA,IAAAC,cAAkB;AA6EX,IAAM,aAAa,cACvB,OAAO,EACP,IAAI,CAAC,EACL,SAAS,gDAAgD;AAErD,IAAM,YAAY,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,yBAAyB;AAMtE,IAAM,OAAO,cACjB,MAAM,cAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EACvB,SAAS,EACT;AAAA,EACC;AACF;AAUK,IAAM,YAAY,cACtB,OAAO,EACP,IAAI,CAAC,EACL,SAAS,EACT;AAAA,EACC;AACF;AAEK,SAAS,OACd,SAC0B;AAC1B,SAAO;AACT;AAiBO,SAAS,SAAS,MAAgB,MAAkC;AACzE,QAAM,SAAS,KAAK,KAAK,CAAC,QAAQ,IAAI,WAAW,GAAG,IAAI,GAAG,CAAC;AAC5D,MAAI,WAAW,QAAW;AACxB,UAAMC,SAAQ,OAAO,MAAM,KAAK,SAAS,CAAC;AAC1C,QAAI,CAACA,OAAO,OAAM,IAAI,wBAAwB,IAAI;AAClD,WAAOA;AAAA,EACT;AAEA,QAAMC,MAAK,KAAK,QAAQ,IAAI;AAC5B,MAAIA,QAAO,GAAI,QAAO;AAEtB,QAAM,QAAQ,KAAKA,MAAK,CAAC;AACzB,MAAI,UAAU,UAAa,MAAM,WAAW,IAAI,GAAG;AACjD,UAAM,IAAI,wBAAwB,IAAI;AAAA,EACxC;AACA,SAAO;AACT;AAMO,SAAS,UAAU,MAAgB,MAAwB;AAChE,QAAM,SAAmB,CAAC;AAC1B,aAAW,CAACA,KAAI,GAAG,KAAK,KAAK,QAAQ,GAAG;AACtC,QAAI,IAAI,WAAW,GAAG,IAAI,GAAG,GAAG;AAC9B,YAAM,QAAQ,IAAI,MAAM,KAAK,SAAS,CAAC;AACvC,UAAI,CAAC,MAAO,OAAM,IAAI,wBAAwB,IAAI;AAClD,aAAO,KAAK,KAAK;AAAA,IACnB,WAAW,QAAQ,MAAM;AACvB,YAAM,QAAQ,KAAKA,MAAK,CAAC;AACzB,UAAI,UAAU,UAAa,MAAM,WAAW,IAAI,GAAG;AACjD,cAAM,IAAI,wBAAwB,IAAI;AAAA,MACxC;AACA,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,YAAY,SAAmB,OAA2B;AACxE,QAAM,OAAiB,CAAC;AACxB,WAASA,MAAK,GAAGA,MAAK,KAAK,QAAQA,OAAM,GAAG;AAC1C,UAAM,MAAM,KAAKA,GAAE;AACnB,QAAI,MAAM,KAAK,CAAC,SAAS,IAAI,WAAW,GAAG,IAAI,GAAG,CAAC,EAAG;AACtD,QAAI,MAAM,SAAS,GAAG,GAAG;AACvB,MAAAA,OAAM;AACN;AAAA,IACF;AACA,SAAK,KAAK,GAAG;AAAA,EACf;AACA,SAAO;AACT;AAOO,SAAS,eACd,SACG,OACiB;AACpB,SAAO,YAAY,KAAK,MAAM,CAAC,GAAG,GAAG,KAAK,EAAE;AAAA,IAC1C,CAAC,QAAQ,CAAC,IAAI,WAAW,IAAI;AAAA,EAC/B;AACF;;;A/B/IA,SAAS,gBAAgB,SAAwC;AAC/D,QAAM,QAAQ;AAAA,IACZ,GAAG,IAAI;AAAA,MACL,QAAQ,QAAQ,CAAC,UAAW,MAAM,WAAW,CAAC,MAAM,QAAQ,IAAI,CAAC,CAAE;AAAA,IACrE;AAAA,EACF,EAAE,KAAK;AACP,SAAO,MAAM,SAAS,GAAG,MAAM,KAAK,KAAK,CAAC,cAAc;AAC1D;AAEO,IAAM,uBAAuB,OAAO;AAAA,EACzC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,cAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,UAAU,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,IACrC,SAAS,cACN,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,YAAY,cACT,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,SAAS,cACN,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,UAAU,SAAS,MAAM,aAAa;AAAA,IACtC,SAAS,KAAK,SAAS,WAAW;AAAA,IAClC,YAAY,KAAK,SAAS,cAAc;AAAA,IACxC,SAAS,KAAK,SAAS,WAAW;AAAA,EACpC;AAAA,EACA,KAAK,OACH,EAAE,OAAO,OAAO,IAAI,GACpB,EAAE,YAAY,MAAM,WAAW,IAAI,UAAU,SAAS,YAAY,QAAQ,MACvE;AACH,UAAM,OAAO,YAAY,QAAQ,IAAI;AACrC,UAAM,SAAS,MAAM,MAAM,KAAK,MAAM,EAAE;AACxC,QAAI,CAAC,OAAQ,OAAM,IAAI,sBAAsB,EAAE;AAE/C,UAAM,UAAU,OAAO,YAAY,mBAAmB,CAAC;AACvD,QAAI,CAAC,QAAQ,QAAQ;AACnB,aAAO;AAAA,QACL,WAAW;AAAA,QACX,SAAS,CAAC;AAAA,QACV,UAAU;AAAA,QACV,MAAM;AAAA,MACR;AAAA,IACF;AAEA,UAAM,UAAiC,CAAC;AACxC,UAAM,UAAsB,CAAC;AAC7B,QAAI,QAAQ;AAEZ,UAAM,UAAU,MAAM,YAAY,SAAS,MAAM,YAAY,IAAI;AACjE,UAAM,YAAY,uBAAuB,EAAE,SAAS,YAAY,KAAK,CAAC;AACtE,UAAM;AAAA,MACJ;AAAA,MACA,QAAQ,IAAI,CAAC,WAAW,OAAO,IAAI;AAAA,IACrC;AAEA,eAAW,UAAU,SAAS;AAC5B,YAAMC,QAGF;AAAA,QACF,MAAM,OAAO;AAAA,QACb,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA,QAIjD,GAAI,OAAO,OAAO,EAAE,YAAY,OAAO,KAAK,IAAI,CAAC;AAAA,MACnD;AACA,YAAM,SAAS,QAAQ,IAAI,MAAM;AACjC,UAAI,OAAO,KAAM,CAAAA,MAAK,OAAO,OAAO;AAEpC,UAAI,CAAC,OAAO,IAAI;AACd,gBAAQ,KAAK,EAAE,GAAGA,OAAM,OAAO,cAAc,QAAQ,OAAO,OAAO,CAAC;AACpE,gBAAQ,KAAK,MAAM;AACnB;AAAA,MACF;AAEA,YAAM,UAAU,kBAAkB,OAAO,QAAQ,QAAQ,SAAS;AAClE,UAAI,CAAC,QAAQ,IAAI;AACf,gBAAQ,KAAK;AAAA,UACX,GAAGA;AAAA,UACH,OAAO;AAAA,UACP,QAAQ,QAAQ;AAAA,QAClB,CAAC;AACD,gBAAQ,KAAK,MAAM;AACnB;AAAA,MACF;AAEA,YAAM,WAAW,QAAQ;AACzB,YAAM,aAAa,QAAQ;AAC3B,YAAM,EAAE,MAAM,aAAa,KAAK,IAAI,aAAa,QAAQ,OAAO;AAChE,YAAM,eAAe,SAAS,UAAU,SAAS,YAAY;AAM7D,YAAM,cAAc,QAAQ,aAAa,QAAQ;AACjD,YAAM,cAAc,QAAQ,aACxB,aAAa,EAAE,GAAG,QAAQ,MAAM,OAAU,GAAG,OAAO,EAAE,OACtD;AAGJ,YAAM,UAAoB;AAAA,QACxB,GAAG;AAAA,QACH,MAAM;AAAA,QACN,WAAW;AAAA,QACX,OAAO;AAAA,QACP,aAAa,IAAI;AAAA,QACjB,GAAI,aAAa,EAAE,UAAU,WAAW,IAAI,CAAC;AAAA,MAC/C;AACA,YAAM,SAAS,OAAO,QAAQ,UAAa,OAAO,SAAS;AAE3D,UAAI,CAAC,OAAO,MAAM;AAGhB,gBAAQ,KAAK;AAAA,UACX,GAAGA;AAAA,UACH,OAAO;AAAA,UACP,aAAa;AAAA,UACb,UAAU;AAAA,UACV,GAAI,aAAa,EAAE,UAAU,WAAW,IAAI,CAAC;AAAA,QAC/C,CAAC;AACD,gBAAQ,KAAK,OAAO;AACpB,gBAAQ;AACR;AAAA,MACF;AAEA,UAAI,OAAO,SAAS,aAAa;AAC/B,gBAAQ,KAAK;AAAA,UACX,GAAGA;AAAA,UACH,OAAO;AAAA,UACP;AAAA,UACA,UAAU;AAAA,UACV,UAAU,UAAU,QAAQ,YAAY;AAAA,UACxC,GAAI,aAAa,EAAE,UAAU,WAAW,IAAI,CAAC;AAAA;AAAA;AAAA,UAG7C,GAAI,gBAAgB,OAAO,QAAQ,QAAQ,UAAU,IACjD,EAAE,QAAQ,mBAA4B,IACtC,CAAC;AAAA,UACL,GAAI,SAAS,EAAE,aAAa,mBAA4B,IAAI,CAAC;AAAA,UAC7D,GAAI,aAAa,EAAE,aAAa,KAAK,IAAI,CAAC;AAAA,QAC5C,CAAC;AACD,gBAAQ,KAAK,aAAa,UAAU,MAAM;AAC1C,YAAI,WAAY,SAAQ;AACxB;AAAA,MACF;AAKA,YAAM,YAAY,SACd,SAAS,QAAQ,QAAQ,SAAS,IAClC;AACJ,UAAI,aAAa,UAAU,SAAS,OAAO,MAAM;AAC/C,gBAAQ,KAAK;AAAA,UACX,GAAGA;AAAA,UACH,OAAO;AAAA,UACP,aAAa,UAAU;AAAA,UACvB,UAAU,UAAU,QAAQ,UAAU,KAAK;AAAA,UAC3C,aAAa;AAAA,QACf,CAAC;AACD,gBAAQ,KAAK,MAAM;AACnB;AAAA,MACF;AAEA,cAAQ,KAAK;AAAA,QACX,GAAGA;AAAA,QACH,OAAO;AAAA,QACP;AAAA,QACA,UAAU;AAAA,QACV,GAAI,aAAa,EAAE,UAAU,WAAW,IAAI,CAAC;AAAA,QAC7C,GAAI,SAAS,EAAE,aAAa,cAAuB,IAAI,CAAC;AAAA,MAC1D,CAAC;AAKD,YAAM,UAAU,WAAW,OAAO,gBAAgB;AAClD,cAAQ,KAAK,UAAU,EAAE,GAAG,QAAQ,aAAa,IAAI,EAAE,IAAI,MAAM;AACjE,UAAI,QAAS,SAAQ;AAAA,IACvB;AAMA,QAAI,SAAS;AACb,QAAI,OAAO;AACT,UAAI;AACF,cAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAAA,MAC/C,SAAS,OAAO;AACd,YAAI,EAAE,iBAAiB,mBAAoB,OAAM;AACjD,iBAAS;AAAA,MACX;AACA,UAAI,CAAC,OAAQ,OAAM,MAAM,cAAc,MAAM,IAAI,SAAS,KAAK;AAAA,IACjE;AACA,UAAM,aAAa,SACf,EAAE,QAAQ,MAAM,MAAM,sCAAsC,IAC5D,CAAC;AAGL,UAAM,QAAQ,aAAa;AAC3B,UAAM,WAAW,MAAM,SAAS,EAAE,MAAM,IAAI,CAAC;AAM7C,UAAM,cAAc,QAAQ;AAAA,MAAO,CAAC,UAClC,kBAAkB,MAAM,MAAM;AAAA,IAChC,EAAE;AACF,UAAM,UAAU,QAAQ,SAAS;AACjC,UAAMC,WAAU,QAAQ,OAAO,CAAC,UAAU,MAAM,UAAU,OAAO,EAAE;AACnE,UAAM,OAAO,GAAGA,QAAO,IAAI,OAAO,iBAChC,cAAc,KAAK,WAAW,iBAAiB,EACjD;AACA,UAAM,QAAQ,UAAU,KAAKA,aAAY,WAAW,gBAAgB;AACpE,QAAI,OAAO;AACT,UAAI;AACF,cAAM,MAAM;AAAA,UACV;AAAA,UACA;AAAA,UACA,mBAAmB,IAAI,KAAK,gBAAgB,OAAO,CAAC;AAAA,UACpD;AAAA,UACA,IAAI;AAAA,QACN;AAAA,MACF,SAAS,OAAO;AAGd,YAAI,EAAE,iBAAiB,yBAA0B,OAAM;AACvD,eAAO;AAAA,UACL,WAAW;AAAA,UACX;AAAA,UACA,UAAU;AAAA,UACV,eAAe;AAAA,UACf,GAAG;AAAA,UACH,GAAG;AAAA,QACL;AAAA,MACF;AACA,aAAO;AAAA,QACL,WAAW;AAAA,QACX;AAAA,QACA,UAAU;AAAA,QACV,GAAG;AAAA,QACH,GAAG;AAAA,MACL;AAAA,IACF;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,MACX;AAAA,MACA,UAAU;AAAA,MACV,GAAI,cAAc,EAAE,KAAK,IAAI,CAAC;AAAA,MAC9B,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,CAAC,WACT,OAA8C,QAAQ;AAAA,IACrD,CAAC,UACC,MAAM,UAAU,aACf,MAAM,UAAU,gBACf,MAAM,eAAe,UACrB,CAAC,kBAAkB,MAAM,MAAM;AAAA,EACrC;AACJ,CAAC;AAED,SAAS,UAAU,QAAkB,SAAgC;AACnE,SAAO,OAAO,UAAU,SAAY,OAAO,KAAK,IAAI,UAAU,OAAO,KAAK;AAC5E;AAGA,SAAS,SACP,QACA,QACA,WAC6C;AAC7C,MAAI,OAAO,SAAS,OAAW,QAAO;AACtC,QAAM,UAAU,kBAAkB,OAAO,MAAM,QAAQ,SAAS;AAChE,MAAI,CAAC,QAAQ,GAAI,QAAO;AACxB,SAAO;AAAA,IACL,MAAM,eAAe,QAAQ,KAAK,IAAI;AAAA,IACtC,OAAO,QAAQ,KAAK,UAAU,QAAQ,KAAK,YAAY;AAAA,EACzD;AACF;AAOA,eAAe,YACb,SACA,MACA,SACsC;AACtC,QAAM,SAAS,IAAI,WAAW,IAAI;AAClC,MAAI,QAAQ,KAAK,CAAC,WAAW,OAAO,IAAI,EAAG,OAAM,OAAO,MAAM;AAC9D,QAAM,UAAU,IAAI;AAAA,IAClB,QAAQ,IAAI,CAAC,WAAW,CAAC,QAAQ,OAAO,UAAU,MAAM,CAAC,CAAU;AAAA,EACrE;AAEA,QAAM,QAAQ,QAAQ,OAAO,CAAC,WAAW,CAAC,QAAQ,IAAI,MAAM,CAAC;AAC7D,QAAM,SAAS,QAAQ,OAAO,CAAC,WAAW,QAAQ,IAAI,MAAM,CAAC;AAC7D,QAAM,QAAQ,MAAM;AAAA,IAClB,MAAM,IAAI,CAAC,WAAW,OAAO,IAAI;AAAA,IACjC,iBAAiB,IAAI;AAAA,EACvB;AACA,QAAM,QAAQ,MAAM,kBAAkB,OAAO,QAAQ,WAAW,GAAG;AAAA,IACjE;AAAA,EACF,CAAC;AAED,QAAM,UAAU,oBAAI,IAA4B;AAChD,aAAW,UAAU,OAAO;AAC1B,UAAM,OAAO,MAAM,IAAI,OAAO,IAAI;AAClC,YAAQ;AAAA,MACN;AAAA,MACA,KAAK,KACD,EAAE,IAAI,MAAM,QAAQ,KAAK,OAAO,IAChC,EAAE,IAAI,OAAO,QAAQ,KAAK,OAAO;AAAA,IACvC;AAAA,EACF;AACA,aAAW,UAAU,QAAQ;AAC3B,UAAM,OAAO,OAAO;AACpB,UAAM,MAAM,iBAAiB,IAAI;AACjC,UAAM,YAAY,MAAM,IAAI,QAAQ,KAAK,QAAW,OAAO,IAAI,CAAC;AAChE,UAAM,UAAU,OAAO,MACnB,MAAM,IAAI,QAAQ,KAAK,OAAO,KAAK,OAAO,IAAI,CAAC,IAC/C;AACJ,QAAI,CAAC,SAAS,IAAI;AAChB,cAAQ,IAAI,QAAQ;AAAA,QAClB,IAAI;AAAA,QACJ,QAAQ,SAAS,OAAO,QAAQ,QAAQ,SAAS;AAAA,QACjD;AAAA,MACF,CAAC;AACD;AAAA,IACF;AACA,YAAQ,IAAI,QAAQ;AAAA,MAClB,IAAI;AAAA,MACJ,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA,GAAI,OAAO,OAAO,WAAW,KAAK,EAAE,MAAM,UAAU,OAAO,IAAI,CAAC;AAAA,IAClE,CAAC;AAAA,EACH;AACA,SAAO;AACT;;;AgChbA,IAAAC,cAAkB;AAIX,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,cAAE,OAAO,EAAE,YAAY,WAAW,QAAQ,cAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,EACpE,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,QAAQ,KAAK,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK;AAAA,EACvC;AAAA,EACA,KAAK,OACH,EAAE,OAAO,MAAM,GACf,EAAE,YAAY,MAAM,WAAW,IAAI,OAAO,MACvC;AACH,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM,OAAO,MAAM,IAAI,QAAQ,KAAK;AACzD,WAAO,EAAE,WAAW,OAAO,UAAU;AAAA,EACvC;AACF,CAAC;;;ACxBD,IAAAC,cAAkB;AAGX,IAAM,mBAAmB,OAAO;AAAA,EACrC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,cAAE,OAAO,EAAE,YAAY,UAAU,CAAC;AAAA,EACzC,UAAU,CAAC,MAAM,UAAU,EAAE,YAAY,MAAM,WAAW,KAAK,CAAC,EAAE;AAAA,EAClE,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,WAAW,GAAG,MACvD,MAAM,UAAU,MAAM,EAAE;AAC5B,CAAC;;;ACbD,IAAAC,eAAkB;;;ACmElB,IAAM,WAA+C;AAAA,EACnD,UAAU;AAAA,EACV,UAAU;AAAA,EACV,OAAO;AAAA,EACP,UAAU;AAAA,EACV,MAAM;AAAA,EACN,UAAU;AAAA,EACV,YAAY;AACd;AASO,SAAS,WACd,MACA,QACA,MAAM,oBAAI,KAAK,GAGf,aACiB;AACjB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,SAAO,KAAK,IAAI,CAAC,WAAW;AAC1B,UAAM,SAAS,OAAO,YAAY;AAClC,UAAM,WAAwB,CAAC;AAC/B,QAAI,QAAoB,CAAC;AAEzB,QAAI,WAAW,cAAc;AAC3B,YAAM,WAAW,aAAa,QAAQ,IAAI;AAC1C,cAAQ,SAAS;AACjB,eAAS,KAAK,GAAG,SAAS,QAAQ;AAClC,UAAI,MAAM,QAAQ;AAChB,iBAAS,KAAK;AAAA,UACZ,MAAM;AAAA,UACN,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,QACxC,CAAC;AAAA,MACH;AAAA,IACF,WAAW,WAAW,YAAY;AAChC,eAAS,KAAK,EAAE,MAAM,WAAW,CAAC;AAAA,IACpC,WAAW,WAAW,WAAW,WAAW,YAAY;AACtD,eAAS,KAAK,EAAE,MAAM,aAAa,OAAO,CAAC;AAAA,IAC7C,WAAW,WAAW,QAAQ;AAC5B,eAAS,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAAA,IAC/C;AAEA,UAAM,aAAa,OAAO,YAAY;AACtC,QAAI,cAAc,KAAK,MAAM,UAAU,IAAI,IAAI,QAAQ,GAAG;AACxD,eAAS,KAAK,EAAE,MAAM,SAAS,WAAW,CAAC;AAAA,IAC7C;AACA,QAAI,CAAC,OAAO,YAAY,UAAU,QAAQ;AACxC,eAAS,KAAK,EAAE,MAAM,aAAa,CAAC;AAAA,IACtC;AAIA,UAAM,SAAS,aAAa,IAAI,OAAO,SAAS,KAAK,CAAC,GAAG;AAAA,MACvD,CAAC,UAAU,MAAM,UAAU;AAAA,IAC7B;AACA,UAAMC,aAAY,MAAM,OAAO,CAAC,UAAU,kBAAkB,MAAM,MAAM,CAAC;AACzE,UAAM,QAAQ,MAAM,OAAO,CAAC,UAAU,CAAC,kBAAkB,MAAM,MAAM,CAAC;AACtE,QAAI,MAAM,QAAQ;AAChB,eAAS,KAAK,EAAE,MAAM,WAAW,SAAS,MAAM,IAAI,aAAa,EAAE,CAAC;AAAA,IACtE;AACA,QAAIA,WAAU,QAAQ;AACpB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,SAASA,WAAU,IAAI,aAAa;AAAA,MACtC,CAAC;AAAA,IACH;AAEA,WAAO,EAAE,QAAQ,UAAU,SAAS,MAAM,GAAG,OAAO,SAAS;AAAA,EAC/D,CAAC;AACH;AAEA,SAAS,cAAc,OAA4C;AACjE,QAAM,EAAE,MAAM,QAAQ,UAAU,QAAQ,MAAM,YAAY,IAAI;AAC9D,SAAO;AAAA,IACL;AAAA,IACA,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,IACzC;AAAA,IACA,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,IACzC,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,IACrC,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,IACnD,GAAI,MAAM,UAAU,SAAY,EAAE,OAAO,MAAM,MAAM,IAAI,CAAC;AAAA,EAC5D;AACF;AAeO,SAAS,aACd,MACA,MAC8C;AAC9C,QAAM,WAAwB,CAAC;AAC/B,QAAM,QAAQ,oBAAI,IAAsB;AACxC,QAAM,OAAO,oBAAI,IAAY,CAAC,KAAK,SAAS,CAAC;AAC7C,QAAM,QAAoB,CAAC,IAAI;AAE/B,SAAO,MAAM,QAAQ;AACnB,UAAM,UAAU,MAAM,MAAM;AAC5B,UAAM,OAAO,WAAW,SAAS,IAAI;AAErC,eAAWC,YAAW,KAAK,SAAS;AAClC,eAAS,KAAK,EAAE,MAAM,gBAAgB,SAAAA,SAAQ,CAAC;AAAA,IACjD;AACA,QAAI,CAAC,KAAK,QAAQ,QAAQ;AACxB,UAAI,QAAQ,cAAc,KAAK;AAC7B,cAAM,IAAI,QAAQ,WAAW,OAAO;AACtC;AAAA,IACF;AACA,eAAW,UAAU,KAAK,SAAS;AACjC,UAAI,KAAK,IAAI,OAAO,SAAS,GAAG;AAC9B,iBAAS,KAAK,EAAE,MAAM,eAAe,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC;AACzD;AAAA,MACF;AACA,WAAK,IAAI,OAAO,SAAS;AACzB,YAAM,KAAK,MAAM;AAAA,IACnB;AAAA,EACF;AAEA,MAAI,MAAM,OAAO,GAAG;AAClB,aAAS,KAAK,EAAE,MAAM,gBAAgB,OAAO,CAAC,GAAG,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,EAClE;AACA,SAAO,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,SAAS;AAChD;AAEA,SAAS,WACP,QACA,MAC4C;AAC5C,QAAM,MAAM,oBAAI,IAAY;AAC5B,QAAM,UAAU,OAAO,YAAY;AACnC,MAAI,QAAS,KAAI,IAAI,OAAO;AAC5B,aAAW,CAAC,IAAI,SAAS,KAAK,MAAM;AAClC,QAAI,UAAU,YAAY,oBAAoB,SAAS,OAAO,SAAS,GAAG;AACxE,UAAI,IAAI,EAAE;AAAA,IACZ;AAAA,EACF;AAEA,QAAM,UAAsB,CAAC;AAC7B,QAAMA,WAAoB,CAAC;AAC3B,aAAW,MAAM,KAAK;AACpB,UAAM,QAAQ,KAAK,IAAI,EAAE;AACzB,QAAI,MAAO,SAAQ,KAAK,KAAK;AAAA,QACxB,CAAAA,SAAQ,KAAK,EAAE;AAAA,EACtB;AACA,SAAO,EAAE,SAAS,SAAAA,SAAQ;AAC5B;;;ACpNO,SAAS,YAAY,QAAkB,QAA8B;AAC1E,MAAI,CAAC,OAAO,MAAM,UAAU,CAAC,OAAO,aAAa,OAAQ,QAAO;AAChE,QAAM,UAAU,IAAI,IAAI,OAAO,YAAY,QAAQ,CAAC,CAAC;AACrD,UACG,OAAO,QAAQ,CAAC,GAAG,MAAM,CAAC,QAAQ,QAAQ,IAAI,GAAG,CAAC,KACnD,EAAE,OAAO,eAAe,CAAC,GAAG,KAAK,CAAC,QAAQ,QAAQ,IAAI,GAAG,CAAC;AAE9D;;;ACaA,IAAM,kBAA8C;AAAA,EAClD,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AAAA,EACX,MAAM;AACR;AAgCO,SAAS,QACd,QACA,UAAuD,CAAC,GACvC;AACjB,QAAM,SAAS,QAAQ,OACnB,OAAO,OAAO,CAAC,WAAW,OAAO,YAAY,SAAS,QAAQ,IAAI,IAClE;AAKJ,QAAM,UAAU,WAAW,QAAQ,QAAQ,QAAQ,OAAO,oBAAI,KAAK,CAAC,EAGjE,OAAO,CAAC,QAAQ,YAAY,IAAI,QAAQ,OAAO,CAAC,EAChD,IAAI,CAAC,SAAS;AAAA,IACb,WAAW,IAAI,OAAO;AAAA,IACtB,MAAM,IAAI,OAAO,YAAY;AAAA,IAC7B,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,IACvC,UAAU,IAAI;AAAA,IACd,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,IACpD,OAAO,IAAI,SAAS,KAAK,CAAC,YAAY,QAAQ,SAAS,OAAO;AAAA,EAChE,EAAE,EACD,KAAK,eAAe;AAEvB,QAAM,YAAY,EAAE,GAAG,gBAAgB;AACvC,aAAW,SAAS,QAAS,WAAU,MAAM,QAAQ,KAAK;AAE1D,SAAO;AAAA,IACL;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB;AAAA,IACA,cAAc,UAAU;AAAA,IACxB,iBAAiB,UAAU;AAAA,IAC3B,YAAY,QAAQ,OAAO,CAAC,UAAU,MAAM,KAAK,EAAE;AAAA,EACrD;AACF;AAGA,SAAS,gBAAgB,MAAsB,OAA+B;AAC5E,SACE,WAAW,KAAK,MAAM,MAAM,IAAI,KAChC,WAAW,KAAK,SAAS,IAAI,MAAM,SAAS,EAAE,KAC9C,WAAW,KAAK,WAAW,MAAM,SAAS;AAE9C;AAUA,SAAS,WAAW,MAAc,OAAuB;AACvD,SAAO,OAAO,QAAQ,KAAK,OAAO,QAAQ,IAAI;AAChD;AAQO,SAAS,kBAAkB,OAA+B;AAC/D,QAAM,QAAQ;AAAA,IACZ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,MAAM,SAAS;AAAA,IACf,MAAM,aAAa,eACf,qBAAgB,MAAM,aAAa,KAAK,IAAI,KAAK,qBAAqB,KACtE,MAAM;AAAA,EACZ;AACA,MAAI,MAAM,MAAO,OAAM,KAAK,OAAO;AACnC,SAAO,KAAK,MAAM,KAAK,QAAK,CAAC;AAC/B;;;AH3IO,IAAM,iBAAiB,OAAO;AAAA,EACnC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,MAAM,eAAE,KAAK,eAAe,EAAE,SAAS;AAAA,IACvC,MAAM;AAAA,EACR,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,OAAO,UAAU,MAAM,OAAO;AAGpC,UAAM,OAAO,eAAe,MAAM,OAAO;AACzC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,KAAK,SAAS,EAAE,KAAK,IAAI,CAAC;AAAA,IAChC;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,MAAM,KAAK,MACpD;AAAA,IACE,MAAM,MAAM,QAAQ,MAAM;AAAA,MACxB,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACzB,CAAC;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACJ,CAAC;AAMD,SAAS,OACP,QACA,QACA,MACA,MACQ;AAGR,QAAM,WAAW;AAAA,IACf,GAAI,OAAO,CAAC,IAAI,IAAI,CAAC;AAAA,IACrB,GAAI,MAAM,SAAS,CAAC,SAAS,KAAK,KAAK,IAAI,CAAC,EAAE,IAAI,CAAC;AAAA,EACrD,EAAE,KAAK,QAAK;AACZ,QAAM,QAAQ;AAAA,IACZ,eAAe,WAAW,WAAM,QAAQ,KAAK,EAAE;AAAA,IAC/C,WAAW,MAAM;AAAA,IACjB,GAAG,MAAM,OAAO,aAAa,QAAQ,CAAC,KAAK,eAAe,MAAM,CAAC;AAAA,EACnE;AAKA,MAAI,OAAO,YAAY;AACrB,UAAM;AAAA,MACJ,GAAG,OAAO,UAAU;AAAA,IACtB;AAAA,EACF;AAEA,QAAM,KAAK,EAAE;AAEb,MAAI,CAAC,OAAO,QAAQ,QAAQ;AAC1B,UAAM;AAAA,MACJ,WACI,wBAAwB,QAAQ,MAChC;AAAA,IACN;AAAA,EACF,OAAO;AACL,eAAW,SAAS,OAAO,QAAS,OAAM,KAAK,kBAAkB,KAAK,CAAC;AAAA,EACzE;AAEA,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAOA,SAAS,eAAe,QAAiC;AACvD,QAAM,QAA+B;AAAA,IACnC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,QAAQ,MAAM,OAAO,CAAC,aAAa,OAAO,UAAU,QAAQ,CAAC,EAAE;AAAA,IACnE,CAAC,aAAa,GAAG,OAAO,UAAU,QAAQ,CAAC,IAAI,QAAQ;AAAA,EACzD;AACA,SAAO,MAAM,SAAS,MAAM,KAAK,QAAK,IAAI;AAC5C;AAEA,SAAS,MAAM,OAAe,MAAsB;AAClD,SAAO,GAAG,KAAK,IAAI,UAAU,IAAI,OAAO,GAAG,IAAI,GAAG;AACpD;;;AItHA,IAAAC,eAAkB;;;ACAlB,IAAAC,mBAAoC;;;ACE7B,IAAM,aAAa;AAE1B,IAAM,UAAU;AAcT,SAAS,YAAY,SAA6B;AACvD,QAAM,QAAQ,CAAC,GAAG,OAAO,EACtB,KAAK,CAAC,MAAM,UAAU,KAAK,UAAU,cAAc,MAAM,SAAS,CAAC,EACnE,IAAI,eAAe;AAEtB,SAAO,GAAG,OAAO;AAAA;AAAA,EAAO,MAAM,KAAK,IAAI,CAAC;AAAA;AAC1C;AAOO,SAAS,gBAAgB,QAA0B;AACxD,QAAM,EAAE,aAAa,GAAG,IAAI;AAC5B,QAAM,QAAQ,CAAC,GAAG,MAAM,GAAG,cAAc;AACzC,MAAI,GAAG,MAAM,OAAQ,OAAM,KAAK,SAAS,GAAG,KAAK,KAAK,IAAI,CAAC,EAAE;AAC7D,MAAI,GAAG,YAAa,OAAM,KAAK,GAAG,WAAW;AAC7C,SAAO,MAAM,GAAG,SAAS,OAAO,SAAS,KAAK,OAAO,SAAS,eAAU,MAAM,KAAK,QAAK,CAAC;AAC3F;AAGO,SAAS,aAAa,QAAuB,UAA2B;AAC7E,SAAO,WAAW;AACpB;;;ADjBA,IAAMC,WAAU;AAMhB,IAAM,yBAAyB;AASxB,IAAM,mBAAqD;AAAA,EAChE,iBAAiB,EAAE,iBAAiB,KAAM;AAAA,EAC1C,SAAS,EAAE,cAAc,KAAM;AAAA,EAC/B,MAAM,EAAE,cAAc,KAAM;AAC9B;AAwCA,SAAS,aAAa,MAAsB;AAC1C,SAAO,KAAK,KAAK,KAAK,SAAS,CAAC;AAClC;AAEA,SAAS,WAAmB;AAC1B,SAAO;AAAA,IACLA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,IAAI;AACb;AAeA,eAAe,WACb,OACA,MACA,cACA,iBACA,SACA,cACA,aACsB;AACtB,QAAM,SAAS,MAAM,MAAM,KAAK,YAAY;AAC5C,MAAI,OAAO,WAAW,GAAG;AACvB,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA,EACF;AAMA,QAAM,UACJ,YAAY,SACR,eACA,YAAY,UACV,IACA;AAER,MAAI;AACJ,MAAI,UAAU,GAAG;AACf,UAAM,OAAO,MAAM,MAAM,KAAK,cAAc;AAAA,MAC1C,cAAc;AAAA,MACd;AAAA,IACF,CAAC;AACD,QAAI,CAAC,KAAK,UAAU,YAAY,QAAQ;AACtC,qBAAe,EAAE,cAAc,KAAK,aAAa;AAAA,IACnD;AACA,QAAI,KAAK,QAAQ;AACf,YAAM,UAAU,KAAK,QAAQ;AAAA,QAAI,CAAC,QAChC;AAAA,UACE,QAAQ,IAAI,OAAO,SAAS,WAAM,IAAI,OAAO,YAAY,SAAS,YAAY,KAAK,IAAI,QAAQ;AAAA,UAC/F;AAAA,UACA,IAAI,OAAO,KAAK,KAAK;AAAA,QACvB,EAAE,KAAK,IAAI;AAAA,MACb;AACA,YAAMC,cAAa,KAAK,WAAW;AAAA,QACjC,CAAC,UACC,OAAO,MAAM,SAAS,2BAAsB,MAAM,aAAa,IAAI,CAAC,OAAO,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,KAAK,uBAAuB;AAAA,MACjI;AACA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,GAAG;AAAA,UACH,GAAIA,YAAW,SACX;AAAA,YACE;AAAA,YACA,GAAGA;AAAA,UACL,IACA,CAAC;AAAA,QACP,EAAE,KAAK,MAAM;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAIA,QAAM,cAAc,WAAW,QAAQ,MAAM,EAAE;AAAA,IAAO,CAAC,QACrD,YAAY,IAAI,QAAQ,EAAE,YAAY,CAAC;AAAA,EACzC;AACA,QAAM,QAAQ,YACX,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C,IAAI,CAAC,QAAQ,gBAAgB,IAAI,MAAM,CAAC;AAC3C,QAAM,aAAa,YAChB,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C;AAAA,IACC,CAAC,QACC,OAAO,IAAI,OAAO,SAAS,2BAAsB,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,KAAK,uBAAuB;AAAA,EAC3I;AACF,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,MAAM;AAAA,IACN,MAAM,CAAC,GAAG,OAAO,GAAG,UAAU,EAAE,KAAK,IAAI;AAAA,IACzC,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,EACzC;AACF;AAOA,eAAsB,aACpB,OACA,cACA,UAA4B,CAAC,GACH;AAC1B,QAAM,UAAU,QAAQ,UACnB,iBAAiB,QAAQ,OAAO,KAAK,CAAC,IACvC,CAAC;AACL,MAAI,eACF,QAAQ,gBAAgB,QAAQ,gBAAgB;AAClD,MAAI,kBAAkB,QAAQ,mBAAmB,QAAQ,mBAAmB;AAM5E,QAAM,SAAS,MAAM,eAAe,YAAY;AAIhD,QAAM,eAAe,qBAAqB,QAAQ,QAAQ,OAAO;AACjE,iBACE,QAAQ,gBACR,aAAa,gBACb,QAAQ,gBACR;AACF,oBACE,QAAQ,mBACR,aAAa,mBACb,QAAQ,mBACR;AACF,QAAM,cACJ,QAAQ,eACR,aAAa,eACb,QAAQ,eACR,CAAC;AAKH,QAAM,OAAO,OAAO,KAAK;AAAA,IACvB,CAAC,QACC,CAAC,IAAI,UAAU,UACf,CAAC,QAAQ,WACT,IAAI,SAAS,SAAS,QAAQ,OAAO;AAAA,EACzC;AACA,MAAI,KAAK,WAAW,GAAG;AACrB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,MACA,OAAO,CAAC;AAAA,IACV;AAAA,EACF;AAEA,QAAM,WAAW,MAAM,QAAQ;AAAA,IAC7B,KAAK,IAAI,OAAO,SAAS;AAAA,MACvB,SAAS,MAAM;AAAA,QACb;AAAA,QACA,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ;AAAA,QACA,IAAI;AAAA,QACJ;AAAA,QACA;AAAA,MACF;AAAA,MACA,QAAQ,IAAI,WAAW;AAAA,IACzB,EAAE;AAAA,EACJ;AAEA,QAAM,YAAY;AAAA,IAChB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAMA,aAAW,EAAE,QAAQ,KAAK,UAAU;AAClC,QAAI,QAAQ,cAAc;AACxB,cAAQ,OAAO;AAAA,QACb,WAAW;AAAA,QACX,MAAM,QAAQ;AAAA,QACd,cAAc,QAAQ,aAAa;AAAA,QACnC;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,WAAW,SAAS,IAAI,CAAC,EAAE,SAAS,OAAO,MAAM;AACrD,UAAM,QAAQ,QAAQ,eAClB,qDAAgD,QAAQ,aAAa,YAAY,+BAA+B,YAAY,mGAC5H,UAAU,QAAQ,IAAI;AAC1B,WAAO;AAAA,MACL,OAAO,QAAQ,IAAI,KAAK,KAAK,GAAG,SAAS,4BAAyB,EAAE;AAAA,MACpE;AAAA,MACA,iBAAiB,QAAQ,YAAY;AAAA,MACrC;AAAA,MACA,QAAQ;AAAA,IACV,EAAE,KAAK,IAAI;AAAA,EACb,CAAC;AAED,QAAM,QAAQ,CAAC,SAAS,GAAG,IAAI,SAAS,KAAK,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI;AACnE,QAAM,QAAQ,SAAS,IAAI,CAAC,EAAE,QAAQ,OAAO;AAAA,IAC3C,MAAM,QAAQ;AAAA,IACd,cAAc,QAAQ;AAAA,IACtB,cAAc,aAAa,QAAQ,IAAI;AAAA,EACzC,EAAE;AACF,QAAM,QAAQ,aAAa,KAAK;AAEhC,MAAI,QAAQ,cAAc;AACxB,YAAQ,OAAO;AAAA,MACb,WAAW;AAAA,MACX,cAAc;AAAA,MACd;AAAA,MACA,OAAO,MAAM,IAAI,CAACC,UAASA,MAAK,IAAI;AAAA,IACtC,CAAC;AAKD,UAAM,UAAU;AAAA,MACdF;AAAA,MACA;AAAA,MACA,6BAA6B,KAAK,qBAAqB,YAAY;AAAA,MACnE;AAAA,MACA;AAAA,MACA;AAAA,MACA,GAAG,MAAM;AAAA,QACP,CAACE,UACC,KAAKA,MAAK,IAAI,YAAOA,MAAK,YAAY,0BAA0BA,MAAK,YAAY;AAAA,MACrF;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AACX,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS,OAAO,cAAc,OAAO,cAAc,MAAM;AAC3E;AAQO,SAAS,WAAW,OAAe,OAAuB;AAC/D,SAAO,KAAK,UAAU;AAAA,IACpB,oBAAoB;AAAA,MAClB,eAAe;AAAA,MACf,mBAAmB;AAAA,IACrB;AAAA,EACF,CAAC;AACH;AAEO,IAAM,gBAAgB;AACtB,IAAM,cAAc;AAa3B,eAAsB,iBACpB,MACA,OACuB;AACvB,QAAM,WAAW,UAAM,2BAAS,MAAM,MAAM,EAAE,MAAM,MAAM,IAAI;AAC9D,QAAM,SAAS,QACX,GAAG,aAAa;AAAA,EAAK,MAAM,KAAK,CAAC;AAAA,EAAK,WAAW,KACjD;AAEJ,MAAI,aAAa,MAAM;AACrB,QAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,QAAQ,YAAY;AAChD,cAAM,4BAAU,MAAM,GAAG,MAAM;AAAA,GAAM,MAAM;AAC3C,WAAO,EAAE,MAAM,QAAQ,UAAU;AAAA,EACnC;AAEA,QAAM,QAAQ,SAAS,QAAQ,aAAa;AAC5C,QAAM,MAAM,SAAS,QAAQ,WAAW;AACxC,MAAI,UAAU,MAAM,QAAQ,MAAM,OAAO,OAAO;AAC9C,UAAM,SAAS,SAAS,MAAM,GAAG,KAAK;AACtC,UAAM,QAAQ,SAAS,MAAM,MAAM,YAAY,MAAM;AACrD,UAAM,OAAO,SACT,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,KAC1B,GAAG,OAAO,QAAQ,QAAQ,IAAI,CAAC,GAAG,MAAM,QAAQ,QAAQ,IAAI,CAAC;AACjE,QAAI,SAAS,SAAU,QAAO,EAAE,MAAM,QAAQ,YAAY;AAC1D,cAAM,4BAAU,MAAM,MAAM,MAAM;AAClC,WAAO,EAAE,MAAM,QAAQ,SAAS,aAAa,UAAU;AAAA,EACzD;AAEA,MAAI,CAAC,OAAQ,QAAO,EAAE,MAAM,QAAQ,YAAY;AAChD,YAAM;AAAA,IACJ;AAAA,IACA,GAAG,SAAS,QAAQ,QAAQ,MAAM,CAAC,GAAG,MAAM;AAAA;AAAA,IAC5C;AAAA,EACF;AACA,SAAO,EAAE,MAAM,QAAQ,WAAW;AACpC;;;ADtbO,IAAM,iBAAiB,OAAO;AAAA,EACnC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd,cAAc,eACX,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,iBAAiB,eACd,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,SAAS,eACN,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,aAAa,eACV,MAAM,eAAE,OAAO,EAAE,IAAI,CAAC,CAAC,EACvB,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,QAAQ,eACL,KAAK,CAAC,YAAY,MAAM,CAAC,EACzB,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,OAAO,eACJ,OAAO,EACP,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,SAAS;AAClB,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAM,YAAY,SAAS,MAAM,cAAc;AAC/C,UAAM,UAAU,SAAS,MAAM,WAAW;AAC1C,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAM,QAAQ,SAAS,MAAM,SAAS;AACtC,UAAM,cAAc,UAAU,MAAM,eAAe;AACnD,WAAO;AAAA,MACL,GAAI,SAAS,EAAE,cAAc,OAAO,MAAM,EAAE,IAAI,CAAC;AAAA,MACjD,GAAI,YAAY,EAAE,iBAAiB,OAAO,SAAS,EAAE,IAAI,CAAC;AAAA,MAC1D,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,GAAI,YAAY,SAAS,EAAE,YAAY,IAAI,CAAC;AAAA,MAC5C,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,MAC3B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IAC3B;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,MAAM,GACR,EAAE,cAAc,iBAAiB,SAAS,aAAa,QAAQ,MAAM,MAClE;AACH,UAAM,SAAS,MAAM,aAAa,OAAO,QAAQ,IAAI,GAAG;AAAA,MACtD,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,MACvC,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,MAC7C,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,GAAI,cAAc,EAAE,YAAY,IAAI,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,MAKrC,MAAM,CAAC,UAAU,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI;AAAA,IACpE,CAAC;AAGD,QAAI,CAAC,OAAO,MAAO,QAAO;AAC1B,WAAO,WAAW,SACd,WAAW,OAAO,OAAO,SAAS,cAAc,IAChD,OAAO;AAAA,EACb;AACF,CAAC;;;AG3FD,IAAAC,eAAkB;;;ACAlB,IAAAC,6BAAyB;AACzB,IAAAC,oBAA0B;AAG1B,IAAMC,qBAAgB,6BAAU,mCAAQ;AAkBjC,IAAM,uBAAuB;AAEpC,IAAM,iBAAiB;AASvB,eAAeC,KAAI,KAAa,MAAoC;AAClE,QAAM,MAAM,EAAE,GAAG,QAAQ,IAAI;AAC7B,SAAO,IAAI,SAAS;AACpB,SAAO,IAAI,eAAe;AAC1B,SAAO,IAAI,gBAAgB;AAC3B,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAMD,eAAc,OAAO,CAAC,MAAM,KAAK,GAAG,IAAI,GAAG;AAAA,MAClE,SAAS;AAAA,MACT,WAAW;AAAA,MACX;AAAA,IACF,CAAC;AACD,WAAO,EAAE,IAAI,MAAM,OAAO;AAAA,EAC5B,QAAQ;AACN,WAAO,EAAE,IAAI,MAAM;AAAA,EACrB;AACF;AAGA,eAAsB,cAAc,UAAqC;AACvE,QAAM,SAAS,MAAMC,KAAI,UAAU,CAAC,YAAY,MAAM,UAAU,CAAC;AACjE,MAAI,CAAC,OAAO,GAAI,QAAO,CAAC;AACxB,SAAO,OAAO,OAAO,MAAM,IAAI,EAAE,OAAO,OAAO;AACjD;AA2BA,eAAsB,cACpB,UACA,QACoB;AACpB,MAAI,CAAC,eAAe,OAAO,IAAI;AAC7B,WAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAE9C,MAAI,OAAO,OAAO,eAAe,OAAO,GAAG,GAAG;AAC5C,UAAMC,SAAQ,MAAM,SAAS,UAAU,OAAO,KAAK,OAAO,IAAI;AAC9D,QAAIA,WAAU,MAAM;AAClB,aAAO;AAAA,QACL,IAAI;AAAA,QACJ,QAAQA;AAAA,QACR,QAAQ,EAAE,MAAM,OAAO,KAAK,OAAO,IAAI;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAEA,QAAMC,MAAK,OAAO;AAClB,MAAI,CAACA,OAAM,OAAO,MAAM,KAAK,MAAMA,GAAE,CAAC,GAAG;AACvC,WAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAAA,EAC9C;AAGA,QAAM,QAAQ,MAAMF,KAAI,UAAU;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA,YAAYE,GAAE;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,EACT,CAAC;AACD,QAAM,MAAM,MAAM,KAAK,MAAM,OAAO,KAAK,IAAI;AAC7C,MAAI,CAAC,OAAO,CAAC,eAAe,GAAG;AAC7B,WAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAE9C,QAAM,QAAQ,MAAM,SAAS,UAAU,KAAK,OAAO,IAAI;AACvD,MAAI,UAAU,KAAM,QAAO,EAAE,IAAI,OAAO,QAAQ,gBAAgB;AAChE,SAAO,EAAE,IAAI,MAAM,QAAQ,OAAO,QAAQ,EAAE,MAAM,WAAW,KAAK,IAAI,EAAE;AAC1E;AAGA,eAAe,SACb,UACA,KACA,MACwB;AACxB,QAAM,OAAO,KAAK,QAAQ,SAAS,EAAE;AACrC,QAAM,SAAS,MAAMF,KAAI,UAAU;AAAA,IACjC;AAAA,IACA;AAAA,IACA,GAAG,GAAG,IAAI,IAAI;AAAA,EAChB,CAAC;AACD,SAAO,OAAO,KAAK,OAAO,SAAS;AACrC;;;AC1IA,IAAAG,mBAAqB;AAoCd,IAAM,yBAAyB;AAUtC,IAAM,eAAe;AA8Bd,SAAS,YACd,UACA,UAA8B,CAAC,GAClB;AACb,QAAM,OAAO,QAAQ,UAAU,iBAAiB,QAAQ;AACxD,QAAM,SAAS,QAAQ,UAAU,SAAS,QAAQ;AAClD,QAAM,WAAW,IAAI,mBAAmB;AACxC,MAAI;AACJ,QAAM,WAAW,oBAAI,IAAY;AAEjC,QAAM,mBAAmB,OAAO,aAAwC;AACtE,kBAAc,cAAc,QAAQ;AACpC,YAAQ,MAAM,WACX,OAAO,CAAC,SAAS,gBAAgB,IAAI,MAAM,QAAQ,EACnD,MAAM,GAAG,sBAAsB;AAAA,EACpC;AAEA,SAAO;AAAA,IACL,MAAM,KAAK,QAAQ;AACjB,YAAM,SAAS,OAAO;AACtB,UAAI,CAAC,OAAQ,QAAO;AAEpB,YAAM,WAAW,gBAAgB,OAAO,IAAI;AAI5C,UAAI,CAAC,SAAU,QAAO,eAAe,QAAQ,MAAM,MAAM;AAEzD,YAAM,aAAa,MAAM,iBAAiB,QAAQ;AAClD,UAAI,CAAC,SAAS,IAAI,QAAQ,GAAG;AAC3B,cAAM,SAAS,QAAQ,WAAW,SAAS,aAAa,CAAC,OAAO,IAAI,CAAC;AACrE,iBAAS,IAAI,QAAQ;AAAA,MACvB;AAIA,YAAM,QAAQ,OAAO,SAAS;AAE9B,eAASC,MAAK,GAAGA,MAAK,WAAW,QAAQA,OAAM,cAAc;AAC3D,cAAM,QAAQ,WAAW,MAAMA,KAAIA,MAAK,YAAY;AACpD,cAAM,OAAO,MAAM;AAAA,UACjB;AAAA,UACA;AAAA,UACA,OAAO,SAAS;AACd,kBAAMC,QAAO,MAAM,OAAO,IAAI;AAG9B,gBAAIA,UAAS,QAAQA,QAAO,MAAO,QAAO;AAC1C,mBAAO,QAAQ,UAAU,MAAM,QAAQ,QAAQ,IAAI;AAAA,UACrD;AAAA,QACF;AAGA,cAAM,QAAQ,KAAK,KAAK,CAAC,QAAQ,QAAQ,MAAS;AAClD,YAAI,MAAO,QAAO;AAAA,MACpB;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,eAAe,QACb,UACA,MACA,QACA,QACA,MACqC;AACrC,QAAM,SAAS,MAAM,KAAK,IAAI;AAC9B,MAAI,CAAC,OAAO,GAAI,QAAO;AACvB,QAAM,aAAa,OAAO,OAAO,QAAQ,SAAS,IAAI;AAEtD,aAAW,SAAS,SAAS,MAAM,YAAY,IAAI,GAAG;AAGpD,UAAM,OACJ,OAAO,cAAc,QACjB,SAAS,UAAU,MAAM,KAAK,MAAM,IAAI,IACxC,MAAM,KAAK;AACjB,QAAI,SAAS,QAAQ,eAAe,IAAI,MAAM,OAAQ;AAGtD,QAAI,SAAS,OAAO,QAAQ,MAAM,WAAW,OAAO,OAAQ;AAC5D,WAAO;AAAA,MACL;AAAA,MACA,QAAQ,MAAM;AAAA,MACd,WAAW,MAAM,KAAK;AAAA,MACtB,SAAS,MAAM,KAAK;AAAA,IACtB;AAAA,EACF;AACA,SAAO;AACT;AAGA,SAAS,SAAS,UAA4D;AAC5E,SAAO,OAAO,SAAS;AACrB,UAAM,OAAO,eAAe,UAAU,IAAI;AAC1C,QAAI,SAAS,KAAM,QAAO;AAC1B,QAAI;AACF,cAAQ,UAAM,uBAAK,IAAI,GAAG;AAAA,IAC5B,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAGA,eAAe,eACb,QACA,MACA,QACqC;AACrC,QAAM,SAAS,OAAO;AAItB,MAAI,CAAC,UAAU,OAAO,cAAc,MAAO,QAAO;AAElD,QAAM,SAAS,MAAM,KAAK,OAAO,IAAI;AACrC,MAAI,CAAC,OAAO,GAAI,QAAO;AACvB,QAAM,QAAQ,OAAO,OAAO,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI;AAE7D,WAASD,MAAK,GAAGA,MAAK,UAAU,MAAM,QAAQA,OAAM;AAClD,QAAI,eAAe,MAAM,MAAMA,KAAIA,MAAK,MAAM,EAAE,KAAK,IAAI,CAAC,MAAM,QAAQ;AACtE;AAAA,IACF;AACA,WAAO;AAAA,MACL,MAAM,OAAO;AAAA,MACb,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;AAAA,MACjD,WAAWA,MAAK;AAAA,MAChB,SAASA,MAAK;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;;;ACxJA,eAAsB,cACpB,UACA,QACA,SACA,UAA2B,CAAC,GACC;AAG7B,QAAM,WAAW,OAAO,YAAY,mBAAmB,CAAC,GAAG;AAAA,IACzD,CAAC,WAAW,OAAO;AAAA,EACrB;AACA,QAAM,SAAS,QAAQ,UAAU,iBAAiB,QAAQ;AAC1D,QAAM,aAAa,IAAI,mBAAmB;AAC1C,QAAM,YAA8B,CAAC,YAAY,aAAa;AAC9D,QAAM,SACJ,QAAQ,UACR,YAAY,UAAU,EAAE,GAAI,QAAQ,SAAS,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAEjE,QAAM,SAA4D,CAAC;AACnE,UAAQ,QAAQ,CAAC,OAAOE,QAAO;AAC7B,UAAM,SAAS,QAAQA,GAAE;AACzB,QAAI,CAAC,OAAQ;AACb,QAAI,MAAM,UAAU,WAAW,kBAAkB,MAAM,MAAM,EAAG;AAChE,WAAO,KAAK,EAAE,QAAQ,MAAM,CAAC;AAAA,EAC/B,CAAC;AACD,MAAI,CAAC,OAAO,OAAQ,QAAO,CAAC;AAE5B,QAAM;AAAA,IACJ;AAAA,IACA,OAAO,IAAI,CAAC,EAAE,OAAO,MAAM,OAAO,IAAI;AAAA,EACxC;AAEA,QAAM,MAA0B,CAAC;AACjC,aAAW,EAAE,QAAQ,MAAM,KAAK,QAAQ;AACtC,UAAM,UAAU,MAAM,OAAO,KAAK,MAAM;AACxC,QAAI,SAAS;AACX,UAAI,KAAK;AAAA,QACP;AAAA,QACA,OAAO,EAAE,GAAG,OAAO,OAAO,SAAS,QAAQ;AAAA,QAC3C,OAAO;AAAA,MACT,CAAC;AACD;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,YAAY,QAAQ,QAAQ,SAAS;AAC3D,UAAM,MACJ,QAAQ,gBAAgB,QACpB,EAAE,IAAI,OAAgB,QAAQ,gBAAyB,IACvD,MAAM,cAAc,UAAU,MAAM;AAC1C,UAAM,UAAU,IAAI,KAAK,OAAO,IAAI,QAAQ,QAAQ,SAAS,IAAI;AAEjE,UAAM,UACJ,YAAY,UACZ,YAAY,UACZ,WAAW,YAAY,OAAO,MAAM,SAAS,OAAO,IAChD,aACC,MAAM,SAAS;AAEtB,QAAI,KAAK;AAAA,MACP;AAAA,MACA,OAAO,EAAE,GAAG,OAAO,OAAO,QAAQ;AAAA,MAClC,OAAO;AAAA,MACP,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC3C,GAAI,YAAY,SAAY,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC3C,GAAI,IAAI,KAAK,EAAE,WAAW,IAAI,OAAO,IAAI,CAAC;AAAA,IAC5C,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAOA,SAAS,WACP,UACA,MACA,QACA,OACS;AACT,MAAI,WAAW,MAAO,QAAO;AAC7B,QAAM,OAAO,SAAS,UAAU,QAAQ,IAAI;AAC5C,QAAM,QAAQ,SAAS,UAAU,OAAO,IAAI;AAC5C,SAAO,SAAS,QAAQ,SAAS;AACnC;AAEA,eAAe,YACb,QACA,QACA,WAC6B;AAC7B,QAAM,OAAO,MAAM,OAAO,OAAO,IAAI;AACrC,MAAI,CAAC,KAAK,GAAI,QAAO;AACrB,SAAO,OAAO,KAAK,QAAQ,QAAQ,SAAS;AAC9C;AAGA,SAAS,OACP,QACA,QACA,WACoB;AACpB,QAAM,UAAU,kBAAkB,QAAQ,QAAQ,SAAS;AAC3D,SAAO,QAAQ,KAAK,QAAQ,KAAK,OAAO;AAC1C;;;AC1JO,IAAM,wBAAwB;AAO9B,IAAM,0BAA0B;AAGhC,IAAM,wBAAwB;AAG9B,SAAS,WAAW,SAAyB;AAClD,MAAI,WAAW,EAAG,QAAO;AACzB,SAAO,KAAK;AAAA,IACV;AAAA,IACA,KAAK;AAAA,MACH;AAAA,MACA,KAAK,MAAM,0BAA0B,OAAO;AAAA,IAC9C;AAAA,EACF;AACF;AAoBO,SAAS,YACd,QACA,OACA,UAAuE,CAAC,GAC3D;AACb,QAAM,MAAM,QAAQ,YAAY;AAChC,QAAM,OAAO,OAAO,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI;AACrD,QAAM,QAAQ,MAAM,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI;AAErD,QAAM,OAAiB,CAAC;AACxB,MAAI,QAAQ;AACZ,MAAI,UAAU;AACd,aAAW,QAAQ,MAAM,MAAM,KAAK,GAAG;AACrC,QAAI,KAAK,SAAS,OAAQ,MAAK,KAAK,IAAI,KAAK,IAAI,EAAE;AAAA,aAC1C,KAAK,SAAS,UAAU;AAC/B,WAAK,KAAK,IAAI,KAAK,IAAI,EAAE;AACzB,iBAAW;AAAA,IACb,OAAO;AACL,WAAK,KAAK,IAAI,KAAK,IAAI,EAAE;AACzB,eAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,YAAY,KAAK,SAAS;AAChC,QAAM,QAAQ,YAAY,KAAK,MAAM,GAAG,GAAG,IAAI;AAC/C,QAAM,SAAS,SAAS,KAAK,MAAM,OAAO,MAAM,MAAM,MACpD,QAAQ,WACJ,IAAI,QAAQ,QAAQ,WAAM,QAAQ,YAAY,EAAE,GAAG,QAAQ,IAC3D,EACN;AACA,QAAM,QAAQ,CAAC,QAAQ,GAAG,KAAK;AAC/B,MAAI,UAAW,OAAM,KAAK,UAAK,KAAK,SAAS,GAAG,kBAAkB;AAElE,SAAO,EAAE,MAAM,MAAM,KAAK,IAAI,GAAG,OAAO,SAAS,UAAU;AAC7D;AAKA,SAAS,MAAM,MAAgB,OAAyB;AACtD,QAAM,OAAO,KAAK;AAClB,QAAM,OAAO,MAAM;AACnB,QAAMC,SAAoB,MAAM;AAAA,IAAK,EAAE,QAAQ,OAAO,EAAE;AAAA,IAAG,MACzD,IAAI,MAAc,OAAO,CAAC,EAAE,KAAK,CAAC;AAAA,EACpC;AACA,WAASC,OAAM,OAAO,GAAGA,QAAO,GAAGA,QAAO;AACxC,aAASC,OAAM,OAAO,GAAGA,QAAO,GAAGA,QAAO;AACxC,MAACF,OAAMC,IAAG,EAAeC,IAAG,IAC1B,KAAKD,IAAG,MAAM,MAAMC,IAAG,IACjBF,OAAMC,OAAM,CAAC,EAAeC,OAAM,CAAC,IAAe,IACpD,KAAK;AAAA,QACFF,OAAMC,OAAM,CAAC,EAAeC,IAAG;AAAA,QAC/BF,OAAMC,IAAG,EAAeC,OAAM,CAAC;AAAA,MAClC;AAAA,IACR;AAAA,EACF;AAEA,QAAM,MAAc,CAAC;AACrB,MAAI,MAAM;AACV,MAAI,MAAM;AACV,SAAO,MAAM,QAAQ,MAAM,MAAM;AAC/B,QAAI,KAAK,GAAG,MAAM,MAAM,GAAG,GAAG;AAC5B,UAAI,KAAK,EAAE,MAAM,QAAQ,MAAM,KAAK,GAAG,EAAY,CAAC;AACpD,aAAO;AACP,aAAO;AAAA,IACT,WACIF,OAAM,MAAM,CAAC,EAAe,GAAG,KAC/BA,OAAM,GAAG,EAAe,MAAM,CAAC,GACjC;AACA,UAAI,KAAK,EAAE,MAAM,UAAU,MAAM,KAAK,GAAG,EAAY,CAAC;AACtD,aAAO;AAAA,IACT,OAAO;AACL,UAAI,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,GAAG,EAAY,CAAC;AACpD,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO,MAAM,MAAM;AACjB,QAAI,KAAK,EAAE,MAAM,UAAU,MAAM,KAAK,GAAG,EAAY,CAAC;AACxD,SAAO,MAAM,MAAM;AACjB,QAAI,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,GAAG,EAAY,CAAC;AACtD,SAAO;AACT;;;AClEA,IAAM,mBAA4C;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AACF;AACA,IAAM,qBAA8C,CAAC,YAAY,MAAM;AAEvE,IAAM,gBAAmD;AAAA,EACvD,wBACE;AAAA,EACF,yBACE;AAAA,EACF,QAAQ;AACV;AA0CA,eAAsB,eACpB,UACA,QACA,SACA,UAAyB,CAAC,GAIzB;AACD,QAAM,aAAa,MAAM,cAAc,UAAU,QAAQ,SAAS;AAAA,IAChE,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IACnD,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,IACnD,aAAa,QAAQ,aAAa;AAAA,EACpC,CAAC;AAED,QAAM,OAAO,WAAW;AAAA,IACtB,CAAC,UAAU,MAAM,UAAU,aAAa,MAAM,UAAU;AAAA,EAC1D;AACA,MAAI,CAAC,KAAK,OAAQ,QAAO,EAAE,QAAQ,MAAM,WAAW;AAEpD,QAAM,SAAS,WAAW,KAAK,MAAM;AACrC,QAAM,UAAU,KAAK;AAAA,IAAI,CAAC,UACxB,aAAa,OAAO,QAAQ,aAAa,MAAM,MAAM;AAAA,EACvD;AAEA,QAAM,OAAO,OAAO,YAAY;AAChC,QAAM,WAA8B,eAAe,IAAI,IACnD,iBAAiB,SAAS,IAAI,IAC5B,yBACA,mBAAmB,SAAS,IAAI,IAC9B,0BACA,WACJ;AAEJ,SAAO;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,MACN,WAAW,OAAO;AAAA,MAClB,OAAO,OAAO,YAAY,SAAS;AAAA,MACnC;AAAA,MACA,UAAU,QAAQ,YAAY;AAAA,MAC9B,KAAK,OAAO,YAAY,eAAe;AAAA,MACvC,OAAO,QAAQ,MAAM;AAAA,MACrB;AAAA,MACA,SAAS,QAAQ,QAAQ,YAAY,CAAC,GAAG,IAAI,CAAC,WAAW;AAAA,QACvD,WAAW,MAAM;AAAA,QACjB,OAAO,MAAM;AAAA,QACb,UAAU,MAAM;AAAA,QAChB,OAAO,MAAM;AAAA,MACf,EAAE;AAAA,MACF,iBAAiB,QAAQ,QAAQ,aAAa;AAAA,MAC9C,SAAS;AAAA,MACT,aAAa,cAAc,QAAQ;AAAA,IACrC;AAAA,EACF;AACF;AAEA,SAAS,aACP,OACA,UACA,UACkB;AAClB,QAAM,EAAE,MAAM,IAAI;AAClB,QAAMG,QAAyB;AAAA,IAC7B,MAAM,MAAM;AAAA,IACZ,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IAC/C,OAAO,MAAM;AAAA,IACb,GAAI,MAAM,SAAS,EAAE,QAAQ,MAAM,OAAO,IAAI,CAAC;AAAA,IAC/C,YAAY,MAAM;AAAA,IAClB,GAAI,MAAM,cAAc,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;AAAA,IAC9D,UAAU,MAAM;AAAA,IAChB,GAAI,MAAM,UAAU,EAAE,SAAS,MAAM,QAAQ,IAAI,CAAC;AAAA,EACpD;AACA,MAAI,CAAC,SAAU,QAAOA;AAEtB,MAAI,MAAM,YAAY,UAAa,CAAC,MAAM,WAAW;AACnD,WAAO,EAAE,GAAGA,OAAM,MAAM,EAAE,QAAQ,gBAAgB,EAAE;AAAA,EACtD;AAGA,QAAM,WAAW,YAAY,MAAM,SAAS,MAAM,WAAW,IAAI;AAAA,IAC/D;AAAA,EACF,CAAC;AACD,SAAO;AAAA,IACL,GAAGA;AAAA,IACH,MAAM;AAAA,MACJ,QAAQ;AAAA,MACR,QAAQ,MAAM,UAAU;AAAA,MACxB,KAAK,MAAM,UAAU;AAAA,MACrB,SAAS,SAAS;AAAA,MAClB,OAAO,SAAS;AAAA,MAChB,SAAS,SAAS;AAAA,MAClB,WAAW,SAAS;AAAA,IACtB;AAAA,EACF;AACF;AAOA,SAAS,QAAQ,QAA4D;AAC3E,QAAM,OAAO,OAAO,YAAY;AAChC,QAAM,UAAU,eAAe,IAAI,IAC/B,aAAa,IAAI,EAAE,SAAS,CAAC,IAC7B;AACJ,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,QAAQ,OAAO,KAAK,QAAQ,SAAS,IAAI,EAAE,MAAM,IAAI;AAC3D,QAAM,QAAQ,MAAM;AAAA,IAClB,CAAC,SAAS,KAAK,KAAK,EAAE,YAAY,MAAM,MAAM,OAAO,GAAG,YAAY;AAAA,EACtE;AACA,MAAI,QAAQ,EAAG,QAAO;AACtB,QAAM,OAAO,MAAM,MAAM,QAAQ,CAAC;AAClC,QAAM,MAAM,KAAK,UAAU,CAAC,SAAS,KAAK,WAAW,KAAK,CAAC;AAC3D,QAAM,QAAQ,MAAM,IAAI,OAAO,KAAK,MAAM,GAAG,GAAG,GAAG,KAAK,IAAI,EAAE,KAAK;AACnE,SAAO,OAAO,EAAE,SAAS,KAAK,IAAI;AACpC;;;ACnNO,IAAM,gBAAgB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAaA,IAAM,mBAAmB,IAAI;AAAA,EAC3B,UAAU,sBAAsB,OAAO,QAAQ,YAAY,EAAE,CAAC;AAAA,EAC9D;AACF;AAWO,IAAM,0BAA6C;AAOnD,SAAS,WACd,MACA,QACA,QAA+B,eAC/B,WAA8B,yBACf;AACf,QAAM,QAAQ,oBAAI,IAAyB;AAC3C,aAAW,QAAQ,OAAO;AACxB,eAAW,UAAU,eAAe,MAAM,QAAQ,MAAM,QAAQ,GAAG;AACjE,YAAM,WAAW,MAAM,IAAI,OAAO,SAAS;AAC3C,UAAI,UAAU;AACZ,YAAI,CAAC,SAAS,IAAI,SAAS,IAAI,EAAG,UAAS,IAAI,KAAK,IAAI;AACxD;AAAA,MACF;AACA,YAAM,IAAI,OAAO,WAAW,EAAE,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;AAAA,IACrD;AAAA,EACF;AACA,SAAO,CAAC,GAAG,MAAM,OAAO,CAAC;AAC3B;AAQO,SAAS,eACd,MACA,QACA,MACA,WAA8B,yBAClB;AACZ,UAAQ,MAAM;AAAA;AAAA;AAAA;AAAA,IAIZ,KAAK,aAAa;AAChB,YAAM,UAAU,IAAI;AAAA,QAClB,CAAC,GAAG,KAAK,KAAK,SAAS,gBAAgB,CAAC,EAAE,IAAI,CAAC,UAAU,MAAM,CAAC,CAAC;AAAA,MACnE;AACA,UAAI,CAAC,QAAQ,KAAM,QAAO,CAAC;AAC3B,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,aAC7B,QAAQ,IAAI,UAAU,SAAS;AAAA,MACnC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOA,KAAK,cAAc;AACjB,YAAM,UAAU,IAAI,IAAI,QAAQ;AAChC,YAAM,UAAU,IAAI;AAAA,SACjB,KAAK,YAAY,iBAAiB,CAAC,GACjC,OAAO,CAACC,UAAS,QAAQ,IAAIA,MAAK,GAAG,CAAC,EACtC,IAAI,CAACA,UAASA,MAAK,MAAM;AAAA,MAC9B;AACA,UAAI,CAAC,QAAQ,KAAM,QAAO,CAAC;AAC3B,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,aAC7B,QAAQ,IAAI,UAAU,SAAS;AAAA,MACnC;AAAA,IACF;AAAA;AAAA;AAAA;AAAA,IAKA,KAAK;AACH,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,cAC5B,UAAU,cAAc,KAAK,YAAY,yBACxC,KAAK,YAAY,oBAAoB;AAAA,UACnC,UAAU;AAAA,QACZ,KACA,UAAU,YAAY,0BAA0B,KAAK,aACrD,UAAU,YAAY,oBAAoB,SAAS,KAAK,SAAS;AAAA,MACvE;AAAA;AAAA;AAAA,IAIF,KAAK,UAAU;AACb,YAAM,OAAO,KAAK,YAAY,mBAAmB,CAAC;AAClD,UAAI,CAAC,KAAK,OAAQ,QAAO,CAAC;AAC1B,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,cAC5B,UAAU,YAAY,mBAAmB,CAAC,GAAG;AAAA,UAAK,CAAC,WAClD,KAAK,KAAK,CAAC,SAAS,aAAa,MAAM,MAAM,CAAC;AAAA,QAChD;AAAA,MACJ;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AACb,YAAM,OAAO,IAAI,KAAK,KAAK,YAAY,WAAW,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;AACtE,UAAI,CAAC,KAAK,KAAM,QAAO,CAAC;AACxB,aAAO,OAAO;AAAA,QACZ,CAAC,cACC,UAAU,cAAc,KAAK,cAC5B,UAAU,YAAY,WAAW,CAAC,GAAG;AAAA,UAAK,CAAC,WAC1C,KAAK,IAAI,OAAO,EAAE;AAAA,QACpB;AAAA,MACJ;AAAA,IACF;AAAA,EACF;AACF;AAWA,SAAS,aACP,MACA,OACS;AACT,MAAI,KAAK,SAAS,MAAM,KAAM,QAAO;AACrC,MAAI,CAAC,KAAK,UAAU,CAAC,MAAM,OAAQ,QAAO;AAC1C,SAAO,KAAK,WAAW,MAAM;AAC/B;;;ACjLO,SAAS,eAAe,SAA4C;AACzE,QAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACxE,QAAM,WAAkC,CAAC;AACzC,QAAM,SAAS,CACb,OACAC,YACA,MACA,WAAiC,YAC9B,SAAS,KAAK,EAAE,OAAO,WAAAA,YAAW,MAAM,SAAS,CAAC;AAEvD,aAAW,UAAU,SAAS;AAC5B,UAAM,EAAE,WAAAA,YAAW,aAAa,GAAG,IAAI;AAIvC,QAAI,CAAC,eAAe,GAAG,IAAI,GAAG;AAC5B,aAAO,QAAQA,YAAW,sBAAsB,GAAG,IAAI,GAAG;AAAA,IAC5D;AAEA,QAAI,GAAG,mBAAmB,cAAc;AACtC,YAAM,KAAK,GAAG;AACd,UAAI,CAAC,IAAI;AACP,eAAO,iBAAiBA,YAAW,gCAAgC;AAAA,MACrE,WAAW,CAAC,KAAK,IAAI,EAAE,GAAG;AACxB,eAAO,iBAAiBA,YAAW,eAAe,EAAE,aAAa;AAAA,MACnE,WACE,CAAC,KAAK,IAAI,EAAE,GAAG,YAAY,oBAAoB,SAASA,UAAS,GACjE;AACA,eAAO,YAAY,IAAI,iBAAiBA,UAAS,gBAAgB;AAAA,MACnE;AAAA,IACF;AAEA,eAAW,OAAO,GAAG,sBAAsB,CAAC,GAAG;AAC7C,YAAM,WAAW,KAAK,IAAI,GAAG;AAC7B,UAAI,CAAC,UAAU;AACb,eAAO,cAAcA,YAAW,UAAU,GAAG,aAAa;AAAA,MAC5D,WAAW,SAAS,YAAY,mBAAmB,cAAc;AAC/D,eAAO,cAAcA,YAAW,GAAG,GAAG,2BAA2B;AAAA,MACnE;AAAA,IACF;AAEA,eAAWC,SAAQ,GAAG,iBAAiB,CAAC,GAAG;AAMzC,UAAI,CAAC,YAAYA,MAAK,GAAG,GAAG;AAC1B;AAAA,UACE;AAAA,UACAD;AAAA,UACA,gBAAgBC,MAAK,GAAG,gBAAgBA,MAAK,MAAM,2BAAsB,aAAa,KAAK,IAAI,CAAC;AAAA,QAClG;AAAA,MACF;AAQA,UAAI,CAAC,sBAAsB,KAAKA,MAAK,MAAM,GAAG;AAC5C;AAAA,UACE;AAAA,UACAD;AAAA,UACA,WAAWC,MAAK,MAAM;AAAA,QACxB;AAAA,MACF,WAAWA,MAAK,WAAWD,YAAW;AAGpC;AAAA,UACE;AAAA,UACAA;AAAA,UACA,oBAAoBC,MAAK,GAAG;AAAA,UAC5B;AAAA,QACF;AAAA,MACF,WAAW,CAAC,KAAK,IAAIA,MAAK,MAAM,GAAG;AACjC;AAAA,UACE;AAAA,UACAD;AAAA,UACA,UAAUC,MAAK,MAAM;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAMA,eAAW,UAAU,GAAG,mBAAmB,CAAC,GAAG;AAC7C,UAAI,OAAO,QAAQ,CAAC,mBAAmB,OAAO,IAAI,GAAG;AACnD;AAAA,UACE;AAAA,UACAD;AAAA,UACA,gBAAgB,OAAO,IAAI;AAAA,UAC3B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAGA,QAAI,GAAG,sBAAsB,GAAG,SAAS,QAAQ;AAC/C,aAAO,cAAcA,YAAW,wCAAwC;AAAA,IAC1E;AAAA,EACF;AAEA,SAAO;AACT;;;AChGO,IAAM,wBAAwB;AAC9B,IAAM,0BAA0B;AAChC,IAAM,qBAAqB;AAiBlC,IAAM,kBAAiD;AAAA,EACrD,SAAS;AAAA,EACT,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,UAAU;AAAA,EACV,uBAAuB;AAAA,EACvB,wBACE;AAAA,EACF,SAAS;AAAA,EACT,WAAW;AACb;AAiEA,IAAM,SAAS;AAGf,SAAS,qBAAqB,QAA4C;AACxE,MAAI,aAAa;AACjB,MAAI,QAAQ;AACZ,aAAW,UAAU,QAAQ;AAC3B,eAAW,UAAU,OAAO,YAAY,mBAAmB,CAAC,GAAG;AAC7D,UAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,OAAQ;AACpC,UAAI,OAAO,aAAa,cAAe,eAAc;AAAA,UAChD,UAAS;AAAA,IAChB;AAAA,EACF;AACA,SAAO,EAAE,OAAO,aAAa,OAAO,YAAY,MAAM;AACxD;AAEO,SAAS,OACd,QACA,UAA2B,CAAC,GACZ;AAChB,QAAM,aAAiC;AAAA,IACrC,cAAc,QAAQ,gBAAgB;AAAA,IACtC,gBAAgB,QAAQ,kBAAkB;AAAA,IAC1C,WAAW,QAAQ,aAAa;AAAA,EAClC;AACA,QAAM,MAAM,QAAQ,OAAO,oBAAI,KAAK;AAEpC,QAAM,cAAc,WAAW,QAAQ,QAAQ,KAAK,QAAQ,WAAW;AACvE,QAAM,YAAY,IAAI;AAAA,IACpB,YAAY,IAAI,CAAC,QAAQ,CAAC,IAAI,OAAO,WAAW,IAAI,QAAQ,CAAC;AAAA,EAC/D;AAIA,QAAM,UAAU,YAAY;AAAA,IAC1B,CAAC,QAAQ,IAAI,aAAa,gBAAgB,IAAI,aAAa;AAAA,EAC7D;AAEA,QAAM,SAA0B;AAAA,IAC9B,MAAM,WAAW,QAAQ,SAAS,GAAG,CAAC;AAAA,IACtC,MAAM,YAAY,SAAS,SAAS,KAAK,WAAW,YAAY,CAAC;AAAA,IACjE,MAAM,cAAc,WAAW,SAAS,KAAK,WAAW,cAAc,CAAC;AAAA,IACvE,MAAM,SAAS,MAAM,SAAS,KAAK,WAAW,SAAS,CAAC;AAAA,IACxD,MAAM,YAAY,SAAS,MAAM,CAAC;AAAA,IAClC,MAAM,uBAAuB,mBAAmB,QAAQ,WAAW,CAAC;AAAA,IACpE,MAAM,wBAAwB,mBAAmB,QAAQ,SAAS,CAAC;AAAA,IACnE,MAAM,WAAW,QAAQ,OAAO,CAAC;AAAA,IACjC,MAAM,aAAa,UAAU,OAAO,CAAC;AAAA,EACvC;AAEA,QAAM,SAAS,OAAO;AAAA,IACpB,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,OAAO,MAAM,KAAK,CAAC;AAAA,EAClD;AACA,QAAM,eAAe,OAAO,OAAO,CAAC,OAAO,UAAU,QAAQ,MAAM,OAAO,CAAC;AAE3E,SAAO;AAAA,IACL,aAAa,OAAO;AAAA,IACpB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB,qBAAqB,MAAM;AAAA,IAC5C,SAAS,iBAAiB;AAAA,EAC5B;AACF;AAEA,SAAS,MACP,OACA,UACe;AACf,SAAO;AAAA,IACL;AAAA,IACA,UAAU,gBAAgB,KAAK;AAAA,IAC/B,OAAO,SAAS;AAAA,IAChB;AAAA,EACF;AACF;AAaA,SAAS,QACP,MACA,KACmB;AACnB,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,IAAI,OAAO,YAAY;AACnC,QAAI,CAAC,IAAK;AACV,UAAME,MAAK,KAAK,MAAM,GAAG;AACzB,QAAI,OAAO,MAAMA,GAAE,GAAG;AACpB,eAAS;AAAA,QACP,QAAQ,IAAI,QAAQ,gBAAgB,GAAG,0BAA0B;AAAA,MACnE;AACA;AAAA,IACF;AACA,QAAIA,MAAK,IAAI,QAAQ,GAAG;AACtB,eAAS;AAAA,QACP;AAAA,UACE,IAAI;AAAA,UACJ,eAAe,GAAG,KAAK,YAAYA,KAAI,IAAI,QAAQ,CAAC,CAAC;AAAA,QACvD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,SACP,MACA,KACA,YACmB;AACnB,QAAM,UAAU,IAAI,QAAQ,IAAI,aAAa;AAC7C,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,UAAM,MAAM,IAAI,OAAO,YAAY;AACnC,QAAI,CAAC,IAAK;AACV,UAAMA,MAAK,KAAK,MAAM,GAAG;AACzB,QAAI,OAAO,MAAMA,GAAE,KAAKA,MAAK,IAAI,QAAQ,KAAKA,MAAK,QAAS;AAC5D,aAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,cAAc,GAAG,QAAQ,YAAY,IAAI,QAAQ,GAAGA,GAAE,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,WACP,MACA,KACA,eACmB;AACnB,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,QAAI,IAAI,OAAO,YAAY,UAAU,OAAQ;AAC7C,UAAM,MAAM,UAAU,IAAI,QAAQ,GAAG;AACrC,QAAI,QAAQ,QAAQ,OAAO,cAAe;AAC1C,aAAS;AAAA,MACP,QAAQ,IAAI,QAAQ,2BAA2B,GAAG,WAAW;AAAA,IAC/D;AAAA,EACF;AACA,SAAO;AACT;AAQA,SAAS,MACP,MACA,KACA,eACmB;AACnB,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,UAAM,SAAS,IAAI,OAAO,YAAY;AACtC,QAAI,WAAW,UAAU,WAAW,WAAY;AAChD,UAAM,MAAM,UAAU,IAAI,QAAQ,GAAG;AACrC,QAAI,QAAQ,QAAQ,OAAO,cAAe;AAC1C,aAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,WAAW,SACP,YAAY,GAAG,UACf,YAAY,GAAG;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACA,SAAO,SAAS;AAAA,IAAK,CAAC,MAAM,UAC1B,KAAK,UAAU,cAAc,MAAM,SAAS;AAAA,EAC9C;AACF;AAmBA,SAAS,SAAS,QAAuC;AACvD,QAAM,UAAU,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,OAAO,SAAS,CAAC;AAChE,QAAM,aAAa,oBAAI,IAAY;AACnC,aAAW,UAAU,QAAQ;AAC3B,eAAW,aAAa,eAAe,QAAQ,QAAQ,WAAW,GAAG;AACnE,iBAAW,IAAI,UAAU,SAAS;AAAA,IACpC;AAGA,eAAW,YAAY,OAAO,YAAY,sBAAsB,CAAC,GAAG;AAClE,iBAAW,IAAI,QAAQ;AAAA,IACzB;AACA,UAAM,cAAc,OAAO,YAAY;AACvC,QAAI,eAAe,QAAQ,IAAI,WAAW,GAAG;AAC3C,iBAAW,IAAI,OAAO,SAAS;AAAA,IACjC;AAAA,EACF;AACA,SAAO,OACJ,OAAO,CAAC,WAAW,CAAC,WAAW,IAAI,OAAO,SAAS,CAAC,EACpD,IAAI,CAAC,WAAW,QAAQ,QAAQ,6BAA6B,CAAC;AACnE;AAaA,IAAM,sBAAsB,oBAAI,IAAI;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,SAAS,mBACP,QACA,aACmB;AACnB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,QAAM,WAA8B,CAAC;AACrC,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,MAAM,CAAC,QAAkB,SAAiB;AAC9C,UAAM,MAAM,GAAG,OAAO,SAAS,KAAS,IAAI;AAC5C,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,aAAS,KAAK,QAAQ,QAAQ,IAAI,CAAC;AAAA,EACrC;AAEA,aAAW,WAAW,eAAe,MAAM,GAAG;AAC5C,QAAI,CAAC,oBAAoB,IAAI,QAAQ,KAAK,EAAG;AAC7C,UAAM,SAAS,KAAK,IAAI,QAAQ,SAAS;AACzC,QAAI,OAAQ,KAAI,QAAQ,QAAQ,IAAI;AAAA,EACtC;AAQA,aAAW,UAAU,QAAQ;AAC3B,UAAM,cAAc,OAAO,YAAY;AACvC,QAAI,CAAC,YAAa;AAClB,QAAI,CAAC,KAAK,IAAI,WAAW,GAAG;AAC1B,UAAI,QAAQ,eAAe,WAAW,aAAa;AAAA,IACrD,WAAW,OAAO,YAAY,mBAAmB,cAAc;AAC7D;AAAA,QACE;AAAA,QACA,SAAS,WAAW;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAEA,aAAW,OAAO,aAAa;AAC7B,eAAW,WAAW,IAAI,UAAU;AAClC,UAAI,QAAQ,SAAS,gBAAgB;AACnC,YAAI,IAAI,QAAQ,eAAe,QAAQ,OAAO,aAAa;AAAA,MAC7D,WAAW,QAAQ,SAAS,eAAe;AACzC;AAAA,UACE,IAAI;AAAA,UACJ,qCAAqC,QAAQ,QAAQ,KAAK,UAAK,CAAC;AAAA,QAClE;AAAA,MACF,WAAW,QAAQ,SAAS,gBAAgB;AAC1C;AAAA,UACE,IAAI;AAAA,UACJ,oCAAoC,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,SAAS;AAAA,IAAK,CAAC,MAAM,UAC1B,KAAK,UAAU,cAAc,MAAM,SAAS;AAAA,EAC9C;AACF;AAoBA,SAAS,mBACP,QACA,WACmB;AACnB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,QAAM,WAA8B,CAAC;AACrC,aAAW,UAAU,QAAQ;AAC3B,UAAM,WAAW,UAAU,IAAI,OAAO,SAAS;AAC/C,QAAI,aAAa,gBAAgB,aAAa,WAAY;AAC1D,eAAW,UAAU,eAAe,QAAQ,QAAQ,WAAW,GAAG;AAChE,YAAM,iBAAiB,UAAU,IAAI,OAAO,SAAS;AACrD,UAAI,mBAAmB,gBAAgB,mBAAmB,YAAY;AACpE;AAAA,MACF;AACA,UAAI,SAAS,QAAQ,MAAM,EAAG;AAC9B,YAAM,cAAc,OAAO,YAAY;AACvC,eAAS;AAAA,QACP;AAAA,UACE;AAAA,UACA,SAAS,cAAc,IAAI,OAAO,SAAS,GACzC,mBAAmB,gBACnB,eACA,KAAK,IAAI,WAAW,IAChB,uBAAkB,WAAW,KAC7B,EACN;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAcA,SAAS,QAAQ,MAAwD;AACvE,SAAO;AAAA,IAAe;AAAA,IAAM;AAAA,IAAW,CAACC,WACtCA,WAAU,IAAI,6BAA6B;AAAA,EAC7C;AACF;AAQA,SAAS,UAAU,MAAwD;AACzE,SAAO;AAAA,IAAe;AAAA,IAAM;AAAA,IAAa,CAACA,WACxCA,WAAU,IAAI,2BAA2B;AAAA,EAC3C;AACF;AAGA,SAAS,eACP,MACA,MACA,UACmB;AACnB,QAAM,WAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,UAAM,UAAU,IAAI,SAAS;AAAA,MAC3B,CAAC,UACC,MAAM,SAAS;AAAA,IACnB;AACA,QAAI,CAAC,QAAS;AACd,UAAM,SAAS,oBAAI,IAAsB;AACzC,eAAW,UAAU,QAAQ,SAAS;AACpC,YAAM,OAAO,OAAO,QAAQ;AAC5B,aAAO,IAAI,MAAM,CAAC,GAAI,OAAO,IAAI,IAAI,KAAK,CAAC,GAAI,eAAe,MAAM,CAAC,CAAC;AAAA,IACxE;AACA,UAAM,SAAS,CAAC,GAAG,OAAO,QAAQ,CAAC,EAAE;AAAA,MAAI,CAAC,CAAC,MAAM,OAAO,MACtD,OAAO,GAAG,IAAI,KAAK,QAAQ,KAAK,IAAI,CAAC,KAAK,QAAQ,KAAK,IAAI;AAAA,IAC7D;AACA,aAAS;AAAA,MACP;AAAA,QACE,IAAI;AAAA,QACJ,GAAG,QAAQ,QAAQ,MAAM,IAAI,SAAS,QAAQ,QAAQ,MAAM,CAAC,KAAK,OAAO,KAAK,IAAI,CAAC;AAAA,MACrF;AAAA,IACF;AAAA,EACF;AACA,SAAO,SAAS;AAAA,IAAK,CAAC,MAAM,UAC1B,KAAK,UAAU,cAAc,MAAM,SAAS;AAAA,EAC9C;AACF;AAEA,SAAS,eAAe,QAAiC;AACvD,QAAMD,MAAK,OAAO,SAAS,GAAG,OAAO,IAAI,IAAI,OAAO,MAAM,KAAK,OAAO;AACtE,MAAI,OAAO,UAAU,QAAQ;AAC3B,WAAO,GAAGA,GAAE,QAAQ,OAAO,SAAS,KAAK,OAAO,MAAM,MAAM,EAAE;AAAA,EAChE;AACA,MAAI,OAAO,OAAQ,QAAO,GAAGA,GAAE,KAAK,OAAO,MAAM;AACjD,MAAI,OAAO,gBAAgB,sBAAsB;AAC/C,WAAO,GAAGA,GAAE;AAAA,EACd;AACA,MAAI,OAAO,aAAa,KAAM,QAAO,GAAGA,GAAE;AAG1C,SAAO,OAAO,aAAa,IACvB,GAAGA,GAAE,wCACL,GAAGA,GAAE,KAAK,OAAO,QAAQ,QAAQ,OAAO,aAAa,IAAI,KAAK,GAAG;AACvE;AAGA,SAAS,SAAS,OAAiB,SAA4B;AAC7D,UACG,MAAM,YAAY,sBAAsB,CAAC,GAAG,SAAS,QAAQ,SAAS,KACvE,QAAQ,YAAY,0BAA0B,MAAM;AAExD;AAEA,SAAS,QAAQ,QAAkB,MAA+B;AAChE,SAAO;AAAA,IACL,WAAW,OAAO;AAAA,IAClB,OAAO,OAAO,YAAY,SAAS;AAAA,IACnC,QAAQ,OAAO,YAAY;AAAA,IAC3B;AAAA,EACF;AACF;AAGA,SAAS,YAAY,MAAc,IAAoB;AACrD,SAAO,KAAK,IAAI,GAAG,KAAK,OAAO,KAAK,QAAQ,MAAM,CAAC;AACrD;AAEA,SAAS,UAAU,QAAkB,KAA0B;AAC7D,QAAMA,MAAK,OAAO,YAAY,WAAW;AACzC,MAAI,CAACA,IAAI,QAAO;AAChB,QAAM,UAAU,KAAK,MAAMA,GAAE;AAC7B,MAAI,OAAO,MAAM,OAAO,EAAG,QAAO;AAClC,SAAO,YAAY,SAAS,IAAI,QAAQ,CAAC;AAC3C;;;ACnlBA,IAAAE,eAAkB;AA2BX,IAAM,kBAAkB,OAAO;AAAA,EACpC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,UAAU,eACP,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,WAAW,KAAK,CAAC;AAAA,MACjB,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,MAC7C,GAAI,KAAK,SAAS,aAAa,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,IAC3D;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,OAAO,MAAM,GACf,EAAE,YAAY,MAAM,WAAW,IAAI,UAAU,SAAS,MACxB;AAC9B,UAAM,OAAO,YAAY,QAAQ,IAAI;AACrC,UAAM,SAAS,MAAM,MAAM,KAAK,IAAI;AACpC,UAAM,SAAS,OAAO,KAAK,CAAC,UAAU,MAAM,cAAc,EAAE;AAC5D,QAAI,CAAC,OAAQ,OAAM,IAAI,sBAAsB,EAAE;AAE/C,UAAM,QAAQ,MAAM,MAAM,YAAY,CAAC,MAAM,GAAG,QAAQ;AACxD,UAAM,UAAU,OAAO,IAAI,EAAE,KAAK,CAAC;AACnC,QAAI,CAAC,QAAQ,KAAK,CAAC,UAAU,MAAM,UAAU,OAAO,GAAG;AACrD,aAAO,EAAE,WAAW,IAAI,QAAQ,MAAM,aAAa,CAAC,GAAG,UAAU,EAAE;AAAA,IACrE;AAEA,UAAM,WAAW,WAAW,QAAQ,MAAM,EAAE;AAAA,MAC1C,CAAC,QAAQ,IAAI,OAAO,cAAc;AAAA,IACpC,GAAG;AAGH,UAAMC,UAAS,MAAM,MAAM,OAAO,MAAM,EAAE;AAE1C,UAAM,EAAE,QAAQ,WAAW,IAAI,MAAM,eAAe,MAAM,QAAQ,SAAS;AAAA,MACzE,GAAI,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,MACrC,QAAAA;AAAA,MACA,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IACjC,CAAC;AAMD,UAAM,QAAQ,WAAW,OAAO,CAAC,UAAU,MAAM,UAAU,OAAO;AAClE,QAAI,SAAS;AACb,UAAM,cAAqC,CAAC;AAC5C,QAAI,MAAM,QAAQ;AAChB,YAAM,YAAY,oBAAI,IAAwB;AAC9C,iBAAW,SAAS,OAAO;AACzB,cAAM,KAAK,MAAM,MAAM;AACvB,YAAI,CAAC,GAAI;AACT,kBAAU,IAAI,MAAM,QAAQ;AAAA,UAC1B,GAAG,MAAM;AAAA,UACT,MAAM,GAAG;AAAA,UACT,GAAI,GAAG,SAAS,EAAE,QAAQ,GAAG,OAAO,IAAI,CAAC;AAAA,QAC3C,CAAC;AACD,oBAAY,KAAK;AAAA,UACf,MAAM,MAAM,OAAO;AAAA,UACnB,GAAI,MAAM,OAAO,SAAS,EAAE,QAAQ,MAAM,OAAO,OAAO,IAAI,CAAC;AAAA,UAC7D,QAAQ,GAAG;AAAA,UACX,GAAI,GAAG,SAAS,EAAE,UAAU,GAAG,OAAO,IAAI,CAAC;AAAA,QAC7C,CAAC;AAAA,MACH;AACA,UAAI;AACF,cAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAAA,MAC/C,SAAS,OAAO;AACd,YAAI,EAAE,iBAAiB,mBAAoB,OAAM;AACjD,iBAAS;AAAA,MACX;AACA,UAAI,CAAC,QAAQ;AACX,cAAM,MAAM;AAAA,UACV;AAAA,UACA;AAAA,WACC,OAAO,YAAY,mBAAmB,CAAC,GAAG;AAAA,YACzC,CAAC,WAAW,UAAU,IAAI,MAAM,KAAK;AAAA,UACvC;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,WAAW;AAAA,MACX;AAAA,MACA,aAAa,SAAS,CAAC,IAAI;AAAA,MAC3B,UAAU,WAAW,OAAO,CAAC,UAAU,MAAM,UAAU,UAAU,EAAE;AAAA,MACnE,GAAI,SACA;AAAA,QACE,QAAQ;AAAA,QACR,MAAM;AAAA,MACR,IACA,CAAC;AAAA,IACP;AAAA,EACF;AAAA,EACA,QAAQ,CAAC,WAAW,eAAe,MAA0B;AAC/D,CAAC;AAOM,SAAS,eAAe,QAAkC;AAC/D,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,OAAO,aAAa;AACrC,UAAM;AAAA,MACJ,gBAAgB,GAAG,KAAK,MAAM,KAAK,MAAM,CAAC,WAAM,GAAG,KAAK,QAAQ,KAAK,QAAQ,CAAC;AAAA,IAChF;AAAA,EACF;AACA,MAAI,OAAO,UAAU;AACnB,UAAM;AAAA,MACJ,GAAG,OAAO,QAAQ,UAAU,OAAO,aAAa,IAAI,KAAK,GAAG;AAAA,IAC9D;AAAA,EACF;AACA,MAAI,OAAO,KAAM,OAAM,KAAK,OAAO,IAAI;AAEvC,QAAM,SAAS,OAAO;AACtB,MAAI,CAAC,QAAQ;AACX,UAAM,KAAK,GAAG,OAAO,SAAS,wBAAwB;AACtD,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAEA,QAAM;AAAA,IACJ;AAAA,IACA,KAAK,OAAO,SAAS,GAAG,OAAO,QAAQ,WAAM,OAAO,KAAK,KAAK,EAAE;AAAA,IAChE,SAAS,OAAO,IAAI,gBAAgB,OAAO,QAAQ;AAAA,IACnD,GAAI,OAAO,MAAM,CAAC,QAAQ,OAAO,GAAG,EAAE,IAAI,CAAC;AAAA,IAC3C,GAAI,OAAO,QACP,CAAC,IAAI,MAAM,OAAO,MAAM,OAAO,IAAI,OAAO,MAAM,IAAI,IACpD,CAAC;AAAA,IACL;AAAA,IACA,eAAe,OAAO,QAAQ,MAAM;AAAA,EACtC;AAEA,aAAW,UAAU,OAAO,SAAS;AACnC,UAAM;AAAA,MACJ,KAAK,GAAG,OAAO,MAAM,OAAO,MAAM,CAAC,WAAM,OAAO,KAAK,GAAG,OAAO,SAAS,KAAK,OAAO,MAAM,MAAM,EAAE;AAAA,IACpG;AACA,QAAI,CAAC,OAAO,KAAM;AAClB,QAAI,OAAO,KAAK,WAAW,iBAAiB;AAC1C,YAAM;AAAA,QACJ;AAAA,MACF;AACA;AAAA,IACF;AACA,UAAM;AAAA,MACJ,aAAa,OAAO,KAAK,GAAG,KAAK,OAAO,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,UAAK,OAAO,KAAK,OAAO;AAAA,MACnG,GAAG,OAAO,KAAK,QAAQ,MAAM,IAAI,EAAE,IAAI,CAAC,SAAS,KAAK,IAAI,EAAE;AAAA,IAC9D;AAAA,EACF;AAEA,MAAI,OAAO,OAAO,QAAQ;AACxB,UAAM,KAAK,IAAI,cAAc,OAAO,OAAO,MAAM,GAAG;AACpD,eAAW,SAAS,OAAO,QAAQ;AACjC,YAAM;AAAA,QACJ,KAAK,MAAM,SAAS,KAAK,MAAM,QAAQ,IAAI,MAAM,QAAQ,WAAM,MAAM,KAAK,KAAK,EAAE;AAAA,MACnF;AAAA,IACF;AACA,QAAI,OAAO,gBAAiB,OAAM,KAAK,yBAAoB;AAAA,EAC7D;AAEA,QAAM,KAAK,IAAI,YAAY,OAAO,OAAO,WAAM,OAAO,WAAW,GAAG;AACpE,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,GAAG,MAAc,QAAyB;AACjD,SAAO,SAAS,GAAG,IAAI,IAAI,MAAM,KAAK;AACxC;;;AT5KA,IAAM,OAAO,CAAC,MAAc,aAC1B,eACG,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT,SAAS,GAAG,IAAI,gBAAgB,QAAQ,GAAG;AAEzC,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,UAAU;AAAA,IACV,cAAc;AAAA,MACZ;AAAA,MACA;AAAA,IACF;AAAA,IACA,gBAAgB;AAAA,MACd;AAAA,MACA;AAAA,IACF;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IACF;AAAA,IACA,SAAS,eACN,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,QAAQ,eACL,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,SAAS,eACN,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,UAAU,eACP,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAMC,YAAW,SAAS,MAAM,iBAAiB;AACjD,UAAMC,cAAa,SAAS,MAAM,mBAAmB;AACrD,UAAM,YAAY,SAAS,MAAM,cAAc;AAC/C,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,MAC7C,GAAID,cAAa,SAAY,EAAE,cAAc,OAAOA,SAAQ,EAAE,IAAI,CAAC;AAAA,MACnE,GAAIC,gBAAe,SACf,EAAE,gBAAgB,OAAOA,WAAU,EAAE,IACrC,CAAC;AAAA,MACL,GAAI,cAAc,SAAY,EAAE,WAAW,OAAO,SAAS,EAAE,IAAI,CAAC;AAAA,MAClE,GAAI,KAAK,SAAS,WAAW,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;AAAA,MACtD,GAAI,KAAK,SAAS,UAAU,IAAI,EAAE,QAAQ,KAAK,IAAI,CAAC;AAAA,MACpD,GAAI,KAAK,SAAS,WAAW,IAAI,EAAE,SAAS,KAAK,IAAI,CAAC;AAAA,MACtD,GAAI,KAAK,SAAS,aAAa,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,IAC3D;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,OAAO,IAAI,GACb;AAAA,IACE,YAAY;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAAC;AAAA,IACA;AAAA,EACF,MACG;AACH,UAAM,YAAY,IAAI;AACtB,UAAM,UAAU,MAAM,MAAM,KAAK,IAAI;AAIrC,UAAM,cAAc,MAAM,MAAM,YAAY,SAAS,UAAU;AAAA,MAC7D,SAAS,YAAY;AAAA,IACvB,CAAC;AACD,UAAM,SAAS,OAAO,SAAS;AAAA,MAC7B,GAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,MACrD,GAAI,mBAAmB,SAAY,EAAE,eAAe,IAAI,CAAC;AAAA,MACzD,GAAI,cAAc,SAAY,EAAE,UAAU,IAAI,CAAC;AAAA,MAC/C,GAAI,gBAAgB,SAAY,EAAE,YAAY,IAAI,CAAC;AAAA,MACnD,KAAK,IAAI,KAAK,SAAS;AAAA,IACzB,CAAC;AACD,UAAM,QAAQ,aAAa;AAC3B,QAAI,CAACA,UAAS;AACZ,aAAO;AAAA,QACL,YAAY;AAAA,QACZ;AAAA,QACA,GAAG;AAAA,QACH,GAAI,MAAM,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,MAClC;AAAA,IACF;AAIA,UAAM,YAAY,IAAI;AAAA,MACpB,WAAW,SAAS,SAAS,IAAI,KAAK,SAAS,CAAC,EAAE,IAAI,CAAC,QAAQ;AAAA,QAC7D,IAAI,OAAO;AAAA,QACX,IAAI;AAAA,MACN,CAAC;AAAA,IACH;AACA,UAAM,UAA8B,CAAC;AACrC,UAAM,gBAA0B,CAAC;AAGjC,UAAM,SAAS,YAAY,YAAY,QAAQ,IAAI,CAAC;AACpD,eAAW,SAAS,OAAO,OAAO,KAAK,CAAC,MAAM,EAAE,UAAU,SAAS,GAC/D,YAAY,CAAC,GAAG;AAClB,YAAM,SAAS,QAAQ;AAAA,QACrB,CAAC,UAAU,MAAM,cAAc,MAAM;AAAA,MACvC;AACA,UAAI,CAAC,OAAQ;AACb,YAAM,WAAW,UAAU,IAAI,OAAO,SAAS;AAC/C,YAAM,QAAQ,MAAM;AAAA,QAClB,YAAY,QAAQ,IAAI;AAAA,QACxB;AAAA,QACA,aAAa,IAAI,OAAO,SAAS,KAAK,CAAC;AAAA,QACvC;AAAA,UACE,GAAI,WAAW,EAAE,UAAU,KAAK,IAAI,CAAC;AAAA,UACrC,QAAQ,MAAM,MAAM,OAAO,MAAM,OAAO,SAAS;AAAA,UACjD,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AACA,UAAI,MAAM,OAAQ,SAAQ,KAAK,MAAM,MAAM;AAC3C,UAAI,MAAM,WAAW,KAAK,CAAC,UAAU,MAAM,UAAU,OAAO,GAAG;AAC7D,sBAAc,KAAK,OAAO,SAAS;AAAA,MACrC;AAAA,IACF;AACA,WAAO;AAAA,MACL,YAAY;AAAA,MACZ;AAAA,MACA,GAAG;AAAA,MACH;AAAA,MACA;AAAA,MACA,GAAI,MAAM,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,IAClC;AAAA,EACF;AAAA,EACA,QAAQ,CAAC,WAAWC,QAAO,MAA+B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO1D,WAAW,CAAC,QAAQ,UAClB,MAAM,WAAW,QAChB,OAAiC,OAAO,UAAU;AACvD,CAAC;AASD,SAASA,QAAO,QAAuC;AACrD,MAAI,OAAO,QAAS,QAAO,cAAc,MAAM;AAC/C,QAAM,EAAE,WAAW,IAAI;AACvB,QAAM,QAAQ;AAAA,IACZ,sBAAiB,OAAO,UAAU;AAAA,IAClC,YAAY,OAAO,WAAW;AAAA,IAC9B,+BAA+B,WAAW,YAAY,sBAAsB,WAAW,cAAc,iBAAiB,WAAW,SAAS;AAAA,IAC1I,YAAY,OAAO,SAAS;AAAA,IAC5B,GAAI,OAAO,gBAAgB,QACvB;AAAA,MACE,YAAY,OAAO,gBAAgB,KAAK,kBAAa,OAAO,gBAAgB,UAAU,iBAAiB,OAAO,gBAAgB,KAAK;AAAA,IACrI,IACA,CAAC;AAAA,IACL;AAAA,EACF;AAEA,QAAMC,SAAQ,KAAK,IAAI,GAAG,OAAO,OAAO,IAAI,CAACC,WAAUA,OAAM,MAAM,MAAM,CAAC;AAC1E,aAAWA,UAAS,OAAO,QAAQ;AACjC,UAAM;AAAA,MACJ,KAAKA,OAAM,MAAM,OAAOD,MAAK,CAAC,KAAK,OAAOC,OAAM,KAAK,EAAE,SAAS,CAAC,CAAC,KAAKA,OAAM,QAAQ;AAAA,IACvF;AAAA,EACF;AAEA,aAAWA,UAAS,OAAO,QAAQ;AACjC,QAAI,CAACA,OAAM,MAAO;AAClB,UAAM,KAAK,IAAI,MAAMA,OAAM,KAAK,KAAKA,OAAM,KAAK,GAAG;AACnD,eAAW,SAASA,OAAM,UAAU;AAClC,YAAM;AAAA,QACJ,KAAK,MAAM,SAAS,GAAG,MAAM,QAAQ,WAAM,MAAM,KAAK,KAAK,EAAE,KAAK,MAAM,IAAI;AAAA,MAC9E;AAAA,IACF;AAAA,EACF;AAEA,aAAW,QAAQ,OAAO,SAAS,CAAC,EAAG,OAAM,KAAK,IAAI,IAAI;AAE1D,QAAM;AAAA,IACJ;AAAA,IACA,OAAO,UACH,uBACA,GAAG,OAAO,YAAY,WAAW,OAAO,iBAAiB,IAAI,KAAK,GAAG,WACnE,OAAO,OAAO,OAAO,CAACA,WAAUA,OAAM,KAAK,EAAE,MAC/C,OAAO,OAAO,OAAO,MAAM;AAAA,EACjC;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAOA,SAAS,cAAc,QAAuC;AAC5D,QAAM,UAAU,OAAO,WAAW,CAAC;AACnC,QAAM,QAAQ;AAAA,IACZ,qBAAgB,OAAO,UAAU;AAAA,IACjC,YAAY,OAAO,SAAS;AAAA,IAC5B,GAAG,QAAQ,MAAM,UAAU,QAAQ,WAAW,IAAI,KAAK,GAAG,oBACxD,OAAO,OAAO,OAChB;AAAA,EACF;AACA,MAAI,OAAO,eAAe,QAAQ;AAChC,UAAM;AAAA,MACJ,2CAA2C,OAAO,cAAc,KAAK,IAAI,CAAC;AAAA,IAC5E;AAAA,EACF;AACA,aAAW,UAAU,SAAS;AAC5B,UAAM;AAAA,MACJ,eAAe;AAAA,QACb,WAAW,OAAO;AAAA,QAClB;AAAA,QACA,aAAa,CAAC;AAAA,QACd,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AUtSA,IAAAC,eAAkB;AAIX,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,OAAO,eACJ,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,MAAM,eACH,MAAM,eAAE,KAAK,mBAAmB,CAAC,EACjC,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,QAAQ,SAAS,MAAM,SAAS;AACtC,UAAM,OAAO,SAAS,MAAM,QAAQ;AACpC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,WAAW,KAAK,CAAC;AAAA,MACjB,GAAI,QAAQ,EAAE,OAAO,OAAO,KAAK,EAAE,IAAI,CAAC;AAAA,MACxC,GAAI,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC;AAAA,IAC1D;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,WAAW,IAAI,OAAO,KAAK,MACpE,MAAM,OAAO,MAAM,IAAI;AAAA,IACrB,GAAI,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC;AAAA,IACvC,GAAI,MAAM,SAAS,EAAE,KAAK,IAAI,CAAC;AAAA,EACjC,CAAC;AACL,CAAC;;;AC3CD,IAAAC,eAAkB;AAUX,IAAM,cAAc,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,MAAM,eAAE,KAAK,eAAe,EAAE,SAAS;AAAA,IACvC,MAAM;AAAA,EACR,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,OAAO,UAAU,MAAM,OAAO;AAGpC,UAAM,OAAO,eAAe,MAAM,OAAO;AACzC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,KAAK,SAAS,EAAE,KAAK,IAAI,CAAC;AAAA,IAChC;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,MAAM,KAAK,OACnD,MAAM,MAAM,KAAK,MAAM,MAAM,EAAE,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG,CAAC,GAAG;AAAA,IAC5D,CAAC,YAAY;AAAA,MACX,WAAW,OAAO;AAAA,MAClB,OAAO,OAAO,YAAY,SAAS;AAAA,MACnC,aAAa,OAAO,YAAY,eAAe;AAAA,MAC/C,QAAQ,OAAO,YAAY;AAAA,MAC3B,SAAS,OAAO,YAAY,mBAAmB,CAAC;AAAA,IAClD;AAAA,EACF;AACJ,CAAC;;;AC1CD,IAAAC,eAAkB;AAIX,IAAM,cAAc,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eACJ,OAAO;AAAA,IACN;AAAA,IACA,MAAM,eAAE,KAAK,eAAe,EAAE,SAAS;AAAA,IACvC,cAAc,eACX,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT,SAAS,+CAA+C;AAAA,IAC3D,KAAK,eACF,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,UAAU;AAAA,EACZ,CAAC,EACA,OAAO,CAAC,UAAU,EAAE,MAAM,OAAO,MAAM,iBAAiB,SAAY;AAAA,IACnE,SACE;AAAA,EACJ,CAAC;AAAA,EACH,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,GAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,WAAW,IAAI,IAAI,EAAE,MAAM,KAAK,CAAC,EAAE,IAAI,CAAC;AAAA,MAChE,GAAI,SAAS,EAAE,cAAc,OAAO,MAAM,EAAE,IAAI,CAAC;AAAA,MACjD,GAAI,KAAK,SAAS,OAAO,IAAI,EAAE,KAAK,KAAK,IAAI,CAAC;AAAA,MAC9C,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,MAAM,GACR,EAAE,YAAY,MAAM,MAAM,cAAc,KAAK,SAAS,MACnD;AACH,UAAM,SAAS,MAAM,MAAM,KAAK,MAAM;AAAA,MACpC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,MACvC,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;AAAA,MACrB,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/C,CAAC;AACD,QAAI,CAAC,OAAO,OAAQ,QAAO;AAC3B,WAAO;AAAA,MACL,GAAG;AAAA,MACH,SAAS,OAAO,QAAQ,IAAI,CAAC,SAAS;AAAA,QACpC,WAAW,IAAI,OAAO;AAAA,QACtB,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,QACvC,UAAU,IAAI;AAAA,QACd,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,QACpD,UAAU,IAAI;AAAA,QACd,SAAS,IAAI,OAAO,YAAY,mBAAmB,CAAC;AAAA,QACpD,MAAM,IAAI,OAAO;AAAA,MACnB,EAAE;AAAA,IACJ;AAAA,EACF;AACF,CAAC;;;ACnED,IAAAC,eAAkB;AAGX,IAAM,aAAa,OAAO;AAAA,EAC/B,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,WAAW,CAAC;AAAA,EAC9B,UAAU,CAAC,OAAO,UAAU,EAAE,YAAY,KAAK;AAAA,EAC/C,KAAK,CAAC,EAAE,MAAM,GAAG,EAAE,YAAY,KAAK,MAAM,MAAM,QAAQ,IAAI;AAC9D,CAAC;;;ACZD,IAAAC,eAAkB;AAKX,IAAM,oBAAoB,OAAO;AAAA,EACtC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,YAAY,QAAQ,eAAE,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;AAAA,EACzD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,QAAQ,KAAK,MAAM,CAAC,EAAE,KAAK,GAAG,EAAE,KAAK;AAAA,EACvC;AAAA,EACA,KAAK,OAAO,EAAE,OAAO,OAAO,IAAI,GAAG,EAAE,YAAY,MAAM,OAAO,MAAM;AAClE,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM;AAAA,MACzB;AAAA,MACA,EAAE,GAAG,wBAAwB,QAAQ,OAAO,IAAI,CAAC,GAAG,WAAW,KAAK;AAAA,MACpE;AAAA,IACF;AACA,WAAO,EAAE,WAAW,OAAO,UAAU;AAAA,EACvC;AACF,CAAC;;;ACzBD,IAAAC,eAAkB;AAKX,IAAM,cAAc,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,MAAM,eACH,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT,SAAS,0DAA0D;AAAA,IACtE,UAAU,eACP,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,cAAc,eACX,OAAO,EACP,IAAI,EACJ,SAAS,EACT,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,OAAO,SAAS,MAAM,QAAQ;AACpC,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,WAAW,KAAK,CAAC;AAAA,MACjB,GAAI,OAAO,EAAE,MAAM,OAAO,IAAI,EAAE,IAAI,CAAC;AAAA,MACrC,GAAI,WAAW,EAAE,UAAU,OAAO,QAAQ,EAAE,IAAI,CAAC;AAAA,MACjD,GAAI,SAAS,EAAE,cAAc,OAAO,MAAM,EAAE,IAAI,CAAC;AAAA,IACnD;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,OAAO,IAAI,GACb,EAAE,YAAY,MAAM,WAAW,MAAM,MAAM,UAAU,aAAa,MAC/D;AACH,UAAM,SAAS,MAAM,MAAM,KAAK,MAAM,MAAM;AAAA,MAC1C,GAAI,SAAS,SAAY,EAAE,KAAK,IAAI,CAAC;AAAA,MACrC,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,MAC7C,GAAI,iBAAiB,SAAY,EAAE,aAAa,IAAI,CAAC;AAAA,IACvD,CAAC;AACD,WAAOC,QAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,EACnC;AACF,CAAC;AAOD,SAASA,QAAO,QAAsB,QAAgBC,KAAoB;AACxE,QAAM,QAAQ;AAAA,IACZ,oBAAe,OAAO,IAAI;AAAA,IAC1B,WAAW,MAAM;AAAA,IACjB,YAAY,OAAO,YAAY,OAAO,OAAO,YAAY,YAAY,OAAO,WAAW;AAAA,IACvF,WAAWA,GAAE;AAAA,IACb;AAAA,IACA,eAAe,OAAO,QAAQ,MAAM;AAAA,EACtC;AAEA,aAAW,UAAU,OAAO,SAAS;AACnC,UAAM;AAAA,MACJ;AAAA,MACA,OAAO,OAAO,SAAS,GAAG,OAAO,QAAQ,WAAM,OAAO,KAAK,KAAK,EAAE,KAAK,OAAO,QAAQ;AAAA,IACxF;AACA,QAAI,OAAO,SAAS,QAAQ;AAC1B,YAAM,KAAK,aAAa,OAAO,SAAS,IAAI,YAAY,EAAE,KAAK,IAAI,CAAC,EAAE;AAAA,IACxE;AACA,QAAI,OAAO,QAAQ,QAAQ;AACzB,YAAM;AAAA,QACJ,YAAY,OAAO,QAChB;AAAA,UAAI,CAAC,WACJ,OAAO,SAAS,GAAG,OAAO,IAAI,IAAI,OAAO,MAAM,KAAK,OAAO;AAAA,QAC7D,EACC,KAAK,IAAI,CAAC;AAAA,MACf;AAAA,IACF;AACA,UAAM,KAAK,IAAI,OAAO,KAAK,QAAQ,CAAC;AAAA,EACtC;AAEA,MAAI,OAAO,WAAW,QAAQ;AAC5B,UAAM,KAAK,IAAI,kBAAkB,OAAO,WAAW,MAAM,GAAG;AAC5D,eAAW,SAAS,OAAO,YAAY;AACrC,YAAM;AAAA,QACJ,KAAK,MAAM,SAAS,WAClB,MAAM,aAAa,KAAK,IAAI,KAAK,qBACnC,GAAG,MAAM,KAAK,KAAK,MAAM,EAAE,MAAM,EAAE;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,SAAS,QAAQ;AAC1B,UAAM,KAAK,IAAI,gBAAgB,OAAO,SAAS,MAAM,GAAG;AACxD,eAAW,OAAO,OAAO,SAAU,OAAM,KAAK,KAAK,GAAG,EAAE;AAAA,EAC1D;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEA,SAAS,aAAa,SAA4B;AAChD,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO,iBAAiB,QAAQ,GAAG,KAAK,IAAI,CAAC;AAAA,IAC/C,KAAK;AACH,aAAO,cAAc,QAAQ,MAAM;AAAA,IACrC,KAAK;AACH,aAAO,uBAAkB,QAAQ,OAAO;AAAA,IAC1C,KAAK;AACH,aAAO,uBAAuB,QAAQ,QAAQ,KAAK,UAAK,CAAC;AAAA,IAC3D,KAAK;AACH,aAAO,6BAAwB,QAAQ,MAAM,KAAK,IAAI,CAAC;AAAA,IACzD,KAAK;AACH,aAAO,eAAe,QAAQ,UAAU;AAAA,IAC1C,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO,QAAQ;AAAA,EACnB;AACF;;;ACvIA,IAAAC,eAAkB;AAIX,IAAM,aAAa,OAAO;AAAA,EAC/B,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,MAAM,eACH,KAAK,CAAC,QAAQ,OAAO,CAAC,EACtB,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,UAAU,eACP,MAAM,eAAE,OAAO,CAAC,EAChB,SAAS,EACT,SAAS,6DAA6D;AAAA,IACzE,OAAO,eACJ,KAAK,CAAC,WAAW,SAAS,MAAM,CAAC,EACjC,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,QAAQ,eACL,QAAQ,EACR,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,aAAa,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,WAAW,IAAI,IAAI,KAAK,CAAC,IAAI;AACpE,UAAM,OAAO,SAAS,MAAM,QAAQ;AACpC,UAAM,WAAW,SAAS,MAAM,YAAY;AAC5C,UAAM,QAAQ,KAAK,SAAS,QAAQ,IAChC,SACA,KAAK,SAAS,SAAS,IACrB,UACA;AACN,UAAM,SAAS,KAAK,SAAS,UAAU,IACnC,OACA,KAAK,SAAS,YAAY,IACxB,QACA;AACN,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,MACvB,GAAI,WACA;AAAA,QACE,UAAU,SACP,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAAA,MACnB,IACA,CAAC;AAAA,MACL,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,MACzB,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,IAC3C;AAAA,EACF;AAAA,EACA,KAAK,CAAC,EAAE,OAAO,IAAI,GAAG,EAAE,YAAY,MAAM,MAAM,UAAU,OAAO,OAAO,MACtE,QAAQ,OAAO,QAAQ,IAAI,GAAG,MAAM,IAAI,GAAG;AAAA,IACzC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACvB,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/B,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,IACzB,GAAI,WAAW,SAAY,EAAE,OAAO,IAAI,CAAC;AAAA,EAC3C,CAAC;AACL,CAAC;;;ACxED,IAAAC,eAAkB;AAIX,IAAM,cAAc,OAAO;AAAA,EAChC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,CAAC,CAAC;AAAA,EAClB,UAAU,OAAO,CAAC;AAAA,EAClB,KAAK,CAAC,EAAE,MAAM,MAAM,SAAS,OAAO,QAAQ,IAAI,CAAC;AACnD,CAAC;;;ACbD,IAAAC,eAAkB;AAYX,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,MAAM,eAAE,OAAO,EAAE,SAAS;AAAA,IAC1B,MAAM,eAAE,KAAK,eAAe,EAAE,SAAS;AAAA,IACvC,mBAAmB,eAAE,QAAQ,EAAE,SAAS;AAAA,IACxC,MAAM;AAAA,IACN,UAAU;AAAA,EACZ,CAAC;AAAA;AAAA,EAED,UAAU,CAAC,MAAM,SAAS;AACxB,UAAM,WAAW,SAAS,MAAM,aAAa;AAC7C,UAAM,OAAO,UAAU,MAAM,OAAO;AACpC,UAAM,QAAQ,YAAY,KAAK,MAAM,CAAC,GAAG,eAAe,OAAO;AAC/D,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,MAAM,MAAM,KAAK,GAAG,EAAE,KAAK;AAAA,MAC3B,mBAAmB;AAAA,MACnB,GAAI,KAAK,SAAS,EAAE,KAAK,IAAI,CAAC;AAAA,MAC9B,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EACA,KAAK,OACH,EAAE,MAAM,GACR,EAAE,YAAY,MAAM,MAAM,MAAM,mBAAmB,MAAM,SAAS,OAGhE,MAAM,MAAM,MAAM,MAAM,QAAQ,IAAI;AAAA,IAClC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACvB,mBAAmB,sBAAsB;AAAA,IACzC,GAAI,OAAO,EAAE,KAAK,IAAI,CAAC;AAAA,IACvB,GAAI,aAAa,SAAY,EAAE,SAAS,IAAI,CAAC;AAAA,EAC/C,CAAC,GACD,IAAI,CAAC,SAAS;AAAA,IACd,WAAW,IAAI,OAAO;AAAA,IACtB,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,IACvC,aAAa,IAAI,OAAO,YAAY,eAAe;AAAA,IACnD,UAAU,IAAI;AAAA,IACd,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,IACpD,UAAU,IAAI;AAAA,IACd,MAAM,IAAI,OAAO;AAAA,EACnB,EAAE;AACN,CAAC;;;AC3DD,IAAAC,eAAkB;AAGX,IAAM,mBAAmB,OAAO;AAAA,EACrC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,WAAW,CAAC;AAAA,EAC9B,UAAU,CAAC,OAAO,UAAU,EAAE,YAAY,KAAK;AAAA,EAC/C,KAAK,CAAC,EAAE,MAAM,GAAG,EAAE,YAAY,KAAK,MAAM,MAAM,UAAU,IAAI;AAChE,CAAC;;;ACZD,IAAAC,eAAkB;;;ACAlB,IAAAC,eAAkB;;;ACAlB,IAAAC,eAAkB;AAEX,IAAM,WAAW;AAEjB,IAAM,mBAAmB,eAC7B,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASN,IAAI,eAAE,IAAI,SAAS;AAAA,EACnB,IAAI,eAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EACpB,WAAW,eAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC3B,WAAW,eAAE,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,EAE3B,QAAQ,eAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AACrC,CAAC,EACA,OAAO;AAwBH,SAAS,eAAe,OAA2B;AACxD,SAAO,GAAG,KAAK,UAAU,iBAAiB,MAAM,KAAK,CAAC,CAAC;AAAA;AACzD;AAQO,SAAS,SAAS,KAA8B;AACrD,QAAM,UAAwB,CAAC;AAC/B,QAAM,YAA8C,CAAC;AACrD,QAAM,OAAO,oBAAI,IAAY;AAE7B,MAAI,MAAM,IAAI,EAAE,QAAQ,CAAC,MAAMC,WAAU;AACvC,QAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAI;AACJ,QAAI;AACF,cAAQ,KAAK,MAAM,IAAI;AAAA,IACzB,QAAQ;AACN,gBAAU,KAAK,EAAE,MAAMA,SAAQ,GAAG,KAAK,CAAC;AACxC;AAAA,IACF;AACA,UAAM,SAAS,iBAAiB,UAAU,KAAK;AAC/C,QAAI,CAAC,OAAO,SAAS;AACnB,gBAAU,KAAK,EAAE,MAAMA,SAAQ,GAAG,KAAK,CAAC;AACxC;AAAA,IACF;AAYA,UAAM,MAAM,KAAK,UAAU,OAAO,IAAI;AACtC,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AAEZ,YAAQ,KAAK,OAAO,IAAI;AAAA,EAC1B,CAAC;AAQD,UAAQ;AAAA,IAAK,CAAC,MAAM,UAClB,KAAK,KAAK,MAAM,KAAK,KAAK,KAAK,KAAK,MAAM,KAAK,IAAI;AAAA,EACrD;AAEA,SAAO,EAAE,SAAS,UAAU;AAC9B;;;ADtFO,SAAS,gBAAyC;AACvD,SAAO;AAAA,IACL,mBAAmB,eAAE,aAAa,2BAA2B;AAAA,MAC3D,IAAI;AAAA,IACN,CAAC;AAAA,IACD,cAAc,eAAE,aAAa,oBAAoB,EAAE,IAAI,QAAQ,CAAC;AAAA,IAChE,UAAU,eAAE,aAAa,kBAAkB,EAAE,IAAI,QAAQ,CAAC;AAAA,EAC5D;AACF;;;ADrBO,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,CAAC,CAAC;AAAA,EAClB,UAAU,OAAO,CAAC;AAAA,EAClB,KAAK,MAAM,QAAQ,QAAQ,cAAc,CAAC;AAC5C,CAAC;;;AGbD,IAAAC,mBAAyB;AACzB,IAAAC,eAAkB;AAelB,IAAM,SAAS;AAER,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd,YAAY,eACT,OAAO,EACP,IAAI,CAAC,EACL,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,IACF,OAAO,eACJ,OAAO,EACP,IAAI,CAAC,EACL,SAAS,EACT;AAAA,MACC;AAAA,IACF;AAAA,EACJ,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,MAAM,QAAQ,mBAAmB;AAChD,UAAM,QAAQ,SAAS,MAAM,SAAS;AACtC,WAAO;AAAA,MACL,GAAI,iBAAiB,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,MAC7C,GAAI,UAAU,SAAY,EAAE,MAAM,IAAI,CAAC;AAAA,IACzC;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAAC,aAAY,MAAM,MAAM;AAC/C,UAAM,UAAUA,cACZ,CAACA,WAAU,KACV,MAAM,eAAe,QAAQ,IAAI,CAAC,GAAG,KAAK;AAAA,MACzC,CAAC,QAAQ,IAAI;AAAA,IACf;AAKJ,QAAI,UAAU,UAAa,OAAO,KAAK,KAAK,KAAK,QAAQ,SAAS,GAAG;AACnE,YAAM,IAAI,2BAA2B,KAAK;AAAA,IAC5C;AAEA,UAAM,SAAS,MAAM,QAAQ;AAAA,MAC3B,QAAQ,IAAI,CAAC,WAAW,MAAM,MAAM,MAAM,CAAC;AAAA,IAC7C;AACA,QAAI,UAAU,QAAW;AACvB,aAAO,OAAO,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,SAAS,KAAK,EAAE;AAAA,IAC5D;AAEA,UAAM,WAAW,MAAM,aAAa,KAAK;AACzC,UAAM,UAA2B,CAAC;AAClC,eAAW,SAAS,QAAQ;AAC1B,YAAM,SAAS,SAAS,OAAO,IAAI,MAAM,IAAI;AAC7C,UAAI,SAAS,WAAW,MAAM;AAC5B,YAAI,SAAS,WAAW,MAAM,OAAQ;AACtC,gBAAQ,KAAK,EAAE,GAAG,OAAO,SAAS,KAAK,CAAC;AACxC;AAAA,MACF;AAGA,UAAI,UAAU,OAAO,WAAW,MAAM,OAAQ;AAC9C,cAAQ,KAAK,EAAE,GAAG,OAAO,SAAS,WAAW,QAAQ,SAAS,KAAK,EAAE,CAAC;AAAA,IACxE;AACA,WAAO;AAAA,EACT;AAAA,EACA,QAAQ,CAAC,WACN,OACE,IAAI,CAAC,WAAW;AACf,UAAM,SAAS,GAAG,OAAO,WAAW,eAAe,OAAO,UAAU,cAClE,OAAO,UAAU,KAAK,OAAO,OAAO,aAAa,EACnD;AACA,UAAM,OAAO,GAAG,OAAO,IAAI,KAAK,OAAO,MAAM,KAAK,MAAM,GACtD,OAAO,WAAW,YAAY,OAAO,QAAQ,KAAK,EACpD;AACA,WAAO,OAAO,SAAS,SACnB,GAAG,IAAI;AAAA,aAAgB,OAAO,QAAQ,KAAK,IAAI,CAAC,KAChD;AAAA,EACN,CAAC,EACA,KAAK,IAAI;AAChB,CAAC;AAED,SAAS,WACP,QACA,OACU;AACV,QAAM,MAAM,IAAI;AAAA,IACd,MAAM,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,OAAO,MAAM,CAAC;AAAA,EACjE;AACA,QAAM,MAAM,oBAAI,IAAY;AAC5B,aAAW,CAACC,YAAW,MAAM,KAAK,KAAK;AACrC,QAAI,QAAQ,IAAIA,UAAS,MAAM,OAAQ,KAAI,IAAIA,UAAS;AAAA,EAC1D;AACA,aAAWA,cAAa,QAAQ,KAAK,KAAK,CAAC,GAAG;AAC5C,QAAI,CAAC,IAAI,IAAIA,UAAS,EAAG,KAAI,IAAIA,UAAS;AAAA,EAC5C;AACA,SAAO,CAAC,GAAG,GAAG,EAAE,KAAK;AACvB;AAOA,eAAe,aAAa,OAGzB;AACD,MAAI,OAAO,KAAK,KAAK,EAAG,QAAO,EAAE,QAAQ,OAAO,QAAQ,oBAAI,IAAI,EAAE;AAElE,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,UAAM,2BAAS,OAAO,MAAM,CAAC;AAAA,EACnD,QAAQ;AACN,UAAM,IAAI,qBAAqB,KAAK;AAAA,EACtC;AAIA,QAAM,UAAU,MAAM,QAAQ,MAAM,IAChC,SACE,QAAmC,UAAU,CAAC;AACpD,QAAM,SAAS,oBAAI,IAGjB;AACF,aAAW,SAAS,SAIf;AACH,QAAI,OAAO,OAAO,SAAS,YAAY,OAAO,OAAO,WAAW,UAAU;AACxE;AAAA,IACF;AACA,WAAO,IAAI,MAAM,MAAM;AAAA,MACrB,QAAQ,MAAM;AAAA,MACd,SAAS,IAAI;AAAA,SACV,MAAM,WAAW,CAAC,GAAG,IAAI,CAAC,WAAW;AAAA,UACpC,OAAO;AAAA,UACP,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO,EAAE,QAAQ,MAAM,OAAO;AAChC;;;ACnKA,IAAAC,eAAkB;AAKX,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,QAAQ,eAAE,KAAK,kBAAkB;AAAA,EACnC,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,QAAQ,KAAK,CAAC;AAAA,EAChB;AAAA,EACA,KAAK,OACH,EAAE,OAAO,MAAM,GACf,EAAE,YAAY,MAAM,WAAW,IAAI,OAAO,MACvC;AACH,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM,UAAU,MAAM,IAAI,QAAQ,KAAK;AAC5D,WAAO,EAAE,WAAW,OAAO,WAAW,OAAO;AAAA,EAC/C;AACF,CAAC;;;AC7BD,IAAAC,eAAkB;AAIX,IAAM,mBAAmB,OAAO;AAAA,EACrC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,YAAY,WAAW,eAAe,UAAU,CAAC;AAAA,EACnE,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,eAAe,KAAK,CAAC;AAAA,EACvB;AAAA,EACA,KAAK,OACH,EAAE,OAAO,MAAM,GACf,EAAE,YAAY,MAAM,WAAW,IAAI,cAAc,MAC9C;AACH,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,MAAM,UAAU,MAAM,IAAI,eAAe,KAAK;AACpD,WAAO,EAAE,YAAY,IAAI,YAAY,cAAc;AAAA,EACrD;AACF,CAAC;;;ACxBD,IAAAC,eAAkB;AAIX,IAAM,0BAA0B,OAAO;AAAA,EAC5C,MAAM;AAAA,EACN,OACE;AAAA,EACF,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd,MAAM,eAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS,wCAAwC;AAAA,IACzE,cAAc,eAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,IACnD,iBAAiB,eAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,IACtD,SAAS,eAAE,OAAO,EAAE,SAAS;AAAA,EAC/B,CAAC;AAAA,EACD,UAAU,CAAC,SAAS;AAClB,UAAM,SAAS,SAAS,MAAM,UAAU;AACxC,UAAM,YAAY,SAAS,MAAM,cAAc;AAC/C,UAAM,UAAU,SAAS,MAAM,WAAW;AAC1C,WAAO;AAAA,MACL,MAAM,KAAK,CAAC;AAAA,MACZ,GAAI,SAAS,EAAE,cAAc,OAAO,MAAM,EAAE,IAAI,CAAC;AAAA,MACjD,GAAI,YAAY,EAAE,iBAAiB,OAAO,SAAS,EAAE,IAAI,CAAC;AAAA,MAC1D,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,IAC/B;AAAA,EACF;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,MAAM,cAAc,iBAAiB,QAAQ,MAAM;AAC1E,UAAM,SAAS,MAAM,aAAa,OAAO,QAAQ,IAAI,GAAG;AAAA,MACtD,GAAI,eAAe,EAAE,aAAa,IAAI,CAAC;AAAA,MACvC,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;AAAA,MAC7C,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC7B,MAAM,CAAC,UAAU,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI;AAAA,IACpE,CAAC;AACD,WAAO,iBAAiB,MAAM,OAAO,KAAK;AAAA,EAC5C;AACF,CAAC;;;ACpCD,IAAAC,eAAkB;;;ACsBX,IAAM,cAAc;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AA6BO,SAAS,MACd,QACA,QACA,UAA0B,CAAC,GACZ;AACf,QAAM,QAAQ,QAAQ,OAAO,SAAS,QAAQ,QAAQ;AACtD,QAAM,WAAW,QAAQ,SAAS;AAClC,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,QAAM,OAAO,KAAK,IAAI,MAAM;AAC5B,MAAI,CAAC,KAAM,QAAO,CAAC;AAEnB,QAAM,UAAU,oBAAI,IAAyB;AAAA,IAC3C,CAAC,QAAQ,EAAE,QAAQ,MAAM,OAAO,GAAG,KAAK,CAAC,EAAE,CAAC;AAAA,EAC9C,CAAC;AACD,MAAI,WAAuB,CAAC,IAAI;AAEhC,WAAS,QAAQ,GAAG,SAAS,YAAY,SAAS,QAAQ,SAAS,GAAG;AACpE,UAAM,OAAmB,CAAC;AAC1B,eAAW,QAAQ,UAAU;AAC3B,iBAAW,QAAQ,OAAO;AACxB,mBAAW,UAAU;AAAA,UACnB;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,GAAG;AACD,gBAAM,WAAW,QAAQ,IAAI,OAAO,SAAS;AAC7C,cAAI,UAAU;AAKZ,gBAAI,SAAS,QAAQ,KAAK,CAAC,SAAS,IAAI,SAAS,IAAI,GAAG;AACtD,uBAAS,IAAI,KAAK,IAAI;AAAA,YACxB;AACA;AAAA,UACF;AACA,kBAAQ,IAAI,OAAO,WAAW,EAAE,QAAQ,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AAC5D,eAAK,KAAK,MAAM;AAAA,QAClB;AAAA,MACF;AAAA,IACF;AACA,eAAW;AAAA,EACb;AAEA,SAAO,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE,KAAK,aAAa;AACjD;AAEA,SAAS,cAAc,MAAmB,OAA4B;AACpE,QAAMC,MAAK,CAAC,SAAsB,KAAK,OAAO,YAAY,WAAW,MAAM;AAC3E,SAAOA,IAAG,IAAI,EAAE,cAAcA,IAAG,KAAK,CAAC,KAAK,KAAK,QAAQ,MAAM;AACjE;;;ADvGO,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,OAAO,eAAE,MAAM,eAAE,KAAK,WAAW,CAAC,EAAE,SAAS;AAAA,IAC7C,OAAO,eAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,EAC9C,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,OAAO,KACJ,MAAM,CAAC,EACP,OAAO,CAAC,SAAU,YAAkC,SAAS,IAAI,CAAC;AAAA,EACvE;AAAA,EACA,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,MAAM,WAAW,IAAI,OAAO,MAAM,OAEnE,MAAM,MAAM,MAAM,MAAM,IAAI;AAAA,IAC1B,GAAI,OAAO,SAAS,EAAE,MAAM,IAAI,CAAC;AAAA,IACjC,GAAI,QAAQ,EAAE,MAAM,IAAI,CAAC;AAAA,EAC3B,CAAC,GACD,IAAI,CAAC,UAAU;AAAA,IACf,WAAW,KAAK,OAAO;AAAA,IACvB,IAAI,KAAK,OAAO,YAAY,WAAW,MAAM;AAAA,IAC7C,QAAQ,KAAK,OAAO,YAAY;AAAA,IAChC,OAAO,KAAK,OAAO,YAAY,SAAS;AAAA,IACxC,OAAO,KAAK;AAAA,IACZ,KAAK,KAAK;AAAA,IACV,MAAM,KAAK,OAAO;AAAA,EACpB,EAAE;AACN,CAAC;;;AEtCD,IAAAC,eAAkB;AAIX,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,CAAC,CAAC;AAAA,EAClB,UAAU,OAAO,CAAC;AAAA,EAClB,KAAK,MAAM,QAAQ,QAAQ,YAAY;AACzC,CAAC;;;ACbD,IAAAC,eAAkB;AAIX,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,WAAW,CAAC;AAAA,EAC9B,UAAU,CAAC,MAAM,UAAU,EAAE,YAAY,KAAK,CAAC,KAAK,KAAK;AAAA,EACzD,KAAK,CAAC,MAAM,EAAE,YAAY,KAAK,MAAM,UAAU,QAAQ,IAAI,GAAG,IAAI;AACpE,CAAC;;;ACbD,IAAAC,eAAkB;AAIX,IAAM,kBAAkB,OAAO;AAAA,EACpC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,WAAW,CAAC;AAAA,EAC9B,UAAU,CAAC,OAAO,UAAU,EAAE,YAAY,KAAK;AAAA,EAC/C,KAAK,OAAO,EAAE,MAAM,GAAG,EAAE,YAAY,KAAK,MACxC,eAAe,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA;AAAA,EAEvC,WAAW,CAAC,WACV,MAAM,QAAQ,MAAM,KACnB,OAAiC;AAAA,IAChC,CAAC,YAAY,QAAQ,aAAa;AAAA,EACpC;AACJ,CAAC;;;ACpBD,IAAAC,eAAkB;AAIX,IAAM,gBAAgB,OAAO;AAAA,EAClC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA;AAAA,IACA,MAAM,eAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,GAAG;AAAA,MAClD,SAAS;AAAA,IACX,CAAC;AAAA,EACH,CAAC;AAAA,EACD,UAAU,CAAC,MAAM,UAAU;AAAA,IACzB,YAAY;AAAA,IACZ,WAAW,KAAK,CAAC;AAAA,IACjB,MAAM,SAAS,MAAM,QAAQ;AAAA,EAC/B;AAAA,EACA,KAAK,OACH,EAAE,OAAO,OAAO,IAAI,GACpB,EAAE,YAAY,MAAM,WAAW,IAAI,KAAK,MACrC;AACH,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM,OAAO,MAAM,IAAI,MAAM,OAAO,IAAI,CAAC;AAC9D,WAAO;AAAA,MACL,WAAW,OAAO;AAAA,MAClB,UAAU,OAAO,YAAY,UAAU,UAAU;AAAA,IACnD;AAAA,EACF;AACF,CAAC;;;ACjCD,IAAAC,eAAkB;AAMX,IAAM,eAAe,OAAO;AAAA,EACjC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO;AAAA,IACd;AAAA,IACA,MAAM,eAAE,KAAK,eAAe;AAAA,IAC5B,OAAO;AAAA,EACT,CAAC;AAAA,EACD,UAAU,OAAO,MAAM,MAAM,WAAW;AAAA,IACtC,YAAY;AAAA,IACZ,MAAM,KAAK,CAAC;AAAA,IACZ,OAAO,KAAK,MAAM,MAAM,MAAM,CAAC;AAAA,EACjC;AAAA,EACA,KAAK,OAAO,EAAE,OAAO,OAAO,IAAI,GAAG,EAAE,YAAY,MAAM,MAAM,MAAM,MAAM;AACvE,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM;AAAA,MACzB;AAAA,MACA,cAAc,MAAsB,OAAO,OAAO,IAAI,CAAC;AAAA,MACvD;AAAA,IACF;AACA,WAAO;AAAA,MACL,WAAW,OAAO;AAAA,MAClB,QAAQ,OAAO;AAAA,MACf,eAAe,OAAO;AAAA,IACxB;AAAA,EACF;AACF,CAAC;;;ACnCD,IAAAC,eAAkB;AAQX,IAAM,uBAAuB,OAAO;AAAA,EACzC,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,aACE;AAAA,EACF,OAAO,eAAE,OAAO,EAAE,YAAY,OAAO,oBAAoB,CAAC;AAAA,EAC1D,UAAU,OAAO,OAAO,MAAM,WAAW;AAAA,IACvC,YAAY;AAAA,IACZ,OAAO,KAAK,MAAM,MAAM,MAAM,CAAC;AAAA,EACjC;AAAA,EACA,KAAK,OAAO,EAAE,OAAO,OAAO,IAAI,GAAG,EAAE,YAAY,MAAM,MAAM,MAAM;AACjE,UAAM,oBAAoB,QAAQ,IAAI,GAAG,IAAI;AAC7C,UAAM,SAAS,MAAM,MAAM;AAAA,MACzB;AAAA,MACA,sBAAsB,OAAO,OAAO,IAAI,CAAC;AAAA,MACzC;AAAA,IACF;AACA,WAAO;AAAA,MACL,WAAW,OAAO;AAAA,MAClB,QAAQ,OAAO;AAAA,MACf,eAAe,OAAO;AAAA,IACxB;AAAA,EACF;AACF,CAAC;;;ACMM,IAAM,cAA2B;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,sBAAsB,IAAI;AAAA,EACrC,YAAY,IAAI,CAAC,YAAY,CAAC,QAAQ,MAAM,OAAO,CAAC;AACtD;;;ACxEA,IAAAC,oBASO;AACP,IAAAC,qBAAmC;;;ACVnC,yBAAmB;AAWZ,SAAS,iCACd,SACA,aACQ;AACR,SAAO,mBAAAC,QAAO,UAAU,SAAS,WAAW;AAC9C;AAEO,SAAS,yBAAyB,MAIvC;AACA,QAAM,WAAO,mBAAAA,SAAO,IAAI;AAExB,SAAO;AAAA,IACL,SAAS,KAAK;AAAA;AAAA;AAAA,IAGd,QAAQ,KAAK,MAAM,GAAG,KAAK,SAAS,KAAK,QAAQ,MAAM;AAAA,IACvD,KAAK,KAAK;AAAA,EACZ;AACF;AASO,SAAS,6BACd,MACA,QAMA;AACA,QAAM,EAAE,SAAS,QAAQ,IAAI,IAAI,yBAAyB,IAAI;AAE9D,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,aAAa,OAAO,UAAU,GAAG;AAAA,EACnC;AACF;;;AClDA,IAAAC,sBAA2B;AASpB,SAASC,QAAO,UAA0B;AAC/C,aAAO,gCAAW,QAAQ,EAAE,OAAO,QAAQ,EAAE,OAAO,KAAK;AAC3D;AAQO,SAAS,YACd,SACA,YACe;AACf,QAAM,UAA2B;AAAA,IAC/B,GAAG,QAAQ,IAAI,CAAC,SAAS;AAAA,MACvB,WAAW,IAAI,OAAO;AAAA,MACtB,QAAQ,WAAWA;AAAA,QACjB;AAAA,UACE,IAAI,OAAO;AAAA,UACX,IAAI,OAAO;AAAA,QACb;AAAA,MACF,CAAC;AAAA,IACH,EAAE;AAAA,IACF,GAAG,WAAW,IAAI,CAAC,WAAW;AAAA,MAC5B,WAAW,MAAM;AAAA,MACjB,QAAQ,cAAcA,QAAO,KAAK,UAAU,KAAK,CAAC,CAAC;AAAA,IACrD,EAAE;AAAA,EACJ,EAAE,KAAK,CAAC,GAAG,MAAO,EAAE,YAAY,EAAE,YAAY,KAAK,CAAE;AAErD,SAAO;AAAA,IACL,QAAQA;AAAA,MACN,QAAQ,IAAI,CAAC,UAAU,GAAG,MAAM,SAAS,IAAI,MAAM,MAAM,EAAE,EAAE,KAAK,IAAI;AAAA,IACxE;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAEO,SAAS,aACd,SACA,YACQ;AACR,SAAO,YAAY,SAAS,UAAU,EAAE;AAC1C;;;AC5DA,IAAAC,mBAAqB;AACrB,IAAAC,qBAAqB;AAKd,IAAM,oBAAoB;AAEjC,IAAM,aAAa;AAmFnB,eAAsB,WACpBC,aACA,OACA,UAAyB,CAAC,GACG;AAC7B,QAAM,MAAM,QAAQ,OAAQ,MAAM,QAAQ,QAAQ,MAAM;AACxD,MAAI,CAAC,IAAK,QAAO;AAEjB,MAAI,QAAyB;AAC7B,MAAI;AACF,YAAS,MAAM,IAAI,YAAY;AAAA,MAC7B,YAAQ,yBAAKA,aAAY,iBAAiB;AAAA,MAC1C,QAAQ;AAAA,QACN,aAAa;AAAA,UACX,CAAC,UAAU,GAAG;AAAA,YACZ,MAAMA;AAAA,YACN,SAAS;AAAA;AAAA,YAET,QAAQ,CAAC,YAAY,QAAQ;AAAA,UAC/B;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,MAAM,QAAQA,WAAU,GAAG;AAC7B,YAAM,MAAM,OAAO,EAAE,aAAa,CAAC,UAAU,EAAE,CAAC;AAAA,IAClD;AAEA,UAAM,OAAO,MAAM,MAAM,UAAU,OAAO;AAAA,MACxC,YAAY;AAAA,MACZ,GAAI,QAAQ,QAAQ,EAAE,OAAO,QAAQ,MAAM,IAAI,CAAC;AAAA,IAClD,CAAC;AACD,WAAO,KACJ,IAAI,CAAC,SAAS;AAAA,MACb,aAAa,IAAI,eAAe,IAAI,YAAY;AAAA,MAChD,OAAO,IAAI,SAAS;AAAA,IACtB,EAAE,EACD,OAAO,CAAC,QAAQ,IAAI,YAAY,SAAS,CAAC;AAAA,EAC/C,SAAS,OAAO;AAGd,YAAQ,QAAQ,OAAO;AAAA,MACrB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD,CAAC;AACD,WAAO;AAAA,EACT,UAAE;AACA,UAAM,OAAO,MAAM,EAAE,MAAM,MAAM,MAAS;AAAA,EAC5C;AACF;AAQA,eAAe,QAAQA,aAAsC;AAC3D,QAAM,UAAU,UAAM,2BAAK,yBAAKA,aAAY,iBAAiB,CAAC,EAC3D,KAAK,CAAC,MAAM,EAAE,OAAO,EACrB,MAAM,MAAM,CAAC;AAChB,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,EAAE,SAAAC,SAAQ,IAAI,MAAM,OAAO,aAAkB;AACnD,QAAM,SAAS,MAAMA,SAAQD,WAAU,EAAE,MAAM,MAAM,CAAC,CAAa,GAAG;AAAA,IACpE,CAAC,SAAS,KAAK,SAAS,KAAK,KAAK,SAAS;AAAA,EAC7C;AAEA,MAAI,QAAQ;AACZ,QAAM,SAAS,OAAO,wBAAwB,OAAO,SAAS;AAC5D,QAAI,MAAO;AACX,UAAME,MAAK,UAAM,2BAAK,yBAAKF,aAAY,IAAI,CAAC,EACzC,KAAK,CAAC,MAAM,EAAE,OAAO,EACrB,MAAM,MAAM,CAAC;AAChB,QAAIE,MAAK,QAAS,SAAQ;AAAA,EAC5B,CAAC;AACD,SAAO;AACT;AASO,SAAS,YACd,MACA,SACK;AACL,QAAM,SAAS,oBAAI,IAAe;AAClC,aAAW,UAAU,SAAS;AAC5B,UAAM,OAAO,QAAQ,OAAO,SAAS;AAErC,QAAI,OAAO,IAAI,IAAI,EAAG,QAAO,OAAO,IAAI;AAAA,QACnC,QAAO,IAAI,MAAM,MAAM;AAAA,EAC9B;AAEA,QAAM,WAAgB,CAAC;AACvB,aAAW,OAAO,MAAM;AACtB,UAAM,OAAO,IAAI,YAAY,MAAM,GAAG,EAAE,IAAI,KAAK;AACjD,UAAM,OAAO,KAAK,SAAS,KAAK,IAAI,KAAK,MAAM,GAAG,CAAC,MAAM,MAAM,IAAI;AACnE,UAAM,SAAS,OAAO,IAAI,QAAQ,IAAI,CAAC;AACvC,QAAI,OAAQ,UAAS,KAAK,MAAM;AAAA,EAClC;AACA,SAAO;AACT;AAEA,SAAS,QAAQ,OAAuB;AACtC,SAAO,MAAM,QAAQ,QAAQ,GAAG,EAAE,YAAY;AAChD;AAQA,IAAM,aAAa;AAQnB,eAAsB,QACpB,QAC2B;AAC3B,MAAI;AACF,WAAQ,MAAM,OAAO;AAAA,EACvB,QAAQ;AACN,YAAQ,OAAO,EAAE,WAAW,aAAa,SAAS,kBAAkB,CAAC;AACrE,WAAO;AAAA,EACT;AACF;;;AChNO,IAAM,oBAAoB;AAC1B,IAAM,yBAAyB;AA0CtC,IAAM,gBAAmC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG,gBAAgB;AAAA,IACjB,CAAC,SAAS,CAAC,CAAC,YAAY,cAAc,aAAa,EAAE,SAAS,IAAI;AAAA,EACpE;AACF;AAkBO,SAAS,KACd,QACA,QACA,UAAyB,CAAC,GACZ;AACd,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,WAAW,QAAQ,YAAY;AACrC,QAAM,eAAe,QAAQ,gBAAgB;AAE7C,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,QAAM,OAAO,KAAK,IAAI,MAAM;AAC5B,MAAI,CAAC,KAAM,OAAM,IAAI,sBAAsB,MAAM;AAKjD,QAAM,UAAqB,CAAC,EAAE,QAAQ,MAAM,OAAO,EAAE,CAAC;AACtD,QAAM,OAAO,oBAAI,IAAI,CAAC,MAAM,CAAC;AAC7B,MAAI,WAAuB,CAAC,IAAI;AAChC,WAAS,QAAQ,GAAG,SAAS,QAAQ,SAAS,GAAG;AAC/C,UAAM,OAAmB,CAAC;AAC1B,eAAW,QAAQ,UAAU;AAC3B,iBAAW,EAAE,OAAO,KAAK,WAAW,MAAM,MAAM,GAAG;AACjD,YAAI,KAAK,IAAI,OAAO,SAAS,EAAG;AAChC,aAAK,IAAI,OAAO,SAAS;AACzB,gBAAQ,KAAK,EAAE,QAAQ,MAAM,CAAC;AAC9B,aAAK,KAAK,MAAM;AAAA,MAClB;AAAA,IACF;AACA,eAAW;AAAA,EACb;AAEA,UAAQ,KAAK,MAAM;AACnB,QAAM,SAAS,QAAQ,OAAO,CAAC,UAAU,MAAM,SAAS,IAAI;AAC5D,QAAM,OAAO,OAAO,MAAM,GAAG,QAAQ;AACrC,QAAM,WAAW;AAAA,IACf,GAAG,OAAO,MAAM,QAAQ;AAAA,IACxB,GAAG,QAAQ,OAAO,CAAC,UAAU,MAAM,QAAQ,IAAI;AAAA,EACjD,EACG,IAAI,CAAC,UAAU,MAAM,OAAO,SAAS,EACrC,KAAK;AAER,QAAM,cAAc;AAAA,IAClB,KAAK,IAAI,CAAC,UAAU,MAAM,MAAM;AAAA,IAChC;AAAA,EACF;AACA,QAAM,aAAa,YAChB,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C,IAAI,IAAI;AACX,QAAM,QAAQ,YAAY,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY;AAEvE,QAAM,eACJ,MAAM,OAAO,CAAC,OAAO,QAAQ,QAAQ,eAAe,IAAI,MAAM,GAAG,CAAC,IAClE,WAAW,OAAO,CAAC,OAAO,UAAU,QAAQ,mBAAmB,KAAK,GAAG,CAAC;AAC1E,QAAM,cAAc,YAAY;AAEhC,MAAI,eAAe,cAAc;AAC/B,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,MAAM,IAAI,CAAC,SAAS;AAAA,MAC3B,WAAW,IAAI,OAAO;AAAA,MACtB,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,MACvC,UAAU,IAAI;AAAA,MACd,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,MACpD,UAAU,IAAI;AAAA,MACd,SAAS,IAAI,OAAO,YAAY,mBAAmB,CAAC;AAAA,MACpD,MAAM,IAAI,OAAO;AAAA,IACnB,EAAE;AAAA,IACF;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,OAAO,MAAe,OAAwB;AACrD,SACE,KAAK,QAAQ,MAAM,SACnB,SAAS,KAAK,MAAM,IAAI,SAAS,MAAM,MAAM,MAC5C,KAAK,OAAO,YAAY,SAAS,IAAI;AAAA,IACpC,MAAM,OAAO,YAAY,SAAS;AAAA,EACpC,KACA,KAAK,OAAO,UAAU,cAAc,MAAM,OAAO,SAAS;AAE9D;AAGA,SAAS,SAAS,QAA0B;AAC1C,QAAMC,SAAQ,cAAc,QAAQ,OAAO,YAAY,IAAI;AAC3D,SAAOA,WAAU,KAAK,cAAc,SAASA;AAC/C;;;AClLO,SAAS,aAAa,QAAkD;AAC7E,QAAM,WAAW,oBAAI,IAA6B;AAElD,aAAW,UAAU,QAAQ;AAC3B,eAAWC,SAAQ,OAAO,YAAY,iBAAiB,CAAC,GAAG;AAGzD,UAAIA,MAAK,WAAW,OAAO,UAAW;AAEtC,YAAM,QAAQ,SAAS,IAAIA,MAAK,MAAM,KAAK,CAAC;AAE5C,UACE,MAAM;AAAA,QACJ,CAAC,SAAS,KAAK,SAAS,OAAO,aAAa,KAAK,QAAQA,MAAK;AAAA,MAChE,GACA;AACA;AAAA,MACF;AACA,YAAM,KAAK,EAAE,MAAM,OAAO,WAAW,KAAKA,MAAK,IAAI,CAAC;AACpD,eAAS,IAAIA,MAAK,QAAQ,KAAK;AAAA,IACjC;AAAA,EACF;AAEA,SAAO;AACT;;;ACrBO,SAAS,UACd,UACA,QACmB;AACnB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,MAAI,CAAC,KAAK,IAAI,QAAQ,EAAG,OAAM,IAAI,sBAAsB,QAAQ;AAEjE,QAAM,aAAa,IAAI;AAAA,IACrB,WAAW,QAAQ,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,OAAO,WAAW,GAAG,CAAC;AAAA,EACrE;AAEA,QAAM,OAAqB,CAAC;AAC5B,aAAW,QAAQ,aAAa,MAAM,EAAE,IAAI,QAAQ,KAAK,CAAC,GAAG;AAC3D,UAAM,SAAS,KAAK,IAAI,KAAK,IAAI;AACjC,QAAI,CAAC,OAAQ;AACb,UAAM,MAAM,WAAW,IAAI,KAAK,IAAI;AACpC,SAAK,KAAK;AAAA,MACR,GAAG;AAAA,MACH,OAAO,OAAO,YAAY,SAAS;AAAA,MACnC,UAAU,KAAK,YAAY;AAAA,MAC3B,UAAU,KAAK,YAAY,CAAC;AAAA,IAC9B,CAAC;AAAA,EACH;AAEA,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,WAAW,KAAK;AAAA,MACd,CAAC,MAAM,UACL,KAAK,KAAK,cAAc,MAAM,IAAI,KAClC,KAAK,IAAI,cAAc,MAAM,GAAG;AAAA,IACpC;AAAA,EACF;AACF;;;ACrBO,SAAS,OACd,UACA,QACA,UAA2B,CAAC,GACZ;AAChB,QAAM,OAAO,IAAI,IAAI,OAAO,IAAI,CAAC,WAAW,CAAC,OAAO,WAAW,MAAM,CAAC,CAAC;AACvE,MAAI,CAAC,KAAK,IAAI,QAAQ,EAAG,OAAM,IAAI,sBAAsB,QAAQ;AAEjE,QAAM,OAAO,YAAY,QAAQ,IAAI;AACrC,QAAM,WAAW,QAAQ,SAAS,OAAO;AACzC,QAAM,UAAU,aAAa,MAAM;AAInC,QAAM,aAAa,IAAI;AAAA,IACrB,WAAW,QAAQ,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,OAAO,WAAW,GAAG,CAAC;AAAA,EACrE;AAEA,QAAM,UAAU,oBAAI,IAA8B;AAClD,QAAM,UAAoB,CAAC;AAC3B,MAAI,WAAW,CAAC,QAAQ;AACxB,MAAI,QAAQ;AAEZ,SAAO,SAAS,UAAU,QAAQ,UAAU;AAC1C,aAAS;AACT,UAAM,OAAiB,CAAC;AAExB,UAAM,WAAW,CAAC,aAAqB,SAAqB;AAE1D,UAAI,gBAAgB,SAAU;AAE9B,YAAM,WAAW,QAAQ,IAAI,WAAW;AACxC,UAAI,UAAU;AACZ,YAAI,CAAC,QAAQ,SAAS,KAAK,IAAI,EAAG,UAAS,IAAI,KAAK,IAAI;AACxD;AAAA,MACF;AAEA,YAAM,SAAS,KAAK,IAAI,WAAW;AAInC,UAAI,CAAC,OAAQ;AAEb,YAAM,MAAM,WAAW,IAAI,WAAW;AACtC,YAAM,QAA0B;AAAA,QAC9B,WAAW;AAAA,QACX,OAAO,OAAO,YAAY,SAAS;AAAA,QACnC,UAAU,KAAK,YAAY;AAAA,QAC3B,UAAU,KAAK,YAAY,CAAC;AAAA,QAC5B;AAAA,QACA,KAAK,CAAC,IAAI;AAAA,MACZ;AACA,cAAQ,IAAI,aAAa,KAAK;AAE9B,UAAI,MAAM,aAAa,gBAAgB,MAAM,aAAa,YAAY;AACpE,gBAAQ,KAAK,WAAW;AACxB;AAAA,MACF;AACA,WAAK,KAAK,WAAW;AAAA,IACvB;AAEA,eAAW,MAAM,UAAU;AAEzB,iBAAW,QAAQ,QAAQ,IAAI,EAAE,KAAK,CAAC,GAAG;AACxC,YAAI,CAAC,KAAK,IAAI,KAAK,GAAG,EAAG;AACzB,YAAI,aAAa,KAAK,GAAG,MAAM,SAAU;AACzC,iBAAS,KAAK,MAAM,EAAE,QAAQ,KAAK,MAAM,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAAA,MACtE;AAGA,iBAAWC,SAAQ,KAAK,IAAI,EAAE,GAAG,YAAY,iBAAiB,CAAC,GAAG;AAChE,YAAI,CAAC,KAAK,IAAIA,MAAK,GAAG,EAAG;AACzB,YAAI,aAAaA,MAAK,GAAG,MAAM,SAAU;AACzC,YAAIA,MAAK,WAAW,GAAI;AACxB,iBAASA,MAAK,QAAQ;AAAA,UACpB,QAAQ;AAAA,UACR,QAAQA,MAAK;AAAA,UACb,KAAKA,MAAK;AAAA,QACZ,CAAC;AAAA,MACH;AAAA,IACF;AAEA,eAAW;AAAA,EACb;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,UAAU,CAAC,GAAG,QAAQ,OAAO,CAAC,EAAE;AAAA,MAC9B,CAAC,MAAM,UACL,KAAK,QAAQ,MAAM,SACnB,KAAK,UAAU,cAAc,MAAM,SAAS;AAAA,IAChD;AAAA,IACA,SAAS,QAAQ,KAAK;AAAA,IACtB,WAAW,SAAS,SAAS;AAAA,IAC7B,YAAY,CAAC,GAAG,QAAQ,EAAE,KAAK;AAAA,EACjC;AACF;AASA,SAAS,YAAY,MAAkD;AACrE,MAAI,CAAC,MAAM,OAAQ,QAAO,IAAI,IAAY,mBAAmB;AAC7D,aAAW,OAAO,MAAM;AACtB,QAAI,CAAC,YAAY,GAAG,KAAK,UAAU,GAAG,EAAE,cAAc,MAAM;AAC1D,YAAM,IAAI,sBAAsB,KAAK,mBAAmB;AAAA,IAC1D;AAAA,EACF;AACA,SAAO,IAAI,IAAI,IAAI;AACrB;AAGA,SAAS,aAAa,KAAyC;AAC7D,SAAO,YAAY,GAAG,IAAI,UAAU,GAAG,EAAE,YAAY;AACvD;AAEA,SAAS,QAAQ,OAAqB,MAA2B;AAC/D,SAAO,MAAM;AAAA,IACX,CAAC,aACC,SAAS,WAAW,KAAK,UACzB,SAAS,WAAW,KAAK,UACzB,SAAS,QAAQ,KAAK;AAAA,EAC1B;AACF;;;ACnJO,IAAM,qBAAqB;AAmB3B,IAAM,mBAAmB,GAAG,QAAQ;AAO3C,SAAS,UAAU,MAA2D;AAC5E,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,CAAC,WAAW,QAAQ,WAAW,GAAG,EAAG,QAAO;AAChD,QAAM,CAAC,SAAS,GAAG,KAAK,IAAI,QAAQ,MAAM,KAAK;AAC/C,SAAO,YAAY,SAAY,OAAO,EAAE,SAAS,MAAM;AACzD;AAuBO,SAAS,oBAAoB,UAA2B;AAC7D,SAAO,SAAS,MAAM,IAAI,EAAE,KAAK,CAAC,SAAS;AACzC,UAAM,SAAS,UAAU,IAAI;AAC7B,QAAI,CAAC,UAAU,OAAO,YAAY,SAAU,QAAO;AACnD,WAAO,OAAO,MAAM;AAAA,MAClB,CAAC,SACC,SAAS,WAAW,SAAS,YAAY,KAAK,WAAW,QAAQ;AAAA,IACrE;AAAA,EACF,CAAC;AACH;AAQO,SAAS,qBAAqB,UAA0B;AAC7D,QAAM,YACJ,SAAS,WAAW,KAAK,SAAS,SAAS,IAAI,IAAI,KAAK;AAC1D,SAAO,GAAG,SAAS,GAAG,gBAAgB;AAAA;AACxC;;;ARFO,IAAM,aAAS,yBAAK,YAAY,IAAI;AAE3C,IAAM,cAAc,oBAAI,IAAI,CAAC,YAAY,UAAU,iBAAiB,CAAC;AAQ9D,IAAM,sBAAsB;AAqG5B,IAAM,UAAN,MAAc;AAAA,EACnB,YAA6B,SAAmB,CAAC,GAAG;AAAvB;AAAA,EAAwB;AAAA,EAAxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAO7B,MAAM,MACJC,aACA,OACA,QAAQ,WACgB;AACxB,QAAI,CAAC,gBAAgB,KAAK,MAAM,IAAI,GAAG;AACrC,YAAM,IAAI,wBAAwB,2BAA2B;AAAA,QAC3D,MAAM,MAAM;AAAA,MACd,CAAC;AAAA,IACH;AACA,QAAI,CAAC,gBAAgB,KAAK,MAAM,IAAI,GAAG;AACrC,YAAM,IAAI,wBAAwB,2BAA2B;AAAA,QAC3D,MAAM,MAAM;AAAA,MACd,CAAC;AAAA,IACH;AAEA,UAAM,cAAc,0BAA0B,MAAM;AAAA,MAClD,GAAG,MAAM;AAAA,MACT,MAAM,MAAM;AAAA,IACd,CAAC;AACD,UAAMC,aAAY,GAAG,MAAM,IAAI,IAAI,MAAM,IAAI;AAC7C,UAAM,OAAO,KAAK,KAAKD,WAAU;AACjC,UAAM,SAAS,KAAK,WAAWA,aAAYC,UAAS;AAEpD,cAAM,yBAAM,MAAM,EAAE,WAAW,KAAK,CAAC;AACrC,UAAM,KAAK;AAAA,MACT;AAAA,MACA,iCAAiC,MAAM,MAAM,WAAW;AAAA,MACxD,MAAM,aAAa;AAAA,MACnBA;AAAA,IACF;AAEA,UAAM,KAAK,OAAO,MAAM;AAAA,MACtB,WAAW,MAAM,YAAY,cAAc;AAAA,MAC3C,WAAAA;AAAA,MACA,IAAI;AAAA,IACN,CAAC;AASD,UAAM,UAAU,IAAI,IAAI,YAAY,sBAAsB,CAAC,CAAC;AAC5D,YAAQ,OAAOA,UAAS;AAKxB,UAAM,gBAA0B,CAAC;AACjC,eAAW,OAAO,SAAS;AACzB,UACE,MAAM,KAAK,uBAAuBD,aAAY,KAAKC,YAAW,KAAK,GACnE;AACA,sBAAc,KAAK,GAAG;AAAA,MACxB;AAAA,IACF;AAEA,SAAK,OAAO,OAAO;AAAA,MACjB,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,WAAAA;AAAA,MACA,SAAS,YAAY,iBAAiB,UAAU;AAAA,IAClD,CAAC;AAED,WAAO;AAAA,MACL,WAAAA;AAAA,MACA;AAAA,MACA,MAAM,MAAM;AAAA,MACZ,QAAQ,cAAc,SAAS,qBAAqB;AAAA,MACpD;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,KAAKD,aAAoBC,YAA6C;AAG1E,UAAM,SAAS,KAAK,WAAWD,aAAYC,UAAS;AACpD,QAAI;AACJ,QAAI;AACF,YAAM,UAAM,4BAAS,QAAQ,MAAM;AAAA,IACrC,QAAQ;AACN,aAAO;AAAA,IACT;AACA,WAAO,KAAK,MAAMA,YAAW,GAAG;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,KACJD,aACA,MACA,SAA8B,CAAC,GACV;AACrB,UAAM,OAAO,KAAK,KAAKA,WAAU;AACjC,QAAI;AACJ,QAAI;AACF,cAAQ,UAAM,2BAAQ,IAAI;AAAA,IAC5B,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAKA,UAAM,SAAS,MACZ,KAAK,EAIL,OAAO,CAAC,SAAS,KAAK,SAAS,KAAK,KAAK,CAAC,YAAY,IAAI,IAAI,CAAC,EAC/D,IAAI,CAAC,UAAU,EAAE,MAAM,WAAW,KAAK,MAAM,GAAG,CAAC,MAAM,MAAM,EAAE,EAAE,EACjE,OAAO,CAAC,EAAE,WAAAC,WAAU,MAAM,CAAC,QAAQA,WAAU,WAAW,GAAG,IAAI,GAAG,CAAC;AAEtE,UAAM,UAAU,MAAM;AAAA,MACpB;AAAA,MACA;AAAA,MACA,OAAO,EAAE,MAAM,WAAAA,WAAU,MACvB,KAAK,MAAMA,YAAW,UAAM,gCAAS,yBAAK,MAAM,IAAI,GAAG,MAAM,CAAC;AAAA,IAClE;AACA,WAAO,QAAQ;AAAA,MACb,CAAC,WACC,WAAW,QAAQ,YAAY,QAAQ,MAAM;AAAA,IACjD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAM,UACJD,aACAC,YACA,QACA,QAAQ,WACW;AACnB,WAAO,KAAK;AAAA,MACVD;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB,EAAE,GAAG,aAAa,gBAAgB,OAAO;AAAA,MAC3D,EAAE,WAAW,UAAU,MAAM,IAAI,IAAI,MAAM;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,cACJD,aACAC,YACA,SACA,QAAQ,WACW;AACnB,WAAO,KAAK;AAAA,MACVD;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB,EAAE,GAAG,aAAa,iBAAiB,QAAQ;AAAA,MAC7D,EAAE,WAAW,kBAAkB,IAAI,MAAM;AAAA,IAC3C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,OACJD,aACAC,YACA,MACA,QAAQ,WACRC,OAAK,oBAAI,KAAK,GAAE,YAAY,GACT;AACnB,UAAM,QAAQ,sBAAsB,MAAM,EAAE,IAAI,OAAO,IAAAA,KAAI,KAAK,CAAC;AAEjE,UAAM,WAAW,MAAM,KAAK,KAAKF,aAAYC,UAAS;AACtD,QAAI,CAAC,SAAU,OAAM,IAAI,sBAAsBA,UAAS;AAMxD,UAAM,cAAc,SAAS,YAAY,WAAW;AACpD,QACE,gBAAgB,UAChB,MAAM,YAAY,MAAM,YAAY,YAAY,KAChD,CAAC,eAAe,KAAK,EAAE,WAAW,QAAQ,GAC1C;AACA,YAAM,KAAK,OAAO,KAAK,KAAKD,WAAU,GAAG;AAAA,QACvC,WAAW;AAAA,QACX,WAAAC;AAAA,QACA,IAAI;AAAA,MACN,CAAC;AACD,YAAM,IAAI,wBAAwBA,YAAW,OAAO,WAAW;AAAA,IACjE;AAEA,WAAO,KAAK;AAAA,MACVD;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB;AAAA,QAChB,GAAG;AAAA,QACH,UAAU,CAAC,GAAI,YAAY,YAAY,CAAC,GAAI,KAAK;AAAA,MACnD;AAAA,MACA,EAAE,WAAW,UAAU,IAAI,MAAM;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UACJD,aACAC,YACA,eACA,QAAQ,WACW;AACnB,UAAM,cAAc,MAAM,KAAK,KAAKD,aAAY,aAAa;AAC7D,QAAI,CAAC,YAAa,OAAM,IAAI,sBAAsB,aAAa;AAE/D,UAAM,aAAa,MAAM,KAAK;AAAA,MAC5BA;AAAA,MACAC;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,UAAM,KAAK;AAAA,MACTD;AAAA,MACA;AAAA,MACA,CAAC,iBAAiB;AAAA,QAChB,GAAG;AAAA,QACH,oBAAoB;AAAA,UAClB,GAAG,oBAAI,IAAI,CAAC,GAAI,YAAY,sBAAsB,CAAC,GAAIC,UAAS,CAAC;AAAA,QACnE;AAAA,MACF;AAAA,MACA,EAAE,WAAW,cAAc,IAAI,OAAO,QAAQA,WAAU;AAAA,IAC1D;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,OACJD,aACAC,YACA,QACA,QAAQ,WACRC,OAAK,oBAAI,KAAK,GAAE,YAAY,GACT;AACnB,WAAO,KAAK;AAAA,MACVF;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB;AAAA,QAChB,GAAG;AAAA,QACH,gBAAgB;AAAA,QAChB,kBAAkB,EAAE,IAAI,OAAO,IAAAC,IAAG;AAAA,MACpC;AAAA,MACA,EAAE,WAAW,UAAU,IAAI,MAAM;AAAA,MACjC,CAAC,SAAS,GAAG,KAAK,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA,EAAoB,MAAM;AAAA;AAAA,IACvD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,MACJF,aACA,MACA,UAIkB,CAAC,GACO;AAC1B,UAAM,SAAS,MAAM,KAAK,KAAKA,WAAU;AACzC,UAAM,SAAS,KAAK,KAAK;AACzB,UAAM,OAAO,SAAS,MAAM,KAAK,KAAKA,aAAY,QAAQ,MAAM,IAAI;AACpE,UAAM,WAAW,QAAQ,OACrB,KAAK,OAAO,CAAC,MAAM,EAAE,YAAY,SAAS,QAAQ,IAAI,IACtD;AACJ,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA,oBAAI,KAAK;AAAA,MACT,MAAM,KAAK,YAAY,UAAU,QAAQ,QAAQ;AAAA,IACnD;AAIA,UAAM,OAAO,YAAY,OAAO,CAAC,QAAQ,YAAY,IAAI,QAAQ,OAAO,CAAC;AAEzE,QAAI,QAAQ,kBAAmB,QAAO;AAKtC,UAAM,UAAU,IAAI,IAAI,KAAK,IAAI,CAAC,QAAQ,IAAI,OAAO,SAAS,CAAC;AAC/D,WAAO,KAAK;AAAA,MACV,CAAC,QACC,IAAI,aAAa,gBACjB,CAAC,IAAI,MAAM,KAAK,CAAC,SAAS,QAAQ,IAAI,KAAK,SAAS,CAAC;AAAA,IACzD;AAAA,EACF;AAAA,EAEA,MAAc,KACZA,aACA,QACA,QACqB;AACrB,UAAM,SAAS,MAAM,WAAW,KAAK,KAAKA,WAAU,GAAG,QAAQ;AAAA,MAC7D,QAAQ,KAAK;AAAA,IACf,CAAC;AACD,QAAI,QAAQ;AACV,YAAM,QAAQ,YAAY,QAAQ,MAAM;AACxC,UAAI,MAAM,OAAQ,QAAO;AAAA,IAC3B;AACA,UAAM,UAAU,OAAO,YAAY;AACnC,WAAO,OAAO,OAAO,CAAC,WAAWG,SAAQ,QAAQ,OAAO,CAAC;AAAA,EAC3D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBA,MAAM,YACJ,SACA,UACA,UAAiC,CAAC,GACsB;AACxD,QAAI;AACF,YAAM,QAAQ,MAAM,kBAAkB,SAAS;AAAA,QAC7C,UAAU,YAAY,QAAQ,IAAI;AAAA;AAAA;AAAA,QAGlC,QAAQ,EAAE,SAAS,QAAQ,YAAY,MAAM;AAAA,MAC/C,CAAC;AACD,UAAI,aAAa,UAAa,uBAAuB,KAAK,GAAG;AAC3D,aAAK,OAAO,OAAO;AAAA,UACjB,WAAW;AAAA,UACX,SAAS;AAAA,UACT,QAAQ;AAAA,QACV,CAAC;AACD,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgCA,MAAM,KACJH,aACA,UAOI,CAAC,GACkB;AACvB,UAAM,eAAe,QAAQ,gBAAgB;AAC7C,UAAM,SAAS,MAAM,KAAK,KAAKA,WAAU;AACzC,UAAM,SAAS,QAAQ,OACnB,OAAO,OAAO,CAAC,WAAW,OAAO,YAAY,SAAS,QAAQ,IAAI,IAClE;AAIJ,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA,oBAAI,KAAK;AAAA,MACT,MAAM,KAAK,YAAY,QAAQ,QAAQ,QAAQ;AAAA,IACjD;AAGA,UAAM,OAAO,YAAY;AAAA,MAAO,CAAC,QAC/B,YAAY,IAAI,QAAQ,EAAE,aAAa,QAAQ,YAAY,CAAC;AAAA,IAC9D;AACA,UAAM,UAAU,KAAK,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY;AAClE,UAAM,aAAa,KAChB,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C,IAAI,IAAI;AAIX,UAAMI,gBACJ,QAAQ,OAAO,CAAC,OAAO,QAAQ,QAAQ,eAAe,IAAI,MAAM,GAAG,CAAC,IACpE,WAAW,OAAO,CAAC,OAAO,UAAU,QAAQ,mBAAmB,KAAK,GAAG,CAAC;AAI1E,UAAM,oBAAoB,aAAa,SAAS,UAAU;AAE1D,QAAI,CAAC,QAAQ,OAAOA,gBAAe,cAAc;AAC/C,aAAO;AAAA,QACL,QAAQ;AAAA,QACR,aAAa,KAAK;AAAA,QAClB,cAAAA;AAAA,QACA;AAAA,QACA,SAAS,eAAe;AAAA,UACtB,cAAAA;AAAA,UACA;AAAA,UACA,MAAM,QAAQ;AAAA,QAChB,CAAC;AAAA,QACD,QAAQ;AAAA,MACV;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,aAAa,KAAK;AAAA,MAClB,cAAcA;AAAA,MACd,cAAc,QAAQ,MAAM,OAAO;AAAA,MACnC;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,MACJJ,aACA,UAAiC,CAAC,GACV;AACxB,UAAM,SAAS,MAAM,KAAK,KAAKA,WAAU;AACzC,UAAM,cAAc,WAAW,QAAQ,QAAQ,oBAAI,KAAK,CAAC;AACzD,UAAM,UAAU,YAAY,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY;AACzE,UAAM,aAAa,YAChB,OAAO,CAAC,QAAQ,IAAI,aAAa,YAAY,EAC7C,IAAI,IAAI;AAEX,UAAM,UAAU,YAAY,SAAS,UAAU;AAC/C,UAAM,QAAQ,OACX,IAAI,CAAC,WAAW,OAAO,YAAY,WAAW,MAAM,IAAI,EACxD,OAAO,CAACE,QAAqB,OAAOA,QAAO,QAAQ,EACnD,KAAK;AAaR,UAAM,QAAQ,MAAM,KAAK,YAAY,QAAQ,QAAQ,QAAQ;AAC7D,UAAMG,WACJ,UAAU,SACN,OACA,CAAC,GAAG,MAAM,OAAO,CAAC,EAAE;AAAA,MAAO,CAAC,YAC1B,QAAQ;AAAA,QACN,CAAC,UACC,MAAM,UAAU,WAAW,CAAC,kBAAkB,MAAM,MAAM;AAAA,MAC9D;AAAA,IACF,EAAE;AAER,WAAO;AAAA,MACL,MAAML;AAAA,MACN,QAAQ,QAAQ;AAAA,MAChB,aAAa,OAAO;AAAA,MACpB,YAAY,WAAW;AAAA,MACvB,UAAU,MAAM,GAAG,EAAE,KAAK;AAAA,MAC1B,SAAS,QAAQ;AAAA,MACjB,SAAAK;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,MACJL,aACA,QACA,UAA0B,CAAC,GACH;AACxB,WAAO,MAAM,QAAQ,MAAM,KAAK,KAAKA,WAAU,GAAG,OAAO;AAAA,EAC3D;AAAA;AAAA,EAGA,MAAM,QACJA,aACA,UAAuD,CAAC,GAC9B;AAC1B,WAAO,QAAQ,MAAM,KAAK,KAAKA,WAAU,GAAG,OAAO;AAAA,EACrD;AAAA;AAAA,EAGA,MAAM,KACJA,aACA,QACA,UAAyB,CAAC,GACH;AACvB,WAAO,KAAK,MAAM,KAAK,KAAKA,WAAU,GAAG,QAAQ,OAAO;AAAA,EAC1D;AAAA;AAAA,EAGA,MAAM,OACJA,aACA,UACA,UAA2B,CAAC,GACH;AACzB,WAAO,OAAO,UAAU,MAAM,KAAK,KAAKA,WAAU,GAAG,OAAO;AAAA,EAC9D;AAAA;AAAA,EAGA,MAAM,UACJA,aACA,UAC4B;AAC5B,WAAO,UAAU,UAAU,MAAM,KAAK,KAAKA,WAAU,CAAC;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,UAAUA,aAAqC;AACnD,UAAM,OAAO,KAAK,KAAKA,WAAU;AACjC,UAAM,WAAW,YAAY,MAAM,KAAK,KAAKA,WAAU,CAAC;AACxD,UAAM,SAAS,UAAM,gCAAS,yBAAK,MAAM,UAAU,GAAG,MAAM,EAAE;AAAA,MAC5D,MAAM;AAAA,IACR;AAEA,QAAI,aAAa,QAAQ,QAAQ,GAAG;AAClC,YAAM,KAAK,YAAQ,yBAAK,MAAM,UAAU,GAAG,UAAU,MAAM,UAAU;AACrE,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,YAAY;AAAA,QACZ,QAAQ,WAAW,OAAO,YAAY;AAAA,MACxC,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,QAAQA,aAA0D;AACtE,UAAM,MAAM,UAAM;AAAA,UAChB,yBAAK,KAAK,KAAKA,WAAU,GAAG,QAAQ;AAAA,MACpC;AAAA,IACF,EAAE,MAAM,MAAM,EAAE;AAChB,UAAM,SAAS,SAAS,GAAG;AAC3B,eAAW,OAAO,OAAO,WAAW;AAClC,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,MAAM,IAAI;AAAA,QACV,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,MAAc,uBACZA,aACAC,YACA,eACA,OACA,UAAU,GACQ;AAClB,aAAS,UAAU,GAAG,WAAW,SAAS,WAAW;AACnD,UAAI;AACF,cAAM,KAAK,eAAeD,aAAYC,YAAW,eAAe,KAAK;AACrE,eAAO;AAAA,MACT,SAAS,OAAO;AACd,YAAI,iBAAiB,sBAAuB,QAAO;AACnD,YAAI,EAAE,iBAAiB,sBAAuB,OAAM;AACpD,YAAI,YAAY,QAAS,QAAO;AAAA,MAClC;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAc,eACZD,aACAC,YACA,eACA,OACmB;AACnB,WAAO,KAAK;AAAA,MACVD;AAAA,MACAC;AAAA,MACA,CAAC,iBAAiB;AAAA,QAChB,GAAG;AAAA,QACH,gBAAgB;AAAA,QAChB,uBAAuB;AAAA,MACzB;AAAA,MACA,EAAE,WAAW,aAAa,IAAI,OAAO,QAAQ,cAAc;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAc,OACZD,aACAC,YACA,QACA,OACA,aAAuC,CAAC,SAAS,MAC9B;AACnB,UAAM,SAAS,KAAK,WAAWD,aAAYC,UAAS;AACpD,UAAM,SAAS,UAAM,4BAAS,QAAQ,MAAM,EAAE,MAAM,MAAM,IAAI;AAC9D,QAAI,WAAW,KAAM,OAAM,IAAI,sBAAsBA,UAAS;AAE9D,UAAM,SAAS,KAAK,MAAMA,YAAW,MAAM;AAC3C,QAAI,CAAC,OAAQ,OAAM,IAAI,sBAAsBA,UAAS;AAEtD,UAAM,cAAc,OAAO,OAAO,WAAW;AAC7C,UAAM,OAAO,WAAW,OAAO,IAAI;AACnC,UAAM,WAAW,iCAAiC,MAAM,WAAW;AAOnE,UAAM,UAAU,UAAM,4BAAS,QAAQ,MAAM,EAAE,MAAM,MAAM,IAAI;AAC/D,QAAI,YAAY,QAAQK,QAAO,OAAO,MAAMA,QAAO,MAAM,GAAG;AAC1D,YAAM,IAAI,qBAAqBL,UAAS;AAAA,IAC1C;AACA,UAAM,KAAK,QAAQ,QAAQ,UAAU,MAAMA,UAAS;AACpD,UAAM,KAAK,OAAO,KAAK,KAAKD,WAAU,GAAG,EAAE,GAAG,OAAO,WAAAC,WAAU,CAAC;AAEhE,WAAO,EAAE,WAAAA,YAAW,aAAa,KAAK;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAc,QACZ,QACA,UACA,WACAA,YACe;AACf,UAAM,UAAU,GAAG,MAAM,IAAI,QAAQ,GAAG;AACxC,cAAM,6BAAU,SAAS,UAAU,MAAM;AAEzC,QAAI;AACF,UAAI,WAAW;AACb,kBAAM,0BAAO,SAAS,MAAM;AAC5B;AAAA,MACF;AACA,gBAAM,wBAAK,SAAS,MAAM;AAAA,IAC5B,SAAS,OAAO;AACd,UAAK,MAAgC,SAAS,UAAU;AACtD,cAAM,IAAI,2BAA2BA,UAAS;AAAA,MAChD;AACA,YAAM;AAAA,IACR,UAAE;AAEA,gBAAM,0BAAO,OAAO,EAAE,MAAM,MAAM,MAAS;AAAA,IAC7C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0CA,MAAc,oBAAoB,MAA6B;AAC7D,UAAM,aAAS,yBAAK,MAAM,kBAAkB;AAC5C,QAAI;AACF,UAAI;AACJ,UAAI;AACF,mBAAW,UAAM,4BAAS,QAAQ,MAAM;AAAA,MAC1C,SAAS,OAAO;AACd,YAAK,MAAgC,SAAS,SAAU,OAAM;AAC9D,mBAAW;AAAA,MACb;AAEA,UAAI,aAAa,MAAM;AACrB,YAAI;AACF,oBAAM,6BAAU,QAAQ,qBAAqB,EAAE,GAAG;AAAA,YAChD,UAAU;AAAA,YACV,MAAM;AAAA,UACR,CAAC;AAAA,QACH,SAAS,OAAO;AAId,cAAK,MAAgC,SAAS,SAAU,OAAM;AAC9D,eAAK,OAAO,OAAO;AAAA,YACjB,WAAW;AAAA,YACX,YAAY;AAAA,YACZ,SAAS;AAAA,UACX,CAAC;AACD;AAAA,QACF;AACA,aAAK,OAAO,OAAO;AAAA,UACjB,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,SAAS;AAAA,QACX,CAAC;AACD;AAAA,MACF;AACA,UAAI,CAAC,oBAAoB,QAAQ,GAAG;AAClC,kBAAM,8BAAW,QAAQ,qBAAqB,QAAQ,GAAG,MAAM;AAC/D,aAAK,OAAO,OAAO;AAAA,UACjB,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF,SAAS,OAAO;AACd,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,OACZ,MACA,OACe;AACf,UAAM,KAAK,oBAAoB,IAAI;AACnC,UAAM,OAAO,eAAe,EAAE,KAAI,oBAAI,KAAK,GAAE,YAAY,GAAG,GAAG,MAAM,CAAC;AACtE,cAAM,kCAAW,yBAAK,MAAM,QAAQ,GAAG,MAAM,MAAM,EAAE,MAAM,CAAC,UAAU;AACpE,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,MAClD,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA,EAEQ,MAAMA,YAAmB,KAA8B;AAC7D,UAAM,SAAS,6BAA6B,KAAK,yBAAyB;AAC1E,QAAI,CAAC,OAAO,YAAY,SAAS;AAC/B,WAAK,OAAO,OAAO;AAAA,QACjB,WAAW;AAAA,QACX,WAAAA;AAAA,QACA,SAAS;AAAA,QACT,OAAO,OAAO,YAAY,MAAM,OAAO,CAAC,GAAG,WAAW;AAAA,MACxD,CAAC;AACD,aAAO;AAAA,IACT;AACA,WAAO;AAAA,MACL,WAAAA;AAAA,MACA,aAAa,OAAO,YAAY;AAAA,MAChC,MAAM,OAAO;AAAA,IACf;AAAA,EACF;AAAA,EAEQ,KAAKD,aAA4B;AACvC,eAAO,4BAAQA,WAAU;AAAA,EAC3B;AAAA;AAAA;AAAA,EAIQ,WAAWA,aAAoBC,YAA2B;AAChE,QAAIA,WAAU,SAAS,sBAAG,KAAKA,WAAU,SAAS,GAAG,GAAG;AACtD,YAAM,IAAI;AAAA,QACR;AAAA,QACA,EAAE,WAAAA,WAAU;AAAA,MACd;AAAA,IACF;AACA,eAAO,yBAAK,KAAK,KAAKD,WAAU,GAAG,GAAGC,UAAS,KAAK;AAAA,EACtD;AACF;AAWO,SAAS,eAAe,QAA0B;AACvD,SAAO,KAAK;AAAA,KACT,OAAO,KAAK,SAAS,KAAK,UAAU,OAAO,WAAW,EAAE,UAAU;AAAA,EACrE;AACF;AAEO,SAAS,mBAAmB,OAAiC;AAClE,SAAO,KAAK,KAAK,KAAK,UAAU,KAAK,EAAE,SAAS,CAAC;AACnD;AAGA,SAAS,eAAe,SAIb;AACT,QAAM,QAAQ,QAAQ,OAAO,YAAY,QAAQ,IAAI,KAAK;AAE1D,SAAO;AAAA,IACL,sCAAsC,QAAQ,YAAY,uBAAuB,QAAQ,YAAY;AAAA,IACrG,0CAA0C,KAAK;AAAA,IAC/C,iDAAiD,QAAQ,YAAY;AAAA,EACvE,EAAE,KAAK,GAAG;AACZ;AASO,SAAS,KAAK,KAAsC;AACzD,SAAO;AAAA,IACL,WAAW,IAAI,OAAO;AAAA,IACtB,OAAO,IAAI,OAAO,YAAY,SAAS;AAAA,IACvC,cAAc,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,SAAS;AAAA,IACpD,IAAI,IAAI,OAAO,YAAY,WAAW,MAAM;AAAA,EAC9C;AACF;AAEA,SAASE,SAAQ,QAAkB,QAAyB;AAC1D,QAAM,EAAE,OAAO,YAAY,IAAI,OAAO;AAItC,SAAO,CAAC,OAAO,WAAW,OAAO,aAAa,OAAO,IAAI,EAAE;AAAA,IAAK,CAAC,UAC/D,OAAO,YAAY,EAAE,SAAS,MAAM;AAAA,EACtC;AACF;AAQA,SAAS,eAAe,IAAoB;AAC1C,QAAM,QAAQ,GAAG,QAAQ,GAAG;AAC5B,MAAI,UAAU,GAAI,QAAO,GAAG,YAAY;AACxC,SAAO,GAAG,MAAM,GAAG,QAAQ,CAAC,EAAE,YAAY,IAAI,GAAG,MAAM,QAAQ,CAAC;AAClE;;;AS9pCO,IAAM,UACX,OACI,WACA;;;A3FAC,SAAS,oBAA+B;AAC7C,QAAM,SAAS,IAAI,qBAAU,EAAE,MAAM,cAAc,SAAS,QAAQ,CAAC;AACrE,QAAM,QAAQ,IAAI,QAAQ;AAAA,IACxB,MAAM,CAAC,UAAU,QAAQ,OAAO,MAAM,GAAG,KAAK,UAAU,KAAK,CAAC;AAAA,CAAI;AAAA,EACpE,CAAC;AACD,QAAM,MAAM;AAAA,IACV;AAAA,IACA,OAAO,QAAQ,IAAI,oBAAoB;AAAA,IACvC,KAAK,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,EACpC;AAEA,aAAW,WAAW,aAAa;AAGjC,QAAI,CAAC,QAAQ,KAAM;AACnB,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,EAAE,aAAa,QAAQ,aAAa,aAAa,QAAQ,MAAM,MAAM;AAAA,MACrE,OAAO,SAAkB;AACvB,cAAM,SAAS,MAAM,QAAQ,IAAI,KAAK,QAAQ,MAAM,MAAM,IAAI,CAAC;AAC/D,eAAO;AAAA,UACL,SAAS;AAAA,YACP;AAAA,cACE,MAAM;AAAA,cACN,MACE,OAAO,WAAW,WACd,SACA,KAAK,UAAU,QAAQ,MAAM,CAAC;AAAA,YACtC;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,eAAsB,iBAAgC;AACpD,QAAM,kBAAkB,EAAE,QAAQ,IAAI,kCAAqB,CAAC;AAC9D;;;A4FtDA,eAAe,EAAE,MAAM,CAAC,UAAmB;AACzC,UAAQ,OAAO;AAAA,IACb,GAAG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA;AAAA,EAC3D;AACA,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["import_zod","import_zod","link","impact","import_zod","at","at","import_node_child_process","import_node_util","execFileAsync","at","group","rejected","at","cached","import_promises","import_node_path","at","import_node_crypto","import_node_path","import_promises","import_promises","import_node_os","import_node_path","sha256","base","resolve","import_node_path","import_zod","sha256","pack","at","pack","import_node_crypto","matches","at","at","at","pack","matches","cached","index","at","tokens","span","conceptId","approxTokens","table","raw","bundlePath","import_node_path","import_promises","import_node_os","import_node_path","import_node_path","import_zod","bundlePath","bundlePath","bundlePath","at","entry","import_node_path","bundlePath","import_zod","value","at","base","matches","import_zod","import_zod","import_zod","unchecked","missing","import_zod","import_promises","HEADING","superseded","base","import_zod","import_node_child_process","import_node_util","execFileAsync","git","shown","at","import_promises","at","size","at","table","row","col","base","link","conceptId","link","at","count","import_zod","impact","expiring","unverified","drifted","render","width","group","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","render","at","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","index","import_promises","import_zod","bundlePath","conceptId","import_zod","import_zod","import_zod","import_zod","at","import_zod","import_zod","import_zod","import_zod","import_zod","import_zod","import_promises","import_node_path","matter","import_node_crypto","sha256","import_promises","import_node_path","bundlePath","readdir","at","index","link","link","bundlePath","conceptId","at","matches","approxTokens","drifted","sha256"]}