npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aiquants/enrichment-core

v0.8.1

Published

Storage metadata AI enrichment core: canonical schemas, RFC 9562 UUIDv7, and API client SDK.

Readme

@aiquants/enrichment-core

Transport- and DB-agnostic storage metadata AI enrichment core: canonical types, RFC 9562 UUIDv7 utility, the document change history contract and diff engine, and API client SDK.

ストレージメタデータ・AI エンリッチメント基盤の正準 TypeScript 型定義、RFC 9562 準拠 UUIDv7 ユーティリティ、およびクライアント SDK を提供する共有コアライブラリ。

Features / 主な機能

  • RFC 9562 UUIDv7: ゼロ依存のブラウザ・Node.js 共通ミリ秒タイムスタンプ付き時間順序 UUIDv7 生成・復元 (generateUuidV7, uuidv7ToDate, isValidUuidV7)。
  • Canonical Types & Schemas: EnrichmentSyncStatus, DocumentStructuredData, BoundingBox, CircuitBreakerStatus 等の正準 TypeScript 型および Zod スキーマ。
  • EnrichmentClient: ハイブリッド検索 (POST /ai/search/hybrid) を呼ぶ HTTP クライアント SDK。要求・応答のスキーマ (SearchRequestSchema / SearchResponseSchema) は Python 側 HybridSearchRequest / HybridSearchResponse と項目ごとに一致する。詳細は下の「Search client contract」。
  • Pipeline flow as data (flow.ts): 文書種 (DOCUMENT_KINDS / classifyDocumentKind)、段 (PIPELINE_STEPS)、種類ごとの段の DAG (PIPELINE_FLOWS / flowFor / orderedSteps)。ワーカーの実行順とコンソールの図はこの 1 つの表から導く。段は自分を閉じるテナントのフラグ (gates) と、閉じたときの意味 (skip / fail) を宣言し、流れは段ごとにその意味を上書きできる (FlowStep.gatePolicy)。流れの中の門は flowStepGates で読む。詳細は下の「Pipeline flow contract」。
  • Source catalog (sourceCatalog.ts): 源の目録 (GET /ai/sources) の厳格な型 (SourceCatalogSchema / SourceSpecSchema) と語彙 (SOURCE_CREDENTIALS / SOURCE_CAPABILITIES)、画面の助け (sourceOfUri / identifierMatches / pastedIdentifier)。源を宣言するのは Python のコアの登録簿だけで、画面は目録を読み、源の型の表を持たない。詳細は下の「Source catalog contract」。
  • Pipeline records (pipelineRecord.ts): 1 回の実行 (PipelineRunRecordSchema) と段ごとの記録 (PipelineStepRecordSchema)、段を除いた実行の要約 (PipelineRunSummarySchema、一覧向け)、段が自身について報告する値 (StageProvenanceSchema、Python 側の StageProvenance と項目ごとに一致)、段の集計 (PipelineStepMetricSchema)、飛ばした理由の文法 (SkipReason / formatSkipReason / parseSkipReason、読む対象が無かったときの値 NOTHING_TO_READ_TOKENS / NothingToReadTokenSchema)。測っていない値は null で、欠落させない。詳細は下の「Pipeline record contract」。
  • Integrity audit contract (integrity.ts): Tri-Store 整合性監査の記録の語彙 (IntegrityStoreSchema を含む 12 の列挙と、所見を記録する区分 IntegrityFindingItemClassSchema)、区分の扱いと処置の表 (INTEGRITY_CLASS_POLICY)、概況 (IntegrityAuditOverviewSchema)、所見の頁と要求 (IntegrityFindingPageSchema / IntegrityFindingsQuerySchema)、 UNRECORDED の組の一括の再同期の 1 回分の要求と答え (IntegrityCellResyncRequestSchema / IntegrityCellResyncResultSchema)、配置の所見が観測したドメイン (IntegrityPlacementObservedSchema)、開始・中止の命令と命令ごとの失敗の語彙 (IntegrityCommandSchema / IntegrityCommandFailureSchema) と (状態, 業務コード) の表 (integrityCommandCodes.json / INTEGRITY_COMMAND_CODES / integrityCommandFailureCodeOf)、ホストのストアの応答 (IntegrityCommandReplySchema)、契約の時刻の前後の比較 (isStrictlyEarlier)。 詳細は下の「Integrity audit contract」。
  • Enrichment stages (strategy.ts): ドメインの戦略行が開閉できる段の唯一の表 (ENRICHMENT_STAGES、パイプラインの順) と段の型・キー (EnrichmentStage / EnrichmentStageKey、DB の列名と 1 対 1)、キーの判定と引き当て (isEnrichmentStageKey / enrichmentStage)。段はテナントの機能フラグと戦略行の 2 つの門を持ちうる (テナントの門の無い段は featureFlagKey が null)。ナレッジグラフのノードを閲覧するときの境界と既定値 (GRAPH_INDEX_LIMITS)。
  • Vocabularies & search modes (vocabulary.ts / search.ts): DB が強制する閉じた語彙 (ModelProviderSchema・ConfidentialityLevelSchema、検索結果に現れない機密区分 QUARANTINED_CONFIDENTIALITY_LEVEL)、検索モードと各モードが走らせる層の表 (SEARCH_MODES / MODE_TIERS と、そこから導く modeScoreIsSimilarity / modeFusesRankings)、調整可能な引数の境界と既定値 (SEARCH_PARAM_LIMITS。問いと文字の絞り込みの文字数を含む)、絞り込める機密区分 (FILTERABLE_CONFIDENTIALITY_LEVELS)、 答えの閉じた語彙 (融合 SEARCH_FUSIONS・品質の段 SEARCH_QUALITY_TIERS・遮断器のストア CIRCUIT_BREAKER_SERVICES と状態 CircuitBreakerStatusSchema・縮退の理由 SEARCH_DEGRADATION_REASONS)。規則は Python のコア (aiquants_enrichment_core.search.contract) に在り、公開 API が OpenAPI に出す値を画面のために写す。
  • Document change history (documentHistory.ts / revisionDiff/ / canonicalJson.ts): 文書の差分履歴 (S1 §8.19) の契約 (語彙・版付きの定数・面ごとの正準の値・変化の計数・比較・行の頁・履歴・直近の変化の一覧と位置・手動の記録の答え・隔離の印 Restricted*MarkSchema と読める項目の包み ReadableEntry)、記録器と読み手が共有する差分エンジン v2 (summarizeTransition / compareStates、純粋な関数で入出力もハッシュも持たない)、システムの中の唯一の正準の JSON (canonicalJson)。詳細は下の「Document history contract」。
  • Processing objects list (processingObjects.ts): コンソールの処理オブジェクト一覧 (テナントの td_file_metadata の全ての行。取り込んだ文書と、その木の節点) の契約 (閉じた絞り込みの語彙 PROCESSING_OBJECT_KINDS ほかと ProcessingObjectFilterSchema、頁の上限、文書と節点の読める行 ProcessingObjectItemSchema、文書だけの隔離の印 RestrictedProcessingObjectMarkSchema、頁 ProcessingObjectPageSchema と位置 encodeProcessingObjectCursor / decodeProcessingObjectCursor)。詳細は下の「Processing objects list contract」。
  • Child asset tree (childTree.ts / childTreeRebuild.ts): 根の下の子アセットの木の節点の道の文法 (TREE_PATH_PATTERN / TreePathSchema)、区画・深さ・親の道 (treePathSegments / treePathDepth / treePathParent)、木の順 (compareTreePaths)、画面の名 (treePathLabel / assetTypeName)、面 assets の項目の道 (treePathOf / AssetPlace)、既存の文書の木をまとめて取り込み直す 1 回分の要求と答え (ChildTreeRebuildRequestSchema / ChildTreeRebuildResultSchema / CHILD_TREE_REBUILD_CHUNK)。詳細は下の「Child asset tree contract」。
  • System parameter ranges (systemParameterRanges.ts): 値域を持つシステムパラメータの唯一の表 (systemParameterRanges.json / SYSTEM_PARAMETER_RANGES) と、書き手が当てる検査 (assertSystemParameterInRange) と読み手が当てる検査 (assertBoundedSystemParameter)。詳細は下の「System parameter ranges」。

Search client contract / 検索クライアントの契約

