Harness Academy
Tài liệu gốc 14 15 phútTiếng Việt + English
docs/adr/0004-milestone-3-skills.mdXem bản gốc
Ngôn ngữ bài đọc
Bản dịch tiếng Việt

Bản dịch đầy đủ theo đúng cấu trúc tài liệu; code, liên kết và định danh kỹ thuật được giữ nguyên.

0004. Cột mốc 3 - Kỹ năng (tiết lộ tiến bộ)

Trạng thái: Đã chấp nhận Ngày: 2026-06-25

Bối cảnh

Các mốc quan trọng 1 và 2 đã vận chuyển một agent vani (ADR-0002) và một hệ thống cấp phép + Danh mục agent (ADR-0003). Mô hình hiện chạy lời nhắc hệ thống cho mỗi người với danh sách cho phép sử dụng công cụ cho mỗi tổng đài viên, tất cả đều ở trạng thái cưỡi ngựa AgentDeps và sự năng động @agent.instructions móc (bộ nhớ + dấu nhắc agent).

Cột mốc 3 bổ sung Kỹ năng: tài liệu hướng dẫn có thể tái sử dụng, được đặt tên mà mô hình (hoặc người dùng) có thể lấy vào theo yêu cầu - một commit kỹ năng thực hiện và cam kết cây làm việc, một review-diff kỹ năng đó đánh giá nó và bất kỳ kỹ năng nào do dự án tạo ra mà một nhóm đưa vào repository của họ. Vấn đề thiết kế là chi phí: chúng tôi muốn có sẵn một thư viện kỹ năng mà không phải trả toàn bộ chi phí token cho mỗi lượt.

Về mặt cấu trúc, các kỹ năng gần giống với Danh mục agent (bao gồm Markdown + YAML frontmatter, một trình tải/trình xác thực, dữ liệu được đóng gói qua importlib.resources, khám phá dự án cục bộ như bộ nhớ), vì vậy cột mốc quan trọng này phản ánh rằng máy móc thay vì phát minh ra các mẫu mới. Hình dạng trên đĩa là Quy ước về thư mục Kỹ năng của agent — mỗi kỹ năng là một thư mục <name>/SKILL.md điều đó có thể gửi các tệp tài nguyên được đóng gói - đã sửa lỗi này từ bản nháp tệp phẳng ban đầu trước cột mốc này sáp nhập. Các quyết định dưới đây đã bị con người nướng và khóa qua hai vòng; chúng có liên quan với nhau (cơ chế quyết định hình dạng thực thể, các nguồn chỉ ra mức độ ưu tiên, quy tắc tất cả các agent chỉ ra cách nối dây công cụ, hai điểm nhập chia sẻ một trình phân giải), vì vậy chúng được ghi lại dưới dạng một cột mốc ADR — phản ánh ADR-0002 và ADR-0003. Phân tích nhiệm vụ theo thứ tự nằm trong tasks/ (đặc điểm skills); ADR này ghi lại tại sao. Xem ADR-0002, ADR-0003.

Hai dữ kiện khung được sử dụng lại không thay đổi từ ADR-0003 (được xác minh dựa trên pydantic-ai 1.107): a năng động @agent.instructions hàm được gọi mỗi lần chạy tại thời điểm xây dựng dấu nhắc và có thể đọc ctx.deps; một công cụ prepare= gọi lại quay trở lại None ẩn một công cụ cho lần chạy hiện tại. Cả hai đã trở lại các móc nhắc bộ nhớ/agent và hạn chế công cụ cho mỗi agent - Các kỹ năng bắt vít vào hai đường nối giống nhau. Bề mặt đầu vào duy nhất của TUI và /agent / /mode phân tích lệnh gạch chéo (ADR-0003 §9) là điểm tái sử dụng thứ ba - /<skill-name> lệnh phản chiếu chúng.

