spec 1.0 · 規範
機械可読サーフェス
5 つの成果物によって、ツールからコンテキストレイヤーを読み取れるようになります。それ以外の部分では、人向けの文章をエージェントも読んでいるにすぎません。ツールが扱う契約は、この 5 つです。
| 成果物 | 既定の場所 | スキーマ |
|---|---|---|
| マニフェスト | leji.json(リポジトリルート、固定) |
context-manifest.schema.json |
| コンテキストインデックス | <root>/context-index.json |
context-index.schema.json |
| コンテキスト変更履歴 | <root>/context-changelog.json |
context-changelog.schema.json |
| エージェントプロファイル | <root>/agents/*.md(フロントマター) |
agent-profile.schema.json |
| 決定記録 | <root>/decisions/*.md(フロントマター) |
decision-record.schema.json |
マニフェスト以外の場所はすべてマニフェストが宣言します。表に示したのは既定値です。
要件#
- マニフェスト。
leji.jsonはリポジトリルートに存在しなければならず(MUST)、そのスキーマに照らして妥当でなければなりません。これは Leji で唯一、名前が固定されたファイルです。ツールが確実に探しにいくファイルです。 - インデックス。
indexed以上の適合性を宣言するコンテキストレイヤーは、生成されるものであって、手で維持されるものではないコンテキストインデックスを持たなければなりません(MUST)。ツールは、カテゴリインデックスファイル(categories.<id>.indexes。content-categories.md に従う)を、そこに列挙された文書へ解決し、統制された文書ごとに 1 エントリを書きます。各エントリは、安定したid、path、title、そしてカテゴリ識別子categoryを持ちます。生成器は、その文書のkind(intentまたはrecord)も出力すべきです(SHOULD)。これはスキーマ上は任意なので、種別が存在する前に書かれたインデックスも妥当なままであり、利用側は値がない場合をintentとして扱います。記録のエントリは、その文書が妥当なフロントマターのdateを宣言している場合、そのdateも併せて持ちます。生成器が日付を取るのはフロントマターからだけであり、散文やファイル名の慣習からではありません。古くなったインデックス(インデックスファイルが解決する内容ともはや一致しないもの)は、検証の失敗として扱われなければなりません(MUST)。federation.mountsを宣言するホストは、同じインデックスの中にトップレベルのmounts配列も持ちます。マウントごとに 1 件の経路の記録(name、source、pin、宣言されていればtrackingRef、owner、宣言されていればrole、そして経路のメタデータcategories/topics/requiredWhen)です。これらは経路の記録に限られます。ツールは、兄弟のエントリや散文をホストのインデックスへコピーしてはなりません(MUST NOT)。またマウントの記録は、ホストの読み手が見てはならないものを何も持ちません(distribution.md の「制限付きマウント」に従います)。 - 変更履歴。
indexed以上の適合性を宣言するコンテキストレイヤーは、コンテキストレイヤーの変更についての機械可読な変更履歴を持たなければなりません(MUST)。各エントリは、安定したid、UTC のdate、type、一行のsummary、影響を受けたpathsを持ちます。正典の順序は位置ではなく導出されるものです。ツールはエントリを(date, id)の昇順で並べなければならず(MUST)、配列上の位置には意味がありません。idは変更履歴の中で一意なので(「識別子」を参照)、2 つの変更がdateを共有していても(date, id)は全順序になります。残っているエントリは不変です。ツールは、以前の状態を確かめられる場所であれば、公開済みエントリの変更を検証の失敗として扱わなければなりません(MUST)。配列の並べ替えは変更にあたりません。その状態を確かめるには、比較対象となる別の基準が必要です。通常の継続的インテグレーションのチェックアウトのように、リファレンスのツールが現在のリビジョンしか持たない場合、その変更はツールには見えず、それを捕まえるのは変更一式のレビューです(conformance.md を参照)。変更履歴は新しさのサーフェスであって、アーカイブではありません。長く使われるコンテキストレイヤーは、際限なく育てるのではなくそれを圧縮すべきです(SHOULD)。またいつでも、その順序の最も古い側からエントリを取り除くことで圧縮して構いません(MAY)。ただし、同じ変更一式がcompaction型のエントリを追加し、そのcompactedフィールドに件数と、取り除いた最初と最後の id を記録することが条件です。最も古いエントリ以外の削除、圧縮エントリを伴わない削除、空のファイルになるまでの圧縮は、いずれも検証の失敗です。追記のみの規律はidを鍵とする集合として扱われ、直前にコミットされた状態と照合されるので、書く時点では git が必要です。ファイル自体は利用側にとって git を必要とせず、完全な記録は git の履歴が保持します。統制された文書(カテゴリインデックスファイルが解決する文書)に触れる変更一式は、変更した統制されたパスを覆うpathsを持つエントリを追加しなければなりません(MUST)。こうして、変更されたすべての統制された文書が、追加されたいずれかのエントリの下に入ります。追記のみの規律が公開済みエントリを不変に保ち、この網羅の規則が記録を完全に保ちます。人が読める変更履歴が併存しても構いません(MAY)。ツールが読むのは JSON の記録です。 - フロントマターの成果物。エージェントプロファイルと決定記録は、YAML フロントマターがそれぞれのスキーマに照らして妥当な markdown 文書です。散文の本文は自由な形式のままで、機械との契約はフロントマターです。純粋な JSON のプロファイルや決定を必須としてはなりません(MUST NOT)。これらの文書は人が読むものです。
- 識別子。すべての
idの値は、いったん公開されたら安定でなければなりません(MUST)。改名や移動が更新するのはpathであって、idではありません。識別子は小文字でハイフン区切り、その成果物の種類の中で一意です。生成されたインデックスエントリのidは、次の優先順で導出されます。その文書のフロントマターがidを宣言していればそれ。なければ、保存済みのインデックスが同じパスに対して、あるいは内容を保った純粋な移動については同じ内容に対して、すでに持っているid。それもなければ、親ディレクトリの中で衝突を避けたファイル名のスラグ。最初に見つかったものが勝つので、公開されたidは改名や移動を生き延び、まったく新しい文書だけが新しいものを得ます。ひとつの変更一式の中で移動かつ編集される可能性のある文書は、フロントマターのidを宣言すべきです(SHOULD)。パスと内容が同時に変わる場合に id を固定できるのはフロントマターだけです(パスによる引き継ぎも内容ハッシュによる引き継ぎも、どちらも取り逃します)。保存済みの id が消えたときはツールが警告するので(id-vanished)、それが残す宙に浮いた参照は捕まえられます。 - タイムスタンプ。変更履歴の
dateの値は UTC の ISO 8601 です。暦日YYYY-MM-DD(その日の始まりT00:00:00Zとして順序づけられます)か、Zで終わる秒単位のタイムスタンプ(たとえば2026-06-13T15:04:05Z)のどちらかです。ゾーンのない時刻、UTC 以外のオフセット、秒未満の小数は許されません。秒未満の小数は、dateの辞書順が時系列順になるという保証を壊します。…05.1Zは…05Zより後の時刻なのに前に並ぶからです。あらゆる成果物のあらゆる日付フィールドは暦の範囲で検査されるので、月が13、日が99のものは不正です。他の成果物の日付は ISO 8601 に従い、日付だけでも構いません(MAY)。パスは POSIX 形式で、リポジトリルートからの相対、先頭に./は付けません。 - マニフェスト以外のすべての JSON 成果物は、それが書かれた対象のスキーマ系列(
schemaVersion)を宣言しなければなりません(MUST。versioning.md に従います)。マニフェストは、自らを名乗るlejiキーで対象の仕様系列を宣言します。 - 派生サーフェスはアクセスの制約を引き継ぎます。インデックス、変更履歴、生成されたビューアー、そしてコンテキストレイヤーの内容から作られたあらゆるコンパイル済みまたはエクスポートされたビューは派生サーフェスであり、エージェントがその内容から生み出した出力も同様です。派生サーフェスは、それが引いてきた内容のうちもっとも制限の強いものの、アクセスの制約を帯びます。派生サーフェスは、明示的でレビューされた墨消しの手順を経て、その読み手のための別のサーフェスを作るのでない限り、その内容よりも広い読み手を持つ場所へ書かれたりコピーされたりしてはなりません(MUST NOT)。またエージェントは、制限された文脈を、より広い読み手を持つサーフェスや、より制限の弱いサーフェス(プルリクエスト、チケット、チャット、コミットメッセージ、公開のコンテキストレイヤー)へ引用したり要約したりしてはなりません(MUST NOT)。制限されたコンテキストレイヤーのインデックスは、その散文と同じくらい機微でありえます。タイトルも、パスも、要約も、すべてそれを説明しているからです。これはツールが行うチェックではなく、ツールを操作する人とエージェントに課された制約です。Leji は、ツールが「より広い読み手」を計算するために読める読み手のモデルを定義していないので(アクセスはバージョン管理システムのものです。governance.md の「アクセスの境界」に従います)、リファレンスの SDK はこれを強制せず、どのツールもせいぜい警告するだけです(ビューアーのエクスポートは、非公開でホストするよう警告します)。
Task routing(作業に応じた経路の決定)#
インデックス、カテゴリの割り当て、決定記録の目的は、エージェントがツリー全体ではなく、作業に必要なコンテキストだけを読み込めるようにすることです。この節では、作業の適用範囲からその一部を選ぶ方法を規範的に定義します。仕様の他の箇所から参照される、唯一の経路決定アルゴリズムです。ブートプロファイルの Loading 節(boot-profile.md)は、実際の作業で使う言葉でエージェントをここへ導きます。決定記録の適用範囲(decisions.md)はこのアルゴリズムで照合され、フェデレーションでの読み取り(distribution.md)でも、作業がどの兄弟に関係するかを決めるために再利用されます。経路の決定はコンテキストを読むためのものであり、タスクエンベロープや実行プロトコルではありません。これらは 1.0 の対象外です(README.md の「拡張の境界」を参照)。
- 入力。作業の適用範囲とは、その作業が読むか変更する、リポジトリルートからの相対の POSIX パスの集合(要件 6 に従って正規化されたもの。POSIX 形式、ルートからの相対、先頭に
./を付けない)に、作業が明示的に名指ししたカテゴリと、作業が明示的に名指ししたトピックを加えたものです。トピックは明示的な入力です。アルゴリズムがそれをパス、カテゴリ、散文、内容から導くことはありません。エージェントやツールがどのように作業から適用範囲を導くかは規範の対象外ですが、以下の照合はそうではありません。 - パスの照合(字面のみ、双方向)。宣言されたパスと作業のパスが一致するのは、正規化のあと(POSIX 形式、ルートからの相対、先頭に
./を付けない、末尾の/を取り除く)、2 つの文字列が等しいか、一方が他方のパス接頭辞としての祖先であるときです。すなわち、短いほうが、長いほうを/の境界で切り詰めたものと等しいときです。照合は純粋に字面上のものです。ファイルシステムを参照することはなく、ファイルを指すパスとディレクトリを指すパスを区別しません。正規化のあとでは、その 2 つは見分けがつかないからです。これはどちらの向きにも成り立つ包含関係であり(リファレンス実装が共有するunderPath関係です)、広い適用範囲を持つ作業と、狭く宣言されたセレクタは、どちらが広くても互いを見つけます。 - カテゴリの照合(狭い)と、2 つのカテゴリ集合。作業のカテゴリは、展開される(expanded)ものと合図となる(signalled)ものに分かれます。作業が明示的に名指ししたカテゴリは、両方の集合に入ります。それ自体が統制された文書である作業のパス(生成されたインデックスのエントリと完全一致するもの。包含では決してありません)は、そのエントリのカテゴリを合図となる集合にだけ寄与します。展開されるカテゴリは、その意図の文書と記録の候補を読み込みます。合図となるカテゴリは、決定とフェデレーションのマウントにとっての照合の合図であり、それ自体は何も読み込みません。カテゴリのセレクタは、任意のリポジトリのファイルからカテゴリを推測してはなりません(MUST NOT)。またそれ自体が統制された文書ではない作業のパスは、統制された文書の祖先ディレクトリも含め、カテゴリをまったく寄与しません。パスの適用範囲はファイルに届きますが、カテゴリの展開はそれに追随しません。
- トピックの照合(完全一致、マウント限定)。トピックは Unicode スカラー値からなる空でない文字列で、その UTF-8 表現によって比較されます。単独のサロゲートは妥当なトピックではありません。この規則は双方に適用されます。Unicode スカラー値からなる空でない文字列でない作業のトピックやマウントの
topicsのエントリは入力の誤りであり、実装は黙って不一致として返すのではなく、それを拒否しなければなりません(MUST)。作業のトピックが宣言されたトピックと一致するのは、デコードされた 2 つの文字列が完全に等しいときです。実装は、どちらの側についても、大文字小文字の変換、Unicode 正規化、ロケールに依存する比較、切り詰め、トークン化、部分文字列の照合、あいまい照合を行ってはなりません(MUST NOT)。したがって、正規等価だがバイト列の異なる綴りは一致しません。この等値の規則は、下にある結果のバイト単位の順序づけとは別のものです。作業のトピックが重複していてもひとつの合図になるので、あるトピックを二度名指ししても、一度名指ししたのとまったく同じように照合されます。フェデレーションのマウントは、作業のいずれかのトピックが、そのマウントが宣言するいずれかのトピックと等しいときに一致します。トピックの一致が選ぶのはマウントだけです。展開される集合にも合図となる集合にも入ってはならず、いかなる文書や記録も読み込んではならず、いかなる決定の経路も定めてはならず、requiredWhenを評価してはならず、マウントを必須にしてはなりません(MUST NOT)。 - ステータスによる絞り込み。いまの指針として経路に載るのは、
statusが拘束力を持つ決定記録だけです。acceptedとdeprecatedは拘束力を持ちます。deprecatedの記録は、古びた姿勢を伴って拘束します。エージェントはそれを、確立したいまの実践ではなく、退場の途上にある指針として扱わなければなりません(MUST)。supersededの記録は、履歴として以外は拘束してはならず(MUST NOT)、supersededByを持たなければなりません(MUST)。proposedとrejectedの記録は拘束してはなりません(MUST NOT)。拘束する記録はlive です。 - 適用範囲のない決定。
affectedPathsもaffectedCategoriesも宣言していない live の決定記録は、組織全体に及びます。作業の適用範囲が何であれ、すべての作業に対して経路に載ります。適用範囲を持つ live の決定は、作業がパス(2)またはカテゴリ(3)で一致したときにだけ経路に載ります。 - パスの適用範囲が空の場合と、適用範囲が空の場合。作業のパスの集合が空のとき、パスの照合は何も寄与せず、エージェントはパスに基づく経路の決定が評価されなかったことを述べなければなりません(MUST)。明示的に名指しされたカテゴリはなお尊重され、なお展開されます。明示的に名指しされたトピックもなお照合されます。名指しされたカテゴリと名指しされたトピックは、どちらも適用範囲を空でなくします。作業の適用範囲全体が空になるのは、パスも、カテゴリも、トピックも名指ししていないときだけです。そのときエージェントは、無条件のブートプロファイルとエージェントプロファイルのコンテキストに加えて、組織全体に及ぶ適用範囲のない live の決定だけを経路に載せます。エージェントは、経路の決まっていない読み込みを、適用範囲の定まったものであるかのように提示してはなりません(MUST NOT)。
- 記録は候補として経路に載ります。展開されるカテゴリは、その意図の文書を必須のコンテキストとして経路に載せます。そのカテゴリの記録は、種別と日付を添えて別に返され、読み手が判断して読み込む候補になります。記録が必須になるのは、作業のパスが項目 2 によってそれを直接選んだとき、エージェントかブートプロファイルがそれを名指ししたとき、人がそれを求めたときだけです。カテゴリで一致したことや、いちばん新しい日付を持つことが、記録を必須にすることは決してありません。記録がカテゴリの候補であると同時にパスで直接選ばれている場合は、直接の選択が勝ち、必須になります。経路の決定が、どの記録かを「最新」や「いまのもの」として認定してはなりません(MUST NOT)。1.0 は記録の系列としての同定も順序の保証も定義していないので、新しさの判断は読み手のものであり、インデックスが示す日付に照らして下されます。決定記録は独自の経路(項目 5 と 6)を保ち、一般の記録として経路に載ることはありません。決定のファイルを作業のパスとして名指ししても、その決定が経路に載るわけではありません。載せるのはその宣言された適用範囲です。
- 引用。経路に載った決定記録を読み込んだエージェントは、一致した記録のうちどれを読み込んだかを引用しなければなりません(MUST)。読み手が、エージェントがどの指針を適用したかを見て、何を適用しなかったかを推し量れるようにするためです。
経路の定まった一部とは、エージェントがある作業のために読み込むものです。それは次の和集合です。ブートプロファイルの無条件の読み込み集合と、有効なエージェントプロファイルの requiredRead(エージェントは、適用範囲とは独立にこれを基礎として保持します)。展開されるカテゴリに属するすべての統制された意図の文書。項目 2 によって作業のパスが選ぶすべての統制されたエントリ。項目 8 によってパスで直接選ばれたすべての記録。そして、作業がパスまたは合図となるもしくは展開されるカテゴリで一致するすべての live の決定に、組織全体に及ぶ適用範囲のない live の決定を加えたものです。
合図となるカテゴリが寄与するのは照合だけで、それも決定とフェデレーションのマウントに対してであり、コーパスを展開することは決してありません。
一部はタスクエンベロープではありません。経路を計算するツールは、その一部とともに、エージェントが指示なしに読み込んではならない材料、すなわち記録の候補と、その周りの候補に関するメタデータを返します。エンベロープごと読み込んでしまえば、経路を決めた意味がなくなります。
結果の順序は規範的です。ツールがそれを出力する場合、独立した実装どうしがバイト単位で一致するように、カテゴリはこの仕様の正典のカテゴリ順、文書と記録と決定はパスの昇順、マウントは名前の昇順です。文字列の比較は UTF-8 上のバイト単位であり、ロケールやコードポイントの照合順に依存しません。
ツールは、パスの集合からこの一部を計算する補助機能を提供しても構いません(MAY)。リファレンス実装はそれを公開しています(route)。そうした補助機能は適用範囲に依存する部分を計算するものであり、呼び出す側がすでに持っている基礎を出力する必要はありません。その基礎を読み込むエージェントの義務は変わりません。素の読み手がこのアルゴリズムに従うなら、いつでも経路の決定は適合しています。
補足(非規範的)#
現在、リファレンスのツールは変更履歴のスキーマと追記のみの規律を確認します(leji validate が両方を実行します)。基準リビジョンに照らした変更履歴の網羅性、すなわち変更されたすべての統制対象パスが追加エントリに含まれることの検証は、報告用チェックとしてロードマップにありますが、現時点では処理を阻止するゲートではありません。それが提供されるまでは、プロセスとして申告されるレビューと CI の規律によって網羅性を担保します(conformance.md を参照)。
インデックスは、統制されたコンテキストをたどるためのナビゲーションの出典です。leji viewer は、統制された中核部分をインデックスから描画し、その下に、閲覧可能な参照領域としてリポジトリ自体のディレクトリツリーを表示します。これにより、ひとつのビューで、統制されたコンテキストとチーム既存のナビゲーションの両方を確認できます。どのドキュメントツールでも、同様にインデックスを投影できます。表示方法は非規範的です。このサーフェスは意図的に小さく設計されています。5 つの形があれば、ツールがコンテキストレイヤーを検証し、差分を取り、鮮度を判定して、エージェントを適切な一部へ導くのに十分です。同時に、チームがサーフェス全体を把握できる程度に少なく抑えられています。この 5 つを超えるものは 1.0 より後の領域であり、実際の運用から必要性が示されるのを待ちます。