| Schema | Mirrors (Python) | Rule / 規則 | | --- | --- | --- | | SearchRequestSchema | HybridSearchRequest | キーは query / tenant_id / domain_key / limit / department_id / search_mode / strategy_id だけ。生産側が extra="forbid" のため strict であり、宣言外のキーは送信前に ZodError で拒む。省略した任意キーは送らず、既定値はサーバー (HybridSearchRequest) が決める。strategy_id はその戦略行のコレクションだけを検索する | | SearchResponseSchema | HybridSearchResponse | hits (SearchHitSchema: metadata_id / chunk_index / text / score)、graph_hits (GraphSearchHitSchema)、tiers (層の名前ごとの真偽値)、metadata | | SearchMetadataSchema | SearchMetadata | circuit_breaker_status と quality_tier は文字列 (検索サービスは走らせたモード、層を飛ばしたときは DEGRADED を報告)、latency_ms、total_hits、fallback_applied、degraded_reason (飛ばした層の理由、無ければ null) |

  • EnrichmentClient が持つのは search だけである。送信先は <baseUrl>/ai/search/hybrid であり、baseUrl はエンリッチメントのルーターが載る API ルート (エンリッチメントのルーターを載せる API サーバーのホストと API 接頭辞、例 https://api.example.com/api/v1)。
  • ルートは Authorization: Bearer <apiKey> の利用者を認可し、テナントを X-Tenant-Id から取る。クライアントは X-Tenant-Id に本文の tenant_id を入れる (両者が食い違えばルートが 403 で拒む)。apiKey には利用者のアクセストークンを渡す (無ければルートが拒む)。
  • 2xx 以外の応答と通信失敗は EnrichmentClientError (statusCode・responseBody・JSON なら parsedBody、通信失敗は statusCode 0)、JSON でない 2xx は EnrichmentClientError、スキーマに反する要求・応答 (空本文を含む) は ZodError を投げる。
  • 縮退の理由の語彙 (SEARCH_DEGRADATION_REASONS、search.ts) は API の閉じた 14 語で、戦略が要した SQL の外の層が走らなかった訳を述べる (管理者の無効化・開いた遮断器・設定の欠け・コレクションの欠け・行スコープ・層ごとの届かない / 期限切れ・後ろ盾の tiers_not_executed)。degraded_reason はそれをカンマで連ねる。

Pipeline flow contract / 流れの契約

Document kind / 文書種

  • classifyDocumentKind(mimeType) は MIME_KIND_RULES を上から照合し、最初に一致した規則の種類を返す (* で終わる規則は前方一致、パラメータと大文字小文字は無視)。どの規則にも一致しない型は other。

  • 種類を名指しするのは抽出が読める書式だけである。Outlook の .msg (application/vnd.ms-outlook) は RFC 822 ではなく抽出が名指しで拒むため規則を持たず、other の流れを取る (最初に本文を読む段がその拒否を記録する)。email は message/rfc822 だけ。

  • ベクタの図形は image/ の型でも image の流れを取らない (その流れの唯一の本文は版面の OCR であり、画素の無い図形からは作れない)。image/svg+xml は抽出が XML の文字として読むため text、image/emf・image/x-emf・image/wmf・image/x-wmf は読み手が無く抽出が名指しで拒むため other の流れを取る。どちらの規則も image/* より前に置く (後ろに置けば image/* が先に一致する)。

  • Markdown (text/markdown・text/x-markdown) は text/* より前の規則で markdown の流れを取る。その流れは文字層と、文書が参照する画像を子アセットとして読み (extract_assets → ocr_children → resolve_body)、版面の OCR (ocr_document) を持たない。他のテキスト (text) の流れは子アセットを読まない。

  • 展開が読む書式の書庫 (ZIP の application/zip・application/x-zip-compressed・application/x-zip、tar の application/x-tar・application/x-gtar、gzip の application/gzip・application/x-gzip、bzip2 の application/x-bzip2、xz の application/x-xz (圧縮した tar も 1 つの圧縮したファイルも)) は archive の流れを取る。 書庫自身は文字層も版面も持たないので、その流れは書庫の暗号を外した後に中身を子アセットとして展開して読み (delete_child_assets → unlock_document → extract_assets → ocr_children → resolve_body → enrich_document → project_to_indexes)、本文は中身の本文だけである。 中身が部品を持つ容れ物 (メール・PDF・Office) なら、その部品も中身の子として取り出して読む (下の「Child asset tree contract」)。OOXML の文書も ZIP の容れ物だが、自身の型を持ち office の規則が名指す。他の書庫の書式 (7z・RAR・zstd) は読み手が無く other の流れを取る。

  • パスワードを持ちうる文書 (pdf・office・archive) の流れだけが、旧版の子アセットの削除の直後に unlock_document を置く (文書のパスワードを外し、解いたファイルを原本にする)。他の全ての段はその後に原本を読む。段は門を持たず (閉じると読めない守られた文書を通すだけになる)、パスワードの無い文書は not_protected で飛ばす。メールの添付など子のパスワードは extract_assets の中で外すので、email の流れは段を持たない。

Gates / 門

| Declared by / 宣言する場所 | Meaning / 意味 | | --- | --- | | PIPELINE_STEPS[key].gates (StepGate) | 段の宣言。skip は段を飛ばして続行、fail は failureStatus で実行を終える | | FlowStep.gatePolicy (FlowGatePolicy) | 1 つの流れに限り、その段の全ての門の意味を上書きする。宣言できるのは { whenClosed: "fail", failureStatus } だけ。門を持たない段に書くと orderedSteps が throw する | | flowStepGates(flowStep) | 流れの中で段が持つ門 (上書きを適用した結果、宣言順)。ワーカーが評価し、コンソールが描くのはこの値であり、PIPELINE_STEPS[key].gates を直に読まない |

  • 子の読み取りの段 (ocr_children) は門を宣言しない。子の文字層 (テキスト・メール・Office・PDF) は ENABLE_OCR に関係なく読まなければならず、段ごと飛ばすと添付のテキストが本文から消えるためである。認識の要る子だけが API サーバーの中で ENABLE_OCR に従い、閉じていればワーカーはその子の行を gate_closed:ENABLE_OCR で SKIPPED と記録する (段のキーに OCR の名が残るのは、共有 DB の段の記録と集計がこのキーで引かれるためであり、運用者に見せる名前は「子アセットの読み取り」)。
  • 出荷する上書きは 3 つだけ: 画像の流れの ocr_document、メディアの流れの analyze_media、書庫の流れの extract_assets。どれも流れの唯一の本文の出所であり (書庫の本文は中身だけなので、中身を取り出す段が唯一の出所)、フラグ (ENABLE_OCR / ENABLE_MEDIA_ANALYSIS / ENABLE_ASSET_EXTRACTION) が閉じていれば、その門で実行を FAILED_EXTRACT として止める。文字層を持つ流れ (pdf / email / office / google_native) の ocr_document は宣言どおり飛ばす。
  • 実行側の契約 (orderedSteps の docstring): ワーカーは orderedSteps(flow) の順に段を走らせ、各段の前に flowStepGates(step) を評価する。最初に閉じていた門が決める — skip は段を gate_closed:<flag> で SKIPPED と記録して次へ進み、fail は段を FAILED と記録してその門の failureStatus で実行を終える。段は全ての門が開いているときだけ走る。
  • どの流れも、門で飛ばされうる段だけに本文を頼らない (文書自身の本文を作りうる段 extract_text / ocr_document / analyze_media のうち少なくとも 1 つは、閉じれば実行を止めるか門を持たない。それらを 1 つも持たない流れ (archive) は子アセットだけが本文なので、子を取り出す段 extract_assets が閉じれば実行を止める)。テストが出荷する全ての流れでこれを検査する。

Golden file / 黄金の写し

  • Python のコアの登録簿 (aiquants_enrichment_core.pipeline) が同じ段と流れを宣言する。2 つを縛るのは、この表から書く黄金の写し (flow-ts-golden.json) で、書き手は tests/flowGolden.spec.ts (書き先を FLOW_GOLDEN_OUT が名指す時だけ走る)。
  • 写しは語彙・段・MIME の事例・流れごとの宣言の並びと位相順・順序の対 (依存の推移閉包)・門・chunkSource・子ごとの段と、orderedSteps が拒む 3 例と通す壊れた 2 例を持つ。封として src/flow.ts の SHA-256 を持つので、ここを直したら写しを書き直す。

Source catalog contract / 源の目録の契約

| Field / 欄 | Meaning / 意味 | | --- | --- | | scheme | 源の型 (^[a-z][a-z0-9+.-]{0,31}$)。目録の中で重ならない | | uri_prefix | <scheme>:// で始まる接頭辞 (例 daily-report://reports/) | | input_pattern / input_example | 接頭辞の後の識別子が全て一致すべき形と、それに全て一致する例 | | paste_patterns | 貼った文 (共有の URL など) から識別子を取る形。捕まえる群はちょうど 1 つ | | credential | 誰の資格情報で読むか (SOURCE_CREDENTIALS) | | capabilities | 読み以外にできること (SOURCE_CAPABILITIES)。重ならない | | delivered_mime_type | 源がどの形を求めても届ける型 (保管層の源は null) |

  • 形は Python の re とブラウザの RegExp が同じに読む部分集合だけを使う (登録簿が組む時に拒む)。どちらも . を全ての字に届かせる (Python は re.DOTALL、ブラウザは s と u の旗)。全て一致は ^(?:<形>)$ で行い、s と u の旗でコンパイルできない形は型が拒む。
  • sourceOfUri は長い接頭辞を先に見る。identifierMatches は全て一致だけを認める。pastedIdentifier は目録の順に源と形を試し、最初に当たった形の群を返す。

Pipeline record contract / 実行記録の契約

Step record / 段の記録

| Field | Writer contract / 書き手の契約 | Checked by the schema / スキーマが検査する規則 | | --- | --- | --- | | stepKey | 流れの段 (PIPELINE_STEP_KEYS) か終端段 record_document_state | storedTermSchema(LEDGER_STEP_KEYS) (LEDGER_STEP_KEYS の 11 語か、今の語彙が知らない鍵の UnknownTerm。下の「保存された語」) | | targetTreePath | 対象が木の節点 (扇出した段の子アセット) なら根からの木の道、根 (文書自身) なら null | 木の道の文法 (TreePathSchema) か null (鍵の欠落は拒む)。targetMetadataId との一致は検査しない | | status | RUNNING / SUCCEEDED / SKIPPED / FAILED | 語彙 | | skipReason | SKIPPED のときだけ formatSkipReason の文字列を書き、それ以外は null | SKIPPED では非 null、SUCCEEDED と FAILED では null。RUNNING の値は検査しない。文法の外の文字列も DB の値 (z.string()) として受け入れ、解釈は読み手が parseSkipReason で行う | | provenance | 段が自身について報告する値。SUCCEEDED では必須、SKIPPED では null (読む対象が無いと答えた段も、モデル欄が null の応答の報告を写さない) | SUCCEEDED では非 null、SKIPPED では null。RUNNING と FAILED の値は検査しない | | strategyId | 段が適用した tm_enrichment_strategy の行 (投影段だけが報告する provenance.strategy_id)。報告の無い段では null | 正の整数か null (キーの欠落は拒む)。provenance.strategy_id との一致は検査しない | | finishedAt | RUNNING では null | RUNNING では null | | durationMs | ワーカーが測った往復時間。SKIPPED の段 (呼び出さなかった段と、読む対象が無いと答えた段) と門が閉じて止まった FAILED の段は null で書く (どれも読み取りの所要の標本ではない) | 0 以上の整数か null。状態との関係は検査しない。共有 DB には所要 0 で書かれた SKIPPED の行が既に在り、それも受け入れる |

PipelineStepRecordSchema が superRefine で検査する状態ごとの規則は次の 6 つだけである: SKIPPED は理由を持ち報告を持たない、SUCCEEDED は報告を持ち理由を持たない、RUNNING は finishedAt を持たない、FAILED は理由を持たない。破られた規則はその項目の経路で報告する。中列にだけ在る約束 (RUNNING の理由、SKIPPED と門が閉じた FAILED の所要が null であること) は書き手の契約であり、読み手はスキーマがそれを破る行を拒むと当てにできない。

Skip reason grammar / 飛ばした理由の文法

| SkipReason | Text (skip_reason) | Meaning | | --- | --- | --- | | { kind: "gate_closed", featureFlagKey } | gate_closed:ENABLE_OCR | 段を閉じる機能フラグ (UPPER_SNAKE_CASE) が無効だった | | { kind: "no_children" } | no_children | 子アセットを生む段は走ったが、子が 1 件も無かった | | { kind: "source_skipped", stepKey } | source_skipped:extract_assets | 扇出の元になる段が同じ実行で飛ばされた (子を探していない) | | { kind: "nothing_to_read", token } | nothing_to_read:no_pages | 呼ばれた読み取りの段 (ocr_document、子ごとの ocr_children) が、読む対象が無いと答えた (モデルは呼んでいない)。token は NOTHING_TO_READ_TOKENS の値 (no_pages: 版面を持たない形、no_pages_rendered: 版面を持つ形からラスタ化器が 1 枚も作らなかった、covered_by_page_recognition: PDF の埋め込み画像が、親の本文である親の版面の認識が既に読んだページに載る) で、enrichment-fastapi の OCR 応答の skipped と同じ閉じた集合 (ocr_disabled は閉じた ENABLE_OCR の門として記録する)。ワーカーは応答の値を読み替えずに写す | | { kind: "not_protected" } | not_protected | 解除の段 (unlock_document) が、外すパスワードが無いと答えた (文書が守られていない・保管層が変換した形を届けた)。enrichment-fastapi の解除の応答の skipped と同じ値で、ワーカーは読み替えずに写す | | { kind: "superseded" } | superseded | 終端段の時に、実行の版の行が文書の現在の行でなくなっていた (状態を写さない) | | { kind: "recording_disabled" } | recording_disabled | 終端段の時に、配備の文書の履歴の記録の切替が false だった | | { kind: "recording_misconfigured" } | recording_misconfigured | 終端段の時に、配備の切替が無いか true / false のどちらでもなかった (false と見分ける) |

  • formatSkipReason(reason) は parseSkipReason が等しい理由へ読み戻せる文字列だけを返し、文法で表せない理由 (書式外のフラグキー・未知の段キー・NOTHING_TO_READ_TOKENS に無い値・未知の種類) は RangeError を投げる。
  • parseSkipReason(text) は完全一致で照合し、文法の外の文字列 (種類を名乗らない素のフラグ名を含む) には null を返す。表示側は null のとき文字列をそのまま示す。
  • source_skipped:<step key> が名指すのは流れの段 (PIPELINE_STEP_KEYS) だけで、終端段の鍵は文法の外 (null) である。

Terminal step / 終端段

実行の流れの後に、ワーカーは文書の状態を捕捉する段を高々 1 つ記録する。鍵は RUN_TERMINAL_STEP_KEY (record_document_state) で、段の記録の鍵の語彙は LEDGER_STEP_KEYS (PIPELINE_STEP_KEYS の 10 の後に終端段を足した 11 語) である。

  • PIPELINE_FLOWS は終端段を名指さない。したがって流れの図と段の集計 (PipelineStepMetricSchema.stepKey は PipelineStepKeySchema) に終端段は現れない。
  • 終端段は実行を失敗させないので、実行の failedStepKey (PipelineRunRecordSchema / PipelineRunSummarySchema。storedTermSchema(PIPELINE_STEP_KEYS)) は流れの段 (PIPELINE_STEP_KEYS) だけを知る値として名指す (終端段の鍵は知る値として受けない)。
  • PipelineStepRecordSchema は終端段の行に次を検め、外れる行を拒む。成功した終端段の報告は detail 以外の全ての鍵が null で、strategyId と httpStatus も null (API を呼ばない)、detail はちょうど { outcome } (RunTerminalStepDetailSchema、outcome は RUN_TERMINAL_STEP_OUTCOMES = RECORDED / UNCHANGED / ALREADY_RECORDED) で、状態の ID・連番・処理時間を持たない。
  • 失敗した終端段の errorCode は RUN_TERMINAL_STEP_ERROR_CODES (history_no_current_row / history_lock_timeout / history_write_failed) の 3 つのどれかで、飛ばした終端段の skipReason は上の表の終端段の 3 種 (superseded / recording_disabled / recording_misconfigured) のどれかである (PipelineStepRecordSchema が検める)。

Run record and summary / 実行の記録と要約

  • trigger (PipelineTriggerSchema) は ingest (取り込み) / retry (手動の再試行) / resync (再同期) だけ。実行を開くのはワーカーだけであり、整合性監査の修復の実行 (パイプラインの実行を開かずに再投影する) と比較投影 (本番の状態を変えない) はきっかけではない。
  • attempt は BullMQ ジョブ内の試行番号 (1 起点)。手動の再試行・再同期は新しいジョブとして 1 から数え、trigger で区別する。
  • retryScheduled は失敗した試行の後にキューが次の試行を予定したか。FAILED の実行だけが true を持てる (superRefine で検査)。
  • documentKind と failedStepKey は storedTermSchema(DOCUMENT_KINDS)・storedTermSchema(PIPELINE_STEP_KEYS) (failedStepKey は null も)。今の語彙が知らない値は UnknownTerm。
  • PipelineRunSummarySchema は PipelineRunRecordSchema から steps を除いた形で、同じ規則に従い、steps キーを拒む。

Stored terms / 保存された語

  • StoredTerm<T> は T | UnknownTerm で、UnknownTerm は { known: false, raw } (storedTerm.ts)。記録が DB の制約なしに保存する語彙 (段の鍵・実行の文書種と止めた段) を、別の版が書いた値でも読めるように運ぶ。
  • storedTermOf(vocabulary, stored) は完全一致で照らし、知る値はそのもの、知らない値は UnknownTerm を返す。isUnknownTerm・storedTermText (保存された時の文字列。写像や試験の ID の鍵) で読む。
  • storedTermSchema(vocabulary) は知る値をそのものとして、知らない値を UnknownTerm として受け、知る値を UnknownTerm の形で運ぶことを拒む (形は 1 つ)。
  • 語彙は足すだけ: DOCUMENT_KINDS と PIPELINE_STEP_KEYS から語を消すことも名を変えることもしない (流れから外した段のキーも残す)。

Step metric / 段の集計

  • 集計は (documentKind, stepKey) の組ごとに 1 件。documentKind は段の記録が属する実行の文書種であり、複数の流れが共有する段 (ocr_document・resolve_body・project_to_indexes など) も種類ごとに別の集計になる。組は現在の流れの表と照合しない (記録は走った流れを持つ)。
  • 百分位 (durationP50Ms / durationP95Ms) は測った所要だけから求める。所要が null の失敗は failed に数えるが所要には入らない。
  • SKIPPED の記録 (読む対象が無いと答えた段を含む) は skipped に数え、sampleCount と百分位には入らない。
  • sampleCount が 0 なら両方の百分位は null (superRefine で検査)。

Unlock contract / 解除の契約

unlock.ts spells what the console reads of removing the password a file carries, as aiquants-enrichment-fastapi answers it. A password is never part of it: a row of the passwords is read without one.

unlock.ts は、ファイルが持つパスワードを外すことについてコンソールが読むものを、aiquants-enrichment-fastapi の答えのまま綴る。パスワードはそこに含まれない (パスワードの行はパスワード無しで読む)。

| Value / 値 | Vocabulary / 語彙 | Meaning / 意味 | | --- | --- | --- | | PROTECTION_FORMATS | zip・pdf・ooxml・legacy_office | 守りの属する書式 (記録 td_file_unlock.protection_format の語彙) | | REMOVABLE_PROTECTION_SCHEMES | zipcrypto・aes・pdf_user_password・pdf_owner_password・office_encryption | 部品が外せる守り方。外したことの記録 (td_file_unlock.protection_scheme) と解除の段の答えが持てる唯一の値 | | PROTECTION_SCHEMES | REMOVABLE_PROTECTION_SCHEMES・strong_encryption | ファイルの守り方。strong_encryption は PKWARE の強い暗号で、どの部品も外せない | | UNLOCK_DISPOSITIONS | source_overwritten・copy_original・copy_promoted・child_decrypted | 版の解いたファイルが原本になった方法 (記録 td_file_unlock.disposition の語彙) | | COPY_REASONS | permission_denied・immutable_source・foreign_application・local_source | 源を上書きせず写しを原本にした理由。isPromotable が真になるのは permission_denied だけ (書けるようになった源へ昇格できる) | | UNLOCK_ERROR_CODES | passwordRequired: 4225・protectionUnsupported: 4226・sourceChanged: 4094 | 解除の段と昇格が失敗する業務コード | | FILE_PASSWORD_SOURCE_KINDS / FILE_PASSWORD_PATTERN_SYNTAXES | gmail・gdrive・gcs・file・daily-report / glob・regex | 条件が名指せる源の種類と、型の書き方 (どちらも値の全体に、大小文字を区別せず当てる) | | FILE_PASSWORD_FIELD_WIDTHS / FILE_PASSWORD_MAX_BYTES | 名 200・送り手 320・件名 400・ファイルの名 400・URI の接頭辞 2048 / 995 | 名と条件の幅 (storedWidth。ホストの nvarchar(n) の列と同じ UTF-16 の単位で、BMP の外の字は 2 つ) と、UTF-8 で数えるパスワードの最長 (passwordByteLength) | | FILE_PASSWORD_PRIORITY_MAX | 2147483647 | 優先度の最大 (ホストの int の列が収める値。優先度は 0 から) |

  • 語彙ごとに、コンソールが見せる名 (*_LABELS、凍結した表) を持つ。
  • FilePasswordConditionsSchema は条件を検める (書いた条件は空でなく幅の中、無い条件は null)。triesEveryFile は条件を 1 つも書かない行 (全てのファイルに試す行) を見分ける。
  • FilePasswordViewSchema は行の見方 (時刻は時差つき)、FilePasswordListSchema と FilePasswordMatchSchema は一覧と照らしの答え (型は FilePasswordView・FilePasswordList・FilePasswordMatch)。契約の外の欄は読まない。
  • 記録の語彙 (PROTECTION_FORMATS・REMOVABLE_PROTECTION_SCHEMES・UNLOCK_DISPOSITIONS・COPY_REASONS) はホストの td_file_unlock の CHECK の、幅はホストの tm_file_password の列の写しでもあり、一致はホストの試験が確かめる。

Integrity audit contract / 整合性監査の契約

監査は API サーバーの中で走り、td_integrity_audit_run / td_integrity_audit_quantity / td_integrity_audit_finding へ記録する。ホストはその行を読み、次の形でコンソールへ渡す。記録の語彙 (下の表の IntegrityStoreSchema から IntegrityRepairSkipReasonSchema までの 12 の列挙と IntegrityFindingItemClassSchema) と区分の方針 (INTEGRITY_CLASS_POLICY) は各表の CHECK 制約の写しであり、実行の行の制約が持つ削除印の保持日数の範囲は、実行の見出しを検める SYSTEM_PARAMETER_RANGES.INTEGRITY_TOMBSTONE_RETENTION_DAYS の写しである。写しの一致はホストの試験が DDL を読んで確かめる (本パッケージはホストの DDL の置き場所を知らない)。

命令の語彙 (IntegrityCommandSchema / IntegrityCommandFailureCodeSchema と命令ごとのその部分集合) はコンソールの契約の持ち物で、DDL に写しを持たない。全てのスキーマは .strict() で、未知の鍵と鍵の欠落を拒む (最初の頁で省く IntegrityFindingsQuerySchema.after と最初の回で省く IntegrityCellResyncRequestSchema.after、sotDomain の他の観測値の鍵をそのまま通す IntegrityPlacementObservedSchema を除く)。null は宣言した項目 (測っていない・まだ無い) だけが持てる。

項目の間の規則の出所は 3 つ:

  • 契約が運ぶ項目についての CHECK 制約の規則。契約が運ばない列の規則 (完了した実行の段、中止した実行の中止の要求) は DB に任せる。
  • ホストが読むときの一意の鍵 (組ごとに量 1 つ、所見は記録順)。
  • 制約は持たないが、書き手 (API サーバー) と読み手 (ホスト) が保証する規則: 概況の各区画の実行は読み手が選んだ状態を持つ (active は RUNNING、lastCompleted は COMPLETED、newerUnsuccessful は FAILED / CANCELLED / ABANDONED)、SCAN の量は修復の件数を持たない、DOCUMENTS の段は範囲を持たない、nextAfter は頁の最後の行の sequence、不成功の REPAIR の hasNewerRepair は真。

これらを破る値は書き手か読み手の欠陥であり、契約は描かずに拒む。

実行の UID (runUid / basisRunUid、所見の要求と応答の runUid を含む) は 16 進の桁を大小文字を問わず受け入れ、小文字へ直して返す (RFC 9562 は桁を大小文字を問わず読み、小文字で書く)。API サーバーは小文字で発行し、SQL Server の uniqueidentifier は tedious から大文字で届くが、契約を通した後は 1 つの実行が 1 つの綴りを持つ (コンソールは実行を文字列の等しさで比べる)。ホストの読み手が綴りを直す必要は無い。

契約の時刻 (readAt・startedAt・heartbeatAt など) の前後は、Date.parse でなく公開する isStrictlyEarlier(earlier, later) で比べる (Date.parse はミリ秒までしか保たず、100 ns 違う 2 つの時刻を等しいと見る)。両方が契約の受ける時刻で earlier が later より厳密に前のときだけ true を返し、時差 (Z・±HH:mm・±HHmm)・秒の省略・1 秒未満の全ての桁を読んで比べる。どちらかが契約の受ける時刻でなければどちらの向きにも false なので、!isStrictlyEarlier(a, b) は「a が b の後か同時」ではない。比べる前に値を契約 (IntegrityAuditOverviewSchema など) で検める。契約自身も同じ関数で、finishedAt と heartbeatAt が startedAt より前でないことを検める。

2 つの時刻の間の長さは、同じ理由で millisecondsBetween(from, to) で取る。全ての桁から差を取り、最後にだけミリ秒へ切り上げるので、その値で置いたタイマーは to より前に鳴らない (to が from の後でなければ 0 以下、どちらかが契約の受ける時刻でなければ null)。コンソールが概況の readAt から実行中の実行の staleAfter までを待つのに使う。

取り込みの出来事の流しの出来事の名は INGESTION_EVENT_NAMES (凍結) が持つ: 整合性監査の実行の状態の変化 integrityRun (integrity_run) と、再開に欠けがあることを知らせる終わりの出来事 resyncRequired (resync-required)。出来事は合図で、ID と状態だけを運ぶ。購読者は合図で概況を読み直し、resync-required の後は記録を読み直してカーソル無しで開き直す。

| Vocabulary / 語彙 | Values / 値 | | --- | --- | | IntegrityStoreSchema | QDRANT / NEO4J | | IntegrityScopeRoleSchema | PRODUCTION / VARIANT / LABEL | | IntegrityItemClassSchema | 27 区分 (EXPECTED・LIVE・HISTORY・TOMBSTONE・AWAITING_SUCCESSOR・情報の 7 区分・不整合の 15 区分)。意味は監査の判定表 (S1 §6.5) が定める | | IntegrityFindingItemClassSchema | 所見を記録する 24 区分 (EXPECTED・LIVE・HISTORY を除く。CK_td_integrity_audit_finding_vocabulary)。所見を開けるのはこの区分の組だけ | | IntegrityUnitSchema | POINT / NODE / CHUNK / DOCUMENT | | IntegrityDispositionSchema | EXPECTED / HEALTHY / RETAINED / INFORMATIONAL / DISCREPANCY | | IntegrityRepairActionSchema | NONE / PURGE / FLAG / REPROJECT | | IntegrityRunModeSchema | SCAN / REPAIR | | IntegrityRunStatusSchema | RUNNING / COMPLETED / FAILED / CANCELLED / ABANDONED | | IntegrityVerdictSchema | CONSISTENT / INCONSISTENT / UNDETERMINED | | IntegrityPhaseSchema | QDRANT / NEO4J / DOCUMENTS | | IntegrityRepairOutcomeSchema | APPLIED / SKIPPED / FAILED | | IntegrityRepairSkipReasonSchema | RECLASSIFIED / IN_FLIGHT / DESTINATION_PENDING / BASIS_EXHAUSTED / PROJECTION_REFUSED / PIPELINE_FAILED / UNRECORDED / OUTSIDE (後の 4 つは、文書の再投影で書き直す項目を、文書を再投影しないときに文書の所属で見送る理由: PIPELINE_FAILED は前段の失敗、UNRECORDED は投影記録なし、PROJECTION_REFUSED は機能フラグか機密区分の方針が投影を拒む、OUTSIDE は店が文書を期待しない (ドメインが不明・本番の戦略なし・その店の段が閉じている・生きたチャンクなし)) |

区分が扱いと処置を決める (INTEGRITY_CLASS_POLICY、CK_td_integrity_audit_quantity_class_policy の写し。表と各行は凍結してある):

| 区分 | 扱い (disposition) | 処置 (repairAction) | | --- | --- | --- | | EXPECTED | EXPECTED | NONE | | LIVE | HEALTHY | NONE | | HISTORY・TOMBSTONE・AWAITING_SUCCESSOR | RETAINED | NONE | | IN_FLIGHT・UNPLACED・UNRECORDED・UNREFERENCED・CHANGED_AFTER_START・PIPELINE_FAILED・PROJECTION_REFUSED | INFORMATIONAL | NONE | | ORPHAN・TOMBSTONE_EXPIRED・STALE_REVISION・MISPLACED・OUT_OF_TIER・DETACHED・UNKEYED | DISCREPANCY | PURGE | | UNPROPAGATED_DELETE・UNMARKED_SUPERSEDED | DISCREPANCY | FLAG | | VARIANT_FLAG_DRIFT・UNKEYED_ENTITY | DISCREPANCY | NONE | | FLAG_DRIFT・MISSING・COUNT_MISMATCH・UNPROJECTED | DISCREPANCY | REPROJECT |

REPROJECT は文書に働く。文書の区分 (MISSING・COUNT_MISMATCH と、段が開いているのにその店の投影の記録も生きた項目も無い文書の UNPROJECTED) では文書を再投影し、項目の区分 (FLAG_DRIFT) では項目を文書の再投影で書き直し (修復済は文書の再投影が成功したことを表し、項目を読み直さない)、再投影しない文書の項目は理由 (IntegrityRepairSkipReasonSchema) を付けて見送る。OUT_OF_TIER は ORPHAN と同じく除き、形の不整合の DETACHED (親の辺の無い旧版のノード) と UNKEYED (鍵の無いか記録に収まらない鍵の項目) も除く。どの除去もその数は根拠の走査の組の件数を上限とする。UNKEYED_ENTITY (鍵の無い共有の Entity のノード) は報告だけ (共有のノードは他の系のマスタの鍵を持ちうる)。

判定 (IntegrityVerdictSchema) は DISCREPANCY の量を数え、CONSISTENT になれるのは扱いに依らず全ての量が測れたときだけ (測れた不整合が 1 つでも正なら、他の量の未測定に依らず INCONSISTENT)。判定の規則は API サーバーが持ち、この契約は判定と量の突き合わせをしない。判定とタイルは単位 (IntegrityUnitSchema) の違う量を足さない。単位を混ぜた唯一の和は、不成功の修復の repairAppliedItems (除去したか印を付けた点とノードの数。処置が PURGE と FLAG の量の直した件数の和で、再投影で書き直した項目は数えない) である。

| Schema | Rules checked across fields / 項目の間で検める規則 | | --- | --- | | IntegrityRunHeaderSchema | REPAIR ⇔ basisRunUid が在る。COMPLETED ⇔ verdict が在る ⇔ reprojectDocuments が在る。reprojectRebuildDocuments は reprojectDocuments と揃って在り、それ以下。RUNNING ⇔ finishedAt が null、finishedAt は startedAt より前でない (1 秒未満の全ての桁と時差を読んで比べる)。errorClass は FAILED と ABANDONED だけ。storeFingerprint は 64 桁の小文字の 16 進。tombstoneRetentionDays は SYSTEM_PARAMETER_RANGES.INTEGRITY_TOMBSTONE_RETENTION_DAYS (1〜3650) の整数 (実行の行の制約の範囲はその写しで、見出しは自分の範囲を持たない)。時刻は時差付きの ISO 8601 (時差は Z・±HH:mm・±HHmm。秒と 1 秒未満の端数は省け、端数は任意の桁数を持てる) | | IntegrityQuantitySchema | 扱いと処置は区分の方針 (INTEGRITY_CLASS_POLICY) のとおり。itemCount === null ⇔ unmeasuredReason !== null ⇔ measuredAt === null (測って 0 件は未測定と別)。修復の 3 つの件数は揃って在るか揃って無く (欠けた件数を報告する)、在るのは処置 (repairAction) のある区分だけで、測れた量では和が itemCount を超えない (測れなかった量も件数を持てる) | | IntegrityActiveRunSchema | 実行は RUNNING。heartbeatAt は run.startedAt より前でない。staleAfter (心拍が古くなる時刻。心拍にテナントの INTEGRITY_RUN_HEARTBEAT_TIMEOUT_SECONDS を足した時刻で、isStale と同じ秒の値で DB が計算する) は heartbeatAt より厳密に後。段が null なら範囲・進行・総数も null。DOCUMENTS の段は範囲 (phaseScope) を持たない。進行は見積もりの総数を超えうる | | IntegrityAuditOverviewSchema | lastCompleted.run は COMPLETED で、量は (店, 範囲, 区分) の組ごとに 1 つ、SCAN の量は修復の件数を持たない。newerUnsuccessful.run は FAILED / CANCELLED / ABANDONED。不成功の SCAN は repairAppliedItems を持たず、不成功の REPAIR の hasNewerRepair は真 (それ自身がより新しい修復)。入れ子の見出し・量・実行中の実行もそれぞれの規則で検める | | IntegrityFindingSchema | repairErrorClass は FAILED だけ、repairSkipReason は SKIPPED だけ。sequence と metadataId (SoT の行の ID) は 1 以上の整数。fileUri と revision は派生ストアの項目が名乗る値の写しなので、空の URI と 0 以下の版もそのまま運ぶ (revision は整数) | | IntegrityPlacementObservedSchema | UNPLACED と OUT_OF_TIER の所見の observed を読む形。sotDomain (SoT が項目の現行の文書に与えるドメイン) は必須で文字列か null、他の観測値の鍵はそのまま通す。null は文書がドメインを持たないこと (再同期が導き直す)、UNPLACED の文字列は本番の戦略の無いドメイン、OUT_OF_TIER の文字列は戦略がその店の段を閉じたドメイン (OUT_OF_TIER は必ず文字列を持つ)。組はドメインを混ぜるので、ドメインは行ごとの値で組の値ではない。SoT が書いた値の写しなので空の文字列も拒まない | | IntegrityFindingPageSchema | 行は sequence の昇順で重複しない。nextAfter は null か、この頁の最後の行の sequence。recordedCount は totalCount と突き合わせない (書き手は鍵の無いグラフのノードを数えた後に標本を取るので、その間に作られたノードで標本が全数を超えうる) | | IntegrityFindingsQuerySchema | itemClass は所見を記録する区分 (IntegrityFindingItemClassSchema) だけ。limit は必須で 1〜INTEGRITY_FINDINGS_PAGE_LIMIT_MAX (100) の整数 (0・負・NaN・文字列を拒む)。after は 1 以上の整数で、最初の頁では省く | | IntegrityCellResyncRequestSchema | 一括の再同期の 1 回分の要求 (runUid・store・scopeKey・itemClass・after)。itemClass は UNRECORDED だけ (再同期が片付ける唯一の区分。店は文書の生きた項目を持つがその店の投影の記録が無い)。after は 1 以上の整数で、最初の回では省く。1 回の件数は要求が選ばず、INTEGRITY_FINDINGS_PAGE_LIMIT_MAX (100) に固定する。ホストはテナントの直近の完了した実行にだけ答え、組の所見を記録順に読む | | IntegrityCellResyncResultSchema | 1 回分の答え (requeued・skipped: { metadataId, reason }[]・nextAfter)。再投入の数と据え置いた文書の数の和 (読んだ文書の数) は 100 以下で、nextAfter はちょうど 100 を読んだときだけ在る (最後に読んだ記録順。100 に満たない回は組の終わり)。据え置いた文書は重複しない。規則は子の木のまとめての取り込み直しの答え (ChildTreeRebuildResultSchema) と共有する 1 つの検査が検める |

  • コンソールが監査の実行について送る命令は IntegrityCommandSchema (start / cancel)。命令と失敗の語彙はコンソールの契約の持ち物で、DDL に写しを持たない。

  • 開始・中止の失敗は IntegrityCommandFailure ({command, code, status: 300〜599 の整数 | null}、command で分かれる和の型) で運ぶ。code はコンソールが示す文ごとに 1 つ (IntegrityCommandFailureCodeSchema) で、各命令はその部分集合だけを持つ (もう一方の命令だけの語彙は code の問題として拒み、型でも持てない):

    • 開始 (IntegrityStartFailureCodeSchema): DEPLOYMENT_DISABLED / RUN_ALREADY_ACTIVE / BASIS_INVALID / FORBIDDEN / UPSTREAM_FAILED
    • 中止 (IntegrityCancelFailureCodeSchema): DEPLOYMENT_DISABLED / RUN_ALREADY_FINISHED / FORBIDDEN / UPSTREAM_FAILED (中止も共有の DB の実行の行を書くので、実行の切替を課される (修復の切替は課さない)。実行を始めることも根拠を名指すことも無い)
    • 命令の語彙の型は IntegrityCommandFailureCodeFor<Command> で引ける。画面の文の表は命令ごとにこの型で漏れなく書ける。
  • 表が名指す code は、その行の状態を持つ (DEPLOYMENT_DISABLED は 503、RUN_ALREADY_ACTIVE / BASIS_INVALID / RUN_ALREADY_FINISHED は 409、FORBIDDEN は 403)。例外は状態の無い FORBIDDEN だけ (ホストはトークンを持たない命令を送らずに拒むので、応答が無い)。UPSTREAM_FAILED は表に無い全ての失敗で、来た状態を持つか、応答が無ければ status: null。違反は status の問題として拒む。

  • (状態, 業務コード) → code の表は integrityCommandCodes.json だけが持つ (このリポジトリの中では API サーバーの試験も同じファイルを読む。公開する成果物は表を埋め込み、表と各行を凍結する。各行はモジュールの読み込みの時に検め、UPSTREAM_FAILED へ写す行・他の鍵を持つ行・300〜599 の外の状態の行があれば読み込みが投げる)。行の code がどの命令のものかは表でなく命令ごとの語彙が決める。

  • integrityCommandFailureCodeOf(command, status, errorCode) は、状態が等しく、業務コードが null か等しく、code がその命令の語彙である最初の行の code を、その命令の語彙の型で返す。業務コードが null の行 (403 → FORBIDDEN) はその状態の全ての業務コードに一致する。その命令について一致する行の無い組 (もう一方の命令だけの語彙へ写す組、503 / 5030 と 503 / 5032 を含む) は UPSTREAM_FAILED。返した code は、命令と応答の状態とともに IntegrityCommandFailureSchema が受け入れる失敗になる。

    | status | errorCode | code | 開始 | 中止 | | --- | --- | --- | --- | --- | | 503 | 5035 | DEPLOYMENT_DISABLED | ○ | ○ | | 409 | 4091 | RUN_ALREADY_ACTIVE | ○ | UPSTREAM_FAILED | | 409 | 4092 | BASIS_INVALID | ○ | UPSTREAM_FAILED | | 409 | 4093 | RUN_ALREADY_FINISHED | UPSTREAM_FAILED | ○ | | 403 | (any) | FORBIDDEN | ○ | ○ |

  • ホストのストアが開始・中止に答える形は IntegrityCommandReply ({ok: true, runUid} か {ok: false, status, errorCode: int | null}) だけで、上流の本文の文面を運ばない。失敗の status は転送を辿った応答の成功でない状態 (300〜599)。

Child asset tree contract / 子アセットの木の契約

部品を持つ文書 (メール・PDF・Office、源が子を名指す文書の根、参照する画像を持つ Markdown の根) は部品を子アセットとして取り出し、部品を持つ子も自身の子を作る。子は根の下の木を成し、各節点は根からの木の道 (td_file_metadata.tree_path) を持つ。書庫は節点にならない: 書庫の中身 (入れ子の書庫の中身も) は、書庫に最も近い書庫でない祖先 (書庫を運んだ節点。文書そのものが書庫なら根) の子 (archive_member) で、名は書庫を通る道 (資料.zip/単価.pdf) である。中身が容れ物なら、その中身が自身の子を持つ。木の深さに上限は無く、木を止めるのは根 1 つの 1 回の走りが引く 2 つの予算 (CHILD_TREE_MAX_NODES・CHILD_TREE_MAX_TOTAL_BYTES、下の「System parameter ranges」) と循環の検査だけである。

  • TREE_PATH_PATTERN / TreePathSchema は木の道の文法 (Python のコアの TREE_PATH_PATTERN と同じ文法) で、<asset_type>-<asset_index> の区画を根から / で繋ぎ、区画の数が深さ (根の子が 1) である。種類 ([a-z_]+) は - を持たないので区画は最後の - で割れ、位置は頭に 0 を持たない 10 進の整数なので、1 つの節点の綴りは 1 つ。道の長さに上限は無い (列は nvarchar(max))。
  • treePathSegments(path) は区画 (TreePathSegment)、treePathDepth(path) は深さ、treePathParent(path) は親の道 (深さ 1 は親が根なので null) を返す。文法の外の文はどれも RangeError で拒む。
  • compareTreePaths(a, b) は木の順で比べる (区画ごとに種類を符号単位で、続いて位置を数で。祖先が子孫の前)。深さ 1 では (assetType, assetIndex) の順と同じ。位置は全ての桁で比べるので、等しいと比べるのは同じ道だけである。
  • treePathLabel(path) は画面が節点を示す名 (添付 0 > 書庫の中身 3 > 埋め込み画像 2。段ごとの種類の名と位置で、節点の名を持たない)、assetTypeName(assetType) は種類の名を返す。名の表 (assetTypeNames.json) は表の CHECK が許す 8 つの種類を API サーバーと同じ名で持ち、名の無い種類は代わりの名を作らずに RangeError で拒む。
  • treePathOf(item) は面 assets の項目の場所 (AssetPlace) から道を導く (親の道 parentPath と自身の区画。深さ 1 の項目は親の道を持たず、区画だけ)。道を検めないので、外から届いた値は TreePathSchema か面の契約で読む。
  • この道を、段の記録の targetTreePath (PipelineStepRecordSchema) と面 assets (AssetFacetItemSchema) が使う。

Bulk rebuild of the trees / 木のまとめての取り込み直し

  • 既存の文書の木に深い節点を作るため、テナントの候補 (現行で削除されていない派生でない根のうち、部品を持つ種類の生きた節点を 1 つ以上持つもの) をまとめて取り込み直す。他の根は取り込み直しても木が変わらない。コンソールはホストに 1 回分ずつ求め、ホストは候補を API サーバーから識別子の昇順の keyset で 1 頁読み、各候補を再同期の唯一の再投入の規則に通す。
  • ChildTreeRebuildRequestSchema は 1 回分の要求で、after (根の識別子。1 以上の整数で、最初の回では省く) だけを持つ。1 回の件数は要求が選ばず、CHILD_TREE_REBUILD_CHUNK (100) に固定する。
  • ChildTreeRebuildResultSchema は 1 回分の答え (requeued・skipped: { metadataId, reason }[]・nextAfter)。再投入の数と据え置いた根の数の和 (読んだ候補の数) は 100 以下で、nextAfter はちょうど 100 を読んだときだけ在り (最後に読んだ根の識別子)、据え置いた根は重複しない。規則は IntegrityCellResyncResultSchema と同じで、両方を 1 回分の大きさを引数に取る 1 つの検査から作る。
  • 再投入した根は流れの全ての段をもう 1 度走らせ、2 度求めれば 2 度取り込み直す。処理中・旧版・削除済みの根と、トークンや読み取りの規則が拒む根は、理由と共に据え置く。

Document history contract / 文書の差分履歴の契約

文書の再同期・再取り込み・新しい版のたびに、ホストの記録器が文書の不変の状態の鎖を書き、読み手が履歴と比較を返す (S1 §8.19)。本パッケージはその契約と、記録器と読み手が共有する差分エンジンを持つ。記録器の結果 (DocumentStateRecordOutcome) はホストの型で、ここに無い (どの答えも運べない状態の識別子を持つ)。

Versioned constants / 版付きの定数

| Constant | Value | Meaning | | --- | --- | --- | | DIFF_ENGINE_VERSION | 2 | エンジンの版。捕捉の時の計数と共に凍結する (保存済みの状態の版は、その時のエンジンの値として残る) | | DIFF_CONTEXT_LINES | 3 | 塊の文脈の行の数 | | HISTOGRAM_MAX_OCCURRENCES | 64 | 錨にできる行の、区間の古い側の出現の上限 | | DIFF_REGION_CELL_BOUND | 1,000,000 | 錨の無い区間を Myers で比べる升目の上限 (超えれば区間ごと置き換える) | | INLINE_REFINE_MAX_GRAPHEMES / INLINE_REFINE_MIN_SIMILARITY | 4,096 / 0.3 | 行の中の精緻化を行う書記素の数の上限と類似度の下限 | | INLINE_REFINE_MAX_EDIT_DISTANCE | 1,024 | 行の中の精緻化を行う対の編集距離 (削除と追加の書記素の和) の上限 | | INLINE_REFINE_CELL_BUDGET | 67,108,864 (2^26) | 1 つの本文の差分の中で精緻化に使える手間の総量 (升目) | | STRUCTURED_DATA_ARRAY_CELL_BOUND | 16,777,216 (2^24) | 1 つの構造化データの差分の中で配列の要素を比べる升目の総量。配列ごとに中ほど (共通の前後を除いた古い要素の数 × 新しい要素の数) を消費し、払えない配列は全体を 1 つの replace にする | | DIFF_LINE_PAGE_MAX | 500 | 差分の行の頁の上限 (DiffLinePageLimitSchema は 1〜500 の整数) | | DOCUMENT_CHANGE_FEED_PAGE_MAX / DOCUMENT_CHANGE_FEED_PAGE_SIZE | 50 / 50 | 直近の変化の一覧の頁 (DocumentChangeFeedLimitSchema は 1〜50 の整数) | | DOCUMENT_STATE_LOCK_TIMEOUT_MS | 10,000 | 1 文書の捕捉が文書の履歴の錠を待てる長さ | | CHUNK_MANIFEST_VERSION | 1 | チャンクの目録の形の版 |

Vocabularies / 語彙

| Vocabulary | Values | | --- | --- | | DOCUMENT_FACETS | classification / metadata / labels / tags / structured_data / text / summary / chunks / assets (表示の順) | | DOCUMENT_STATE_CAUSES | RUN / PRE_WRITE / MANUAL / BACKFILL | | DOCUMENT_STATE_RUN_OUTCOMES | SUCCEEDED / FAILED (ワーカーが実行をどう分類したか) | | CHUNK_CHANGE_KINDS / CHUNK_PAIRINGS | ADDED / REMOVED / MODIFIED / MOVED、変更の対の規則 clause / breadcrumbs | | CHUNK_BODY_FIDELITIES | EXACT / WHITESPACE_NORMALIZED / UNVERIFIED | | RESTRICTED_MARK_SUBJECTS | run / ingest / failure / state / change | | LINE_ENDINGS | LF / CRLF / CR / MIXED / NONE |

語彙のうち DDL の CHECK 制約が持つもの (面・契機・実行の分類・機密区分・本文の出所) の一致は、ホストの試験が DDL を読んで確かめる。

Facet values and counts / 面の値と計数

  • DocumentFacetValuesSchema は 1 つの状態の全ての面の正準の値で、鍵は面の綴りそのもの (structured_data を含む)。集合の面は正準の順 (ラベルは labelKey、タグは文字列で、どちらも UTF-16 の符号単位の順で compareCodeUnits が比べる。面 assets は導いた木の道の木の順で compareAssetKeys が比べる) で鍵を重ねない。タグの null (列が NULL) と空の配列、本文の null (抽出本文が無い) と空の本文は別の値である。
  • 面 assets は根の木の生きた節点の全てを持つ。項目 (AssetFacetItemSchema) は 5 つの欄 (assetType・assetIndex・mimeType・fileSize・textSha256) を持ち、深さ 2 からの項目だけが親の道 parentPath を持つ (深さ 1 の項目は欄を持たず、null も値が undefined の鍵も拒む)。項目の道は導き (treePathOf)、treePath・depth は保存しない。種類は木の道の区画の種類 ([a-z_]+)、位置は安全な整数なので、導いた道は 1 つの節点だけを名指す。各 parentPath は先の項目の道に等しい (並びは生きた親の下の部分木だけを持つ)。深さ 1 だけの木は同じ 5 つの欄・同じ順・同じ正準の JSON になるので、保存済みの状態はそのまま読め、digest も変わらない。
  • ChunkManifestSchema (CHUNK_MANIFEST_VERSION) は子チャンクを index の昇順に、親を子から初めて辿った順の序数で持ち、行と版に依る値 (親とチャンクの uid・metadata_id) を持たない。同じ本文を同じ実装でチャンク化すれば、どの行・版でも目録のバイト列が等しい。チャンクを持たない状態の目録は null で、空の目録は無い。
  • FacetChangeCountsSchema は変わった 1 つの面の計数で、当てはまる計数 (FACET_APPLICABLE_COUNTS) は 0 以上の整数、他は null である (CK_td_file_state_facet_change_counts の写し)。

Comparison and line pages / 比較と行の頁

  • DocumentComparisonSchema は全ての面を表示の順に UNCHANGED か面ごとの差分 (FacetDiffSchema) で持ち、計算したエンジンの版 (diffEngineVersion) を持つ。分類とメタデータは項目の変化 (FieldChange)、ラベルと木の節点は鍵付き集合 (KeyedItem の追加・削除と KeyedItemChange の変更。節点の鍵は導いた道 attachment-0/embedded_image-2 で、親の道は鍵の一部なので比べる欄でなく、親の変わった節点は削除と追加になる)、タグは集合、構造化データは RFC 6902 の操作 (JsonPatchOperationSchema: add / remove / replace だけで、取り除く値を previous に持つ)、本文と要約は索引 (TextDiffIndexSchema: 属性の変化・統計・塊の索引)、チャンクは対応付け (ChunkChangeSchema、片側ごとに読み手が確かめた忠実度) と textUnchangedChunkingChanged である。
  • 本文・要約・チャンクの本文の行は比較に含めず、DiffLinePageSchema ({ lines, next }、next は塊の次の行の位置か null) で頁ごとに読む。チャンクの対の本文は両方の全体を 1 つの塊 (塊 0) にする。

History, change feed and restricted marks / 履歴・直近の変化・隔離の印

  • DocumentHistorySchema は現在の行 (隔離でない)、読める版の行 (新しい順、現在の版はちょうど 1 つ)、状態の一覧 (DocumentStateEntrySchema: ReadableEntry<DocumentStateSummary> か RestrictedStateMark、確定の時刻の新しい順) と実行の一覧 (DocumentRunEntrySchema: ReadableEntry<PipelineRunRecord> か RestrictedRunMark) を持つ。
  • DocumentStateSummarySchema は連番を持たない。previousStateId・計数・エンジンの版・modelOnlyChange は直前の状態が読める時だけ値を持ち、最初の状態と直前を読めない状態はどちらも previousStateId: null である。RUN の状態だけが runId と runOutcome を持つ。
  • 隔離の印 (RestrictedRunMarkSchema / RestrictedIngestMarkSchema / RestrictedFailureMarkSchema / RestrictedStateMarkSchema / RestrictedChangeMarkSchema) は種類・項目自身の時刻・結果か状態だけを持ち (取り込みの印の syncStatus は EnrichmentSyncStatusSchema の値か、エンリッチメントの行の無い文書 (取り込みがメタデータの行の後に止まった) では null、失敗の印の syncStatus はその失敗の状態 PipelineFailureStatusSchema)、どれも .strict() で識別に使える鍵を 1 つでも持てば拒む。一覧の要素は kind で分かれる判別和 (z.discriminatedUnion("kind", [readableEntrySchema(<項目>), <一覧の印>])) で、 印は一覧と合う subject だけを許す。ホストの一覧 (取り込み・失敗) は readableEntrySchema と印の schema から同じ形の和を作り、直近の実行の表は RecentPipelineRunEntrySchema を使う。
  • DocumentChangeFeedPageSchema は { rows, next } で保存量を持たない。行は ReadableEntry<DocumentChangeFeedEntry> か RestrictedChangeMark (到着の状態の時刻の新しい順)。next は頁の最後の行 (印を含む) の到着の状態の位置で (位置の時刻は最後の行の時刻と同じ時点でなければならない)、encodeChangeFeedCursor({ settledAt, id }) が { id, settledAt } の正準の JSON の base64url に書き、decodeChangeFeedCursor は自分が書く文字列そのものだけを読み戻す (壊れた base64url・UTF-8 でない・JSON でない・形の外・別の綴りは null)。
  • 手動の記録の答え DocumentCaptureAnswerSchema は { outcome: "RECORDED" | "UNCHANGED" } だけである。

Diff engine v2 / 差分エンジン v2

  • summarizeTransition(transitions) は記録器の入口で、変わった面ごとの古い値と新しい値 (FacetTransition) から、変わった面ごとの計数の行を表示の順に返す。面が無い・同じ面が 2 度・値の等しい面は RangeError。
  • compareStates(from, to) は読み手の入口で、両側の面の値と、目録の子ごとに読み手が確かめた忠実度 (ComparedState) から比較を返す。行の頁は textFacetDiff / summaryFacetDiff / diffChunkBodies の差分 (TextDiff) を diffLinePage で読み、索引は textDiffIndex で読む (比較と同じ差分なので塊の番号が一致する)。
  • 本文: 行は \r\n・\r・\n で分け (改行は内容でなく属性で、改行だけの変換は 1 つの属性の変化)、共通の前後を除いて histogram 差分 (古い側で出現の最も少ない行を錨にし、連なりはその中で最も稀な行の出現で競い、同点は長い連なり、次に区間の中央に近い連なり、次に新しい側で前から始まる連なり、次に古い側で前から始まる連なりを選ぶ) で区間に分け、錨の無い区間は両側が共有する行の上の Myers で対応付ける (升目が上限を超えれば区間ごと置き換え)。手順は常に正しく、最小は約束せず、同点は削除を先にする。間の等しい行が文脈の 2 倍以下の塊は繋ぐ。
  • 行の中: 変化の塊の i 番目の削除の行と i 番目の追加の行を書記素 (Intl.Segmenter) で比べ、両方が上限以下で、編集の間の 1 書記素以下の等しい部分を編集へ繋いだ後の類似度が下限以上なら区切る。最長共通部分列の長さ (ビット並列で測る) が下限に届かない対は Myers を走らせずに外す (結果は変わらない)。類似度は 2 × 等しい書記素 / (古い書記素 + 新しい書記素) で、両方が空なら null。
  • 精緻化の手間の上限 (エンジンの一部): 対の編集距離 (最長共通部分列から Myers の前に決まる) が INLINE_REFINE_MAX_EDIT_DISTANCE を超える対は精緻化しない。1 つの本文の差分 (面の古い値と新しい値の 1 組。本文・要約・チャンクの本文の差分はそれぞれ満ちた予算で始まる) は INLINE_REFINE_CELL_BUDGET 升の予算を持ち、対を決まった順 (変化の塊の順、その中は i 番目の削除と i 番目の追加) に見て、Myers を走らせる対は自分の升目のうち Myers が探る帯 ((N + M) × 編集距離) を消費する。残りに収まらない対が現れた時に予算は尽き、その対から後ろの対は精緻化しない。精緻化しない対は、類似度が下限に届かない対と同じく行全体の削除と追加として数える (出力の形は変わらない)。どちらの上限も入力だけで決まるので、同じ入力は常に同じ計数になる。上限 1,024 は 731 書記素以下の行の対に決して掛からず (精緻化できる対の距離は両側の書記素の和の 0.7 倍以下)、予算は通常の編集 (数行の編集・1 行の編集・短い行の OCR の読み直し・長い段落の誤字の修正) では尽きない。
  • 頁: 状態の頁の区切り ([{ start, end, page_number }]、符号位置) の上で各行の始まりを二分探索し、削除の行は古い側、他は新しい側の頁を付ける。頁を名指さない区間 (シート・スライド) と配列でない区切りは頁を持たない。
  • チャンク: (1) ハッシュの列の最長共通部分列が錨 (変わらない。番号のずれは移動でない)、(2) 錨の外の同じハッシュを出現ごとに順に MOVED、(3) 残りのうち各側にちょうど 1 度だけ現れる非 NULL の条項を MODIFIED (clause)、(4) 錨の間の隙間ごとに見出しの等しい残りを位置の順に MODIFIED (breadcrumbs)、(5) 残りは REMOVED / ADDED。項目は新しいチャンクの位置の順で、削除は削除された隙間の始まりに置く。
  • 構造化データ: オブジェクトは鍵の順に再帰し、配列は要素の正準の JSON の最長共通部分列で対にし (1 回の差分は配列を辿る順 (鍵の順の深さ優先、要素の順) に STRUCTURED_DATA_ARRAY_CELL_BOUND 升の予算から各配列の中ほどの升目を払い、払えない配列は要素ごとに比べず、配列全体を 1 つの replace にする)、隙間の同じ位置の要素はどちらもオブジェクトかどちらも配列なら再帰し、それ以外は削除して追加する。操作を順に古い値へ当てると新しい値になる。
  • codePointSlicer(text) はチャンクの区間 (Python の符号位置) を 1 度の走査で作る表で切り、本文の外で終わる区間は null。String.prototype.slice を区間に直接使わない。stripWhitespace は JavaScript の \s (u フラグ) を除き、記録器の whitespaceFreeHash と読み手の照合が共に使う。忠実度の SHA-256 はホストが計算する (本パッケージはブラウザでも読み込まれるのでハッシュを持たない)。

Canonical JSON / 正準の JSON

canonicalJson(value) は鍵をどの深さでも UTF-16 の符号単位の昇順に並べ、文字列の外に空白を置かず、文字列と数を JSON.stringify の書き方で書き、有限でない数は RangeError で拒む。1 つの値は 1 つの文字列だけを持ち、内容と状態の digest と規程の衝突の事実のハッシュはこの上で取る。

Processing objects list contract / 処理オブジェクト一覧の契約

運用管理コンソールの処理オブジェクト一覧は、テナントの td_file_metadata の行 (取り込んだ文書と、その木の節点 = 添付・書庫の中身・埋め込みの画像・参照の画像) を、操作者が読める範囲で 1 件残らずたどる一覧です。並びは id の降順で、頁送りは id の keyset です。

  • 絞り込みは閉じた語彙で、ProcessingObjectFilterSchema は 5 つの鍵を全て求める (.strict())。既定の値は画面とホストが書き (PROCESSING_OBJECT_DEFAULT_FILTER はどの語彙も先頭の値と q: null)、経路は補わない。

    | 鍵 | 語彙 | 意味 | | --- | --- | --- | | kind | PROCESSING_OBJECT_KINDS (all・documents・nodes) | 文書と節点の両方・文書だけ・節点だけ | | revision | PROCESSING_OBJECT_REVISIONS (current・all) | 現行の版だけ・古い版の行も | | deleted | PROCESSING_OBJECT_DELETIONS (excluded・included) | 削除済み (退役した子を含む) を除く・含める | | status | PROCESSING_OBJECT_STATUSES (all・in_flight・synced・failed・no_record) | 同期の状態 (節点は根の状態)。PROCESSING_OBJECT_STATUS_SYNC_STATUSES が in_flight を IN_FLIGHT_SYNC_STATUSES、synced を SYNCED、failed を PIPELINE_FAILURE_STATUSES に結び、3 つで同期の状態の語彙を重なり無く分ける。no_record はエンリッチメントの行の無い行 | | q | ProcessingObjectQuerySchema (前後の空白を落として 1〜PROCESSING_OBJECT_QUERY_MAX_CHARS (200) 字) か null | 文書の名と URI、節点の source_name の部分一致 |

  • IN_FLIGHT_SYNC_STATUSES (types.ts) は SYNCED でも PIPELINE_FAILURE_STATUSES でもない全ての同期の状態で、列挙から導く。

  • 頁の大きさは ProcessingObjectLimitSchema (1〜PROCESSING_OBJECT_PAGE_MAX (100) の整数) で、画面は PROCESSING_OBJECT_PAGE_SIZE (50) で読む。

  • 読める行 ProcessingObjectItemSchema は kind で分かれる。

    • 文書 (document) は自身の同期の状態 (エンリッチメントの行が無ければ null) を持ち、誤りの文 (errorMessage) は同期の状態が失敗の間だけ持てる。
    • 節点 (node) は自身の取り込みを持たないので、根の同期の状態 (rootSyncStatus) と、自身の読みの結果 (ProcessingNodeReadingSchema: 根の最新の実行のうち、その節点を対象にした最後の段の鍵・状態・飛ばした理由。理由の規則は段の記録と同じ) を持つ。種類 (assetType) は木の道 (treePath) の最後の区画の種類と一致し、節点は自分の根ではない。
    • どちらも機密区分は隔離でない区分 (ReadableConfidentialityLevelSchema) だけを持つ。
  • 隔離の印 RestrictedProcessingObjectMarkSchema は文書の行だけの印で、subject: "object"・登録と更新の時刻・同期の状態だけを持つ (.strict()。行の id・木の道・根の ID を持てない)。節点は読める時だけ載り、印にならない (隔離された文書の節点の印は、その木の大きさを明かす)。名前で絞った一覧 (q) は印を持たない。

  • ProcessingObjectPageSchema は { rows, next, total } である。

    • 読める行は id の降順に並ぶ。
    • next は頁の最後の行 (印を含む) の id の位置で、最後の行が読める行ならその id を名指し、印なら頁の読める行の全てより下にある。空の頁は next を持たない。
    • total は絞り込みが通す全ての行 (読める行と印を合わせて) の数で、最初の頁 (位置なしで求めた頁) だけが持ち、後の頁は null である。読み手は行と同じ文から数を取るので、total は頁の行より少なくなく、続く頁の無い最初の頁はちょうどその数の行を持つ。
  • encodeProcessingObjectCursor({ id }) は { id } の正準の JSON を base64url に書き、decodeProcessingObjectCursor は自分が書く文字列そのものだけを読み戻す (壊れた base64url・UTF-8 でない・JSON でない・形の外・別の綴りは null)。直近の変化の一覧の位置と同じ規則で、base64url の符号化は内部の 1 つの実装 (internal/base64Url.ts) を共有する。

System parameter ranges / システムパラメータの値域

| Key | Range | | --- | --- | | INTEGRITY_TOMBSTONE_RETENTION_DAYS | 1〜3650 | | INTEGRITY_FINDING_SAMPLE_LIMIT | 1〜5000 | | INTEGRITY_RUN_HEARTBEAT_TIMEOUT_SECONDS | 30〜3600 | | INTEGRITY_RUN_RETENTION_COUNT | 2〜100 | | POLICY_CONFLICT_MAX_TIE_GROUP_SIZE | 2〜60 | | CHILD_TREE_MAX_NODES | 1〜100000 | | CHILD_TREE_MAX_TOTAL_BYTES | 1048576〜4294967296 | | CHILD_TREE_MAX_SECONDS | 60〜3600 | | ARCHIVE_MAX_MEMBER_BYTES | 65536〜1073741824 | | ARCHIVE_MAX_COMPRESSION_RATIO | 10〜10000 | | ARCHIVE_READER_MAX_MEMORY_BYTES | 268435456〜17179869184 |

  • 表の正本は src/systemParameterRanges.json の 1 つ。他の言語のホストは自分の写しを持ち、このリポジトリの中ではその試験がこのファイルを読んで一致を確かめる (API サーバーの PARAMETER_RANGES・ARCHIVE_LIMIT_RANGES・CHILD_TREE_LIMIT_RANGES)。公開する成果物は表を埋め込む。
  • CHILD_TREE_MAX_NODES と CHILD_TREE_MAX_TOTAL_BYTES は根 1 つの 1 回の走りが引く子の木の予算 (どの種類・どの深さの節点も 1 つ数え、根より下で開く書庫も節点にならないまま開く前に 1 つを引き、抽出した全てのバイトを数える)。CHILD_TREE_MAX_SECONDS は同じ走り (木の抽出、または解除 1 回) が書庫の仕事に使える秒数で、尽きた後は根より下の書庫を開かない。ARCHIVE_MAX_MEMBER_BYTES と ARCHIVE_MAX_COMPRESSION_RATIO は書庫の中身 1 つの上限、ARCHIVE_READER_MAX_MEMORY_BYTES は書庫を解く読み手 1 つの記憶の上限 (xz の伸張器の辞書の記憶) である。木の深さと書庫全体の中身の数・総量の鍵は無い (木の予算が縛る)。
  • SYSTEM_PARAMETER_RANGES は表と各値域を凍結してあり、型も値域まで読み取り専用である (プロセスの中の読み手の 1 つが値域を広げ、他の書き手と読み手の拒否を外すことができない)。
  • INTEGRITY_TOMBSTONE_RETENTION_DAYS の値域は、実行の行の制約 (保持日数の範囲) と実行の見出しの契約 (IntegrityRunHeaderSchema.tombstoneRetentionDays) の範囲でもある。制約はこの表の写しなので、値域を変えるときは制約も同じ変更で改める (ホストの試験が一致を検める)。
  • 表が抑えるパラメータは全て整数である。整数でないパラメータは、項目が型を宣言するまで表に加えられない。
  • 2 つの検査は、表が値域を持つ鍵について、値が範囲の整数でなければ (NaN・無限大・端数を含む) 同じ RangeError (<鍵> は <下限>〜<上限> の整数で指定してください。、コンソールが運用者へ示す文そのもの) を投げる。違いは表に値域の無い鍵の扱いだけ。表の鍵は表自身の鍵だけで判定し、toString などの原型の名を値域の鍵と取り違えない。
    • assertSystemParameterInRange(key: string, value) は書き手の検査。全ての鍵を受けるパラメータの書き手が型の検査の後に当て、表に値域の無い鍵は何もしない (値域を持たないパラメータは型だけで検める)。
    • assertBoundedSystemParameter(key: SystemParameterRangeKey, value) は読み手の検査。鍵は表から型付けされるので、表から外れた鍵 (改名・削除・綴りの誤り) を読む読み手は型検査で落ち、検査されずに通ることが無い。型の無い呼び出し元から届いた表に無い鍵は TypeError で拒む。
  • 書き手は値域の外を拒み、読み手は保存された値域の外の値を既定値へ置き換えずに拒む。

Installation / インストール

pnpm add @aiquants/enrichment-core 'zod@^3.25.0'

zod ^3.25.0 は peer dependency (素の zod は範囲外の latest (4.x) を入れる)。

Usage / 利用例

import { generateUuidV7, uuidv7ToDate, EnrichmentClient } from "@aiquants/enrichment-core"

// UUIDv7 の生成とタイムスタンプ復元
const id = generateUuidV7()
const createdAt = uuidv7ToDate(id)

// クライアントの初期化と検索 (baseUrl は API 接頭辞まで含める)
const client = new EnrichmentClient({ baseUrl: "https://api.example.com/api/v1", apiKey: accessToken })
const result = await client.search({
    query: "契約書の第3条",
    tenant_id: "acme",
    search_mode: "DENSE",
})
console.log(result.hits.map((hit) => `${hit.metadata_id}:${hit.chunk_index} ${hit.score}`), result.metadata.quality_tier)
import { classifyDocumentKind, flowFor, flowStepGates, orderedSteps, PIPELINE_STEPS } from "@aiquants/enrichment-core"

// 文書種から流れを引き、依存順に段を回す (ワーカーとコンソールが同じ表を読む)
const kind = classifyDocumentKind("image/png") // "image"
for (const flowStep of orderedSteps(flowFor(kind))) {
    const step = PIPELINE_STEPS[flowStep.step]
    // 門は流れの上書きを適用した flowStepGates で読む (画像の ocr_document は閉じれば fail)
    console.log(step.phase, step.endpoint, flowStepGates(flowStep).map((gate) => `${gate.featureFlagKey}:${gate.whenClosed}`))
}
import { formatSkipReason, NothingToReadTokenSchema, parseSkipReason, PipelineRunSummarySchema } from "@aiquants/enrichment-core"

// 書き手は理由を判別付きの値で渡し、文法どおりの文字列を得る
const text = formatSkipReason({ kind: "source_skipped", stepKey: "extract_assets" }) // "source_skipped:extract_assets"

// 読む対象が無いと答えた OCR 段は、応答の skipped の値を読み替えずに理由へ写す
const nothing = formatSkipReason({ kind: "nothing_to_read", token: NothingToReadTokenSchema.parse(ocrResponse.skipped) }) // "nothing_to_read:no_pages"

// 読み手は文法の外の文字列 (null) をそのまま示す
const reason = parseSkipReason(text) // { kind: "source_skipped", stepKey: "extract_assets" }

// 一覧は段を持たない要約として検証する
const runs = PipelineRunSummarySchema.array().parse(body.runs)
import { assertBoundedSystemParameter, assertSystemParameterInRange, type IntegrityCommandFailure, type IntegrityCommandReply, IntegrityAuditOverviewSchema, integrityCommandFailureCodeOf } from "@aiquants/enrichment-core"

// 監査の概況はホストの読み手が組んだ値を契約で検める (未測定は null のまま)
const overview = IntegrityAuditOverviewSchema.parse(body.overview)

// 中止のストアの失敗の応答を、画面が中止の文を選ぶ語彙へ写す (開始だけの語彙は型でも持てない)
const toCancelFailure = (reply: Extract<IntegrityCommandReply, { ok: false }>): IntegrityCommandFailure => ({ command: "cancel", code: integrityCommandFailureCodeOf("cancel", reply.status, reply.errorCode), status: reply.status })

// パラメータの書き手と読み手は同じ表で値域の外を拒む (RangeError の文面をそのまま示せる)
assertSystemParameterInRange(key, value) // 書き手: 値域の無い鍵は何もしない
assertBoundedSystemParameter("INTEGRITY_RUN_HEARTBEAT_TIMEOUT_SECONDS", 120) // 読み手: 表に無い鍵は型検査で落ちる