Quyết định

  1. Cơ chế = tiết lộ lũy tiến theo BA cấp. (a) Cấp 1 — Danh mục kỹ năng: mỗi kỹ năng name + một dòng description, được đưa vào dấu nhắc hệ thống bằng một lệnh động @agent.instructions hook, luôn hiện diện, giá rẻ và không có đường dẫn (không có thư mục nào chứa lời nhắc luôn bật). (b) Cấp 2 — Cơ quan điều phối kỹ năng: skill(name) công cụ (và của người dùng /<skill-name> command) trả về kỹ năng đó đầy đủ SKILL.md Phần thân Markdown chỉ theo yêu cầu. Đối với cấp 1–2, chúng tôi giữ mô hình cơ thể trả lại của người điều phối (KHÔNG phải "mô hình readlà một tệp kỹ năng", kiểu Pi): danh mục là menu, bộ điều phối là điểm nhập được gõ duy nhất và mô hình không bao giờ cần đường dẫn trên đĩa của kỹ năng để gọi nó. (c) Cấp 3 — tài nguyên đi kèm: kỹ năng của dự án SKILL.md cơ thể có thể tham khảo tập tin anh chị em theo đường dẫn tương đối (references/, examples/, scripts/, …) mà mô hình chỉ tải ** khi nó hành động**, thông qua sự bình thường của nó read/bash công cụ. Cầu từ tầng 2 đến tầng 3 ngắn đoạn giới thiệu tài nguyên được thêm vào nội dung được trả lại — chỉ khi kỹ năng thực sự được gói kèm tài nguyên (tích hợp sẵn chỉ có SKILL.md, §3): nó đặt tên cho thư mục của kỹ năng (a read-có thể giải quyết được, cwd-relative path) để mô hình biết đọc từ đâu. Kỹ năng dự án tích hợp hoặc không cần tài nguyên trả về phần nội dung với đoạn giới thiệu no, do đó, lớp đọc tệp sẽ hiển thị chính xác khi có một cái gì đó để đọc. Do đó, Cấp 3 là tính năng kỹ năng dự án.

  2. Chữ ký của người điều phối là skill(name) chỉ - không args. Phiên bản v1 lười biếng: không có kỹ năng tích hợp nào cần các đối số có cấu trúc và ý định dạng tự do có thể nằm trong nội dung hoặc dấu gạch chéo ở cuối của người dùng văn bản (quyết định 5). Thêm một args tham số sau này là phụ gia và không thay đổi trình phân giải.

  3. Hình dạng trên đĩa = quy ước thư mục <name>/SKILL.md; hai nguồn; tên từ frontmatter; dự án có chủ ý ghi đè (chuyển đổi cứng - không có định dạng phẳng). Kỹ năng là một thư mục chứa một SKILL.md (Vật chất phía trước YAML + phần thân); trình tải chỉ nhận ra ** <name>/SKILL.md thư mục - không có căn hộ nào <name>.md hỗ trợ (đây là sự hợp nhất trước, vì vậy không có định dạng phát hành nào bị hỏng và không có có miếng chêm tương thích). Các kỹ năng tích hợp được gửi dưới dạng các thư mục được đóng gói bên dưới src/decode/skills/builtin/<name>/SKILL.md (đi bộ qua importlib.resources.files("decode.skills.builtin") vào từng thư mục con, phản ánh chính xác agents/builtin/) và chỉ SKILL.md (tài nguyên của họ sẽ không thể đọc được trong các gói trang web, vì vậy cấp 3 là tính năng kỹ năng dự án - §1). Kỹ năng dự án-địa phương được phát hiện tại <cwd>/.decode/skills/<name>/SKILL.md (đường dẫn qua settings.skills_dir, đĩa đơn config reader) và có thể gửi các thư mục/tệp tài nguyên anh chị em (references/, examples/, scripts/hoặc bất cứ điều gì) được tải theo yêu cầu. Tên ** của một kỹ năng xuất phát từ name: frontmatter**, không phải thư mục tên — tên thư mục là mỹ phẩm: skills/foo/SKILL.md với name: commit là là commit kỹ năng. Tên thư mục ≠ tên frontmatter không khớp vẫn tải (được khóa bởi frontmatter name) nhưng là đã đăng nhập tại CẢNH BÁO, để bắt các phiếu sao chép-dán. Khi xảy ra xung đột tên, kỹ năng project-local ghi đè phần tích hợp cùng tên; ghi đè này là có chủ ý và im lặng (một nhóm bóng tối commit/review-diff với những quy ước riêng của họ), với source trường giữ nó có thể theo dõi được trong nhật ký. Lỗi phân tích cú pháp tích hợp tăng lên rõ rệt (lỗi đóng gói của chúng tôi); một dự án không đúng định dạng/không thể đọc được SKILL.mdvà một thư mục con không có SKILL.md, được ghi lại tại CẢNH BÁO và bị bỏ qua (lỗi đánh máy của người dùng không bao giờ ngắt phiên — phản ánh trạng thái không thể đọc được của bộ nhớ và người dùng settings.json khoan dung).

  4. Tất cả các agent nhìn thấy tất cả các kỹ năng; người điều phối phải ở trong mỗi agent tools. Không có agent mới trường frontmatter - danh mục đầy đủ được đưa vào cho mọi agent. Nhưng sổ đăng ký ẩn mọi công cụ không có trong agent đang hoạt động tools danh sách cho phép (_restrict_to_active_agent), vậy skill được thêm vào tất cả bốn agent tích hợp (build, plan, explore, code-reviewer) — nếu không thì danh mục sẽ quảng cáo kỹ năng mô hình không có công cụ để tải.

  5. Hai điểm vào, một trình phân giải, một tải trọng. Một kỹ năng có thể được kích hoạt theo hai cách, cả hai đều có khả năng giải quyết thông qua cùng một load_skills(cwd) và giống nhau format_skill_payload(skill, cwd) người trợ giúp cho giống hệt tải trọng — nội dung, cộng với đoạn giới thiệu tài nguyên khi (và chỉ khi) kỹ năng mang theo tài nguyên đi kèm (quyết định 1, §6):

    • model — cái skill(name) công cụ điều phối (quyết định 1); tải trọng trả về dưới dạng kết quả của công cụ.
    • Người dùng — a /<skill-name> lệnh được nhập vào TUI (ví dụ: /commit, /review-diff), phản ánh hiện tại /agent / /mode phân tích cú pháp trên bề mặt đầu vào duy nhất; tải trọng tương tự được đưa vào như chuyển đầu vào (văn bản theo sau tùy chọn sau khi tên được thêm vào) và mô hình sẽ tuân theo nó thông qua đường dẫn gửi thông thường. Các lệnh TUI tích hợp giành chiến thắng (/quit, /agent, /mode lấy ưu tiên; /resume là cờ CLI, không phải lệnh TUI) - một kỹ năng va chạm với tên dành riêng là vẫn có thể truy cập được thông qua người điều phối. Không được công nhận /<x> đó không phải là dành riêng cũng không được biết đến kỹ năng hiển thị một dòng thân thiện liệt kê các kỹ năng có sẵn (không có lượt), tăng gấp đôi khi khám phá.
  6. SkillDef = các lệnh được chèn thuần túy (+ một con trỏ tài nguyên tùy chọn). Thực thể (entities/skill_def.py, gương đóng băng + có rãnh, tự xác thực) AgentDef nhưng cắt theo M3 thực tế: name, description, body, a source trường xuất xứ (vì vậy ghi đè dự án là có thể theo dõi) và tùy chọn resource_dir: Path | None = None - kỹ năng dự án thư mục tài nguyên đi kèm iff thư mục đó chứa bất cứ thứ gì ngoài SKILL.md, khác None (kỹ năng dự án tích hợp và không cần tài nguyên). Đó là bit duy nhất mà người điều phối đọc để quyết định có nên nối thêm đoạn giới thiệu tài nguyên hay không (quyết định 1). Không tools/mode/allow/deny trường - một kỹ năng là sự hướng dẫn mà mô hình tuân theo, không phải là cá nhân hay mật mã; thực thể không bao giờ chạm vào hệ thống tập tin (bộ tải resource_dir).

  7. Người điều phối không có mã số; các hành động mà một kỹ năng gây ra thì không. skill(ctx, name) đã được đăng ký như ToolKind.OTHER nhưng, giống như ask_user / sleep / enter_plan_mode, không bao giờ tăng ApprovalRequired, vì vậy nó không bao giờ đến được cổng cấp phép — hướng dẫn tải là vô hại. Một tên không rõ tăng ModelRetry liệt kê các kỹ năng sẵn có Điều quan trọng là, hủy hoại người điều phối không hủy bỏ hành động mà kỹ năng mô tả. commit kỹ năng là ví dụ điển hình: nó yêu cầu mô hình chạy git add và git commit, đi qua cổng bash công cụ - vì vậy trong chế độ mặc định, người dùng vẫn phê duyệt từng lệnh gọi git và ở chế độ kế hoạch, cam kết bị từ chối. Kỹ năng thay đổi những gì mô hình được yêu cầu, không bao giờ những gì nó được phép làm.

  8. Hai kỹ năng tích hợp, với các cấu hình tác dụng phụ khác nhau. commit đang hoạt động: nó kiểm tra cây làm việc, sắp xếp các tệp thích hợp, soạn thông báo Cam kết thông thường và chạy git commit — cam kết chính xác những gì nó đã dàn dựng (tất cả các hoạt động git thông qua cổng kiểm soát bash công cụ, theo quyết định 7). review-diff là tư vấn / chỉ đọc: nó đọc git diff và báo cáo lỗi + kỹ thuật quá mức và không chỉnh sửa hoặc cam kết. Cả hai đều là phần hướng dẫn Markdown của mô hình theo sau, không phải mã thực thi.

  9. Dây điện tái sử dụng các đường nối hiện có. assemble_skills_catalog(cwd) (trong skills/catalog.py) định dạng thực đơn và quay trở lại "" khi trống (không có tiêu đề trống), giống hệt như assemble_memory. Một cái mới _register_skills_catalog_instructions móc vào agent/factory.py tiêm nó mỗi lần chạy từ ctx.deps.cwd, cùng với các móc nhắc bộ nhớ và agent. Người điều phối là một nữa ToolSpec trong sổ đăng ký căn hộ; TOOL_KIND / KNOWN_TOOL_NAMES lấy được skill tự động. các /<skill-name> lệnh là một trình phân tích cú pháp thuần túy hơn (parse_skill_command) + trình xử lý trong tui/app.py, sau /agent / /mode chi nhánh.

  10. Trì hoãn (rõ ràng không có mục tiêu cho cột mốc này): a ~/.decode/skills Nguồn user-home (cái này bước chỉ dành cho dự án cục bộ); danh sách cho phép kỹ năng của mỗi agent (tất cả các agent đều thấy tất cả các kỹ năng — không có cho mỗi agent trường phạm vi); giới hạn kích thước cơ thể (các kỹ năng được tác giả tin cậy và nhỏ, không giống như mô hình duy trì MEMORY.md cái nào được giới hạn); và ** có cấu trúc args** về người điều phối (quyết định 2). Mỗi cái là một phần mở rộng bổ sung, không phải là viết lại: nguồn gốc là một tầng khám phá nữa trong quá trình hợp nhất, một danh sách cho phép là một trường quan trọng hơn, giới hạn là một cuộc gọi clip, args là một tham số công cụ nữa.

  11. Kỷ luật (không thay đổi từ ADR-0002/0003/AGENTS.md). filterwarnings=["error"], nhận biết UTC ngày giờ, bao gồm cả chú thích kiểu đầy đủ. -> None, nhật ký mã thư viện (không bao giờ print()), cơ sở hạ tầng nhập khẩu-không-trừu tượng, tests/ gương src/ 1:1, TDD-first, không có mạng trong CI (FunctionModel). PyYAML đã là phần phụ thuộc được khai báo (ADR-0003 §10) — không có phần phụ thuộc mới.

