spec 1.0 · 規範

Leji コンテキストマニフェスト(leji.json)

AI エージェントの支援による翻訳です。内容に相違がある場合は、英語版ページが優先されます。文章に問題を見つけた際は、Issueまたはプルリクエストをお願いします。

Leji コンテキストレイヤーの、機械向けエントリポイントです。リポジトリルートに leji.json として置かれます。

正規の $idhttps://leji.org/schemas/v1.0/context-manifest.schema.json
生ファイル:context-manifest.schema.json

フィールド

#lejistring必須

このコンテキストレイヤーが対象とする Leji の仕様系列です。たとえば "1.0"。自らを名乗るこのキーは OpenAPI の慣習に倣ったもので、このファイルが Leji のマニフェストであることを示します。

パターン ^\d+\.\d+$

#namestring必須

このコンテキストレイヤーの、短く安定した識別子です。たとえば "acme-billing-context"。

#descriptionstring

このコンテキストレイヤーが何を扱うのかの、一行の要約です。

#rootPathstring必須

コンテキストルートです。リポジトリルートからの相対の POSIX パスで指定します。コンテキストレイヤーがどこにあるかを宣言するもので、自らが管轄するパスの基準を取り直すことはありません。インデックスのエントリ、ピン留めしたページ、プロファイルのパスをはじめ、Leji の成果物のその他すべてのパスは、リポジトリルートから解決されます。ビューアーの homepagelogofavicon は例外です。これらはコンテキストルートからの相対で書かれ、その下に収まるリポジトリルートからの相対パスも受け付けられます。

パターン ^(?!/)(?!\./)(?!.*(^|/)\.\.(/|$))(?!.*\\).*$

#bootProfilePathstring必須

ブートプロファイルへのパスです。ブートプロファイルは、あらゆるホストとあらゆる人が起点とする、エージェントに依存しないエントリポイントです。

パターン ^(?!/)(?!\./)(?!.*(^|/)\.\.(/|$))(?!.*\\).+\.md$

#categoriesobject必須

論理的なカテゴリから、インデックスファイルへの対応づけです。キーは 5 つのカテゴリ識別子で、それぞれが、そのカテゴリの内容を列挙する、人が記述した 1 つ以上のインデックスファイルに対応します。

以下の各キーは、いずれも同じ形をとります。

indexes文字列の配列必須

このカテゴリのための、リポジトリルートからの相対のインデックスファイルです。1 つ以上を指定します。各インデックスファイルは人が記述した markdown で、フェンス付きの leji-index ブロックを持ちます。そのブロックの - path: <ディレクトリまたはファイル> の行が、このカテゴリに属する内容を選びます。内容はいまある場所に置かれたままで、インデックスファイルはそれを含めることを宣言するだけです。

domainobject

domain の内容が置かれる場所です。ビジネスの言葉と、製品の意味づけ。

systemobject

system の内容が置かれる場所です。アーキテクチャと、すべての変更が尊重する不変条件。

practiceobject

practice の内容が置かれる場所です。規約と、効果が確かめられたパターン。

governanceobject

governance の内容が置かれる場所です。エージェントのガードレールと、運用の規則。

decisionsobject

決定記録が置かれる場所です。物事がいまの形である理由の、日付のある記録。

#machineobject

機械可読な成果物の場所です。インデックス、変更履歴、プロファイル、決定記録。

indexPathstring

生成されるコンテキストインデックスへのパスです。

changelogPathstring

機械可読なコンテキスト変更履歴へのパスです。

agentProfilesPathstring

エージェントプロファイル文書を置くディレクトリです。

decisionRecordsPathstring

決定記録を置くディレクトリです。

#agentsマップ

ロールとエージェントプロファイルの結び付けです。キーはロール識別子(たとえば "thought-partner"、"reviewer")、値はエージェントプロファイル文書へのパスです。プロトコルがロールを関与させ、そのロールを誰が担うかはこのマップが決めます。

#actorsマップ

ロールを担えるアクターの登録簿です。任意です。キーは安定したアクター識別子です。各アクターは、自分が担えるロールと、ロールごとのコマンドテンプレートを宣言します。ひとつのロールに担えるアクターが複数いるとき、あるいはひとつのアクターが、担うロールによって異なる呼び出し方を必要とするときに使います。どちらか一方だけでも十分な理由になります。アクターがひとりしかおらず、必要なコマンドもひとつだけのロールは、エージェントプロファイル自身の host と invocation で足ります。

