@kaddo/cli 3.20.0 → 3.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/dist/index.js +525 -77
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -505,6 +505,9 @@ create --from roadmap → owners → guard → explain`.
|
|
|
505
505
|
| v3.16 | Knowledge Capsules: `kaddo capsule export/add`, External Knowledge in context/explain, new `capsule-agent` |
|
|
506
506
|
| v3.17 | Knowledge Graph Export: `kaddo graph export` (`.kaddo/graph.json` + `.mmd`, `--scope`/`--format`); graph summary in context/explain |
|
|
507
507
|
| v3.18 | Graph relationship quality & metadata hints: `graph-hints.md`/`.json`, quality levels, `graph-agent`; hints in context/explain/understand |
|
|
508
|
+
| v3.19 | Read-only MCP server `@kaddo/mcp` (resources, tools, prompts over stdio) |
|
|
509
|
+
| v3.20 | MCP derived tools: safe regeneration of context/explain/understand/graph/capsule-draft under `.kaddo/` |
|
|
510
|
+
| v3.21 | Reusable Skills layer (`kaddo add skills`); skills in context/explain/understand, agent prompts and MCP |
|
|
508
511
|
|
|
509
512
|
**Optional modules (installed with `kaddo add`):**
|
|
510
513
|
|
package/dist/index.js
CHANGED
|
@@ -1487,6 +1487,386 @@ var guardAdvancedModule = {
|
|
|
1487
1487
|
]
|
|
1488
1488
|
};
|
|
1489
1489
|
|
|
1490
|
+
// src/skills/skills.ts
|
|
1491
|
+
function skill(id, title, group, appliesTo, body) {
|
|
1492
|
+
const frontMatter2 = [
|
|
1493
|
+
"---",
|
|
1494
|
+
"type: skill",
|
|
1495
|
+
`id: ${id}`,
|
|
1496
|
+
`title: ${title}`,
|
|
1497
|
+
"version: 1",
|
|
1498
|
+
`group: ${group}`,
|
|
1499
|
+
"applies_to:",
|
|
1500
|
+
...appliesTo.map((a) => ` - ${a}`),
|
|
1501
|
+
"---",
|
|
1502
|
+
""
|
|
1503
|
+
].join("\n");
|
|
1504
|
+
return { id, title, group, appliesTo, content: frontMatter2 + body.trimStart() };
|
|
1505
|
+
}
|
|
1506
|
+
var ADR_WRITING = skill(
|
|
1507
|
+
"adr-writing",
|
|
1508
|
+
"ADR Writing Skill",
|
|
1509
|
+
"tech",
|
|
1510
|
+
["decision-agent", "architecture-agent", "implementation-agent"],
|
|
1511
|
+
`
|
|
1512
|
+
# ADR Writing Skill
|
|
1513
|
+
|
|
1514
|
+
## Purpose
|
|
1515
|
+
|
|
1516
|
+
Standardize how Architecture Decision Records are written so every decision is captured the same
|
|
1517
|
+
way and stays auditable.
|
|
1518
|
+
|
|
1519
|
+
## When to use
|
|
1520
|
+
|
|
1521
|
+
When a real, consequential technical decision is being made or recognized \u2014 and only then.
|
|
1522
|
+
|
|
1523
|
+
## Inputs
|
|
1524
|
+
|
|
1525
|
+
The context pack, the relevant Work Item or architecture note, and the decision being made.
|
|
1526
|
+
|
|
1527
|
+
## Output
|
|
1528
|
+
|
|
1529
|
+
A single ADR containing: context, the decision, alternatives considered, consequences, the code
|
|
1530
|
+
paths it governs (\`code:\` globs when known) and the decision status (proposed / accepted /
|
|
1531
|
+
superseded).
|
|
1532
|
+
|
|
1533
|
+
## Rules
|
|
1534
|
+
|
|
1535
|
+
- One ADR = one decision. Never mix unrelated decisions.
|
|
1536
|
+
- Never invent decisions; never write an ADR without a clear reason.
|
|
1537
|
+
- Record alternatives honestly, including the one chosen and why.
|
|
1538
|
+
- Prefer narrow governed \`code:\` globs over broad ones.
|
|
1539
|
+
|
|
1540
|
+
## Quality checklist
|
|
1541
|
+
|
|
1542
|
+
- Context explains why the decision was needed.
|
|
1543
|
+
- The decision and its alternatives are explicit.
|
|
1544
|
+
- Consequences (positive and negative) are stated.
|
|
1545
|
+
- Status and governed paths are present.
|
|
1546
|
+
|
|
1547
|
+
## Example output
|
|
1548
|
+
|
|
1549
|
+
\`\`\`md
|
|
1550
|
+
# ADR-0007 \u2014 Use SQLite for local persistence
|
|
1551
|
+
Status: accepted
|
|
1552
|
+
## Context
|
|
1553
|
+
...
|
|
1554
|
+
## Decision
|
|
1555
|
+
...
|
|
1556
|
+
## Alternatives considered
|
|
1557
|
+
...
|
|
1558
|
+
## Consequences
|
|
1559
|
+
...
|
|
1560
|
+
\`\`\`
|
|
1561
|
+
`
|
|
1562
|
+
);
|
|
1563
|
+
var WORK_ITEM_REFINEMENT = skill(
|
|
1564
|
+
"work-item-refinement",
|
|
1565
|
+
"Work Item Refinement Skill",
|
|
1566
|
+
"delivery",
|
|
1567
|
+
["work-item-agent", "backlog-agent", "roadmap-agent"],
|
|
1568
|
+
`
|
|
1569
|
+
# Work Item Refinement Skill
|
|
1570
|
+
|
|
1571
|
+
## Purpose
|
|
1572
|
+
|
|
1573
|
+
Standardize how a Work Item is sharpened from a rough idea into a ready, implementable item.
|
|
1574
|
+
|
|
1575
|
+
## When to use
|
|
1576
|
+
|
|
1577
|
+
When improving a draft Work Item, or turning a backlog idea / roadmap candidate into a ready item.
|
|
1578
|
+
|
|
1579
|
+
## Inputs
|
|
1580
|
+
|
|
1581
|
+
The context pack and the Work Item (draft or candidate).
|
|
1582
|
+
|
|
1583
|
+
## Output
|
|
1584
|
+
|
|
1585
|
+
An improved Work Item with: problem, expected result, scope, out of scope, acceptance criteria,
|
|
1586
|
+
validation (how to test it), definition of done, open questions and dependencies.
|
|
1587
|
+
|
|
1588
|
+
## Rules
|
|
1589
|
+
|
|
1590
|
+
- Do not implement code.
|
|
1591
|
+
- Do not expand scope without explicit confirmation.
|
|
1592
|
+
- Do not create mega Work Items \u2014 split when it covers multiple outcomes.
|
|
1593
|
+
- Keep acceptance criteria testable.
|
|
1594
|
+
|
|
1595
|
+
## Quality checklist
|
|
1596
|
+
|
|
1597
|
+
- Problem and expected result are unambiguous.
|
|
1598
|
+
- Scope and out-of-scope are explicit.
|
|
1599
|
+
- Acceptance criteria and validation are present and testable.
|
|
1600
|
+
- Open questions and dependencies are surfaced, not hidden.
|
|
1601
|
+
|
|
1602
|
+
## Example output
|
|
1603
|
+
|
|
1604
|
+
A Work Item markdown with the sections above filled in, ready for the implementation-agent.
|
|
1605
|
+
`
|
|
1606
|
+
);
|
|
1607
|
+
var OWNERSHIP_SUGGESTION = skill(
|
|
1608
|
+
"ownership-suggestion",
|
|
1609
|
+
"Ownership Suggestion Skill",
|
|
1610
|
+
"tech",
|
|
1611
|
+
["ownership-agent", "work-item-agent", "graph-agent", "implementation-agent"],
|
|
1612
|
+
`
|
|
1613
|
+
# Ownership Suggestion Skill
|
|
1614
|
+
|
|
1615
|
+
## Purpose
|
|
1616
|
+
|
|
1617
|
+
Standardize how precise \`code:\` ownership globs are proposed so Guard can relate code changes to
|
|
1618
|
+
the right knowledge.
|
|
1619
|
+
|
|
1620
|
+
## When to use
|
|
1621
|
+
|
|
1622
|
+
When a Work Item or artifact is missing ownership, or its ownership is too broad/inaccurate.
|
|
1623
|
+
|
|
1624
|
+
## Inputs
|
|
1625
|
+
|
|
1626
|
+
The context pack, the Work Item, and the technical inventory / codebase notes.
|
|
1627
|
+
|
|
1628
|
+
## Output
|
|
1629
|
+
|
|
1630
|
+
A \`code:\` glob proposal, e.g.
|
|
1631
|
+
|
|
1632
|
+
\`\`\`yaml
|
|
1633
|
+
code:
|
|
1634
|
+
- src/database/**
|
|
1635
|
+
- src/cli/**
|
|
1636
|
+
\`\`\`
|
|
1637
|
+
|
|
1638
|
+
## Rules
|
|
1639
|
+
|
|
1640
|
+
- Prefer small, specific globs; avoid \`src/**\`.
|
|
1641
|
+
- Use only real paths; validate intent against the Work Item.
|
|
1642
|
+
- Explain uncertainty instead of guessing.
|
|
1643
|
+
- Propose only \u2014 the human applies with \`kaddo owners suggest\`.
|
|
1644
|
+
|
|
1645
|
+
## Quality checklist
|
|
1646
|
+
|
|
1647
|
+
- Every glob maps to a real path relevant to the item.
|
|
1648
|
+
- No catch-all globs.
|
|
1649
|
+
- Uncertainty is marked.
|
|
1650
|
+
|
|
1651
|
+
## Example output
|
|
1652
|
+
|
|
1653
|
+
The YAML \`code:\` block above plus a one-line rationale per glob.
|
|
1654
|
+
`
|
|
1655
|
+
);
|
|
1656
|
+
var GRAPH_METADATA_REVIEW = skill(
|
|
1657
|
+
"graph-metadata-review",
|
|
1658
|
+
"Graph Metadata Review Skill",
|
|
1659
|
+
"tech",
|
|
1660
|
+
["graph-agent", "ownership-agent", "work-item-agent"],
|
|
1661
|
+
`
|
|
1662
|
+
# Graph Metadata Review Skill
|
|
1663
|
+
|
|
1664
|
+
## Purpose
|
|
1665
|
+
|
|
1666
|
+
Standardize how \`kaddo graph export\` hints become precise relationship front matter.
|
|
1667
|
+
|
|
1668
|
+
## When to use
|
|
1669
|
+
|
|
1670
|
+
When relationship quality is partial/sparse/empty, or when reviewing \`.kaddo/graph-hints.md\`.
|
|
1671
|
+
|
|
1672
|
+
## Inputs
|
|
1673
|
+
|
|
1674
|
+
The context pack, \`.kaddo/graph.json\` and \`.kaddo/graph-hints.md\`, plus the affected artifacts.
|
|
1675
|
+
|
|
1676
|
+
## Output
|
|
1677
|
+
|
|
1678
|
+
Front matter proposals, e.g.
|
|
1679
|
+
|
|
1680
|
+
\`\`\`yaml
|
|
1681
|
+
capabilities:
|
|
1682
|
+
- local-persistence
|
|
1683
|
+
decisions:
|
|
1684
|
+
- ADR-0001
|
|
1685
|
+
code:
|
|
1686
|
+
- src/database/**
|
|
1687
|
+
capsules:
|
|
1688
|
+
- orders-service
|
|
1689
|
+
\`\`\`
|
|
1690
|
+
|
|
1691
|
+
## Rules
|
|
1692
|
+
|
|
1693
|
+
- Never invent relationships, paths or IDs.
|
|
1694
|
+
- Do not try to resolve every hint at once \u2014 propose what is justified.
|
|
1695
|
+
- Do not modify artifacts; the human applies and re-runs \`kaddo graph export\`.
|
|
1696
|
+
|
|
1697
|
+
## Quality checklist
|
|
1698
|
+
|
|
1699
|
+
- Each proposal maps to a real artifact/path/capability/ADR/capsule.
|
|
1700
|
+
- Globs are narrow; uncertainty is marked.
|
|
1701
|
+
|
|
1702
|
+
## Example output
|
|
1703
|
+
|
|
1704
|
+
The YAML proposal above, grouped per artifact, with a short reason each.
|
|
1705
|
+
`
|
|
1706
|
+
);
|
|
1707
|
+
var CAPSULE_WRITING = skill(
|
|
1708
|
+
"capsule-writing",
|
|
1709
|
+
"Capsule Writing Skill",
|
|
1710
|
+
"integration",
|
|
1711
|
+
["capsule-agent", "architecture-agent", "product-agent"],
|
|
1712
|
+
`
|
|
1713
|
+
# Capsule Writing Skill
|
|
1714
|
+
|
|
1715
|
+
## Purpose
|
|
1716
|
+
|
|
1717
|
+
Standardize how a Knowledge Capsule is written/reviewed so external consumers get safe, useful
|
|
1718
|
+
context.
|
|
1719
|
+
|
|
1720
|
+
## When to use
|
|
1721
|
+
|
|
1722
|
+
When creating or refining a Knowledge Capsule for sharing with another project.
|
|
1723
|
+
|
|
1724
|
+
## Inputs
|
|
1725
|
+
|
|
1726
|
+
The context pack, capabilities, current-state, decisions and any public contracts.
|
|
1727
|
+
|
|
1728
|
+
## Output
|
|
1729
|
+
|
|
1730
|
+
A capsule with: purpose, responsibilities, capabilities, contracts, dependencies, risks, owners,
|
|
1731
|
+
out of scope and usage notes.
|
|
1732
|
+
|
|
1733
|
+
## Rules
|
|
1734
|
+
|
|
1735
|
+
- Never include secrets, tokens, credentials, source code, PII or unnecessary internal detail.
|
|
1736
|
+
- Never invent contracts; mark unknowns.
|
|
1737
|
+
- Summarize boundaries; prefer "unknown" over guessing.
|
|
1738
|
+
|
|
1739
|
+
## Quality checklist
|
|
1740
|
+
|
|
1741
|
+
- Purpose and boundaries are clear.
|
|
1742
|
+
- Contracts are real, not invented.
|
|
1743
|
+
- No secrets/source/PII included.
|
|
1744
|
+
|
|
1745
|
+
## Example output
|
|
1746
|
+
|
|
1747
|
+
A \`*.capsule.md\` with the sections above.
|
|
1748
|
+
`
|
|
1749
|
+
);
|
|
1750
|
+
var LEARNING_CAPTURE = skill(
|
|
1751
|
+
"learning-capture",
|
|
1752
|
+
"Learning Capture Skill",
|
|
1753
|
+
"delivery",
|
|
1754
|
+
["implementation-agent", "guard-agent", "architecture-agent", "work-item-agent"],
|
|
1755
|
+
`
|
|
1756
|
+
# Learning Capture Skill
|
|
1757
|
+
|
|
1758
|
+
## Purpose
|
|
1759
|
+
|
|
1760
|
+
Standardize how a Work Item's learning is captured when it closes.
|
|
1761
|
+
|
|
1762
|
+
## When to use
|
|
1763
|
+
|
|
1764
|
+
When finishing a Work Item, after implementation and verification.
|
|
1765
|
+
|
|
1766
|
+
## Inputs
|
|
1767
|
+
|
|
1768
|
+
The Work Item, the diff/result, and any decisions or surprises that came up.
|
|
1769
|
+
|
|
1770
|
+
## Output
|
|
1771
|
+
|
|
1772
|
+
A learning record: what was implemented, what changed, what was learned, what decision emerged,
|
|
1773
|
+
which knowledge must be updated, and what remains pending.
|
|
1774
|
+
|
|
1775
|
+
## Rules
|
|
1776
|
+
|
|
1777
|
+
- Do not close a Work Item without validation.
|
|
1778
|
+
- Do not hide failures; record them honestly.
|
|
1779
|
+
- Do not assume everything is done if errors remain.
|
|
1780
|
+
|
|
1781
|
+
## Quality checklist
|
|
1782
|
+
|
|
1783
|
+
- Implemented vs changed vs learned are distinct.
|
|
1784
|
+
- Knowledge to update is named (ADR / capabilities / current-state).
|
|
1785
|
+
- Pending items are listed.
|
|
1786
|
+
|
|
1787
|
+
## Example output
|
|
1788
|
+
|
|
1789
|
+
A short learning section appended to the Work Item or a learning note.
|
|
1790
|
+
`
|
|
1791
|
+
);
|
|
1792
|
+
var IMPLEMENTATION_PLANNING = skill(
|
|
1793
|
+
"implementation-planning",
|
|
1794
|
+
"Implementation Planning Skill",
|
|
1795
|
+
"delivery",
|
|
1796
|
+
["implementation-agent", "work-item-agent"],
|
|
1797
|
+
`
|
|
1798
|
+
# Implementation Planning Skill
|
|
1799
|
+
|
|
1800
|
+
## Purpose
|
|
1801
|
+
|
|
1802
|
+
Standardize the plan produced before implementation starts.
|
|
1803
|
+
|
|
1804
|
+
## When to use
|
|
1805
|
+
|
|
1806
|
+
Before writing code for a ready Work Item.
|
|
1807
|
+
|
|
1808
|
+
## Inputs
|
|
1809
|
+
|
|
1810
|
+
The context pack and the ready Work Item.
|
|
1811
|
+
|
|
1812
|
+
## Output
|
|
1813
|
+
|
|
1814
|
+
A plan with: technical scope, expected files, risks, validations, out of scope, implementation
|
|
1815
|
+
steps, and stop criteria (when to pause and ask).
|
|
1816
|
+
|
|
1817
|
+
## Rules
|
|
1818
|
+
|
|
1819
|
+
- Do not start coding without confirmation.
|
|
1820
|
+
- Do not expand scope.
|
|
1821
|
+
- Never make commits or push \u2014 suggest only.
|
|
1822
|
+
|
|
1823
|
+
## Quality checklist
|
|
1824
|
+
|
|
1825
|
+
- Scope and expected files are explicit.
|
|
1826
|
+
- Risks and validations are listed.
|
|
1827
|
+
- Stop criteria are defined.
|
|
1828
|
+
|
|
1829
|
+
## Example output
|
|
1830
|
+
|
|
1831
|
+
A numbered plan covering the sections above, ending with a request to confirm before coding.
|
|
1832
|
+
`
|
|
1833
|
+
);
|
|
1834
|
+
var SKILLS = [
|
|
1835
|
+
ADR_WRITING,
|
|
1836
|
+
WORK_ITEM_REFINEMENT,
|
|
1837
|
+
OWNERSHIP_SUGGESTION,
|
|
1838
|
+
GRAPH_METADATA_REVIEW,
|
|
1839
|
+
CAPSULE_WRITING,
|
|
1840
|
+
LEARNING_CAPTURE,
|
|
1841
|
+
IMPLEMENTATION_PLANNING
|
|
1842
|
+
];
|
|
1843
|
+
var SKILL_GROUPS = {
|
|
1844
|
+
delivery: ["work-item-refinement", "implementation-planning", "learning-capture"],
|
|
1845
|
+
tech: ["adr-writing", "ownership-suggestion", "graph-metadata-review"],
|
|
1846
|
+
integration: ["capsule-writing"]
|
|
1847
|
+
};
|
|
1848
|
+
var SKILL_GROUP_NAMES = Object.keys(SKILL_GROUPS);
|
|
1849
|
+
var RECOMMENDED_SKILLS = [...SKILL_GROUPS.delivery, ...SKILL_GROUPS.tech];
|
|
1850
|
+
function skillInstallPath(id) {
|
|
1851
|
+
return `knowledge/skills/${id}/skill.md`;
|
|
1852
|
+
}
|
|
1853
|
+
function selectSkills(opts) {
|
|
1854
|
+
if (opts.all) {
|
|
1855
|
+
return { ids: SKILLS.map((s) => s.id), label: "all skills" };
|
|
1856
|
+
}
|
|
1857
|
+
if (opts.group) {
|
|
1858
|
+
const group = opts.group;
|
|
1859
|
+
const ids = SKILL_GROUPS[group];
|
|
1860
|
+
if (!ids) {
|
|
1861
|
+
throw new Error(
|
|
1862
|
+
`Unknown skill group "${opts.group}". Valid groups: ${SKILL_GROUP_NAMES.join(", ")}.`
|
|
1863
|
+
);
|
|
1864
|
+
}
|
|
1865
|
+
return { ids, label: `group: ${group}` };
|
|
1866
|
+
}
|
|
1867
|
+
return { ids: RECOMMENDED_SKILLS, label: "recommended skills" };
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1490
1870
|
// src/agents/responsibility.ts
|
|
1491
1871
|
var RESPONSIBILITY_MATRIX = {
|
|
1492
1872
|
"business-agent": {
|
|
@@ -1758,14 +2138,30 @@ function renderLanguageRule() {
|
|
|
1758
2138
|
""
|
|
1759
2139
|
].join("\n");
|
|
1760
2140
|
}
|
|
2141
|
+
function renderSkillsSection(agent) {
|
|
2142
|
+
const applicable = SKILLS.filter((s) => s.appliesTo.includes(agent));
|
|
2143
|
+
if (applicable.length === 0) return "";
|
|
2144
|
+
return [
|
|
2145
|
+
"## Reusable Skills",
|
|
2146
|
+
"",
|
|
2147
|
+
"Apply these reusable skills when relevant (install with `kaddo add skills`; read them in",
|
|
2148
|
+
"`knowledge/skills/` or via the Kaddo MCP server):",
|
|
2149
|
+
"",
|
|
2150
|
+
...applicable.map((s) => `- **${s.id}** \u2014 ${s.title}.`),
|
|
2151
|
+
""
|
|
2152
|
+
].join("\n");
|
|
2153
|
+
}
|
|
1761
2154
|
function withResponsibilityTrace(fileName, content) {
|
|
1762
2155
|
const agent = fileName.replace(/\.md$/, "");
|
|
1763
2156
|
if (!RESPONSIBILITY_MATRIX[agent]) return content;
|
|
2157
|
+
const skills = renderSkillsSection(agent);
|
|
2158
|
+
const skillsBlock = skills ? `${skills}
|
|
2159
|
+
` : "";
|
|
1764
2160
|
return `${content.trimEnd()}
|
|
1765
2161
|
|
|
1766
2162
|
${renderLanguageRule()}
|
|
1767
2163
|
${renderAgentBoundaries(agent)}
|
|
1768
|
-
${renderAgentTrace(agent)}`;
|
|
2164
|
+
${skillsBlock}${renderAgentTrace(agent)}`;
|
|
1769
2165
|
}
|
|
1770
2166
|
|
|
1771
2167
|
// src/agents/prompts.ts
|
|
@@ -3532,74 +3928,40 @@ var agentsModule = {
|
|
|
3532
3928
|
};
|
|
3533
3929
|
|
|
3534
3930
|
// src/modules/skills.ts
|
|
3931
|
+
var skillsReadme = {
|
|
3932
|
+
path: "knowledge/skills/README.md",
|
|
3933
|
+
content: [
|
|
3934
|
+
"# Skills",
|
|
3935
|
+
"",
|
|
3936
|
+
"Reusable **skill** definitions \u2014 capabilities shared across agents. A skill does not decide",
|
|
3937
|
+
"WHAT to do (that is the agent); it defines HOW to do one thing well. Agents orchestrate;",
|
|
3938
|
+
"skills standardize; knowledge grounds; MCP exposes.",
|
|
3939
|
+
"",
|
|
3940
|
+
"Skills never execute anything \u2014 they are reusable instructions, not tools. They never run",
|
|
3941
|
+
"git, never call an LLM and never modify files.",
|
|
3942
|
+
"",
|
|
3943
|
+
"## Installed skills",
|
|
3944
|
+
"",
|
|
3945
|
+
...SKILLS.map((s) => `- \`${s.id}\` (${s.group}) \u2014 ${s.title}. Applies to: ${s.appliesTo.join(", ")}.`),
|
|
3946
|
+
"",
|
|
3947
|
+
"## Groups",
|
|
3948
|
+
"",
|
|
3949
|
+
...Object.entries(SKILL_GROUPS).map(([g, ids]) => `- **${g}**: ${ids.join(", ")}`),
|
|
3950
|
+
"",
|
|
3951
|
+
"Install: `kaddo add skills` (recommended), `--all`, or `--group <delivery|tech|integration>`."
|
|
3952
|
+
].join("\n")
|
|
3953
|
+
};
|
|
3954
|
+
var skillFiles = SKILLS.map((s) => ({
|
|
3955
|
+
path: skillInstallPath(s.id),
|
|
3956
|
+
content: s.content
|
|
3957
|
+
}));
|
|
3535
3958
|
var skillsModule = {
|
|
3536
3959
|
name: "skills",
|
|
3537
|
-
description: "Reusable skills \u2014 capabilities shared across agents,
|
|
3960
|
+
description: "Reusable skills \u2014 capabilities shared across agents (adr-writing, work-item-refinement, \u2026)",
|
|
3538
3961
|
configKey: "module_skills",
|
|
3539
3962
|
dirs: ["knowledge/skills"],
|
|
3540
|
-
files: [
|
|
3541
|
-
|
|
3542
|
-
path: "knowledge/skills/.gitkeep",
|
|
3543
|
-
content: ""
|
|
3544
|
-
},
|
|
3545
|
-
{
|
|
3546
|
-
path: "knowledge/skills/README.md",
|
|
3547
|
-
content: [
|
|
3548
|
-
"# Skills",
|
|
3549
|
-
"",
|
|
3550
|
-
"This directory contains skill definitions \u2014 reusable capabilities that agents",
|
|
3551
|
-
"or team members can invoke.",
|
|
3552
|
-
"",
|
|
3553
|
-
"A skill is a well-defined, repeatable capability with:",
|
|
3554
|
-
"- Clear inputs and outputs",
|
|
3555
|
-
"- A defined trigger (when to use it)",
|
|
3556
|
-
"- Known preconditions",
|
|
3557
|
-
"",
|
|
3558
|
-
"Skills differ from agents: a skill is a single capability,",
|
|
3559
|
-
"an agent is an orchestrator that uses skills."
|
|
3560
|
-
].join("\n")
|
|
3561
|
-
}
|
|
3562
|
-
],
|
|
3563
|
-
workItemTypes: [
|
|
3564
|
-
{
|
|
3565
|
-
name: "skill",
|
|
3566
|
-
knowledgeLevel: "K3",
|
|
3567
|
-
description: "Skill \u2014 a reusable capability shared across agents, teams, or projects.",
|
|
3568
|
-
questions: [
|
|
3569
|
-
{
|
|
3570
|
-
id: "what_it_does",
|
|
3571
|
-
prompt: "What does this skill do?",
|
|
3572
|
-
placeholder: "e.g. Reads the artifact front matters and returns ownership gaps",
|
|
3573
|
-
frontMatterField: "what_it_does",
|
|
3574
|
-
required: true
|
|
3575
|
-
},
|
|
3576
|
-
{
|
|
3577
|
-
id: "trigger",
|
|
3578
|
-
prompt: "When should this skill be invoked?",
|
|
3579
|
-
placeholder: "e.g. When a guard FYI has no matching artifact with code globs",
|
|
3580
|
-
frontMatterField: "trigger",
|
|
3581
|
-
required: true
|
|
3582
|
-
},
|
|
3583
|
-
{
|
|
3584
|
-
id: "inputs_outputs",
|
|
3585
|
-
prompt: "What are the inputs and outputs?",
|
|
3586
|
-
placeholder: "e.g. Input: list of touched files. Output: suggested artifact IDs to update",
|
|
3587
|
-
frontMatterField: "inputs_outputs",
|
|
3588
|
-
required: true
|
|
3589
|
-
}
|
|
3590
|
-
],
|
|
3591
|
-
qualityGate: [
|
|
3592
|
-
"Skill is scoped to a single, reusable capability.",
|
|
3593
|
-
"Trigger condition is explicit.",
|
|
3594
|
-
"Inputs and outputs are defined."
|
|
3595
|
-
],
|
|
3596
|
-
extraFrontMatter: {
|
|
3597
|
-
skill_type: "analysis",
|
|
3598
|
-
reusable_by: [],
|
|
3599
|
-
code: []
|
|
3600
|
-
}
|
|
3601
|
-
}
|
|
3602
|
-
]
|
|
3963
|
+
files: [skillsReadme, ...skillFiles],
|
|
3964
|
+
workItemTypes: []
|
|
3603
3965
|
};
|
|
3604
3966
|
|
|
3605
3967
|
// src/modules/global-docs.ts
|
|
@@ -5346,7 +5708,7 @@ function runIgnoreRemove(artifactId) {
|
|
|
5346
5708
|
}
|
|
5347
5709
|
|
|
5348
5710
|
// src/commands/explain.ts
|
|
5349
|
-
import
|
|
5711
|
+
import matter4 from "gray-matter";
|
|
5350
5712
|
import { parse as parseYaml9 } from "yaml";
|
|
5351
5713
|
|
|
5352
5714
|
// src/core/delivery-phase.ts
|
|
@@ -6084,6 +6446,42 @@ function loadGraphHints(dir) {
|
|
|
6084
6446
|
}
|
|
6085
6447
|
}
|
|
6086
6448
|
|
|
6449
|
+
// src/services/installed-skills.ts
|
|
6450
|
+
import matter3 from "gray-matter";
|
|
6451
|
+
var SKILLS_DIR = join("knowledge", "skills");
|
|
6452
|
+
function discoverInstalledSkills(dir) {
|
|
6453
|
+
const base = join(dir, SKILLS_DIR);
|
|
6454
|
+
if (!exists(base) || !isDir(base)) return [];
|
|
6455
|
+
const out = [];
|
|
6456
|
+
for (const entry of readDir(base)) {
|
|
6457
|
+
const skillFile = join(base, entry, "skill.md");
|
|
6458
|
+
if (!isFile(skillFile)) continue;
|
|
6459
|
+
try {
|
|
6460
|
+
const { data } = matter3(readFile(skillFile));
|
|
6461
|
+
if (data.type && String(data.type) !== "skill") continue;
|
|
6462
|
+
const id = String(data.id ?? entry);
|
|
6463
|
+
out.push({
|
|
6464
|
+
id,
|
|
6465
|
+
title: String(data.title ?? id),
|
|
6466
|
+
group: String(data.group ?? "unknown"),
|
|
6467
|
+
appliesTo: Array.isArray(data.applies_to) ? data.applies_to.map(String).filter(Boolean) : [],
|
|
6468
|
+
relPath: `${SKILLS_DIR.replace(/\\/g, "/")}/${entry}/skill.md`
|
|
6469
|
+
});
|
|
6470
|
+
} catch {
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
return out.sort((a, b) => a.id.localeCompare(b.id));
|
|
6474
|
+
}
|
|
6475
|
+
function skillGroupCounts(skills) {
|
|
6476
|
+
const counts = {};
|
|
6477
|
+
for (const s of skills) counts[s.group] = (counts[s.group] ?? 0) + 1;
|
|
6478
|
+
return counts;
|
|
6479
|
+
}
|
|
6480
|
+
function skillsForAgents(skills, agents) {
|
|
6481
|
+
const set = new Set(agents.map((a) => a.replace(/\.md$/, "")));
|
|
6482
|
+
return skills.filter((s) => s.appliesTo.some((a) => set.has(a))).map((s) => s.id);
|
|
6483
|
+
}
|
|
6484
|
+
|
|
6087
6485
|
// src/core/knowledge-discovery.ts
|
|
6088
6486
|
var KNOWLEDGE4 = "knowledge";
|
|
6089
6487
|
var CONSOLIDATED_TYPE = {
|
|
@@ -6416,6 +6814,10 @@ function buildProjectExplanation(dir) {
|
|
|
6416
6814
|
externalCapsules: loadExternalCapsules(dir),
|
|
6417
6815
|
graph: loadGraphSummary(dir),
|
|
6418
6816
|
graphHints: loadGraphHints(dir),
|
|
6817
|
+
skills: (() => {
|
|
6818
|
+
const installed = discoverInstalledSkills(dir);
|
|
6819
|
+
return { total: installed.length, byGroup: skillGroupCounts(installed) };
|
|
6820
|
+
})(),
|
|
6419
6821
|
layers,
|
|
6420
6822
|
roadmap,
|
|
6421
6823
|
mappedModules,
|
|
@@ -6566,6 +6968,15 @@ function renderExplanationHuman(exp) {
|
|
|
6566
6968
|
if (exp.graph.generatedAt) lines.push(`- Last exported: ${exp.graph.generatedAt}`);
|
|
6567
6969
|
lines.push("");
|
|
6568
6970
|
}
|
|
6971
|
+
if (exp.skills.total > 0) {
|
|
6972
|
+
lines.push(`## Skills installed: ${exp.skills.total}`);
|
|
6973
|
+
const groups = Object.entries(exp.skills.byGroup).sort((a, b) => a[0].localeCompare(b[0]));
|
|
6974
|
+
if (groups.length > 0) {
|
|
6975
|
+
lines.push("Groups:");
|
|
6976
|
+
for (const [g, n] of groups) lines.push(`- ${g}: ${n}`);
|
|
6977
|
+
}
|
|
6978
|
+
lines.push("");
|
|
6979
|
+
}
|
|
6569
6980
|
if (exp.missingKnowledge.length > 0) {
|
|
6570
6981
|
lines.push("## Missing Knowledge");
|
|
6571
6982
|
for (const m of exp.missingKnowledge) lines.push(`- ${m}`);
|
|
@@ -6609,7 +7020,7 @@ function readKnowledge(dir) {
|
|
|
6609
7020
|
if (!exists(knowledgePath)) return null;
|
|
6610
7021
|
try {
|
|
6611
7022
|
const raw = readFile(knowledgePath);
|
|
6612
|
-
const { data, content } =
|
|
7023
|
+
const { data, content } = matter4(raw);
|
|
6613
7024
|
return { content, data };
|
|
6614
7025
|
} catch {
|
|
6615
7026
|
return null;
|
|
@@ -6620,7 +7031,7 @@ function readRoadmap(dir) {
|
|
|
6620
7031
|
if (!exists(roadmapPath)) return null;
|
|
6621
7032
|
try {
|
|
6622
7033
|
const raw = readFile(roadmapPath);
|
|
6623
|
-
const { content } =
|
|
7034
|
+
const { content } = matter4(raw);
|
|
6624
7035
|
return content.trim();
|
|
6625
7036
|
} catch {
|
|
6626
7037
|
return null;
|
|
@@ -6789,7 +7200,7 @@ function runExplain(opts) {
|
|
|
6789
7200
|
}
|
|
6790
7201
|
|
|
6791
7202
|
// src/core/context-pack.ts
|
|
6792
|
-
import
|
|
7203
|
+
import matter5 from "gray-matter";
|
|
6793
7204
|
var CONTEXT_PACK_VERSION = "1";
|
|
6794
7205
|
var ARCH_DIR6 = "knowledge";
|
|
6795
7206
|
function readScanJson(dir) {
|
|
@@ -6802,7 +7213,7 @@ function readScanJson(dir) {
|
|
|
6802
7213
|
}
|
|
6803
7214
|
}
|
|
6804
7215
|
function firstParagraph2(markdown) {
|
|
6805
|
-
const body =
|
|
7216
|
+
const body = matter5(markdown).content.trim();
|
|
6806
7217
|
const para = body.split("\n\n").map((p2) => p2.trim()).find((p2) => p2 && !p2.startsWith("#"));
|
|
6807
7218
|
return para ?? "";
|
|
6808
7219
|
}
|
|
@@ -6975,6 +7386,7 @@ function buildContextPack(dir, config, now = /* @__PURE__ */ new Date()) {
|
|
|
6975
7386
|
external: loadExternalCapsules(dir),
|
|
6976
7387
|
graph: loadGraphSummary(dir),
|
|
6977
7388
|
graphHints: loadGraphHints(dir),
|
|
7389
|
+
skills: discoverInstalledSkills(dir).map((s) => s.id),
|
|
6978
7390
|
mappedModules,
|
|
6979
7391
|
missing,
|
|
6980
7392
|
// VS-052: the handoff is driven by the REAL phase, not project.state, so the pack never
|
|
@@ -7168,6 +7580,12 @@ function renderContextPack(pack) {
|
|
|
7168
7580
|
`);
|
|
7169
7581
|
}
|
|
7170
7582
|
}
|
|
7583
|
+
if (pack.skills.length > 0) {
|
|
7584
|
+
parts.push("## Skills\n");
|
|
7585
|
+
parts.push("Available reusable skills (agents apply these; content is not inlined):\n");
|
|
7586
|
+
parts.push(pack.skills.map((s) => `- ${s}`).join("\n") + "\n");
|
|
7587
|
+
parts.push("Read full skill definitions in `knowledge/skills/` or via the Kaddo MCP server (`kaddo://skills`).\n");
|
|
7588
|
+
}
|
|
7171
7589
|
parts.push("## Missing Context\n");
|
|
7172
7590
|
if (missing.length > 0) {
|
|
7173
7591
|
parts.push(missing.map((m) => `- ${m}`).join("\n") + "\n");
|
|
@@ -7489,6 +7907,14 @@ function runUnderstand() {
|
|
|
7489
7907
|
if (assessment.nextStep) {
|
|
7490
7908
|
console.log(`Next step: ${assessment.nextStep}`);
|
|
7491
7909
|
}
|
|
7910
|
+
const installedSkills = discoverInstalledSkills(dir);
|
|
7911
|
+
if (installedSkills.length > 0 && assessment.recommendedAgents.length > 0) {
|
|
7912
|
+
const recSkills = skillsForAgents(installedSkills, assessment.recommendedAgents);
|
|
7913
|
+
if (recSkills.length > 0) {
|
|
7914
|
+
console.log("Recommended skills:");
|
|
7915
|
+
for (const s of recSkills) console.log(` - ${s}`);
|
|
7916
|
+
}
|
|
7917
|
+
}
|
|
7492
7918
|
if (exp.externalCapsules.length > 0) {
|
|
7493
7919
|
console.log("");
|
|
7494
7920
|
console.log("External knowledge:");
|
|
@@ -7803,7 +8229,7 @@ function runStatus() {
|
|
|
7803
8229
|
}
|
|
7804
8230
|
|
|
7805
8231
|
// src/commands/learn.ts
|
|
7806
|
-
import
|
|
8232
|
+
import matter6 from "gray-matter";
|
|
7807
8233
|
var ARCH_DIR9 = "knowledge";
|
|
7808
8234
|
var WORK_ITEMS_DIR2 = "knowledge/delivery/work-items";
|
|
7809
8235
|
function findWorkItemFile(dir, id) {
|
|
@@ -7815,7 +8241,7 @@ function findWorkItemFile(dir, id) {
|
|
|
7815
8241
|
}
|
|
7816
8242
|
function updateWorkItemFile(filePath, learning) {
|
|
7817
8243
|
const raw = readFile(filePath);
|
|
7818
|
-
const { data, content } =
|
|
8244
|
+
const { data, content } = matter6(raw);
|
|
7819
8245
|
data.status = "done";
|
|
7820
8246
|
data.completed_at = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
7821
8247
|
let updatedContent = content;
|
|
@@ -7840,7 +8266,7 @@ ${learning.trim()}
|
|
|
7840
8266
|
${learning.trim()}
|
|
7841
8267
|
`;
|
|
7842
8268
|
}
|
|
7843
|
-
const newRaw =
|
|
8269
|
+
const newRaw = matter6.stringify(updatedContent, data);
|
|
7844
8270
|
writeFile(filePath, newRaw);
|
|
7845
8271
|
}
|
|
7846
8272
|
async function runLearn(artifactId) {
|
|
@@ -7968,6 +8394,12 @@ function selectAgentModuleFiles(files, opts, state) {
|
|
|
7968
8394
|
);
|
|
7969
8395
|
return { files: selected, label };
|
|
7970
8396
|
}
|
|
8397
|
+
function selectSkillModuleFiles(files, opts) {
|
|
8398
|
+
const { ids, label } = selectSkills({ all: opts.all, group: opts.group });
|
|
8399
|
+
const wanted = new Set(ids.map((id) => skillInstallPath(id)));
|
|
8400
|
+
const selected = files.filter((f) => f.path.endsWith("README.md") || wanted.has(f.path));
|
|
8401
|
+
return { files: selected, label };
|
|
8402
|
+
}
|
|
7971
8403
|
function markModuleInstalled(dir, configKey, moduleName) {
|
|
7972
8404
|
const configPath = join(dir, CONFIG_PATH5);
|
|
7973
8405
|
if (!exists(configPath)) return;
|
|
@@ -8028,6 +8460,15 @@ function runAdd(moduleName, opts = {}, dir = cwd()) {
|
|
|
8028
8460
|
console.error(err instanceof Error ? err.message : String(err));
|
|
8029
8461
|
process.exit(1);
|
|
8030
8462
|
}
|
|
8463
|
+
} else if (mod.name === "skills") {
|
|
8464
|
+
try {
|
|
8465
|
+
const sel = selectSkillModuleFiles(mod.files, opts);
|
|
8466
|
+
filesToInstall = sel.files;
|
|
8467
|
+
log2.info(`Installing skills (${sel.label}).`);
|
|
8468
|
+
} catch (err) {
|
|
8469
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
8470
|
+
process.exit(1);
|
|
8471
|
+
}
|
|
8031
8472
|
}
|
|
8032
8473
|
const written = [];
|
|
8033
8474
|
const skipped = [];
|
|
@@ -8058,6 +8499,13 @@ function runAdd(moduleName, opts = {}, dir = cwd()) {
|
|
|
8058
8499
|
outro2("Agents installed. Kaddo prepares context \u2014 your LLM does the interpretation.");
|
|
8059
8500
|
return;
|
|
8060
8501
|
}
|
|
8502
|
+
if (mod.name === "skills") {
|
|
8503
|
+
log2.info("Skills are reusable capabilities agents apply \u2014 they never run anything.");
|
|
8504
|
+
log2.info("More skills: `kaddo add skills --all` or `--group <delivery|tech|integration>`.");
|
|
8505
|
+
log2.info("Read them in `knowledge/skills/` or via the Kaddo MCP server (`kaddo://skills`).");
|
|
8506
|
+
outro2("Skills installed. Agents orchestrate; skills standardize.");
|
|
8507
|
+
return;
|
|
8508
|
+
}
|
|
8061
8509
|
if (mod.workItemTypes.length > 0) {
|
|
8062
8510
|
log2.info(`New work item types available:`);
|
|
8063
8511
|
for (const t of mod.workItemTypes) {
|
|
@@ -8068,7 +8516,7 @@ function runAdd(moduleName, opts = {}, dir = cwd()) {
|
|
|
8068
8516
|
}
|
|
8069
8517
|
|
|
8070
8518
|
// src/core/ownership-suggest.ts
|
|
8071
|
-
import
|
|
8519
|
+
import matter7 from "gray-matter";
|
|
8072
8520
|
var SCAN_PATH = ".kaddo/scan.json";
|
|
8073
8521
|
function normalizeGlob(input) {
|
|
8074
8522
|
let g = input.trim().replace(/\\/g, "/");
|
|
@@ -8190,11 +8638,11 @@ function suggestGlobs(artifact, signals) {
|
|
|
8190
8638
|
return [...new Set(out)];
|
|
8191
8639
|
}
|
|
8192
8640
|
function applyOwnership(raw, globs, mode = "replace") {
|
|
8193
|
-
const parsed =
|
|
8641
|
+
const parsed = matter7(raw);
|
|
8194
8642
|
const existing = toStringArray3(parsed.data.code);
|
|
8195
8643
|
const next = mode === "append" ? [.../* @__PURE__ */ new Set([...existing, ...globs])] : [...new Set(globs)];
|
|
8196
8644
|
const data = { ...parsed.data, code: next };
|
|
8197
|
-
return
|
|
8645
|
+
return matter7.stringify(parsed.content, data);
|
|
8198
8646
|
}
|
|
8199
8647
|
|
|
8200
8648
|
// src/commands/owners.ts
|
|
@@ -10444,7 +10892,7 @@ modulesCmd.command("map").description("Register a secondary repository as a modu
|
|
|
10444
10892
|
modulesCmd.command("list").description("List mapped modules").action(() => {
|
|
10445
10893
|
runModulesList();
|
|
10446
10894
|
});
|
|
10447
|
-
program.command("add [module]").description("Install an optional Kaddo module (adr, incident, rfc, migration, legacy, agents, standards, security, stack, git-strategy)").option("--all", "For `add agents`: install every
|
|
10895
|
+
program.command("add [module]").description("Install an optional Kaddo module (adr, incident, rfc, migration, legacy, agents, skills, standards, security, stack, git-strategy)").option("--all", "For `add agents` / `add skills`: install every item (not just the recommended set)").option("--group <name>", "For `add agents`: business|product|tech|delivery|utilities. For `add skills`: delivery|tech|integration").action((moduleName, opts) => {
|
|
10448
10896
|
runAdd(moduleName ?? "", { all: opts.all, group: opts.group });
|
|
10449
10897
|
});
|
|
10450
10898
|
program.parseAsync(process.argv).catch((err) => {
|