spec 1.0 · chuẩn tắc

Context manifest của Leji (leji.json)

Bản dịch có sự hỗ trợ của AI agent. Nếu có khác biệt, trang tiếng Anh là bản có hiệu lực. Nếu bạn thấy vấn đề nào trong văn bản, rất mong bạn mở một issue hoặc gửi một pull request.

Điểm vào cho máy của một lớp ngữ cảnh Leji. Nằm ở gốc kho mã nguồn với tên leji.json.

$id chuẩn: https://leji.org/schemas/v1.0/context-manifest.schema.json
Tệp gốc: context-manifest.schema.json

Các trường

#lejistringbắt buộc

Nhánh đặc tả Leji mà lớp ngữ cảnh này nhắm tới, ví dụ "1.0". Khoá tự đặt tên theo quy ước của OpenAPI và cho biết tệp này là một manifest Leji.

Mẫu ^\d+\.\d+$

#namestringbắt buộc

Một định danh ngắn, ổn định cho lớp ngữ cảnh này, ví dụ "acme-billing-context".

#descriptionstring

Tóm tắt một dòng về phạm vi lớp ngữ cảnh này bao phủ.

#rootPathstringbắt buộc

Gốc ngữ cảnh, đường dẫn POSIX tương đối so với gốc kho mã nguồn. Nó khai báo lớp ngữ cảnh nằm ở đâu; nó không tính lại các đường dẫn mà nó quản trị: các mục index, các trang được ghim, các đường dẫn tới profile và mọi đường dẫn khác trong các tệp Leji đều phân giải từ gốc kho mã nguồn. homepage, logofavicon của viewer là ngoại lệ: chúng được viết tương đối so với gốc ngữ cảnh, và một đường dẫn tương đối so với gốc kho mã nguồn nhưng nằm dưới gốc ngữ cảnh cũng được chấp nhận.

Mẫu ^(?!/)(?!\./)(?!.*(^|/)\.\.(/|$))(?!.*\\).*$

#bootProfilePathstringbắt buộc

Đường dẫn tới boot profile, điểm vào không phụ thuộc agent mà mọi host và mọi người đều bắt đầu từ đó.

Mẫu ^(?!/)(?!\./)(?!.*(^|/)\.\.(/|$))(?!.*\\).+\.md$

#categoriesobjectbắt buộc

Ánh xạ từ danh mục logic sang tệp index. Khoá là năm định danh danh mục; mỗi khoá trỏ tới một hoặc nhiều tệp index được biên soạn, liệt kê nội dung của danh mục đó.

Mỗi khoá bên dưới đều có cùng một hình dạng:

indexesmảng chuỗibắt buộc

Một hoặc nhiều tệp index cho danh mục này, đường dẫn tương đối so với gốc kho mã nguồn. Mỗi tệp index là markdown được biên soạn, mang một khối leji-index có rào, trong đó các dòng - path: <thư-mục-hoặc-tệp> chọn nội dung thuộc về danh mục này. Nội dung vẫn nằm nguyên chỗ của nó; tệp index chỉ khai báo việc đưa vào.

domainobject

Nơi nội dung domain nằm: ngôn ngữ nghiệp vụ và ngữ nghĩa sản phẩm.

systemobject

Nơi nội dung system nằm: kiến trúc và những bất biến mà mọi thay đổi phải tôn trọng.

practiceobject

Nơi nội dung practice nằm: quy ước và những khuôn mẫu đã được kiểm chứng.

governanceobject

Nơi nội dung governance nằm: các ràng buộc bảo vệ cho agent và các quy tắc vận hành.

decisionsobject

Nơi các bản ghi quyết định nằm: những bản ghi có ngày tháng về lý do mọi thứ ở trạng thái hiện tại.

#machineobject

Vị trí của các tệp máy đọc được: index, changelog, các profile, và các bản ghi quyết định.

indexPathstring

Đường dẫn tới context index được sinh ra.

changelogPathstring

Đường dẫn tới context changelog máy đọc được.

agentProfilesPathstring

Thư mục chứa các tài liệu agent profile.

decisionRecordsPathstring

Thư mục chứa các bản ghi quyết định.

#agentsmap

Gắn vai trò với agent profile. Khoá là định danh vai trò (ví dụ "thought-partner", "reviewer"); giá trị là đường dẫn tới tài liệu agent profile. Các quy trình gọi vai trò; map này quyết định ai đảm nhận vai trò đó.

#actorsmap