Sơ đồ

Tiết lộ lũy tiến ba cấp — danh mục giá rẻ luôn được nhắc nhở (cấp 1, không có đường dẫn); gọi một kỹ năng (người điều phối mô hình hoặc người dùng /<skill>) trả về phần thân SKILL.md (cấp 2); khi nào - và chỉ khi - kỹ năng mang các tài nguyên đi kèm, đoạn giới thiệu sẽ đặt tên cho thư mục của nó để mô hình tải những tài nguyên đó tập tin theo yêu cầu thông qua cổng read/bash công cụ (cấp 3). Tích hợp dừng ở cấp 2; kỹ năng dự án có thể đạt cấp 3. Ghi đè dự án tích hợp sẵn và các hành động vẫn bị kiểm soát không thay đổi.

flowchart TD
    subgraph t1["Tier 1 — system prompt (every turn, cheap, paths-free)"]
        catalog["Skills Catalog<br/>name + description list<br/>via @agent.instructions"]:::menu
    end

    user["User types /&lt;skill&gt; in the TUI"]:::user
    model["Model decides it needs a skill<br/>(prompted by the catalog)"]:::model

    disp["skill(name) — Skill Dispatcher<br/>(ungated tool)"]:::tool
    slash["/&lt;skill-name&gt; TUI command<br/>(reserved cmds win)"]:::tool

    load["load_skills(cwd)<br/>scan &lt;name&gt;/SKILL.md<br/>name from frontmatter"]:::loader
    builtin[("built-in skills<br/>decode/skills/builtin/&lt;name&gt;/SKILL.md<br/>SKILL.md-only")]:::store
    project[("project skills<br/>&lt;cwd&gt;/.decode/skills/&lt;name&gt;/SKILL.md<br/>+ optional bundled resources")]:::store

    subgraph t2["Tier 2 — body on demand"]
        payload["format_skill_payload(skill, cwd)"]:::body
        body["SKILL.md body"]:::body
        trailer{"resource_dir set?<br/>(dir has files besides SKILL.md)"}:::rule
        bodyonly["body only (no trailer)"]:::body
        bodytrail["body + trailer naming &lt;dir&gt;/"]:::body
    end

    subgraph t3["Tier 3 — bundled resources (project skills only)"]
        res[("references/ · examples/ · scripts/")]:::store
        read["read('&lt;dir&gt;/references/x.md')<br/>or bash('&lt;dir&gt;/scripts/...')<br/>STILL pass the permission gate"]:::gate
    end

    catalog --> model --> disp
    user --> slash
    disp --> load
    slash --> load
    builtin --> load
    project --> load
    load --> payload --> body --> trailer
    trailer -- "no (built-in / resource-less)" --> bodyonly
    trailer -- "yes (project w/ resources)" --> bodytrail
    bodytrail -- "model follows the body" --> read
    res --> read

    classDef menu fill:#1e293b,stroke:#0ea5e9,color:#bae6fd
    classDef user fill:#334155,stroke:#ec4899,color:#fbcfe8
    classDef model fill:#334155,stroke:#a855f7,color:#e9d5ff
    classDef tool fill:#713f12,stroke:#eab308,color:#fef9c3
    classDef loader fill:#0f172a,stroke:#64748b,color:#cbd5e1
    classDef store fill:#1e293b,stroke:#f59e0b,color:#fde68a
    classDef rule fill:#334155,stroke:#f59e0b,color:#fde68a
    classDef body fill:#14532d,stroke:#22c55e,color:#dcfce7
    classDef gate fill:#7f1d1d,stroke:#ef4444,color:#fee2e2

