spec 1.0 · chuẩn tắc
Bề mặt máy đọc được
Năm artifact giúp công cụ đọc được lớp ngữ cảnh. Phần còn lại là văn xuôi viết cho con người mà agent cũng có thể đọc; chính năm artifact này mới tạo thành hợp đồng để công cụ dựa vào.
| Artifact | Vị trí mặc định | Schema |
|---|---|---|
| Manifest | leji.json (gốc kho mã nguồn, cố định) |
context-manifest.schema.json |
| Context index | <root>/context-index.json |
context-index.schema.json |
| Context changelog | <root>/context-changelog.json |
context-changelog.schema.json |
| Agent profile | <root>/agents/*.md (frontmatter) |
agent-profile.schema.json |
| Bản ghi quyết định | <root>/decisions/*.md (frontmatter) |
decision-record.schema.json |
Mọi vị trí trừ manifest đều do manifest khai báo; bảng trên chỉ nêu giá trị mặc định.
Yêu cầu#
- Manifest.
leji.jsonMUST tồn tại ở gốc kho mã nguồn và hợp lệ theo schema của nó. Đây là tên tệp cố định duy nhất trong Leji: chính là tệp mà công cụ luôn tìm tới. - Index. Một lớp ngữ cảnh tuyên bố mức tuân thủ
indexedtrở lên MUST mang một context index được sinh ra, không bao giờ duy trì bằng tay: công cụ giải các tệp index của danh mục (categories.<id>.indexes, theo content-categories.md) thành những tài liệu mà chúng liệt kê, rồi ghi một mục cho mỗi tài liệu được quản trị. Mỗi mục mang mộtidổn định, mộtpath, mộttitle, và một định danhcategory. Bộ sinh SHOULD phát ra thêmkindcủa tài liệu (intenthoặcrecord); trường này là tuỳ chọn trong schema để một index viết ra từ trước khi có khái niệm loại vẫn hợp lệ, và bên tiêu thụ coi giá trị vắng mặt làintent. Mục của một bản ghi mang thêmdatecủa nó khi tài liệu khai mộtdatehợp lệ trong frontmatter; bộ sinh chỉ lấy ngày từ frontmatter, không bao giờ từ văn xuôi hay quy ước tên tệp. Một index lỗi thời (một index không còn khớp với những gì các tệp index giải ra) MUST được coi là một lỗi kiểm tra. Một lớp chủ có khai báofederation.mountscòn mang, trong cùng index đó, một mảngmountsở mức trên cùng: mỗi mount một bản ghi định tuyến (name,source,pin,trackingRefkhi có khai,owner,rolekhi có khai, cùng siêu dữ liệu định tuyếncategories/topics/requiredWhen). Đó chỉ là các bản ghi định tuyến; công cụ MUST NOT chép các mục hay văn xuôi của một lớp ngang hàng vào index của lớp chủ, và một bản ghi mount không mang theo bất cứ thứ gì mà nhóm đối tượng của lớp chủ không được phép thấy (theo distribution.md, phần Mount bị giới hạn). - Changelog. Một lớp ngữ cảnh tuyên bố mức tuân thủ
indexedtrở lên MUST mang một changelog máy đọc được ghi lại các thay đổi của lớp ngữ cảnh. Mỗi mục mang mộtidổn định, mộtdatetheo UTC, mộttype, mộtsummarygói trong một dòng, và cácpathsbị ảnh hưởng. Thứ tự chính thống là được suy ra, không theo vị trí: công cụ MUST sắp các mục theo(date, id)tăng dần, và vị trí trong mảng không mang ý nghĩa gì. Vìidlà duy nhất trong changelog (xem phần Định danh),(date, id)là một thứ tự toàn phần ngay cả khi hai thay đổi trùngdate. Các mục còn sống là bất biến: công cụ MUST coi việc sửa một mục đã công bố là một lỗi kiểm tra ở bất cứ đâu nó xác lập được trạng thái trước đó, còn việc sắp xếp lại mảng thì không phải là sửa. Việc xác lập trạng thái đó cần một mốc riêng để đối chiếu; ở nơi công cụ tham chiếu chỉ có phiên bản hiện tại, như trong một bản checkout tích hợp liên tục thông thường, thì việc sửa là không nhìn thấy được đối với nó và việc xem xét bộ thay đổi mới là thứ bắt được (xem conformance.md). Changelog là một bề mặt về độ mới, không phải một kho lưu trữ: một lớp ngữ cảnh sống lâu SHOULD nén nó lại thay vì để nó phình vô hạn, và MAY nén nó bất cứ lúc nào bằng cách bỏ các mục ở đầu cũ nhất của thứ tự ấy, miễn là cùng bộ thay đổi đó ghi thêm một mục kiểucompactionvới trườngcompactedghi lại số lượng cùng id đầu và id cuối đã bị bỏ. Việc bỏ bất cứ thứ gì ngoài các mục cũ nhất, việc bỏ mà không kèm mục nén, và việc nén tới mức tệp rỗng, đều là lỗi kiểm tra. Kỷ luật chỉ thêm mới được khoá theo tậpidvà được kiểm so với trạng thái đã commit trước đó, nên nó cần git ở thời điểm soạn thảo; bản thân tệp vẫn không cần git đối với bên tiêu thụ, và lịch sử git giữ toàn bộ phần ghi chép. Một bộ thay đổi có động tới tài liệu được quản trị (những tài liệu mà các tệp index của danh mục giải ra) MUST ghi thêm một mục cópathsphủ hết các đường dẫn được quản trị mà nó đã đổi, để mọi tài liệu được quản trị đã đổi đều nằm dưới một mục nào đó: kỷ luật chỉ thêm mới giữ cho các mục đã công bố là bất biến, còn quy tắc phủ này giữ cho phần ghi chép là đầy đủ. Một changelog người đọc được MAY tồn tại song song; bản ghi JSON mới là thứ công cụ đọc. - Các artifact dạng frontmatter. Agent profile và bản ghi quyết định là những tài liệu markdown có frontmatter YAML hợp lệ theo schema của chúng. Phần thân văn xuôi vẫn tự do; frontmatter mới là hợp đồng với máy. Profile hay quyết định dạng JSON thuần MUST NOT bị bắt buộc: người ta còn phải đọc những tài liệu này.
- Định danh. Mọi giá trị
idMUST ổn định một khi đã công bố: đổi tên và di chuyển thì cập nhậtpath, không bao giờ cập nhậtid. Định danh viết thường, ngăn cách bằng dấu gạch nối, và duy nhất trong phạm vi loại artifact của nó.idcủa một mục index được sinh ra là suy ra được theo thứ tự ưu tiên:idtrong frontmatter của tài liệu nếu nó có khai; nếu không thìidmà index đã lưu vốn đang mang cho chính đường dẫn đó, hoặc, với một lần di chuyển thuần tuý giữ nguyên nội dung, cho chính nội dung đó; nếu vẫn không thì là một slug từ tên tệp, được khử trùng lặp trong phạm vi thư mục cha. Cái đầu tiên tồn tại sẽ thắng, nên mộtidđã công bố sống sót qua một lần đổi tên hay di chuyển, và chỉ một tài liệu hoàn toàn mới mới đúc ra mộtidmới. Một tài liệu có thể vừa bị di chuyển vừa bị sửa trong cùng một bộ thay đổi thì SHOULD khai mộtidtrong frontmatter: chỉ có frontmatter mới ghim được id qua một lần đổi đồng thời cả đường dẫn lẫn nội dung (cả hai phương án dự phòng, mang theo theo đường dẫn và mang theo theo mã băm, đều trượt), và công cụ sẽ cảnh báo (id-vanished) khi một id đã lưu biến mất, để những tham chiếu treo mà nó để lại bị bắt được. - Dấu thời gian. Các giá trị
datetrong changelog theo ISO 8601 ở múi UTC: hoặc là một ngày theo lịchYYYY-MM-DD(được sắp như thời điểm bắt đầu ngày đó,T00:00:00Z), hoặc là một dấu thời gian tròn giây kết thúc bằngZ(ví dụ2026-06-13T15:04:05Z). Giờ không kèm múi, độ lệch khác UTC và phần giây lẻ đều không được phép: phần giây lẻ sẽ phá vỡ bảo đảm rằng sắpdatetheo thứ tự từ điển cũng là sắp theo thứ tự thời gian, vì…05.1Zđứng trước…05Ztrong khi thực ra lại muộn hơn. Mọi trường ngày trong mọi artifact đều bị ràng theo lịch, nên tháng13hay ngày99là không hợp lệ. Ngày ở các artifact khác cũng theo ISO 8601 và MAY chỉ gồm phần ngày. Đường dẫn theo kiểu POSIX, tương đối từ gốc kho mã nguồn, không có./ở đầu. - Mọi artifact JSON trừ manifest MUST khai báo nhánh schema mà nó được viết theo (
schemaVersion), theo versioning.md; manifest khai báo nhánh đặc tả mà nó nhắm tới bằng khoá tự đặt tênleji. - Bề mặt dẫn xuất thừa hưởng các ràng buộc truy cập. Index, changelog, viewer được sinh ra, và mọi khung nhìn được biên dịch hay xuất ra từ nội dung của lớp ngữ cảnh, đều là bề mặt dẫn xuất, và đầu ra mà một agent tạo ra từ nội dung đó cũng vậy. Một bề mặt dẫn xuất mang theo các ràng buộc truy cập của phần nội dung bị giới hạn chặt nhất mà nó lấy từ đó. Một bề mặt dẫn xuất MUST NOT được ghi hay chép sang một nơi có nhóm đối tượng rộng hơn nhóm của phần nội dung ấy, nếu không có một bước biên tập che thông tin tường minh và đã được xem xét, tạo ra một bề mặt riêng cho nhóm đối tượng đó; và một agent MUST NOT trích dẫn hay tóm tắt ngữ cảnh bị giới hạn vào một bề mặt có nhóm đối tượng rộng hơn hay ít bị giới hạn hơn (một pull request, một ticket, chat, thông điệp commit, hay một lớp ngữ cảnh công khai). Index của một lớp ngữ cảnh bị giới hạn có thể nhạy cảm ngang với văn xuôi của nó: tiêu đề, đường dẫn và tóm tắt đều mô tả nó. Đây là một ràng buộc đặt lên những người và agent vận hành công cụ, chứ không phải một phép kiểm mà công cụ thực hiện: Leji không định nghĩa một mô hình nhóm đối tượng nào mà công cụ đọc được để tính ra “nhóm đối tượng rộng hơn” (quyền truy cập thuộc về hệ quản lý phiên bản, theo governance.md, phần Ranh giới truy cập), nên SDK tham chiếu không cưỡng chế nó và nhiều nhất thì một công cụ chỉ cảnh báo (bản xuất viewer cảnh báo rằng nên host nó ở chế độ riêng tư).
Định tuyến tác vụ#
Index, phép gán danh mục và bản ghi quyết định giúp agent nạp đúng lát cắt ngữ cảnh cần cho tác vụ, thay vì cả cây. Mục này định nghĩa theo nghĩa chuẩn tắc cách phạm vi tác vụ chọn ra lát cắt đó. Đây là thuật toán định tuyến duy nhất được phần còn lại của bản đặc tả dẫn chiếu: mục Nạp của boot profile (boot-profile.md) hướng agent tới đây bằng ngôn ngữ tác vụ, phạm vi của bản ghi quyết định (decisions.md) được đối sánh bằng thuật toán này, và quy trình đọc trong federation (distribution.md) dùng lại nó để xác định tác vụ chạm tới lớp ngang hàng nào. Định tuyến là việc đọc ngữ cảnh; nó không phải bao tác vụ hay giao thức thực thi, vốn vẫn nằm ngoài 1.0 (xem README.md, phần Ranh giới mở rộng).
- Đầu vào. Phạm vi của một tác vụ là tập các đường dẫn POSIX tương đối từ gốc kho mã nguồn mà tác vụ đọc hoặc thay đổi (đã chuẩn hoá theo Yêu cầu 6: kiểu POSIX, tương đối từ gốc, không có
./ở đầu), cùng với mọi danh mục mà tác vụ nêu tên tường minh và mọi chủ đề mà tác vụ nêu tên tường minh. Chủ đề là đầu vào tường minh: thuật toán không bao giờ suy chúng ra từ đường dẫn, danh mục, văn xuôi hay nội dung. Việc một agent hay công cụ suy ra phạm vi từ tác vụ như thế nào thì nằm ngoài phạm vi chuẩn tắc; phần đối sánh bên dưới thì không. - Đối sánh đường dẫn (theo từ vựng, hai chiều). Một đường dẫn đã khai và một đường dẫn của tác vụ khớp nhau khi, sau khi chuẩn hoá (kiểu POSIX, tương đối từ gốc, không
./ở đầu, bỏ mọi dấu/ở cuối), hai chuỗi bằng nhau, hoặc chuỗi này là tổ tiên theo tiền tố đường dẫn của chuỗi kia: chuỗi ngắn hơn bằng đúng chuỗi dài hơn khi cắt tại một ranh giới/. Việc đối sánh là thuần tuý từ vựng: nó không bao giờ tra hệ tệp, và nó không phân biệt một đường dẫn trỏ tới tệp với một đường dẫn trỏ tới thư mục, vì sau khi chuẩn hoá thì hai thứ đó không phân biệt được. Đây là quan hệ bao hàm theo cả hai chiều (chính là quan hệunderPathmà các bản hiện thực tham chiếu dùng chung), nên một tác vụ có phạm vi rộng và một bộ chọn khai báo hẹp vẫn tìm thấy nhau, bất kể bên nào rộng hơn. - Đối sánh danh mục (theo nghĩa hẹp), và hai tập danh mục. Các danh mục của một tác vụ chia thành được nở ra và được phát tín hiệu. Một danh mục mà tác vụ nêu tên tường minh thì vào cả hai tập. Một đường dẫn của tác vụ mà tự nó đã là một tài liệu được quản trị (khớp với mục index sinh ra của nó theo đẳng thức chính xác, không bao giờ theo quan hệ bao hàm) sẽ đóng góp danh mục của mục đó vào chỉ tập được phát tín hiệu. Các danh mục được nở ra sẽ nạp tài liệu chủ ý và các ứng viên bản ghi của chúng; các danh mục được phát tín hiệu chỉ là tín hiệu đối sánh cho quyết định và cho mount federation, và tự chúng không nạp gì cả. Một bộ chọn danh mục MUST NOT suy ra danh mục cho một tệp bất kỳ trong kho mã nguồn, và một đường dẫn của tác vụ mà tự nó không phải một tài liệu được quản trị, kể cả mọi thư mục tổ tiên của một tài liệu như vậy, thì không đóng góp danh mục nào cả. Phạm vi theo đường dẫn với tới các tệp; việc nở danh mục thì không đi theo nó.
- Đối sánh chủ đề (chính xác, chỉ dành cho mount). Một chủ đề là một chuỗi không rỗng gồm các Unicode scalar value, được so sánh theo mã hoá UTF-8 của nó; một surrogate đứng lẻ không phải một chủ đề hợp lệ. Cả hai phía đều bị ràng theo quy tắc đó: một chủ đề của tác vụ hoặc một mục trong
topicscủa một mount mà không phải chuỗi không rỗng gồm các Unicode scalar value là một lỗi đầu vào, và một bản hiện thực MUST từ chối nó chứ không trả về như một lần không khớp âm thầm. Một chủ đề của tác vụ khớp với một chủ đề đã khai khi hai chuỗi đã giải mã bằng nhau chính xác. Các bản hiện thực MUST NOT đổi hoa thường, chuẩn hoá Unicode, so sánh theo locale, cắt khoảng trắng, tách token, đối sánh chuỗi con hay đối sánh mờ ở bất kỳ phía nào, nên những cách viết tương đương chính tắc nhưng khác byte thì không khớp; quy tắc đẳng thức này tách bạch với việc sắp thứ tự theo byte của kết quả bên dưới. Các chủ đề trùng nhau của tác vụ hợp thành một tín hiệu duy nhất, nên nêu một chủ đề hai lần cũng khớp y hệt như nêu một lần. Một mount federation khớp khi bất kỳ chủ đề nào của tác vụ bằng bất kỳ chủ đề nào mà mount đó khai. Một lần khớp chủ đề chỉ chọn ra mount mà thôi: nó MUST NOT đi vào tập danh mục được nở ra hay được phát tín hiệu, không nạp tài liệu hay bản ghi nào, không định tuyến quyết định nào, không đánh giárequiredWhen, và không làm cho một mount trở thành bắt buộc. - Bộ lọc trạng thái. Chỉ bản ghi quyết định nào có
statuscòn ràng buộc mới được định tuyến như hướng dẫn hiện hành.acceptedvàdeprecatedthì ràng buộc; một bản ghideprecatedràng buộc với một tư thế đã cũ, và một agent MUST coi nó là hướng dẫn đang trên đường rút lui chứ không phải thực hành hiện hành đã yên vị. Một bản ghisupersededMUST NOT ràng buộc, trừ với tư cách lịch sử, và MUST mangsupersededBy; các bản ghiproposedvàrejectedMUST NOT ràng buộc. Một bản ghi còn ràng buộc thì gọi là còn hiệu lực. - Quyết định không phạm vi. Một bản ghi quyết định còn hiệu lực mà không khai cả
affectedPathslẫnaffectedCategorieslà quyết định ở mức toàn tổ chức: nó được định tuyến cho mọi tác vụ, bất kể phạm vi của tác vụ là gì. Các quyết định còn hiệu lực có phạm vi thì chỉ được định tuyến khi tác vụ khớp với chúng theo đường dẫn (mục 2) hoặc theo danh mục (mục 3). - Phạm vi đường dẫn rỗng, và phạm vi rỗng. Khi tập đường dẫn của tác vụ là rỗng, việc đối sánh đường dẫn không đóng góp gì và một agent MUST nói rõ rằng phần định tuyến theo đường dẫn đã không được đánh giá; các danh mục được nêu tên tường minh vẫn được tôn trọng và vẫn nở ra, còn các chủ đề được nêu tên tường minh vẫn được đối sánh. Danh mục được nêu tên và chủ đề được nêu tên đều tính là làm cho phạm vi trở nên không rỗng. Toàn bộ phạm vi của tác vụ chỉ rỗng khi nó không nêu đường dẫn nào, không nêu danh mục nào, và không nêu chủ đề nào; khi đó agent chỉ định tuyến phần ngữ cảnh vô điều kiện của boot profile và agent profile, cộng với các quyết định còn hiệu lực không phạm vi ở mức toàn tổ chức. Một agent MUST NOT trình bày một lần nạp không định tuyến như thể nó có phạm vi.
- Bản ghi được định tuyến như ứng viên. Một danh mục được nở ra sẽ định tuyến các tài liệu chủ ý của nó như ngữ cảnh bắt buộc; còn các bản ghi của danh mục đó được trả về riêng, mỗi bản kèm loại và ngày của nó, như những ứng viên mà người đọc nạp theo phán đoán của mình. Một bản ghi chỉ trở thành bắt buộc khi đường dẫn của tác vụ chọn thẳng nó theo mục 2, khi một agent hay boot profile nêu tên nó, hoặc khi một người yêu cầu nó; việc khớp danh mục, hay việc mang ngày mới nhất, không bao giờ làm cho một bản ghi trở thành bắt buộc. Ở nơi một bản ghi vừa là ứng viên theo danh mục vừa được chọn trực tiếp theo đường dẫn, thì lựa chọn trực tiếp thắng và nó là bắt buộc. Việc định tuyến MUST NOT chứng nhận bản ghi nào là “mới nhất” hay “bản hiện hành”: 1.0 không định nghĩa danh tính hay bảo đảm về thứ tự cho một chuỗi bản ghi, nên phán đoán về độ mới thuộc về người đọc, dựa trên những ngày mà index làm nổi lên. Bản ghi quyết định giữ cách định tuyến riêng của chúng (mục 5 và 6) và không bao giờ được định tuyến như bản ghi thông thường. Việc nêu tên một tệp quyết định như một đường dẫn của tác vụ không định tuyến quyết định đó; phạm vi mà nó khai báo mới làm việc ấy.
- Trích dẫn. Một agent có nạp các bản ghi quyết định đã định tuyến MUST trích dẫn những bản ghi đã khớp mà nó nạp, để người đọc thấy được agent đã áp dụng hướng dẫn nào và suy ra được nó đã không áp dụng những gì.
Lát cắt đã định tuyến là những gì một agent nạp cho một tác vụ. Nó là hợp của: tập nạp vô điều kiện của boot profile và requiredRead của agent profile đang hoạt động, thứ mà agent giữ như phần nền độc lập với mọi phạm vi; mọi tài liệu chủ ý được quản trị trong một danh mục được nở ra; mọi mục được quản trị mà đường dẫn của tác vụ chọn theo mục 2; mọi bản ghi được chọn trực tiếp theo đường dẫn theo mục 8; và mọi quyết định còn hiệu lực mà tác vụ khớp theo đường dẫn hoặc theo một danh mục được phát tín hiệu hay được nở ra, cộng với các quyết định còn hiệu lực không phạm vi ở mức toàn tổ chức.
Các danh mục được phát tín hiệu chỉ đóng góp việc đối sánh, cho quyết định và cho mount federation, và không bao giờ nở ra một kho ngữ liệu nào.
Lát cắt không đồng nghĩa với toàn bộ gói kết quả. Công cụ tính kết quả định tuyến sẽ trả về lát cắt cùng phần tài liệu mà agent không được nạp khi chưa có yêu cầu: các ứng viên bản ghi và siêu dữ liệu định tuyến đi kèm. Nạp toàn bộ gói kết quả sẽ làm mất đi mục đích của việc định tuyến.
Thứ tự kết quả là chuẩn tắc ở nơi một công cụ có phát ra kết quả, để các bản hiện thực độc lập nhất trí với nhau tới từng byte: danh mục theo đúng thứ tự danh mục chính tắc của bản đặc tả này; tài liệu, bản ghi và quyết định theo đường dẫn tăng dần; mount theo tên tăng dần. Việc so sánh chuỗi là theo byte trên UTF-8, không phụ thuộc vào locale hay vào phép đối chiếu theo codepoint.
Công cụ MAY cung cấp một hàm trợ giúp tính ra lát cắt này từ một tập đường dẫn; các bản hiện thực tham chiếu có phơi ra một hàm như vậy (route). Một hàm như thế tính phần phụ thuộc phạm vi và không bắt buộc phải phát ra phần nền, vốn là thứ bên gọi đã cầm sẵn; nghĩa vụ nạp phần nền đó của agent thì không đổi. Việc định tuyến là tuân thủ bất cứ khi nào một người đọc thô đi theo đúng thuật toán này.
Ghi chú (tham khảo)#
Công cụ tham chiếu hôm nay kiểm schema của changelog và kỷ luật chỉ thêm mới (leji validate chạy cả hai); còn việc xác minh độ phủ của changelog so với một phiên bản gốc, tức mọi đường dẫn được quản trị đã đổi đều xuất hiện trong một mục được ghi thêm, là một phép kiểm dạng báo cáo còn nằm trong lộ trình, chưa phải một cổng chặn. Cho tới khi có nó, độ phủ dựa vào kỷ luật xem xét và CI được khai theo quy trình (xem conformance.md).
Index là nguồn điều hướng cho phần ngữ cảnh được quản trị: leji viewer dùng index để dựng bộ khung của phần này, rồi đặt cây thư mục của kho mã nguồn bên dưới như một vùng tham khảo có thể xem xét. Nhờ đó, cùng một khung nhìn cho thấy cả ngữ cảnh được quản trị lẫn hệ thống điều hướng sẵn có của nhóm. Bất kỳ công cụ tài liệu nào cũng có thể trình bày index theo cách tương tự. Cách trình bày không mang tính chuẩn tắc. Bề mặt này được chủ ý giữ nhỏ. Năm hình thái đủ để công cụ kiểm tra lớp ngữ cảnh, so sánh thay đổi, đánh giá độ tươi và định tuyến agent tới đúng lát cắt, đồng thời vẫn đủ gọn để cả nhóm ghi nhớ. Mọi thứ vượt ra ngoài năm hình thái này đều thuộc giai đoạn sau 1.0 và phải chờ thực tiễn chứng minh.