Danh bạ các actor có thể đảm nhận vai trò; không bắt buộc. Khoá là định danh actor ổn định. Một actor khai báo những vai trò nó đủ điều kiện đảm nhận và một mẫu câu lệnh cho mỗi vai trò. Hãy dùng khi một vai trò có nhiều hơn một actor đủ điều kiện, hoặc khi một actor cần cách gọi khác nhau tuỳ vai trò nó đang đảm nhận; chỉ một trong hai điều đó đã là đủ lý do. Một vai trò chỉ có một actor và chỉ cần một câu lệnh thì đã được phục vụ bởi host và invocation của chính agent profile.

#ownersobjectbắt buộc

Ai chịu trách nhiệm về sức khoẻ của lớp ngữ cảnh. Chủ sở hữu chịu trách nhiệm giữ cho lớp ngữ cảnh luôn hiện thời và được tỉa gọn; không phải chỉ mình họ viết hay biên soạn nội dung đó (governance.md).

Mỗi khoá bên dưới đều có cùng một hình dạng:

namestringbắt buộc

Tên của người đó.

contactstring

Cách liên hệ với họ, ví dụ một địa chỉ email.

primaryobjectbắt buộc

Người chịu trách nhiệm về tính hiện thời của lớp ngữ cảnh. Lớp ngữ cảnh không có chủ thì sẽ mục ruỗng.

continuityobject

Không bắt buộc. Một người khác mang đúng trách nhiệm đó khi người chính vắng mặt hoặc rời đi; những lần áp dụng có hỗ trợ nên chỉ định một người trước khi bên hỗ trợ rút đi. Nêu lại chính người chính thì không tạo ra tính liên tục nào, và một agent không thể đảm nhận: chủ sở hữu là những con người chịu trách nhiệm.

#conformanceobject

Mức tuân thủ mà lớp ngữ cảnh này tuyên bố, công cụ kiểm được.

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

Mức tuân thủ được tuyên bố: core, indexed, governed, hoặc federated.

claimedAtstring

Ngày ISO 8601 tuyên bố được khẳng định lần gần nhất.

#federationobject

Những lớp ngang hàng được mount vào kho mã nguồn này (bản đặc tả: distribution.md, khuôn mẫu 3). Vòng tròn ghép các quyền sở hữu lại với nhau; nó không tập trung hoá chúng.

mountsmảng các đối tượng

Mỗi mount là một lớp ngữ cảnh ngang hàng được đọc tại một phiên bản đã ghim, thông qua phép chiếu lớp do resolver nạp về, đồng thời giữ nguyên kho mã nguồn, quyền sở hữu và cổng xem xét của riêng nó. Nội dung được tạo thành tệp cục bộ nằm trong bộ nhớ đệm của resolver, được Git bỏ qua và không bao giờ được commit vào đây.

namestringbắt buộc

Tên của lớp ngang hàng; phải khớp với name trong manifest của chính lớp đó.

sourcestringbắt buộc

Địa chỉ kho mã nguồn đã chuẩn hoá của lớp ngang hàng: một URL từ xa dạng https://, ssh://, hoặc kiểu SCP. Đây là gốc phân giải và là không gian tên của pin. Đường dẫn tệp cục bộ chỉ hợp lệ trong những gợi ý cục bộ của máy, không bao giờ ở đây.

pinstringbắt buộc

Id commit đầy đủ và bất biến (SHA-1 hoặc SHA-256) của bản sửa đổi lớp ngang hàng mà lớp chủ này đọc. Đây là trạng thái mong muốn do manifest giữ: việc cập nhật pin là hành động biên soạn có chủ ý và đã qua xem xét.

trackingRefstring