hậu quả

  • Danh mục hỗ trợ mọi lời nhắc — và không có đường dẫn. Chi phí nhỏ, luôn hiện hữu (tên + mô tả, không có thư mục); chi phí cơ thể chỉ được thanh toán khi có yêu cầu và tài nguyên đi kèm thư mục chỉ được đặt tên trong đoạn giới thiệu của người điều phối (cấp 2→3), không bao giờ có trong lời nhắc luôn bật. Bởi vì các phần mềm cài sẵn luôn được vận chuyển, danh mục không bao giờ trống trong thực tế — ""-khi hợp đồng trống là đối xứng phòng thủ với assemble_memory.
  • Tất cả bốn agent tích hợp đều có được một skill công cụ. Của họ tools danh sách tăng lên một (ví dụ: build 12 → 13); bất kỳ thử nghiệm danh mục agent nào ghim số lượng công cụ chính xác đều phải cập nhật. Một agent tùy chỉnh có tools bỏ qua skill sẽ có các kỹ năng quảng cáo danh mục mà nó không thể tải - do đó tất cả các phần mềm tích hợp sẵn bao gồm nó; phạm vi kỹ năng của mỗi agent là một phần mở rộng bị trì hoãn.
  • commit tự chủ nhưng vẫn bị kiểm soát. Nó thực hiện và cam kết mà không có "chỉ soạn thảo" riêng biệt bước này, tuy nhiên mọi lệnh gọi git đều đi qua bước hiện có bash cổng - vì vậy chế độ mặc định vẫn hỏi và lập kế hoạch chế độ vẫn từ chối. Đây là lý do tương tự mà móng guốc ask_user/sleep/enter_plan_mode: cái người điều phối là một tín hiệu thuần túy, các tác dụng phụ giữ cổng của họ.
  • Hai điểm vào, một trọng tải. Người dùng có thể bắn một kỹ năng bằng /commit và mô hình có thể bắn cùng kỹ năng với skill("commit") - cả hai đều giải quyết thông qua load_skills và giống nhau format_skill_payload(skill, cwd) người trợ giúp, do đó có một nguồn sự thật, một quy tắc ghi đè và một body(+trailer) hai con đường không thể tách rời nhau. Đường dẫn người dùng lần lượt đưa tải trọng vào; cái đường dẫn mô hình trả về nó dưới dạng kết quả công cụ.
  • Đoạn giới thiệu tài nguyên có điều kiện nên trường hợp thông thường vẫn gọn gàng. Một kỹ năng không có tập tin đi kèm trả lại chính xác phần thân của nó - không có tiếng ồn của xe kéo. Mô hình chỉ nghe về thư mục tài nguyên khi một cái tồn tại và nó vừa chọn tải kỹ năng đó, sau đó nó đọc các tệp đó thông qua trình duyệt thông thường. có cổng read/bash công cụ (cấp 3 không cấp quyền mới - cổng vẫn chi phối mọi thao tác đọc/thực thi). Các kỹ năng tích hợp và dự án khác nhau một cách có chủ ý theo khả năng: các phần tích hợp chỉ dành cho SKILL.md (cấp 2 max), vì các tệp của họ sẽ không thể đọc được trong các gói trang web; kỹ năng dự án có thể mang theo tài nguyên cấp 3.
  • Một kẻ đi lạc /foo bây giờ liệt kê các kỹ năng thay vì đi đến mô hình. Trước đây là dấu gạch chéo không được nhận dạng rơi vào runner.submit("/foo", …); với /<skill-name> nhánh nó bị chặn bởi một dòng khám phá kỹ năng sẵn có (không rẽ). Cải tiến UX có chủ ý - SWE cập nhật mọi bài kiểm tra TUI dựa vào sự thất bại cũ.
  • Kỹ năng dự án ghi đè lên các phần dựng sẵn, một cách âm thầm và có chủ ý. Một nhóm bóng tối commit/review-diff bằng cách thả một-name nộp hồ sơ vào <cwd>/.decode/skills/; source làm cho xuất xứ có thể nhìn thấy được trong logs nên việc ghi đè không bao giờ là điều bí ẩn.
  • SkillDef cố tình mỏng hơn AgentDef. Không có công cụ/chế độ/quy tắc nào — chỉ name, description, body, source, và một tùy chọn resource_dir (con trỏ tài nguyên đi kèm người điều phối đọc để quyết định trailer). Việc thêm bất kỳ trường nào sau này là một phần bổ sung cho trình tải đã chấp nhận (các khóa phía trước không xác định bị bỏ qua), tương thích về phía trước.
  • Các đường nối còn lại cho các mốc quan trọng sau: a ~/.decode/skills nguồn trang chủ của người dùng, danh sách cho phép kỹ năng của mỗi agent, một nắp kích thước cơ thể kỹ năng (song song với MEMORY.md cap) và bộ điều phối có cấu trúc args - mỗi chất phụ gia.
  • Rủi ro cần xác nhận trong quá trình triển khai: con giống vận chuyển ổ skills/builtin/<name>/SKILL.md các tập tin dữ liệu trong bánh xe (mặt phẳng *.md được vận chuyển theo mặc định - xác minh lại bố cục thư mục với uv build + unzip -l; nếu dữ liệu lồng nhau bị bỏ qua, hãy thêm một bánh xe rõ ràng artifacts/include toàn cầu như src/decode/skills/builtin/**/*.md, không đi lạc __init__.py tập tin); đó importlib.resources duyệt qua các thư mục con tích hợp (iterdir/is_dir/joinpath/read_text trên Traversable) từ bánh xe được lắp đặt cũng như trong cây; mà văn bản nhắc danh mục bổ sung thực hiện không làm phiền test_milestone1_capstone.py (nó xác nhận kết quả của công cụ + bản ghi được hiển thị, không phải lời nhắc chính xác văn bản); rằng /<skill-name> nhánh ngồi chính xác sau /agent//mode nên các lệnh dành riêng luôn giành chiến thắng trên bề mặt đầu vào duy nhất; rằng xe kéo sẽ vạch ra một con đường read/bash công cụ chấp nhận (cwd-tương đối, trong cwd); và kỹ năng dự án có cùng tên với kỹ năng được tích hợp sẵn sẽ ghi đè rõ ràng thông qua load_skills cho cả hai điểm vào (capstone ghim điểm này).
Mục lục nguồn