#ownersobject必須

コンテキストレイヤーの健全さについて、説明責任を負うのは誰かです。所有者は、コンテキストレイヤーが現状に即した状態に保たれ、適切に刈り込まれることに責任を負います。ひとりで書いたり整えたりするわけではありません(governance.md)。

以下の各キーは、いずれも同じ形をとります。

namestring必須

その人の名前です。

contactstring

連絡の取り方です。たとえばメールアドレス。

primaryobject必須

コンテキストレイヤーを現状に即した状態に保つことに、説明責任を負う人です。所有者のいないコンテキストレイヤーは朽ちていきます。

continuityobject

任意です。主たる所有者が不在のとき、あるいは離れたときに、同じ説明責任を引き受ける別の人です。支援を受けた導入では、外部の助けが去る前にこの人を名指しすべきです。主たる所有者を再び挙げても継続性にはならず、エージェントがこれを担うこともできません。所有者は説明責任を負う人だからです。

#conformanceobject

このコンテキストレイヤーが宣言する適合レベルです。ツールで確認できます。

claimedLevel"core" · "indexed" · "governed" · "federated"

宣言する適合レベルです。core、indexed、governed、federated のいずれか。

claimedAtstring

その宣言を最後に主張した日付(ISO 8601)です。

#federationobject

このリポジトリにマウントされた兄弟レイヤーです(仕様: distribution.md のパターン 3)。輪は所有を組み合わせるものであり、中央に集めるものではありません。

mountsオブジェクトの配列

各マウントは、リゾルバがハイドレートしたレイヤーの投影を通じて、ピン留めされたバージョンで読まれる兄弟コンテキストレイヤーです。自分のリポジトリ、所有、レビューのゲートはそのまま保ちます。実体化された内容は gitignore されたリゾルバのキャッシュに置かれ、ここにコミットされることはありません。

namestring必須

兄弟レイヤーの名前です。兄弟自身のマニフェストにある name と一致しなければなりません。

sourcestring必須

兄弟レイヤーの、正規化されたリポジトリの所在です。https://、ssh://、または SCP 形式のリモート URL を指定します。これが解決の起点であり、ピンの名前空間になります。ローカルファイルシステムのパスが妥当なのは、そのマシンに閉じたヒントの中だけで、ここでは使えません。

pinstring必須

このホストが読む兄弟のリビジョンの、不変なコミット id(SHA-1 または SHA-256)を完全な形で示したものです。マニフェストが保持する望ましい状態であり、ピンの更新は意図的で、レビューを経た手入れです。

trackingRefstring