Ref đối chiếu có tên đầy đủ trên nguồn (refs/heads/* hoặc refs/tags/*), dùng làm mốc cho báo cáo pin lỗi thời và kiểm tra khả năng truy cập trong federation; không bắt buộc. Nếu vắng, nhánh mặc định mà nguồn quảng bá sẽ được dùng và được ghi lại trong kết quả câu lệnh.

ownerobjectbắt buộc

Chủ sở hữu của lớp ngang hàng. Quyền sở hữu vẫn thuộc về nhóm của lớp đó; lớp chủ không bao giờ hấp thụ nội dung của nó.

rolestring

Lớp ngang hàng này mang những gì, viết bằng lời, ví dụ "ngữ cảnh phía sản phẩm". Dành cho con người; việc định tuyến dùng các trường có cấu trúc bên dưới.

categoriesmảng gồm "domain" · "system" · "practice" · "governance" · "decisions"

Những phạm vi danh mục nội dung mà lớp ngang hàng này có thể trả lời. Chỉ là siêu dữ liệu định tuyến; nội dung của lớp ngang hàng vẫn nằm ở lớp đó. Bắt buộc với mức tuân thủ federated.

topicsmảng chuỗi

Các nhãn chủ đề ngắn mà lớp chủ nhìn thấy, dùng để định tuyến một tác vụ tới lớp ngang hàng này, ví dụ "billing", "checkout". Chỉ là siêu dữ liệu định tuyến.

requiredWhenmảng chuỗi

Những điều kiện tác vụ mà ở đó người đọc phải phân giải mount này, hoặc dừng lại và báo rằng ngữ cảnh chưa đầy đủ nếu không phân giải được (dừng an toàn). Lớp chủ nhìn thấy được; không được tiết lộ bất cứ điều gì người đọc của lớp chủ không được phép thấy.

#vendorAdaptersmảng chuỗi

Các tệp điểm vào của nhà cung cấp có mặt trong kho mã nguồn này; mỗi tệp phải chuyển hướng về boot profile.

#viewerobject

Tuỳ chọn trình bày mà leji viewer đọc. Đây là cấu hình tiện lợi, không mang tính chuẩn tắc; bản thân việc trình bày nằm ngoài phạm vi chuẩn tắc.

portinteger

Cổng ưa dùng cho bản xem trước cục bộ của leji viewer serve. Cờ --port sẽ ghi đè; mặc định là 5354 (LEJI trên bàn phím điện thoại).

logostring

Ảnh logo cho viewer, dạng đường dẫn nằm dưới gốc ngữ cảnh (ví dụ "assets/logo.svg"). Mặc định là dấu hiệu của Leji.

titlestring

Tiêu đề hiển thị của viewer (đầu thanh bên và tiêu đề trang). Mặc định là tên lớp ngữ cảnh.

agentsLabelstring

Nhãn thanh bên cho nhóm agent profile (dùng emoji cũng được). Mặc định là "🤖 Agents". Nhóm này liệt kê các agent profile của lớp và được sắp xếp theo viewer.groupOrder như mọi nhóm khác.

faviconstring

Favicon cho viewer, dạng đường dẫn nằm dưới gốc ngữ cảnh (ví dụ "assets/icon.svg"). Mặc định là dấu hiệu của Leji.

homepagestring

Trang đích của viewer, dạng đường dẫn tương đối so với gốc ngữ cảnh (ví dụ "README.md"). Mặc định là tệp overview.md được tạo sẵn.

pinsmảng các phần tử

Các trang được ghim lên đầu thanh bên: đường dẫn markdown tương đối so với gốc kho mã nguồn, hoặc {path, label} nếu muốn nhãn tự biên soạn. Ghim boot profile sẽ thay cho dòng mặc định của nó.

groupOrdermảng chuỗi

Trình tự nhóm trên thanh bên do người dùng biên soạn, theo đúng nhãn nhóm (chính là H1 của tệp index). Những nhóm được liệt kê xếp trước theo thứ tự này; các nhóm còn lại theo sau theo thứ tự suy ra.

themeobject

Ghi đè chủ đề của viewer.

primarystring

Màu chính/màu nhấn dạng màu CSS hex (ví dụ "#009F71"). Nó chi phối khung viewer, các trạng thái đang hoạt động và màu nhấn của sơ đồ; còn liên kết trong phần thân và mã nội dòng dùng tông màu dễ tiếp cận đã cố định, trừ khi viewer.theme.link cung cấp một màu vượt qua được ngưỡng tương phản.

linkstring

Màu liên kết dạng màu CSS hex (ví dụ "#5A50F9"). Chỉ áp dụng cho liên kết trong phần thân và mã nội dòng khi nó đạt tỉ lệ 4,5:1 so với nền mã nội dòng, là nền hẹp hơn trong hai nền mà chúng nằm lên; nếu không, tông màu dễ tiếp cận đã cố định vẫn được giữ và leji view / leji export sẽ cảnh báo.

mermaidboolean

Kết xuất các khối mã ```mermaid có rào thành sơ đồ trong viewer. Mặc định là true.

poweredByboolean

Hiển thị dấu hiệu nhỏ "Powered by Leji" ở góc viewer. Mặc định là true; đặt false để bỏ đi.

categoryEmojisobject

Ghi đè emoji mặc định hiển thị bên cạnh mỗi danh mục trong bản đồ lớp được sinh ra. (Các nhóm trên thanh bên được đặt nhãn theo chính H1 của mỗi tệp index.)

Schema và ví dụ

{
  "$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."
    }
  }
}

Một manifest hợp lệ ở gốc kho mã nguồn.

{
  "$schema": "https://leji.org/schemas/v1.0/context-manifest.schema.json",
  "leji": "1.0",
  "name": "acme-billing-context",
  "description": "Lớp ngữ cảnh dùng chung cho monorepo nền tảng thanh toán của 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"
  }
}

← Tất cả schema