ソース上の、証跡となる完全修飾の参照(refs/heads/* または refs/tags/*)です。任意で、古くなったピンの報告と、フェデレーションでの到達可能性がこれを照合の相手にします。指定がない場合は、ソースが提示する既定ブランチが使われ、コマンドの出力に記録されます。

ownerobject必須

兄弟レイヤーの所有者です。所有は兄弟のチームに残り、ホストがその内容を取り込むことはありません。

rolestring

この兄弟レイヤーが何を担っているかを、散文で述べます。たとえば "製品側のコンテキスト"。人のためのもので、経路の決定には下の構造化されたフィールドを使います。

categories"domain" · "system" · "practice" · "governance" · "decisions" の配列

この兄弟が答えを返せる、コンテンツカテゴリの範囲です。経路のメタデータに限られ、兄弟の内容は兄弟に置かれたままです。federated の適合性では必須です。

topics文字列の配列

ホストから見える短いトピックのラベルで、作業をこの兄弟へ振り分けるために使います。たとえば "billing"、"checkout"。経路のメタデータに限られます。

requiredWhen文字列の配列

読み手がこのマウントを解決しなければならない作業の条件です。解決できないときは、手を止めてコンテキストが不完全であることを報告します(フェイルクローズ)。ホストから見えるので、ホストの読み手が見てはならないものを何も明かしてはなりません。

#vendorAdapters文字列の配列

このリポジトリに置かれた、ベンダーのエントリポイントファイルです。それぞれがブートプロファイルへ誘導しなければなりません。

#viewerobject

leji viewer が読む、表示の設定です。規範ではない、利便のための設定であり、表示のしかたそのものは規範の対象外です。

portinteger

leji viewer serve でローカルのプレビューに使いたいポートです。--port フラグが優先されます。既定は 5354(電話のキーパッドで LEJI)です。

logostring

ビューアーのロゴ画像です。コンテキストルート以下のパスで指定します(たとえば "assets/logo.svg")。既定は Leji のマークです。

titlestring

ビューアーの表示タイトルです(サイドバーの見出しとページタイトル)。既定はコンテキストレイヤーの名前です。

agentsLabelstring

エージェントプロファイルのグループに付ける、サイドバーのラベルです(絵文字も歓迎です)。既定は "🤖 Agents"。このグループはレイヤーのエージェントプロファイルを列挙し、他のグループと同じく viewer.groupOrder で並び順が決まります。

faviconstring

ビューアーのファビコンです。コンテキストルート以下のパスで指定します(たとえば "assets/icon.svg")。既定は Leji のマークです。

homepagestring

ビューアーの入口となるページです。コンテキストルートからの相対パスで指定します(たとえば "README.md")。既定は、最初に用意される overview.md です。

pins要素の配列

サイドバーの先頭にピン留めするページです。リポジトリルートからの相対の markdown パスか、ラベルを自分で決めたい場合は {path, label} を指定します。ブートプロファイルをピン留めすると、その既定の行が置き換わります。

groupOrder文字列の配列

サイドバーのグループの並び順を、自分で決めるための設定です。グループのラベル(インデックスファイルの H1)と正確に一致させて指定します。挙げたグループがこの順で先に並び、挙げなかったグループは導出された順で続きます。

themeobject

ビューアーのテーマの上書きです。

primarystring

基調色・アクセント色を、16 進の CSS カラーで指定します(たとえば "#009F71")。ビューアーの外枠、選択中の状態、図のアクセントに効きます。本文のリンクとインラインコードは、viewer.theme.link がコントラストの基準を満たす色を与えないかぎり、アクセシビリティに配慮した固定の色調を使います。

linkstring

リンクの色を、16 進の CSS カラーで指定します(たとえば "#5A50F9")。本文のリンクとインラインコードに適用されるのは、それらが載る 2 つの背景のうち条件の厳しいインラインコードの背景に対して、4.5:1 に達したときだけです。届かない場合は、アクセシビリティに配慮した固定の色調がそのまま使われ、leji viewleji export が警告します。

mermaidboolean

フェンス付きの ```mermaid コードブロックを、ビューアーで図として描画します。既定は true です。

poweredByboolean

ビューアーの隅に、小さな "Powered by Leji" の表示を出します。既定は true で、false にすると消えます。

categoryEmojisobject

生成されるレイヤーマップで、各カテゴリの横に表示される既定の絵文字を上書きします。(サイドバーのグループのラベルは、各インデックスファイル自身の H1 です。)

スキーマと実例

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://leji.org/schemas/v1.0/context-manifest.schema.json",
  "title": "Leji context manifest (leji.json)",
  "description": "The machine entrypoint of a Leji context layer. Lives at the repository root as leji.json.",
  "type": "object",
  "required": [
    "leji",
    "name",
    "rootPath",
    "bootProfilePath",
    "categories",
    "owners"
  ],
  "additionalProperties": false,
  "properties": {
    "$schema": {
      "description": "Optional pointer to this schema, for editor validation and tooling.",
      "type": "string"
    },
    "leji": {
      "type": "string",
      "description": "The Leji spec line this context layer targets, e.g. \"1.0\". The self-naming key follows the OpenAPI convention and identifies the file as a Leji manifest.",
      "pattern": "^\\d+\\.\\d+$"
    },
    "name": {
      "description": "A short, stable identifier for this context layer, e.g. \"acme-billing-context\".",
      "type": "string",
      "minLength": 1
    },
    "description": {
      "description": "One-line summary of what this context layer covers.",
      "type": "string"
    },
    "rootPath": {
      "type": "string",
      "description": "Context root, POSIX path relative to the repository root. Declares where the context layer lives; it does not re-base the paths it governs: index entries, pinned pages, profile paths, and every other path in Leji artifacts resolve from the repository root. The viewer's `homepage`, `logo`, and `favicon` are the exception: they are written relative to the context root, and a repository-root-relative path under it is accepted too.",
      "pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).*$"
    },
    "bootProfilePath": {
      "description": "Path to the boot profile, the agent-agnostic entrypoint every host and person starts from.",
      "type": "string",
      "pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).+\\.md$"
    },
    "categories": {
      "type": "object",
      "description": "Logical category to index-file mapping. Keys are the five category identifiers; each maps to one or more curated index files that list the category's content.",
      "additionalProperties": false,
      "minProperties": 1,
      "properties": {
        "domain": {
          "description": "Where domain content lives: business language and product semantics.",
          "$ref": "#/$defs/categoryMapping"
        },
        "system": {
          "description": "Where system content lives: architecture and the invariants every change respects.",
          "$ref": "#/$defs/categoryMapping"
        },
        "practice": {
          "description": "Where practice content lives: conventions and proven patterns.",
          "$ref": "#/$defs/categoryMapping"
        },
        "governance": {
          "description": "Where governance content lives: agent guardrails and operating rules.",
          "$ref": "#/$defs/categoryMapping"
        },
        "decisions": {
          "description": "Where decision records live: dated records of why things are the way they are.",
          "$ref": "#/$defs/categoryMapping"
        }
      }
    },
    "machine": {
      "description": "Locations of the machine-readable artifacts: index, changelog, profiles, and decision records.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "indexPath": {
          "description": "Path to the generated context index.",
          "$ref": "#/$defs/relPath"
        },
        "changelogPath": {
          "description": "Path to the machine-readable context changelog.",
          "$ref": "#/$defs/relPath"
        },
        "agentProfilesPath": {
          "description": "Directory holding agent profile documents.",
          "$ref": "#/$defs/relPath"
        },
        "decisionRecordsPath": {
          "description": "Directory holding decision records.",
          "$ref": "#/$defs/relPath"
        }
      }
    },
    "agents": {
      "type": "object",
      "description": "Role to agent-profile binding. Keys are role identifiers (e.g. \"thought-partner\", \"reviewer\"); values are paths to agent profile documents. Protocols engage roles; this map decides who fills them.",
      "additionalProperties": false,
      "patternProperties": {
        "^[a-z0-9]+(-[a-z0-9]+)*$": {
          "$ref": "#/$defs/relPath"
        }
      }
    },
    "actors": {
      "type": "object",
      "description": "Optional registry of actors that can fill roles. Keys are stable actor identifiers. An actor declares the roles it is eligible for and a command template per role. Use it when a role has more than one eligible actor, or when one actor needs a different invocation depending on which role it is filling; either alone is reason enough. A role whose single actor needs only one command is served by the agent profile's own host and invocation.",
      "additionalProperties": false,
      "patternProperties": {
        "^[a-z0-9]+(-[a-z0-9]+)*$": {
          "$ref": "#/$defs/actor"
        }
      }
    },
    "owners": {
      "type": "object",
      "description": "Who is accountable for the context layer's health. Owners answer for the context layer staying current and pruned; they do not author or curate it alone (governance.md).",
      "required": [
        "primary"
      ],
      "additionalProperties": false,
      "properties": {
        "primary": {
          "$ref": "#/$defs/owner",
          "description": "The person accountable for the context layer's currency. Ownerless context layers rot."
        },
        "continuity": {
          "$ref": "#/$defs/owner",
          "description": "Optional. A different person who carries the same accountability when the primary is unavailable or steps away; assisted adoptions should name one before outside help leaves. Naming the primary again provides no continuity, and an agent cannot fill it: owners are accountable people."
        }
      }
    },
    "conformance": {
      "description": "The conformance level this context layer claims, checkable by tooling.",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "claimedLevel": {
          "description": "The conformance level claimed: core, indexed, governed, or federated.",
          "enum": [
            "core",
            "indexed",
            "governed",
            "federated"
          ]
        },
        "claimedAt": {
          "description": "ISO 8601 date the claim was last asserted.",
          "$ref": "#/$defs/isoDate"
        }
      }
    },
    "federation": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "mounts": {
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "name",
              "source",
              "pin",
              "owner"
            ],
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "description": "The sibling layer's name; must match the `name` in the sibling's own manifest."
              },
              "source": {
                "type": "string",
                "minLength": 1,
                "description": "Normalized repository locator of the sibling layer: an https://, ssh://, or SCP-style remote URL. The resolution root and the pin's namespace. Local filesystem paths are valid only in machine-local hints, never here."
              },
              "pin": {
                "type": "string",
                "pattern": "^([0-9a-f]{40}|[0-9a-f]{64})$",
                "description": "Full immutable commit id (SHA-1 or SHA-256) of the sibling revision this host reads. Manifest-held desired state: pin updates are deliberate, reviewed curation."
              },
              "trackingRef": {
                "type": "string",
                "pattern": "^refs/(heads|tags)/.+$",
                "description": "Optional fully qualified witness ref on the source (refs/heads/* or refs/tags/*) that stale-pin reporting and federated reachability compare against. Absent, the source's advertised default branch is used and recorded in command output."
              },
              "owner": {
                "$ref": "#/$defs/owner",
                "description": "The owner of the sibling layer. Ownership stays with the sibling's team; the host never absorbs its content."
              },
              "role": {
                "type": "string",
                "description": "What this sibling layer carries, in prose, e.g. \"product-side context\". For humans; routing uses the structured fields below."
              },
              "categories": {
                "type": "array",
                "items": {
                  "enum": [
                    "domain",
                    "system",
                    "practice",
                    "governance",
                    "decisions"
                  ]
                },
                "minItems": 1,
                "description": "The content-category scopes this sibling can answer for. Routing metadata only; the sibling's content stays in the sibling. Required for federated conformance."
              },
              "topics": {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "Short host-visible topic labels used to route a task to this sibling, e.g. \"billing\", \"checkout\". Routing metadata only."
              },
              "requiredWhen": {
                "type": "array",
                "items": {
                  "type": "string",
                  "minLength": 1
                },
                "description": "Task conditions under which a reader must resolve this mount, or stop and report incomplete context if it cannot (fail closed). Host-visible; must not disclose anything the host's audience may not see."
              }
            }
          },
          "description": "Each mount is a sibling context layer read at a pinned version through a resolver-hydrated layer projection, keeping its own repository, ownership, and review gate. Materialized content lives in the gitignored resolver cache, never committed here."
        }
      },
      "description": "Sibling layers mounted into this repository (spec: distribution.md pattern 3). The circle composes ownership; it doesn't centralize it."
    },
    "vendorAdapters": {
      "type": "array",
      "description": "Vendor entrypoint files present in this repository; each must redirect to the boot profile.",
      "items": {
        "$ref": "#/$defs/relPath"
      }
    },
    "viewer": {
      "type": "object",
      "description": "Presentation preferences read by `leji viewer`. Non-normative convenience configuration; presentation itself is out of normative scope.",
      "additionalProperties": false,
      "properties": {
        "port": {
          "type": "integer",
          "minimum": 1,
          "maximum": 65535,
          "description": "Preferred local-preview port for `leji viewer serve`. The --port flag overrides; the default is 5354 (LEJI on a phone keypad)."
        },
        "logo": {
          "type": "string",
          "description": "Logo image for the viewer, as a path under the context root (e.g. \"assets/logo.svg\"). Defaults to the Leji mark."
        },
        "title": {
          "type": "string",
          "description": "Display title for the viewer (sidebar header and page title). Defaults to the context layer name."
        },
        "agentsLabel": {
          "type": "string",
          "description": "Sidebar label for the agent-profiles group (emoji welcome). Defaults to \"🤖 Agents\". The group lists the layer's agent profiles and is ordered by viewer.groupOrder like any other group."
        },
        "favicon": {
          "type": "string",
          "description": "Favicon for the viewer, as a path under the context root (e.g. \"assets/icon.svg\"). Defaults to the Leji mark."
        },
        "homepage": {
          "type": "string",
          "description": "The viewer's landing page, as a path relative to the context root (e.g. \"README.md\"). Defaults to the seeded overview.md."
        },
        "pins": {
          "type": "array",
          "items": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "path"
                ],
                "properties": {
                  "path": {
                    "type": "string",
                    "description": "Repository-root-relative markdown path to pin."
                  },
                  "label": {
                    "type": "string",
                    "description": "Curated sidebar label for the pin (emoji welcome). Derived from the file when omitted."
                  }
                }
              }
            ]
          },
          "description": "Pages pinned at the top of the sidebar: repository-root-relative markdown paths, or {path, label} for a curated label. Pinning the boot profile replaces its default line."
        },
        "groupOrder": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Curated sidebar group sequence, by exact group label (the index file's H1). Listed groups come first in this order; unlisted groups follow in derived order."
        },
        "theme": {
          "type": "object",
          "additionalProperties": false,
          "description": "Viewer theme overrides.",
          "properties": {
            "primary": {
              "type": "string",
              "description": "Primary/accent color as a hex CSS color (e.g. \"#009F71\"). Drives the viewer chrome, active states, and diagram accents; body links and inline code use the fixed accessible tone unless viewer.theme.link supplies one that clears the contrast guard."
            },
            "link": {
              "type": "string",
              "description": "Link color as a hex CSS color (e.g. \"#5A50F9\"). Applied to body links and inline code only when it reaches 4.5:1 against the inline-code ground, the narrower of the two backgrounds they land on; otherwise the fixed accessible tone stays and `leji view` / `leji export` warn."
            }
          }
        },
        "mermaid": {
          "type": "boolean",
          "description": "Render fenced ```mermaid code blocks as diagrams in the viewer. Defaults to true."
        },
        "poweredBy": {
          "type": "boolean",
          "description": "Show the small \"Powered by Leji\" mark in the viewer's corner. Defaults to true; set false to remove it."
        },
        "categoryEmojis": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          },
          "propertyNames": {
            "enum": [
              "domain",
              "system",
              "practice",
              "governance",
              "decisions"
            ]
          },
          "description": "Override the default emoji shown beside each category in the generated layer map. (Sidebar groups are labeled by each index file's own H1.)"
        }
      }
    }
  },
  "$defs": {
    "relPath": {
      "type": "string",
      "pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).+$"
    },
    "isoDate": {
      "type": "string",
      "pattern": "^\\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\\d|3[01])([T ].*)?$"
    },
    "owner": {
      "type": "object",
      "required": [
        "name"
      ],
      "additionalProperties": false,
      "properties": {
        "name": {
          "description": "The person's name.",
          "type": "string",
          "minLength": 1
        },
        "contact": {
          "description": "How to reach them, e.g. an email address.",
          "type": "string"
        }
      }
    },
    "categoryMapping": {
      "type": "object",
      "required": [
        "indexes"
      ],
      "additionalProperties": false,
      "properties": {
        "indexes": {
          "description": "One or more repository-root-relative index files for this category. Each index file is curated markdown carrying a fenced `leji-index` block whose `- path: <dir-or-file>` lines select the content that belongs to this category. Content stays where it lives; the index file declares inclusion.",
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "string",
            "pattern": "^(?!/)(?!\\./)(?!.*(^|/)\\.\\.(/|$))(?!.*\\\\).+\\.md$"
          }
        }
      }
    },
    "actor": {
      "type": "object",
      "required": [
        "roles",
        "commands"
      ],
      "additionalProperties": false,
      "properties": {
        "roles": {
          "type": "array",
          "minItems": 1,
          "uniqueItems": true,
          "items": {
            "$ref": "#/$defs/roleId"
          },
          "description": "Role identifiers this actor is eligible to fill. Every entry must have a matching key in commands."
        },
        "commands": {
          "type": "object",
          "minProperties": 1,
          "propertyNames": {
            "$ref": "#/$defs/roleId"
          },
          "additionalProperties": {
            "$ref": "#/$defs/actorCommand"
          },
          "description": "Command templates keyed by role identifier. The key set must equal roles. Keying by role is the point: one actor can need different invocations for different roles."
        }
      }
    },
    "actorCommand": {
      "type": "string",
      "minLength": 1,
      "pattern": "<prompt>",
      "description": "Command template used to engage this actor in the keyed role. Must carry the <prompt> placeholder, standing as its own unquoted shell word; the pattern verifies the substitution site exists, placement is the spec's rule."
    },
    "roleId": {
      "type": "string",
      "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$",
      "description": "A role identifier, lowercase and hyphen-separated, as used by the agents map."
    }
  }
}

リポジトリルートに置かれた、適合するマニフェストです。

{
  "$schema": "https://leji.org/schemas/v1.0/context-manifest.schema.json",
  "leji": "1.0",
  "name": "acme-billing-context",
  "description": "Acme の課金プラットフォームのモノレポのための、共有コンテキストレイヤー。",
  "rootPath": "docs/",
  "bootProfilePath": "docs/boot-profile.md",
  "categories": {
    "domain": {
      "indexes": [
        "docs/context/domain.md"
      ]
    },
    "system": {
      "indexes": [
        "docs/context/system.md"
      ]
    },
    "decisions": {
      "indexes": [
        "docs/context/decisions.md"
      ]
    }
  },
  "machine": {
    "indexPath": "docs/context-index.json",
    "changelogPath": "docs/context-changelog.json",
    "agentProfilesPath": "docs/agents/",
    "decisionRecordsPath": "docs/decisions/"
  },
  "agents": {
    "thought-partner": "docs/agents/thought-partner.md"
  },
  "owners": {
    "primary": {
      "name": "Acme Platform Team",
      "contact": "platform@acme.example"
    }
  },
  "conformance": {
    "claimedLevel": "indexed",
    "claimedAt": "2026-06-10"
  }
}

← スキーマ一覧