agents-united 0.10.0 → 0.12.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 +30 -3
- package/dist/cli.js +515 -56
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/registry/agents/orchestrator-business.md +19 -6
- package/registry/agents/orchestrator-design.md +21 -6
- package/registry/agents/orchestrator-digital-agency.md +22 -3
- package/registry/agents/orchestrator-engineering.md +88 -29
- package/registry/agents/orchestrator-marketing.md +21 -7
- package/registry/agents/orchestrator-research.md +18 -4
- package/registry/agents/orchestrator-security.md +20 -8
- package/registry/agents/orchestrator-system-architecture.md +20 -6
- package/registry/agents/orchestrator-universal.md +17 -1
- package/registry/agents/subagent-accessibility-lead.md +8 -0
- package/registry/agents/subagent-ai-model-architect.md +8 -0
- package/registry/agents/subagent-android-architect.md +9 -0
- package/registry/agents/subagent-appsec-penetration-tester.md +7 -0
- package/registry/agents/subagent-backend-architect.md +22 -1
- package/registry/agents/subagent-business-panel-experts.md +8 -0
- package/registry/agents/subagent-cloud-infrastructure-architect.md +9 -0
- package/registry/agents/subagent-cloud-security-architect.md +8 -0
- package/registry/agents/subagent-code-reviewer.md +11 -2
- package/registry/agents/subagent-compliance-grc-specialist.md +8 -0
- package/registry/agents/subagent-cross-platform-specialist.md +10 -0
- package/registry/agents/subagent-data-engineer.md +8 -0
- package/registry/agents/subagent-database-administrator.md +8 -0
- package/registry/agents/subagent-deep-research.md +9 -0
- package/registry/agents/subagent-design-ops-lead.md +9 -0
- package/registry/agents/subagent-design-researcher.md +8 -0
- package/registry/agents/subagent-design-systems-architect.md +9 -0
- package/registry/agents/subagent-designer-toolkit-expert.md +9 -0
- package/registry/agents/subagent-devops-engineer.md +9 -0
- package/registry/agents/subagent-distributed-systems-architect.md +10 -0
- package/registry/agents/subagent-e2e-tester.md +9 -0
- package/registry/agents/subagent-financial-analyst.md +10 -2
- package/registry/agents/subagent-finops-cost-engineer.md +7 -0
- package/registry/agents/subagent-frontend-architect.md +23 -0
- package/registry/agents/subagent-interaction-designer.md +10 -0
- package/registry/agents/subagent-ios-architect.md +9 -0
- package/registry/agents/subagent-legal-contract-analyst.md +13 -5
- package/registry/agents/subagent-lifecycle-email-specialist.md +8 -0
- package/registry/agents/subagent-literature-patent-analyst.md +15 -5
- package/registry/agents/subagent-market-intelligence-analyst.md +13 -3
- package/registry/agents/subagent-marketing-campaign-specialist.md +8 -0
- package/registry/agents/subagent-marketing-content-strategist.md +9 -0
- package/registry/agents/subagent-marketing-conversion-specialist.md +10 -0
- package/registry/agents/subagent-marketing-creative-designer.md +15 -2
- package/registry/agents/subagent-marketing-growth-strategist.md +8 -0
- package/registry/agents/subagent-ml-platform-engineer.md +8 -0
- package/registry/agents/subagent-operations-strategist.md +11 -2
- package/registry/agents/subagent-paid-acquisition-specialist.md +8 -0
- package/registry/agents/subagent-plg-strategist.md +8 -0
- package/registry/agents/subagent-prototype-tester.md +8 -0
- package/registry/agents/subagent-qa-automation-lead.md +10 -0
- package/registry/agents/subagent-repo-index.md +8 -2
- package/registry/agents/subagent-security-engineer.md +6 -0
- package/registry/agents/subagent-seo-specialist.md +10 -0
- package/registry/agents/subagent-socratic-mentor.md +7 -0
- package/registry/agents/subagent-statistical-analyst.md +6 -0
- package/registry/agents/subagent-sysops-sre-lead.md +8 -0
- package/registry/agents/subagent-system-architect.md +9 -0
- package/registry/agents/subagent-ui-designer.md +12 -0
- package/registry/agents/subagent-ux-strategist.md +10 -0
- package/registry/bundles.json +216 -275
- package/registry/skills/a11y-debugging/SKILL.md +98 -0
- package/registry/skills/a11y-debugging/references/a11y-snippets.md +92 -0
- package/registry/skills/ab-test-setup/SKILL.md +1 -1
- package/registry/skills/accessibility-audit/SKILL.md +1 -1
- package/registry/skills/clickable-prototype-spec/SKILL.md +1 -1
- package/registry/skills/component-library-management/SKILL.md +1 -1
- package/registry/skills/component-playground-setup/SKILL.md +1 -1
- package/registry/skills/content-calendar-strategy/SKILL.md +1 -1
- package/registry/skills/conversion-funnel-optimization/SKILL.md +1 -1
- package/registry/skills/copywriting-frameworks/SKILL.md +1 -1
- package/registry/skills/debug-optimize-lcp/SKILL.md +133 -0
- package/registry/skills/debug-optimize-lcp/references/elements-and-size.md +27 -0
- package/registry/skills/debug-optimize-lcp/references/lcp-breakdown.md +23 -0
- package/registry/skills/debug-optimize-lcp/references/lcp-snippets.md +79 -0
- package/registry/skills/debug-optimize-lcp/references/optimization-strategies.md +38 -0
- package/registry/skills/design-handoff-spec/SKILL.md +1 -1
- package/registry/skills/design-ops-workflow/SKILL.md +1 -1
- package/registry/skills/design-system-governance/SKILL.md +1 -1
- package/registry/skills/design-system-tokens/SKILL.md +1 -1
- package/registry/skills/design-tokens-management/SKILL.md +1 -1
- package/registry/skills/design-version-control/SKILL.md +1 -1
- package/registry/skills/email-marketing-automation/SKILL.md +1 -1
- package/registry/skills/finishing-a-development-branch/SKILL.md +1 -1
- package/registry/skills/frontend-design/LICENSE.txt +177 -0
- package/registry/skills/frontend-design/SKILL.md +64 -0
- package/registry/skills/generative_ui/SKILL.md +131 -0
- package/registry/skills/growth-experiment-design/SKILL.md +1 -1
- package/registry/skills/interaction-pattern-library/SKILL.md +1 -1
- package/registry/skills/interactive-prototype-builder/SKILL.md +1 -1
- package/registry/skills/mcp-setup/SKILL.md +22 -7
- package/registry/skills/micro-interaction-design/SKILL.md +1 -1
- package/registry/skills/mobile-first-design/SKILL.md +1 -1
- package/registry/skills/modern-web-guidance/SKILL.md +139 -0
- package/registry/skills/product-launch-playbook/SKILL.md +1 -1
- package/registry/skills/responsive-design-audit/SKILL.md +1 -1
- package/registry/skills/seo-audit/SKILL.md +1 -1
- package/registry/skills/signup-flow-cro/SKILL.md +1 -1
- package/registry/skills/social-media-campaign/SKILL.md +1 -1
- package/registry/skills/state-driven-ui-animation/SKILL.md +1 -1
- package/registry/skills/stitch-design-taste/DESIGN.md +121 -0
- package/registry/skills/stitch-design-taste/SKILL.md +194 -0
- package/registry/skills/subagent-driven-development/SKILL.md +1 -1
- package/registry/skills/ui-component-spec/SKILL.md +1 -1
- package/registry/skills/usability-testing-protocol/SKILL.md +1 -1
- package/registry/skills/user-flow-mapping/SKILL.md +1 -1
- package/registry/skills/user-journey-mapping/SKILL.md +1 -1
- package/registry/{workflows/workflow-agency-ad-creative-sprint.md → skills/workflow-agency-ad-creative-sprint/SKILL.md} +14 -7
- package/registry/{workflows/workflow-agency-brand-design-system.md → skills/workflow-agency-brand-design-system/SKILL.md} +14 -7
- package/registry/{workflows/workflow-agency-client-pitch-proposal.md → skills/workflow-agency-client-pitch-proposal/SKILL.md} +14 -7
- package/registry/{workflows/workflow-agency-cro-funnel-teardown.md → skills/workflow-agency-cro-funnel-teardown/SKILL.md} +14 -7
- package/registry/{workflows/workflow-agency-full-campaign.md → skills/workflow-agency-full-campaign/SKILL.md} +14 -7
- package/registry/{workflows/workflow-agency-seo-content-engine.md → skills/workflow-agency-seo-content-engine/SKILL.md} +14 -7
- package/registry/{workflows/workflow-analyze.md → skills/workflow-analyze/SKILL.md} +13 -6
- package/registry/{workflows/workflow-api-contract-design.md → skills/workflow-api-contract-design/SKILL.md} +11 -4
- package/registry/{workflows/workflow-app-store-release.md → skills/workflow-app-store-release/SKILL.md} +11 -4
- package/registry/{workflows/workflow-brainstorm.md → skills/workflow-brainstorm/SKILL.md} +14 -7
- package/registry/{workflows/workflow-build.md → skills/workflow-build/SKILL.md} +14 -7
- package/registry/{workflows/workflow-business-panel.md → skills/workflow-business-panel/SKILL.md} +14 -7
- package/registry/{workflows/workflow-cleanup.md → skills/workflow-cleanup/SKILL.md} +14 -8
- package/registry/{workflows/workflow-deploy-staging.md → skills/workflow-deploy-staging/SKILL.md} +11 -4
- package/registry/{workflows/workflow-design-code.md → skills/workflow-design-code/SKILL.md} +14 -7
- package/registry/{workflows/workflow-design-ops--handoff.md → skills/workflow-design-ops-handoff/SKILL.md} +14 -7
- package/registry/{workflows/workflow-design-ops--plan-sprint.md → skills/workflow-design-ops-plan-sprint/SKILL.md} +14 -7
- package/registry/{workflows/workflow-design-ops--setup-workflow.md → skills/workflow-design-ops-setup-workflow/SKILL.md} +14 -7
- package/registry/{workflows/workflow-design-orchestrate.md → skills/workflow-design-orchestrate/SKILL.md} +14 -7
- package/registry/{workflows/workflow-design-systems--audit-system.md → skills/workflow-design-systems-audit-system/SKILL.md} +14 -7
- package/registry/{workflows/workflow-design-systems--create-component.md → skills/workflow-design-systems-create-component/SKILL.md} +13 -7
- package/registry/{workflows/workflow-design-systems--tokenize.md → skills/workflow-design-systems-tokenize/SKILL.md} +14 -7
- package/registry/{workflows/workflow-diagnose.md → skills/workflow-diagnose/SKILL.md} +11 -4
- package/registry/{workflows/workflow-e2e-testing.md → skills/workflow-e2e-testing/SKILL.md} +11 -4
- package/registry/{workflows/workflow-email-drip-sequence.md → skills/workflow-email-drip-sequence/SKILL.md} +14 -7
- package/registry/{workflows/workflow-estimate.md → skills/workflow-estimate/SKILL.md} +14 -7
- package/registry/{workflows/workflow-explain.md → skills/workflow-explain/SKILL.md} +14 -7
- package/registry/{workflows/workflow-frontend-audit.md → skills/workflow-frontend-audit/SKILL.md} +11 -4
- package/registry/{workflows/workflow-git.md → skills/workflow-git/SKILL.md} +12 -5
- package/registry/{workflows/workflow-grill.md → skills/workflow-grill/SKILL.md} +11 -4
- package/registry/{workflows/workflow-implement.md → skills/workflow-implement/SKILL.md} +15 -8
- package/registry/{workflows/workflow-incident-triage.md → skills/workflow-incident-triage/SKILL.md} +11 -4
- package/registry/{workflows/workflow-interaction-design--design-interaction.md → skills/workflow-interaction-design-design-interaction/SKILL.md} +14 -7
- package/registry/{workflows/workflow-interaction-design--error-flow.md → skills/workflow-interaction-design-error-flow/SKILL.md} +14 -7
- package/registry/{workflows/workflow-interaction-design--map-states.md → skills/workflow-interaction-design-map-states/SKILL.md} +14 -7
- package/registry/{workflows/workflow-marketing-audit.md → skills/workflow-marketing-audit/SKILL.md} +14 -7
- package/registry/{workflows/workflow-marketing-campaign-builder.md → skills/workflow-marketing-campaign-builder/SKILL.md} +14 -7
- package/registry/{workflows/workflow-marketing-content-pipeline.md → skills/workflow-marketing-content-pipeline/SKILL.md} +13 -7
- package/registry/{workflows/workflow-marketing-growth-experiment.md → skills/workflow-marketing-growth-experiment/SKILL.md} +14 -7
- package/registry/{workflows/workflow-marketing-launch.md → skills/workflow-marketing-launch/SKILL.md} +14 -7
- package/registry/{workflows/workflow-marketing-panel.md → skills/workflow-marketing-panel/SKILL.md} +14 -7
- package/registry/{workflows/workflow-ml-eval.md → skills/workflow-ml-eval/SKILL.md} +14 -7
- package/registry/{workflows/workflow-mobile-build.md → skills/workflow-mobile-build/SKILL.md} +13 -6
- package/registry/{workflows/workflow-onboarding-funnel-cro.md → skills/workflow-onboarding-funnel-cro/SKILL.md} +14 -7
- package/registry/{workflows/workflow-paid-acquisition-campaign.md → skills/workflow-paid-acquisition-campaign/SKILL.md} +14 -7
- package/registry/{workflows/workflow-paid-campaign-launch.md → skills/workflow-paid-campaign-launch/SKILL.md} +14 -7
- package/registry/{workflows/workflow-plan.md → skills/workflow-plan/SKILL.md} +14 -7
- package/registry/{workflows/workflow-prototyping-testing--evaluate.md → skills/workflow-prototyping-testing-evaluate/SKILL.md} +14 -7
- package/registry/{workflows/workflow-prototyping-testing--experiment.md → skills/workflow-prototyping-testing-experiment/SKILL.md} +14 -7
- package/registry/{workflows/workflow-prototyping-testing--prototype-plan.md → skills/workflow-prototyping-testing-prototype-plan/SKILL.md} +14 -7
- package/registry/{workflows/workflow-prototyping-testing--test-plan.md → skills/workflow-prototyping-testing-test-plan/SKILL.md} +14 -7
- package/registry/{workflows/workflow-rag-pipeline-deploy.md → skills/workflow-rag-pipeline-deploy/SKILL.md} +14 -7
- package/registry/{workflows/workflow-recommend.md → skills/workflow-recommend/SKILL.md} +14 -7
- package/registry/{workflows/workflow-research.md → skills/workflow-research/SKILL.md} +14 -7
- package/registry/{workflows/workflow-review.md → skills/workflow-review/SKILL.md} +13 -6
- package/registry/{workflows/workflow-seo-audit-pipeline.md → skills/workflow-seo-audit-pipeline/SKILL.md} +14 -7
- package/registry/{workflows/workflow-seo-content-pipeline.md → skills/workflow-seo-content-pipeline/SKILL.md} +14 -7
- package/registry/{workflows/workflow-serverless-gpu-deploy.md → skills/workflow-serverless-gpu-deploy/SKILL.md} +14 -7
- package/registry/{workflows/workflow-spec.md → skills/workflow-spec/SKILL.md} +11 -4
- package/registry/{workflows/workflow-spec-panel.md → skills/workflow-spec-panel/SKILL.md} +14 -7
- package/registry/{workflows/workflow-test.md → skills/workflow-test/SKILL.md} +15 -8
- package/registry/{workflows/workflow-troubleshoot.md → skills/workflow-troubleshoot/SKILL.md} +14 -7
- package/registry/{workflows/workflow-ui-design--color-palette.md → skills/workflow-ui-design-color-palette/SKILL.md} +13 -7
- package/registry/{workflows/workflow-ui-design--design-screen.md → skills/workflow-ui-design-design-screen/SKILL.md} +13 -7
- package/registry/{workflows/workflow-ui-design--responsive-audit.md → skills/workflow-ui-design-responsive-audit/SKILL.md} +14 -7
- package/registry/{workflows/workflow-ui-design--type-system.md → skills/workflow-ui-design-type-system/SKILL.md} +14 -7
- package/registry/{workflows/workflow-ux-strategy--benchmark.md → skills/workflow-ux-strategy-benchmark/SKILL.md} +14 -7
- package/registry/{workflows/workflow-ux-strategy--frame-problem.md → skills/workflow-ux-strategy-frame-problem/SKILL.md} +14 -7
- package/registry/{workflows/workflow-ux-strategy--strategize.md → skills/workflow-ux-strategy-strategize/SKILL.md} +14 -7
package/dist/cli.js
CHANGED
|
@@ -10,12 +10,21 @@ import path14 from "path";
|
|
|
10
10
|
// src/core/registry.ts
|
|
11
11
|
import path from "path";
|
|
12
12
|
import fs from "fs-extra";
|
|
13
|
+
import yaml from "yaml";
|
|
13
14
|
import { fileURLToPath } from "url";
|
|
14
15
|
var __filename = fileURLToPath(import.meta.url);
|
|
15
16
|
var __dirname = path.dirname(__filename);
|
|
16
|
-
var RegistryResolver = class {
|
|
17
|
+
var RegistryResolver = class _RegistryResolver {
|
|
18
|
+
/**
|
|
19
|
+
* Host entrypoint rules (Plan 015 §0/C7). `GEMINI.md` is always resolved so
|
|
20
|
+
* Antigravity-family hosts keep their entrypoint; it is never declared in an
|
|
21
|
+
* agent's frontmatter.
|
|
22
|
+
*/
|
|
23
|
+
static BASELINE_RULES = ["GEMINI.md"];
|
|
17
24
|
registryDir;
|
|
18
25
|
bundlesManifest = null;
|
|
26
|
+
/** Memoized agent file -> declared rules (Plan 015 §0/C6). */
|
|
27
|
+
agentRuleCache = /* @__PURE__ */ new Map();
|
|
19
28
|
constructor(customRegistryDir) {
|
|
20
29
|
if (customRegistryDir) {
|
|
21
30
|
this.registryDir = path.resolve(customRegistryDir);
|
|
@@ -71,18 +80,20 @@ var RegistryResolver = class {
|
|
|
71
80
|
const agents = /* @__PURE__ */ new Set();
|
|
72
81
|
const skills = /* @__PURE__ */ new Set();
|
|
73
82
|
const workflows = /* @__PURE__ */ new Set();
|
|
83
|
+
const rules = new Set(_RegistryResolver.BASELINE_RULES);
|
|
74
84
|
for (const b of domainBundles) {
|
|
75
85
|
const resolved = await this.resolve(b.name);
|
|
76
86
|
resolved.agents.forEach((a) => agents.add(a));
|
|
77
87
|
resolved.skills.forEach((s) => skills.add(s));
|
|
78
88
|
resolved.workflows.forEach((w) => workflows.add(w));
|
|
89
|
+
resolved.rules.forEach((r) => rules.add(r));
|
|
79
90
|
}
|
|
80
91
|
return {
|
|
81
92
|
targetBundle: `domain:${domainName}`,
|
|
82
93
|
agents: Array.from(agents),
|
|
83
94
|
skills: Array.from(skills),
|
|
84
95
|
workflows: Array.from(workflows),
|
|
85
|
-
rules:
|
|
96
|
+
rules: Array.from(rules).sort()
|
|
86
97
|
};
|
|
87
98
|
}
|
|
88
99
|
}
|
|
@@ -91,7 +102,8 @@ var RegistryResolver = class {
|
|
|
91
102
|
const agents = /* @__PURE__ */ new Set();
|
|
92
103
|
const skills = new Set(bundle.skills || []);
|
|
93
104
|
const workflows = new Set(bundle.workflows || []);
|
|
94
|
-
const rules =
|
|
105
|
+
const rules = new Set(_RegistryResolver.BASELINE_RULES);
|
|
106
|
+
(bundle.rules || []).forEach((r) => rules.add(r));
|
|
95
107
|
if (bundle.parentBundle) {
|
|
96
108
|
const parent = await this.getBundle(bundle.parentBundle);
|
|
97
109
|
if (parent) {
|
|
@@ -99,16 +111,24 @@ var RegistryResolver = class {
|
|
|
99
111
|
if (parent.agents) parent.agents.forEach((a) => agents.add(a));
|
|
100
112
|
if (parent.skills) parent.skills.forEach((s) => skills.add(s));
|
|
101
113
|
if (parent.workflows) parent.workflows.forEach((w) => workflows.add(w));
|
|
114
|
+
(parent.rules || []).forEach((r) => rules.add(r));
|
|
102
115
|
}
|
|
103
116
|
}
|
|
104
117
|
if (bundle.orchestrator) agents.add(bundle.orchestrator);
|
|
105
118
|
if (bundle.agents) bundle.agents.forEach((a) => agents.add(a));
|
|
119
|
+
for (const agentFile of agents) {
|
|
120
|
+
for (const rule of await this.extractRulesFromAgent(agentFile)) {
|
|
121
|
+
rules.add(rule);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const sortedRules = Array.from(rules).sort();
|
|
125
|
+
this.assertRulesExist(sortedRules, `bundle "${bundle.name}"`);
|
|
106
126
|
return {
|
|
107
127
|
targetBundle: bundle.name,
|
|
108
128
|
agents: Array.from(agents),
|
|
109
129
|
skills: Array.from(skills),
|
|
110
130
|
workflows: Array.from(workflows),
|
|
111
|
-
rules
|
|
131
|
+
rules: sortedRules
|
|
112
132
|
};
|
|
113
133
|
}
|
|
114
134
|
const agentPath = path.join(this.registryDir, "agents", identifier.endsWith(".md") ? identifier : `${identifier}.md`);
|
|
@@ -120,7 +140,9 @@ var RegistryResolver = class {
|
|
|
120
140
|
rules: []
|
|
121
141
|
};
|
|
122
142
|
}
|
|
143
|
+
const sanitizedSkillId = identifier.replace(/\.md$/, "").replace(/--/g, "-");
|
|
123
144
|
const skillPath = path.join(this.registryDir, "skills", identifier);
|
|
145
|
+
const sanitizedSkillPath = path.join(this.registryDir, "skills", sanitizedSkillId);
|
|
124
146
|
if (await fs.pathExists(skillPath)) {
|
|
125
147
|
return {
|
|
126
148
|
agents: [],
|
|
@@ -128,6 +150,22 @@ var RegistryResolver = class {
|
|
|
128
150
|
workflows: [],
|
|
129
151
|
rules: []
|
|
130
152
|
};
|
|
153
|
+
} else if (await fs.pathExists(sanitizedSkillPath)) {
|
|
154
|
+
return {
|
|
155
|
+
agents: [],
|
|
156
|
+
skills: [sanitizedSkillId],
|
|
157
|
+
workflows: [],
|
|
158
|
+
rules: []
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const workflowSkillPath = path.join(this.registryDir, "skills", `workflow-${sanitizedSkillId}`);
|
|
162
|
+
if (await fs.pathExists(workflowSkillPath)) {
|
|
163
|
+
return {
|
|
164
|
+
agents: [],
|
|
165
|
+
skills: [`workflow-${sanitizedSkillId}`],
|
|
166
|
+
workflows: [],
|
|
167
|
+
rules: []
|
|
168
|
+
};
|
|
131
169
|
}
|
|
132
170
|
const workflowFileName = identifier.startsWith("workflow-") ? `${identifier}.md` : `workflow-${identifier}.md`;
|
|
133
171
|
const workflowPath = path.join(this.registryDir, "workflows", workflowFileName);
|
|
@@ -167,7 +205,7 @@ var RegistryResolver = class {
|
|
|
167
205
|
}
|
|
168
206
|
const skillsDir = path.join(this.registryDir, "skills");
|
|
169
207
|
let matchedSkills = [];
|
|
170
|
-
if (!options?.type || options.type === "skill") {
|
|
208
|
+
if (!options?.type || options.type === "skill" || options.type === "workflow") {
|
|
171
209
|
if (await fs.pathExists(skillsDir)) {
|
|
172
210
|
const dirs = await fs.readdir(skillsDir);
|
|
173
211
|
matchedSkills = dirs.filter((d) => {
|
|
@@ -176,15 +214,19 @@ var RegistryResolver = class {
|
|
|
176
214
|
});
|
|
177
215
|
}
|
|
178
216
|
}
|
|
179
|
-
const workflowsDir = path.join(this.registryDir, "workflows");
|
|
180
217
|
let matchedWorkflows = [];
|
|
181
218
|
if (!options?.type || options.type === "workflow") {
|
|
219
|
+
matchedWorkflows = matchedSkills.filter((s) => s.startsWith("workflow-"));
|
|
220
|
+
const workflowsDir = path.join(this.registryDir, "workflows");
|
|
182
221
|
if (await fs.pathExists(workflowsDir)) {
|
|
183
222
|
const files = await fs.readdir(workflowsDir);
|
|
184
|
-
|
|
223
|
+
const legacyMatches = files.filter((f) => f.endsWith(".md")).filter((f) => {
|
|
185
224
|
if (!q) return true;
|
|
186
225
|
return f.toLowerCase().includes(q);
|
|
187
226
|
});
|
|
227
|
+
legacyMatches.forEach((f) => {
|
|
228
|
+
if (!matchedWorkflows.includes(f)) matchedWorkflows.push(f);
|
|
229
|
+
});
|
|
188
230
|
}
|
|
189
231
|
}
|
|
190
232
|
return {
|
|
@@ -194,6 +236,55 @@ var RegistryResolver = class {
|
|
|
194
236
|
workflows: matchedWorkflows
|
|
195
237
|
};
|
|
196
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Plan 015 Step 1 / §0/C6 — extract the `rules:` binding from an agent's YAML
|
|
241
|
+
* frontmatter. Rules are declared as a BLOCK SEQUENCE:
|
|
242
|
+
* rules:
|
|
243
|
+
* - git-guardrails.md
|
|
244
|
+
* Never regex for an inline `rules: [a, b]`. Returns `[]` (never throws) when
|
|
245
|
+
* the file is missing, has no frontmatter, or the YAML is unparsable so that
|
|
246
|
+
* resolution stays resilient; existence of the referenced rule files is
|
|
247
|
+
* enforced separately by `assertRulesExist`.
|
|
248
|
+
*/
|
|
249
|
+
async extractRulesFromAgent(agentFileName) {
|
|
250
|
+
const cached = this.agentRuleCache.get(agentFileName);
|
|
251
|
+
if (cached) {
|
|
252
|
+
return cached;
|
|
253
|
+
}
|
|
254
|
+
let declared = [];
|
|
255
|
+
const agentPath = path.join(this.registryDir, "agents", agentFileName);
|
|
256
|
+
if (await fs.pathExists(agentPath)) {
|
|
257
|
+
const content = await fs.readFile(agentPath, "utf8");
|
|
258
|
+
const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
259
|
+
if (match) {
|
|
260
|
+
try {
|
|
261
|
+
const meta = yaml.parse(match[1]) ?? {};
|
|
262
|
+
if (Array.isArray(meta.rules)) {
|
|
263
|
+
declared = meta.rules.filter((r) => typeof r === "string");
|
|
264
|
+
}
|
|
265
|
+
} catch {
|
|
266
|
+
declared = [];
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
this.agentRuleCache.set(agentFileName, declared);
|
|
271
|
+
return declared;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Plan 015 §0/D2 — a declared rule binding that cannot be satisfied is a
|
|
275
|
+
* configuration defect, not something to skip silently: installer.ts guards
|
|
276
|
+
* its copy loop with `pathExists`, so a typo would otherwise deploy no rule at
|
|
277
|
+
* all with no error surfaced anywhere.
|
|
278
|
+
*/
|
|
279
|
+
assertRulesExist(rules, context) {
|
|
280
|
+
for (const rule of rules) {
|
|
281
|
+
if (!fs.existsSync(path.join(this.registryDir, "rules", rule))) {
|
|
282
|
+
throw new Error(
|
|
283
|
+
`Registry validation error: ${context} references rule "${rule}" which does not exist in registry/rules/.`
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
197
288
|
/**
|
|
198
289
|
* ADR 0015 — fail-fast validation of planningLoop configuration.
|
|
199
290
|
* @throws if any bundle violates planner-orchestrator invariants.
|
|
@@ -201,6 +292,15 @@ var RegistryResolver = class {
|
|
|
201
292
|
validateBundles(manifest) {
|
|
202
293
|
const validModes = ["subagent-first", "planner-orchestrator"];
|
|
203
294
|
for (const [name, bundle] of Object.entries(manifest.bundles)) {
|
|
295
|
+
if (Array.isArray(bundle.rules)) {
|
|
296
|
+
for (const rule of bundle.rules) {
|
|
297
|
+
if (!fs.existsSync(path.join(this.registryDir, "rules", rule))) {
|
|
298
|
+
throw new Error(
|
|
299
|
+
`Registry validation error: bundle "${name}" references rule "${rule}" which does not exist in registry/rules/.`
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
204
304
|
const pl = bundle.planningLoop;
|
|
205
305
|
if (!pl || !pl.enabled) continue;
|
|
206
306
|
const mode = pl.mode ?? "subagent-first";
|
|
@@ -367,10 +467,10 @@ var AgentHostAdapter = class {
|
|
|
367
467
|
import YAML from "yaml";
|
|
368
468
|
|
|
369
469
|
// src/core/cline-projector.ts
|
|
370
|
-
import
|
|
470
|
+
import yaml2 from "yaml";
|
|
371
471
|
import path4 from "path";
|
|
372
472
|
import fs2 from "fs-extra";
|
|
373
|
-
var ClineProjector = class {
|
|
473
|
+
var ClineProjector = class _ClineProjector {
|
|
374
474
|
/**
|
|
375
475
|
* Managed marker inserted after YAML frontmatter in every rendered artifact.
|
|
376
476
|
*/
|
|
@@ -411,7 +511,7 @@ complete the role in the main session.`;
|
|
|
411
511
|
}
|
|
412
512
|
let parsed = {};
|
|
413
513
|
try {
|
|
414
|
-
parsed =
|
|
514
|
+
parsed = yaml2.parse(match[1]) || {};
|
|
415
515
|
} catch {
|
|
416
516
|
parsed = {};
|
|
417
517
|
}
|
|
@@ -428,7 +528,7 @@ complete the role in the main session.`;
|
|
|
428
528
|
} else if (typeof defaultMaxIterations === "number") {
|
|
429
529
|
cleanFrontmatter.maxIterations = defaultMaxIterations;
|
|
430
530
|
}
|
|
431
|
-
const frontmatterStr =
|
|
531
|
+
const frontmatterStr = yaml2.stringify(cleanFrontmatter).trim();
|
|
432
532
|
const bodyStr = match[2].trim();
|
|
433
533
|
return `---
|
|
434
534
|
${frontmatterStr}
|
|
@@ -450,7 +550,7 @@ ${bodyStr}
|
|
|
450
550
|
let humanName;
|
|
451
551
|
if (match) {
|
|
452
552
|
try {
|
|
453
|
-
const parsed =
|
|
553
|
+
const parsed = yaml2.parse(match[1]) || {};
|
|
454
554
|
if (typeof parsed.name === "string" && parsed.name.trim().length > 0) {
|
|
455
555
|
humanName = parsed.name.trim();
|
|
456
556
|
}
|
|
@@ -471,7 +571,7 @@ ${bodyStr}
|
|
|
471
571
|
let description;
|
|
472
572
|
if (match) {
|
|
473
573
|
try {
|
|
474
|
-
const parsed =
|
|
574
|
+
const parsed = yaml2.parse(match[1]) || {};
|
|
475
575
|
if (typeof parsed.description === "string" && parsed.description.trim().length > 0) {
|
|
476
576
|
description = parsed.description.trim();
|
|
477
577
|
}
|
|
@@ -480,7 +580,7 @@ ${bodyStr}
|
|
|
480
580
|
}
|
|
481
581
|
const cleanFrontmatter = { name: slug };
|
|
482
582
|
if (description) cleanFrontmatter.description = description;
|
|
483
|
-
const frontmatterStr =
|
|
583
|
+
const frontmatterStr = yaml2.stringify(cleanFrontmatter).trim();
|
|
484
584
|
const bodyStr = match ? match[2].trim() : canonicalContent.trim();
|
|
485
585
|
return `---
|
|
486
586
|
${frontmatterStr}
|
|
@@ -506,11 +606,11 @@ ${canonicalContent.trim()}`;
|
|
|
506
606
|
const rawBody = match[2];
|
|
507
607
|
let parsed = {};
|
|
508
608
|
try {
|
|
509
|
-
parsed =
|
|
609
|
+
parsed = yaml2.parse(rawYaml) || {};
|
|
510
610
|
} catch {
|
|
511
611
|
parsed = {};
|
|
512
612
|
}
|
|
513
|
-
const frontmatterStr =
|
|
613
|
+
const frontmatterStr = yaml2.stringify(parsed).trim();
|
|
514
614
|
const bodyStr = rawBody.trim();
|
|
515
615
|
return `---
|
|
516
616
|
${frontmatterStr}
|
|
@@ -534,7 +634,8 @@ ${bodyStr}
|
|
|
534
634
|
canonicalPath: `agents/${agentFile}`
|
|
535
635
|
}));
|
|
536
636
|
const sortedSkills = [...bundle.skills || []].sort();
|
|
537
|
-
const
|
|
637
|
+
const rawWorkflows = bundle.workflows && bundle.workflows.length > 0 ? bundle.workflows : (bundle.skills || []).filter((s) => s.startsWith("workflow-"));
|
|
638
|
+
const sortedWorkflows = [...rawWorkflows].sort();
|
|
538
639
|
const recommendedAddons = (bundle.recommendedAddons || []).filter((a) => !excludeAddons.includes(a));
|
|
539
640
|
const manifest = {
|
|
540
641
|
schemaVersion: 1,
|
|
@@ -566,7 +667,7 @@ ${bodyStr}
|
|
|
566
667
|
manifest.personas = Object.entries(bundle.personaAliases).map(([persona, role]) => ({ persona, role }));
|
|
567
668
|
}
|
|
568
669
|
}
|
|
569
|
-
return
|
|
670
|
+
return yaml2.stringify(manifest);
|
|
570
671
|
}
|
|
571
672
|
/**
|
|
572
673
|
* Render the coordinator rule file (.agents/plugins/<bundle>/rules/agents-united-<bundle>.md).
|
|
@@ -583,6 +684,15 @@ ${bodyStr}
|
|
|
583
684
|
const name = agentFile.replace(/\.md$/, "");
|
|
584
685
|
return `- **${name}**: \`.agents/agents/${agentFile}\``;
|
|
585
686
|
});
|
|
687
|
+
const rawWorkflows = [
|
|
688
|
+
...(bundle.workflows || []).map((w) => w.replace(/\.md$/i, "")),
|
|
689
|
+
...(bundle.skills || []).filter((s) => s.startsWith("workflow-"))
|
|
690
|
+
];
|
|
691
|
+
const uniqueWorkflows = Array.from(new Set(rawWorkflows)).sort();
|
|
692
|
+
const workflowSection = uniqueWorkflows.length > 0 ? `
|
|
693
|
+
### Installed Workflows & Workflow Skills
|
|
694
|
+
Execute multi-step engineering procedures by consulting the corresponding workflow skill runbook (\`.agents/skills/<name>/SKILL.md\`) or triggering its slash command (\`/<name>\`):
|
|
695
|
+
` + uniqueWorkflows.map((w) => `- **${w}**: \`.cline/workflows/${w}.md\` | \`.agents/skills/${w}/SKILL.md\``).join("\n") + "\n" : "";
|
|
586
696
|
const addons = (bundle.recommendedAddons || []).filter((a) => !excludeAddons.includes(a));
|
|
587
697
|
const addonSection = addons.length > 0 ? `
|
|
588
698
|
### Recommended Addon Policy
|
|
@@ -617,7 +727,7 @@ ${planningSection}${personaSection}
|
|
|
617
727
|
${specialistLines.length > 0 ? `
|
|
618
728
|
### Installed Specialist Roles
|
|
619
729
|
${specialistLines.join("\n")}` : ""}
|
|
620
|
-
${addonSection}
|
|
730
|
+
${workflowSection}${addonSection}
|
|
621
731
|
`;
|
|
622
732
|
}
|
|
623
733
|
/**
|
|
@@ -694,7 +804,24 @@ ${addonSection}
|
|
|
694
804
|
}
|
|
695
805
|
}
|
|
696
806
|
}
|
|
697
|
-
|
|
807
|
+
const workflowSkillNames = resolved.skills.filter((s) => s.startsWith("workflow-"));
|
|
808
|
+
for (const skillName of workflowSkillNames) {
|
|
809
|
+
const canonicalRel = `skills/${skillName}/SKILL.md`;
|
|
810
|
+
const skillFilePath = path4.join(registryDir, "skills", skillName, "SKILL.md");
|
|
811
|
+
if (await fs2.pathExists(skillFilePath)) {
|
|
812
|
+
const content = await fs2.readFile(skillFilePath, "utf8");
|
|
813
|
+
const slug = skillName;
|
|
814
|
+
const rendered = this.renderWorkflowProjection(content, canonicalRel);
|
|
815
|
+
artifacts.push({
|
|
816
|
+
kind: "workflow",
|
|
817
|
+
canonical: canonicalRel,
|
|
818
|
+
relPath: `.cline/workflows/${slug}.md`.replace(/\\/g, "/"),
|
|
819
|
+
content: rendered,
|
|
820
|
+
managedMarker: true
|
|
821
|
+
});
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
for (const workflowFile of resolved.workflows || []) {
|
|
698
825
|
const canonicalRel = `workflows/${workflowFile}`;
|
|
699
826
|
const srcPath = path4.join(registryDir, "workflows", workflowFile);
|
|
700
827
|
if (await fs2.pathExists(srcPath)) {
|
|
@@ -717,6 +844,24 @@ ${addonSection}
|
|
|
717
844
|
content: ruleContent,
|
|
718
845
|
managedMarker: true
|
|
719
846
|
});
|
|
847
|
+
const hostEntrypointRules = /* @__PURE__ */ new Set(["GEMINI.md", "AGENTS.md", "CLAUDE.md", "CURSOR.md"]);
|
|
848
|
+
for (const ruleFile of [...resolved.rules || []].sort()) {
|
|
849
|
+
if (hostEntrypointRules.has(ruleFile)) continue;
|
|
850
|
+
const ruleSrcPath = path4.join(registryDir, "rules", ruleFile);
|
|
851
|
+
if (await fs2.pathExists(ruleSrcPath)) {
|
|
852
|
+
const ruleFileContent = await fs2.readFile(ruleSrcPath, "utf8");
|
|
853
|
+
artifacts.push({
|
|
854
|
+
kind: "rule",
|
|
855
|
+
canonical: `rules/${ruleFile}`,
|
|
856
|
+
relPath: `.cline/rules/${ruleFile}`.replace(/\\/g, "/"),
|
|
857
|
+
content: `${_ClineProjector.marker(`rules/${ruleFile}`)}
|
|
858
|
+
|
|
859
|
+
${ruleFileContent.trim()}
|
|
860
|
+
`,
|
|
861
|
+
managedMarker: true
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
}
|
|
720
865
|
const manifestContent = this.renderTeamManifest(bundle, scope, excludeAddons);
|
|
721
866
|
artifacts.push({
|
|
722
867
|
kind: "team-manifest",
|
|
@@ -921,6 +1066,7 @@ ${normalizedBody}`;
|
|
|
921
1066
|
};
|
|
922
1067
|
|
|
923
1068
|
// src/core/installer.ts
|
|
1069
|
+
import YAML2 from "yaml";
|
|
924
1070
|
var InstallEngine = class _InstallEngine {
|
|
925
1071
|
registry;
|
|
926
1072
|
constructor(registry2) {
|
|
@@ -1054,6 +1200,70 @@ var InstallEngine = class _InstallEngine {
|
|
|
1054
1200
|
}
|
|
1055
1201
|
}
|
|
1056
1202
|
}
|
|
1203
|
+
/**
|
|
1204
|
+
* Plan 015c / §5.7 — host-scoped projection namespaces.
|
|
1205
|
+
*
|
|
1206
|
+
* A re-projection run is authoritative only for the paths it produces inside
|
|
1207
|
+
* its own host namespace. Bundle-scoped lanes (`.agents/plugins/<bundle>/`) are
|
|
1208
|
+
* additionally narrowed to the bundle that owns them, so re-projecting bundle A
|
|
1209
|
+
* never drops bundle B's plugin-lane entries.
|
|
1210
|
+
*/
|
|
1211
|
+
static projectionNamespacePrefixes(host, bundleName) {
|
|
1212
|
+
switch (host) {
|
|
1213
|
+
case "cline":
|
|
1214
|
+
return [".cline/", `.agents/plugins/${bundleName}/`];
|
|
1215
|
+
case "claude":
|
|
1216
|
+
return [".claude/"];
|
|
1217
|
+
case "cursor":
|
|
1218
|
+
return [".cursor/"];
|
|
1219
|
+
case "gemini":
|
|
1220
|
+
return [".gemini/"];
|
|
1221
|
+
case "opencode":
|
|
1222
|
+
return [".opencode/"];
|
|
1223
|
+
case "codex":
|
|
1224
|
+
return ["AGENTS.md"];
|
|
1225
|
+
default:
|
|
1226
|
+
return [];
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
/**
|
|
1230
|
+
* Plan 015c / §5.7 — reconcile `projectedTo` instead of only appending.
|
|
1231
|
+
*
|
|
1232
|
+
* `recordProjectedTo()` appends and is never told when a projection *path*
|
|
1233
|
+
* changes (e.g. the ADR 0016 workflow slug rename from
|
|
1234
|
+
* `.cline/workflows/implement-feature-or-fix.md` to
|
|
1235
|
+
* `.cline/workflows/workflow-implement.md`). The obsolete-projection cleanup
|
|
1236
|
+
* iterates `lockfile.projections`, which no longer contains the legacy path, so
|
|
1237
|
+
* the stale pointer in `files[canonical].projectedTo` survived forever and
|
|
1238
|
+
* `agents doctor` warned "Missing projection ... Re-run: agents add ... --fanout"
|
|
1239
|
+
* — a remediation that provably cannot clear it.
|
|
1240
|
+
*
|
|
1241
|
+
* For every canonical this run actually produced projections for, drop the
|
|
1242
|
+
* entries inside this run's namespace that the current plan did not produce.
|
|
1243
|
+
* Entries for other hosts and for other bundles survive untouched.
|
|
1244
|
+
*/
|
|
1245
|
+
reconcileProjectedTo(lockfile, host, bundleName, producedByCanonical) {
|
|
1246
|
+
const prefixes = _InstallEngine.projectionNamespacePrefixes(host, bundleName);
|
|
1247
|
+
if (prefixes.length === 0 || producedByCanonical.size === 0) return;
|
|
1248
|
+
for (const [canonical, producedPaths] of producedByCanonical) {
|
|
1249
|
+
const posixKey = canonical.replace(/\\/g, "/");
|
|
1250
|
+
const sysKey = canonical.replace(/\//g, path5.sep);
|
|
1251
|
+
const targetKey = lockfile.files[posixKey] ? posixKey : lockfile.files[sysKey] ? sysKey : null;
|
|
1252
|
+
if (!targetKey) continue;
|
|
1253
|
+
const asset = lockfile.files[targetKey];
|
|
1254
|
+
if (!asset.projectedTo || asset.projectedTo.length === 0) continue;
|
|
1255
|
+
const produced = new Set(producedPaths.map((p) => this.toPosix(p)));
|
|
1256
|
+
const kept = asset.projectedTo.filter(
|
|
1257
|
+
(p) => !(prefixes.some((prefix) => p.startsWith(prefix)) && !produced.has(p))
|
|
1258
|
+
);
|
|
1259
|
+
if (kept.length === asset.projectedTo.length) continue;
|
|
1260
|
+
if (kept.length === 0) {
|
|
1261
|
+
delete asset.projectedTo;
|
|
1262
|
+
} else {
|
|
1263
|
+
asset.projectedTo = kept;
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1057
1267
|
async removeEmptyProjectionDirs(workspaceRoot, projPath) {
|
|
1058
1268
|
let dir = path5.dirname(path5.join(workspaceRoot, projPath));
|
|
1059
1269
|
while (dir !== workspaceRoot && dir.startsWith(workspaceRoot)) {
|
|
@@ -1067,6 +1277,97 @@ var InstallEngine = class _InstallEngine {
|
|
|
1067
1277
|
dir = path5.dirname(dir);
|
|
1068
1278
|
}
|
|
1069
1279
|
}
|
|
1280
|
+
// ADR 0016: Silent auto-migration of legacy .agents/workflows/*.md into
|
|
1281
|
+
// .agents/skills/workflow-<name>/SKILL.md, synchronizing lockfiles and pruning empty dirs.
|
|
1282
|
+
async migrateLegacyWorkspaceWorkflows(targetDir, lockfile) {
|
|
1283
|
+
const subPaths = AgentHostAdapter.getSubPaths(targetDir);
|
|
1284
|
+
let migratedCount = 0;
|
|
1285
|
+
let targetLockfile = lockfile;
|
|
1286
|
+
let lockfileLoadedFromDisk = false;
|
|
1287
|
+
if (!targetLockfile && await fs3.pathExists(subPaths.lockfile)) {
|
|
1288
|
+
try {
|
|
1289
|
+
targetLockfile = await fs3.readJson(subPaths.lockfile);
|
|
1290
|
+
lockfileLoadedFromDisk = true;
|
|
1291
|
+
} catch {
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
if (await fs3.pathExists(subPaths.workflowsDir)) {
|
|
1295
|
+
const entries = await fs3.readdir(subPaths.workflowsDir).catch(() => []);
|
|
1296
|
+
for (const entry of entries) {
|
|
1297
|
+
if (entry.endsWith(".md")) {
|
|
1298
|
+
const legacyPath = path5.join(subPaths.workflowsDir, entry);
|
|
1299
|
+
let skillName = entry.replace(/\.md$/, "").replace(/--/g, "-");
|
|
1300
|
+
if (!skillName.startsWith("workflow-")) {
|
|
1301
|
+
skillName = `workflow-${skillName}`;
|
|
1302
|
+
}
|
|
1303
|
+
const targetSkillDir = path5.join(subPaths.skillsDir, skillName);
|
|
1304
|
+
const targetSkillFile = path5.join(targetSkillDir, "SKILL.md");
|
|
1305
|
+
if (!await fs3.pathExists(targetSkillFile)) {
|
|
1306
|
+
await fs3.ensureDir(targetSkillDir);
|
|
1307
|
+
const legacyContent = await fs3.readFile(legacyPath, "utf8");
|
|
1308
|
+
let skillContent = legacyContent;
|
|
1309
|
+
const fmMatch = legacyContent.match(/^---\r?\n([\s\S]+?)\r?\n---/);
|
|
1310
|
+
if (fmMatch) {
|
|
1311
|
+
try {
|
|
1312
|
+
const meta = YAML2.parse(fmMatch[1]) || {};
|
|
1313
|
+
meta.name = skillName;
|
|
1314
|
+
if (!meta.metadata) {
|
|
1315
|
+
meta.metadata = {
|
|
1316
|
+
author: "Agents United",
|
|
1317
|
+
version: "1.0.0",
|
|
1318
|
+
icon: "\u{1F504}"
|
|
1319
|
+
};
|
|
1320
|
+
}
|
|
1321
|
+
const rest = legacyContent.replace(/^---\r?\n[\s\S]+?\r?\n---/, "");
|
|
1322
|
+
skillContent = `---
|
|
1323
|
+
${YAML2.stringify(meta).trim()}
|
|
1324
|
+
---${rest}`;
|
|
1325
|
+
} catch {
|
|
1326
|
+
}
|
|
1327
|
+
}
|
|
1328
|
+
await fs3.writeFile(targetSkillFile, skillContent, "utf8");
|
|
1329
|
+
}
|
|
1330
|
+
await fs3.remove(legacyPath).catch(() => {
|
|
1331
|
+
});
|
|
1332
|
+
migratedCount++;
|
|
1333
|
+
if (targetLockfile) {
|
|
1334
|
+
const legacyRel = this.toPosix(path5.relative(targetDir, legacyPath));
|
|
1335
|
+
const newRel = this.toPosix(path5.relative(targetDir, targetSkillFile));
|
|
1336
|
+
if (targetLockfile.files && targetLockfile.files[legacyRel]) {
|
|
1337
|
+
targetLockfile.files[newRel] = targetLockfile.files[legacyRel];
|
|
1338
|
+
delete targetLockfile.files[legacyRel];
|
|
1339
|
+
}
|
|
1340
|
+
if (targetLockfile.installed && targetLockfile.installed.skills) {
|
|
1341
|
+
if (!targetLockfile.installed.skills.includes(skillName)) {
|
|
1342
|
+
targetLockfile.installed.skills.push(skillName);
|
|
1343
|
+
}
|
|
1344
|
+
}
|
|
1345
|
+
}
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
const remaining = await fs3.readdir(subPaths.workflowsDir).catch(() => []);
|
|
1349
|
+
if (remaining.length === 0) {
|
|
1350
|
+
await fs3.remove(subPaths.workflowsDir).catch(() => {
|
|
1351
|
+
});
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
if (targetLockfile && targetLockfile.installed && targetLockfile.installed.workflows && targetLockfile.installed.workflows.length > 0) {
|
|
1355
|
+
for (const w of targetLockfile.installed.workflows) {
|
|
1356
|
+
let skillName = w.replace(/\.md$/, "").replace(/--/g, "-");
|
|
1357
|
+
if (!skillName.startsWith("workflow-")) {
|
|
1358
|
+
skillName = `workflow-${skillName}`;
|
|
1359
|
+
}
|
|
1360
|
+
if (targetLockfile.installed.skills && !targetLockfile.installed.skills.includes(skillName)) {
|
|
1361
|
+
targetLockfile.installed.skills.push(skillName);
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
targetLockfile.installed.workflows = [];
|
|
1365
|
+
}
|
|
1366
|
+
if (targetLockfile && (lockfileLoadedFromDisk || await fs3.pathExists(subPaths.lockfile))) {
|
|
1367
|
+
await fs3.writeJson(subPaths.lockfile, targetLockfile, { spaces: 2 });
|
|
1368
|
+
}
|
|
1369
|
+
return migratedCount;
|
|
1370
|
+
}
|
|
1070
1371
|
/**
|
|
1071
1372
|
* Dry-run: compute the projection plan (paths + warnings) without writing anything.
|
|
1072
1373
|
*/
|
|
@@ -1206,6 +1507,17 @@ var InstallEngine = class _InstallEngine {
|
|
|
1206
1507
|
this.recordProjectedTo(lockfile, artifact.canonical, artifact.relPath);
|
|
1207
1508
|
}
|
|
1208
1509
|
}
|
|
1510
|
+
const producedByCanonical = /* @__PURE__ */ new Map();
|
|
1511
|
+
for (const artifact of artifacts) {
|
|
1512
|
+
if (!artifact.canonical) continue;
|
|
1513
|
+
const producedPaths = producedByCanonical.get(artifact.canonical);
|
|
1514
|
+
if (producedPaths) {
|
|
1515
|
+
producedPaths.push(artifact.relPath);
|
|
1516
|
+
} else {
|
|
1517
|
+
producedByCanonical.set(artifact.canonical, [artifact.relPath]);
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
this.reconcileProjectedTo(lockfile, "cline", bundleDef.name, producedByCanonical);
|
|
1209
1521
|
if (bundleDef.parentBundle) {
|
|
1210
1522
|
const parentDef = await this.registry.getBundle(bundleDef.parentBundle);
|
|
1211
1523
|
if (parentDef) {
|
|
@@ -1249,6 +1561,10 @@ var InstallEngine = class _InstallEngine {
|
|
|
1249
1561
|
const res = HostProjector.projectAgent(content, HOST_REGISTRY[host].profile, canonicalRel);
|
|
1250
1562
|
const projName = host === "cline" ? `${agentFile.replace(/\.md$/i, "").replace(/^subagent-/, "")}.yml` : agentFile;
|
|
1251
1563
|
const dest = path5.join(base, subdir, projName);
|
|
1564
|
+
const projPath = this.toPosix(path5.relative(root, dest));
|
|
1565
|
+
if (host === "cline" && lockfile.projections?.[projPath]?.kind === "role") {
|
|
1566
|
+
continue;
|
|
1567
|
+
}
|
|
1252
1568
|
if (await fs3.pathExists(dest) && !options.force) {
|
|
1253
1569
|
const existing = await fs3.readFile(dest, "utf8");
|
|
1254
1570
|
if (!HostProjector.hasManagedMarker(existing)) {
|
|
@@ -1258,9 +1574,20 @@ var InstallEngine = class _InstallEngine {
|
|
|
1258
1574
|
}
|
|
1259
1575
|
}
|
|
1260
1576
|
await this.deployProjection(dest, res.content);
|
|
1261
|
-
const projPath = this.toPosix(path5.relative(root, dest));
|
|
1262
1577
|
projections.push({ host, path: projPath, kind: "role", warnings: res.warnings });
|
|
1263
1578
|
this.recordProjectedTo(lockfile, this.lockRel("agents", agentFile), projPath);
|
|
1579
|
+
if (host === "cline") {
|
|
1580
|
+
lockfile.projections = lockfile.projections || {};
|
|
1581
|
+
lockfile.projections[projPath] = {
|
|
1582
|
+
host,
|
|
1583
|
+
kind: "role",
|
|
1584
|
+
canonical: canonicalRel,
|
|
1585
|
+
owners: resolved.targetBundle ? [resolved.targetBundle] : [],
|
|
1586
|
+
hash: await this.calculateHash(dest),
|
|
1587
|
+
installedAt: lockfile.projections[projPath]?.installedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1588
|
+
managedMarker: true
|
|
1589
|
+
};
|
|
1590
|
+
}
|
|
1264
1591
|
}
|
|
1265
1592
|
}
|
|
1266
1593
|
}
|
|
@@ -1295,9 +1622,12 @@ var InstallEngine = class _InstallEngine {
|
|
|
1295
1622
|
const subPaths = AgentHostAdapter.getSubPaths(targetDir);
|
|
1296
1623
|
await fs3.ensureDir(subPaths.agentsDir);
|
|
1297
1624
|
await fs3.ensureDir(subPaths.skillsDir);
|
|
1298
|
-
|
|
1625
|
+
if (resolved.workflows && resolved.workflows.length > 0) {
|
|
1626
|
+
await fs3.ensureDir(subPaths.workflowsDir);
|
|
1627
|
+
}
|
|
1299
1628
|
await fs3.ensureDir(subPaths.rulesDir);
|
|
1300
1629
|
const lockfile = await this.readLockfile(subPaths.lockfile);
|
|
1630
|
+
await this.migrateLegacyWorkspaceWorkflows(targetDir, lockfile);
|
|
1301
1631
|
lockfile.scope = scope;
|
|
1302
1632
|
lockfile.method = method;
|
|
1303
1633
|
lockfile.hosts = hosts;
|
|
@@ -1387,6 +1717,7 @@ var InstallEngine = class _InstallEngine {
|
|
|
1387
1717
|
installedAt: existing?.installedAt ?? now,
|
|
1388
1718
|
...existing?.projectedTo ? { projectedTo: existing.projectedTo } : {}
|
|
1389
1719
|
};
|
|
1720
|
+
lockfile.installed.workflows = lockfile.installed.workflows || [];
|
|
1390
1721
|
if (!lockfile.installed.workflows.includes(workflowFile)) {
|
|
1391
1722
|
lockfile.installed.workflows.push(workflowFile);
|
|
1392
1723
|
}
|
|
@@ -1673,7 +2004,9 @@ var UninstallEngine = class {
|
|
|
1673
2004
|
}
|
|
1674
2005
|
lockfile.installed.agents = lockfile.installed.agents.filter((a) => survival.has(`agents/${a}`));
|
|
1675
2006
|
lockfile.installed.skills = lockfile.installed.skills.filter((s) => survival.has(`skills/${s}/SKILL.md`));
|
|
1676
|
-
|
|
2007
|
+
if (lockfile.installed.workflows) {
|
|
2008
|
+
lockfile.installed.workflows = lockfile.installed.workflows.filter((w) => survival.has(`workflows/${w}`));
|
|
2009
|
+
}
|
|
1677
2010
|
await this.refreshParentCoordination(bundleName, workspaceRoot, lockfile, scope);
|
|
1678
2011
|
await fs4.writeJson(subPaths.lockfile, lockfile, { spaces: 2 });
|
|
1679
2012
|
} else {
|
|
@@ -2175,7 +2508,8 @@ var UpdateEngine = class {
|
|
|
2175
2508
|
// src/core/doctor.ts
|
|
2176
2509
|
import path10 from "path";
|
|
2177
2510
|
import fs8 from "fs-extra";
|
|
2178
|
-
import
|
|
2511
|
+
import crypto4 from "crypto";
|
|
2512
|
+
import YAML3 from "yaml";
|
|
2179
2513
|
|
|
2180
2514
|
// src/core/cline-capabilities.ts
|
|
2181
2515
|
import path9 from "path";
|
|
@@ -2377,6 +2711,56 @@ var DoctorEngine = class {
|
|
|
2377
2711
|
}
|
|
2378
2712
|
return HostProjector.hasManagedMarker(content);
|
|
2379
2713
|
}
|
|
2714
|
+
/**
|
|
2715
|
+
* ADR 0017 — re-render the compound projections owned by the installed bundles so
|
|
2716
|
+
* doctor can compare what is on disk with what the current renderer produces.
|
|
2717
|
+
*
|
|
2718
|
+
* Returns projection path -> acceptable content variants, or `null` when the registry
|
|
2719
|
+
* is unavailable (the freshness check is then skipped rather than guessed).
|
|
2720
|
+
*
|
|
2721
|
+
* Two variants are produced per path on purpose: the coordinator rule and team manifest
|
|
2722
|
+
* legitimately render either with or without the installed-bundle addon exclusions
|
|
2723
|
+
* (installer primary path vs parent-bundle refresh path). Matching *either* means the
|
|
2724
|
+
* projection is fresh, which keeps the check false-positive free while still catching
|
|
2725
|
+
* content that matches neither.
|
|
2726
|
+
*/
|
|
2727
|
+
static async renderProjectionVariants(owners, installedBundles) {
|
|
2728
|
+
if (owners.size === 0) return null;
|
|
2729
|
+
let resolver;
|
|
2730
|
+
try {
|
|
2731
|
+
resolver = new RegistryResolver();
|
|
2732
|
+
await resolver.loadBundles();
|
|
2733
|
+
} catch {
|
|
2734
|
+
return null;
|
|
2735
|
+
}
|
|
2736
|
+
const registryDir = resolver.getRegistryDir();
|
|
2737
|
+
const variants = /* @__PURE__ */ new Map();
|
|
2738
|
+
for (const owner of owners) {
|
|
2739
|
+
try {
|
|
2740
|
+
const bundleDef = await resolver.getBundle(owner);
|
|
2741
|
+
if (!bundleDef) continue;
|
|
2742
|
+
const resolved = await resolver.resolve(bundleDef.name);
|
|
2743
|
+
for (const excludeAddons of [void 0, installedBundles]) {
|
|
2744
|
+
const artifacts = await ClineProjector.planCompoundProjection(
|
|
2745
|
+
bundleDef,
|
|
2746
|
+
"project",
|
|
2747
|
+
resolved,
|
|
2748
|
+
registryDir,
|
|
2749
|
+
excludeAddons
|
|
2750
|
+
);
|
|
2751
|
+
for (const artifact of artifacts) {
|
|
2752
|
+
if (artifact.content === void 0) continue;
|
|
2753
|
+
const list = variants.get(artifact.relPath) ?? [];
|
|
2754
|
+
if (!list.includes(artifact.content)) list.push(artifact.content);
|
|
2755
|
+
variants.set(artifact.relPath, list);
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
} catch {
|
|
2759
|
+
continue;
|
|
2760
|
+
}
|
|
2761
|
+
}
|
|
2762
|
+
return variants;
|
|
2763
|
+
}
|
|
2380
2764
|
static async runDoctor(targetDir, host) {
|
|
2381
2765
|
const root = AgentHostAdapter.resolveHostDir("project", "agents", targetDir);
|
|
2382
2766
|
const subPaths = AgentHostAdapter.getSubPaths(root);
|
|
@@ -2396,7 +2780,9 @@ var DoctorEngine = class {
|
|
|
2396
2780
|
manifest = parsed;
|
|
2397
2781
|
agentsCount = parsed.installed?.agents?.length || 0;
|
|
2398
2782
|
skillsCount = parsed.installed?.skills?.length || 0;
|
|
2399
|
-
|
|
2783
|
+
const legacyWorkflows = parsed.installed?.workflows?.length || 0;
|
|
2784
|
+
const workflowSkillCount = (parsed.installed?.skills || []).filter((s) => String(s).startsWith("workflow-")).length;
|
|
2785
|
+
workflowsCount = legacyWorkflows + workflowSkillCount;
|
|
2400
2786
|
isInitialized = true;
|
|
2401
2787
|
} catch (err) {
|
|
2402
2788
|
issues.push(`Corrupt lockfile at ${subPaths.lockfile}: ${err.message}`);
|
|
@@ -2414,7 +2800,7 @@ var DoctorEngine = class {
|
|
|
2414
2800
|
warnings.push(`Agent ${file} is missing YAML frontmatter.`);
|
|
2415
2801
|
} else {
|
|
2416
2802
|
try {
|
|
2417
|
-
const meta =
|
|
2803
|
+
const meta = YAML3.parse(frontmatterMatch[1]);
|
|
2418
2804
|
if (!meta.name) issues.push(`Agent ${file} missing 'name' in frontmatter.`);
|
|
2419
2805
|
if (!meta.description) warnings.push(`Agent ${file} missing 'description'.`);
|
|
2420
2806
|
if (!meta.model) warnings.push(`Agent ${file} missing 'model' definition.`);
|
|
@@ -2425,6 +2811,12 @@ var DoctorEngine = class {
|
|
|
2425
2811
|
}
|
|
2426
2812
|
}
|
|
2427
2813
|
}
|
|
2814
|
+
if (await fs8.pathExists(subPaths.workflowsDir)) {
|
|
2815
|
+
const remainingWorkflowFiles = (await fs8.readdir(subPaths.workflowsDir)).filter((f) => f.endsWith(".md"));
|
|
2816
|
+
if (remainingWorkflowFiles.length > 0) {
|
|
2817
|
+
warnings.push(`Detected ${remainingWorkflowFiles.length} legacy workflows in ${subPaths.workflowsDir}. Run 'agents update' to automatically migrate them to modern skills.`);
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2428
2820
|
if (manifest) {
|
|
2429
2821
|
const workspaceRoot = path10.resolve(path10.dirname(root));
|
|
2430
2822
|
for (const [relPath, assetMeta] of Object.entries(manifest.files)) {
|
|
@@ -2433,9 +2825,24 @@ var DoctorEngine = class {
|
|
|
2433
2825
|
for (const projPath of projectedTo) {
|
|
2434
2826
|
const absProjection = path10.join(workspaceRoot, projPath);
|
|
2435
2827
|
if (!await fs8.pathExists(absProjection)) {
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2828
|
+
let superseding = null;
|
|
2829
|
+
for (const [projRelPath, proj] of Object.entries(manifest.projections ?? {})) {
|
|
2830
|
+
if (projRelPath === projPath) continue;
|
|
2831
|
+
if (proj.canonical !== relPath) continue;
|
|
2832
|
+
if (!await fs8.pathExists(path10.join(workspaceRoot, projRelPath))) continue;
|
|
2833
|
+
superseding = { relPath: projRelPath, host: proj.host, owners: proj.owners ?? [] };
|
|
2834
|
+
break;
|
|
2835
|
+
}
|
|
2836
|
+
if (superseding) {
|
|
2837
|
+
const owner = superseding.owners[0];
|
|
2838
|
+
warnings.push(
|
|
2839
|
+
`Stale projection ${projPath} for canonical ${relPath} (superseded by ${superseding.relPath}).` + (owner ? ` Run: agents update ${owner} --fanout ${superseding.host} to reconcile.` : "")
|
|
2840
|
+
);
|
|
2841
|
+
} else {
|
|
2842
|
+
warnings.push(
|
|
2843
|
+
`Missing projection ${projPath} for canonical ${relPath}. Re-run: agents add ... --fanout`
|
|
2844
|
+
);
|
|
2845
|
+
}
|
|
2439
2846
|
continue;
|
|
2440
2847
|
}
|
|
2441
2848
|
const managed = await this.isManagedProjection(absProjection, projPath === "AGENTS.md");
|
|
@@ -2459,6 +2866,41 @@ var DoctorEngine = class {
|
|
|
2459
2866
|
}
|
|
2460
2867
|
}
|
|
2461
2868
|
}
|
|
2869
|
+
if (manifest.projections && manifest.installed) {
|
|
2870
|
+
const ownerNames = /* @__PURE__ */ new Set();
|
|
2871
|
+
for (const proj of Object.values(manifest.projections)) {
|
|
2872
|
+
for (const owner of proj.owners) ownerNames.add(owner);
|
|
2873
|
+
}
|
|
2874
|
+
const expectedVariants = await this.renderProjectionVariants(ownerNames, manifest.installed.bundles ?? []);
|
|
2875
|
+
if (expectedVariants) {
|
|
2876
|
+
for (const [projRelPath, proj] of Object.entries(manifest.projections)) {
|
|
2877
|
+
const absPath = path10.join(workspaceRoot, projRelPath);
|
|
2878
|
+
if (!await fs8.pathExists(absPath)) continue;
|
|
2879
|
+
if (!proj.managedMarker) continue;
|
|
2880
|
+
const content = await fs8.readFile(absPath, "utf8");
|
|
2881
|
+
if (!HostProjector.hasManagedMarker(content)) continue;
|
|
2882
|
+
if (proj.hash) {
|
|
2883
|
+
const diskHash = `sha256:${crypto4.createHash("sha256").update(await fs8.readFile(absPath)).digest("hex")}`;
|
|
2884
|
+
if (diskHash !== proj.hash) {
|
|
2885
|
+
const owner = proj.owners[0];
|
|
2886
|
+
warnings.push(
|
|
2887
|
+
`Content drift ${projRelPath} \u2014 edited after installation (recorded ${proj.hash.slice(0, 16)}\u2026, on disk ${diskHash.slice(0, 16)}\u2026).` + (owner ? ` Run: agents update ${owner} --fanout ${proj.host} to restore it.` : "")
|
|
2888
|
+
);
|
|
2889
|
+
continue;
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
const variants = expectedVariants.get(projRelPath);
|
|
2893
|
+
if (!variants || variants.length === 0) continue;
|
|
2894
|
+
const onDisk = content.replace(/\r\n/g, "\n");
|
|
2895
|
+
if (!variants.some((variant) => variant.replace(/\r\n/g, "\n") === onDisk)) {
|
|
2896
|
+
const owner = proj.owners[0];
|
|
2897
|
+
warnings.push(
|
|
2898
|
+
`Outdated projection ${projRelPath} (content differs from the current render).` + (owner ? ` Run: agents update ${owner} --fanout ${proj.host} to refresh it.` : "")
|
|
2899
|
+
);
|
|
2900
|
+
}
|
|
2901
|
+
}
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2462
2904
|
const installedBundles = manifest.installed?.bundles ?? [];
|
|
2463
2905
|
const fileOwnersOf = (rec) => rec.owners ?? (rec.bundle ? [rec.bundle] : []);
|
|
2464
2906
|
if (manifest.projections) {
|
|
@@ -2508,7 +2950,7 @@ var DoctorEngine = class {
|
|
|
2508
2950
|
// src/core/cline-launcher.ts
|
|
2509
2951
|
import path11 from "path";
|
|
2510
2952
|
import os3 from "os";
|
|
2511
|
-
import
|
|
2953
|
+
import crypto5 from "crypto";
|
|
2512
2954
|
import fs9 from "fs-extra";
|
|
2513
2955
|
var ClineLauncher = class _ClineLauncher {
|
|
2514
2956
|
probe;
|
|
@@ -2522,7 +2964,7 @@ var ClineLauncher = class _ClineLauncher {
|
|
|
2522
2964
|
*/
|
|
2523
2965
|
static generateTeamName(bundleName, workspace) {
|
|
2524
2966
|
const sanitizedBundle = bundleName.replace(/[^A-Za-z0-9_-]/g, "-");
|
|
2525
|
-
const hash =
|
|
2967
|
+
const hash = crypto5.createHash("sha256").update(path11.resolve(workspace)).digest("hex").slice(0, 8);
|
|
2526
2968
|
const prefix = `au-${sanitizedBundle}`;
|
|
2527
2969
|
const maxPrefixLen = 64 - 9;
|
|
2528
2970
|
const truncatedPrefix = prefix.slice(0, maxPrefixLen);
|
|
@@ -3633,7 +4075,7 @@ var BUNDLE_DISPLAY_NAMES = {
|
|
|
3633
4075
|
},
|
|
3634
4076
|
"full": {
|
|
3635
4077
|
title: "All-in-One Autonomous Department",
|
|
3636
|
-
summary: "Complete suite with all 7 team leads, 38 agents, and all skills & workflows"
|
|
4078
|
+
summary: "Complete suite with all 7 team leads, 38 agents, and all 160 modular skills & workflows"
|
|
3637
4079
|
}
|
|
3638
4080
|
};
|
|
3639
4081
|
cli.command("add [identifier]", "Add a bundle, agent, skill, or workflow to project or global configuration").option("-g, --global", "Install globally into home directory (~/.agents/)").option("-s, --symlink", "Create symbolic links to central registry cache (default / recommended)").option("--copy", "Create independent standalone copies of asset files").option("-t, --target <hosts>", "Which assistants to set up (agents = main library; claude, cursor, cline, opencode, codex get translated copies)", { default: "agents" }).option("--fanout <hosts>", "Also make translated copies for these assistants: claude, cursor, cline, opencode, codex").option("--mode <mode>", "Execution mode for organization bundles (operational | brainstorming)", { default: "operational" }).option("--allow-missing-prereqs", "Proceed with installation even if some prerequisites are missing").option("--allow-under-construction", "Allow installation of bundles marked as under construction").option("-y, --yes", "Skip confirmation prompts").option("-f, --force", "Force overwrite user modified files").option("--start", "Start the installed team in Cline immediately after setup").option("--dry-run", "Simulate installation without writing files").action(async (targetIdentifier, options = {}) => {
|
|
@@ -4400,7 +4842,7 @@ function renderBundleDetailTree(bundle) {
|
|
|
4400
4842
|
if (bundle.name === "full") {
|
|
4401
4843
|
const lines2 = [];
|
|
4402
4844
|
lines2.push(`\u{1F4E6} ${pc.bold(pc.green("full"))} ${pc.cyan("(Universal Autonomous Department)")} ${pc.green("\u2B50 [Recommended]")}`);
|
|
4403
|
-
lines2.push(`\u2502 ${pc.white("Complete suite with all 7 lead orchestrators, 38 subagents,
|
|
4845
|
+
lines2.push(`\u2502 ${pc.white("Complete suite with all 7 lead orchestrators, 38 subagents, and 160 modular skills (91 domain skills + 69 workflow playbooks).")}`);
|
|
4404
4846
|
lines2.push(`\u2502`);
|
|
4405
4847
|
lines2.push(`\u251C\u2500\u2500 \u{1F916} Lead Orchestrators (7 department domains):`);
|
|
4406
4848
|
lines2.push(`\u2502 \u251C\u2500\u2500 \u{1F6E0}\uFE0F ${pc.blue("orchestrator-engineering")} ${pc.dim("(Software Engineering & Delivery)")}`);
|
|
@@ -4411,8 +4853,8 @@ function renderBundleDetailTree(bundle) {
|
|
|
4411
4853
|
lines2.push(`\u2502 \u251C\u2500\u2500 \u{1F52C} ${pc.blue("orchestrator-research")} ${pc.dim("(Deep Technical Research)")}`);
|
|
4412
4854
|
lines2.push(`\u2502 \u2514\u2500\u2500 \u{1F4BC} ${pc.blue("orchestrator-business")} ${pc.dim("(Business Strategy & Economics)")}`);
|
|
4413
4855
|
lines2.push(`\u251C\u2500\u2500 \u{1F916} Specialized Sub-Agents: ${pc.blue("38 worker agents across all 8 departments")}`);
|
|
4414
|
-
lines2.push(`\u251C\u2500\u2500 \u26A1 Skills: ${pc.yellow("
|
|
4415
|
-
lines2.push(`\u251C\u2500\u2500 \u{1F504} Workflows: ${pc.magenta("
|
|
4856
|
+
lines2.push(`\u251C\u2500\u2500 \u26A1 Skills: ${pc.yellow("91 modular domain skills & runbooks")}`);
|
|
4857
|
+
lines2.push(`\u251C\u2500\u2500 \u{1F504} Workflows: ${pc.magenta("69 guided multi-step workflow playbooks")}`);
|
|
4416
4858
|
lines2.push(`\u251C\u2500\u2500 \u{1F50C} Prerequisites: ${pc.dim("None (Self-contained universal suite)")}`);
|
|
4417
4859
|
lines2.push(`\u2514\u2500\u2500 \u{1F4A1} Execution Modes: ${pc.green("Operational")}`);
|
|
4418
4860
|
return lines2.join("\n");
|
|
@@ -4457,27 +4899,34 @@ function renderBundleDetailTree(bundle) {
|
|
|
4457
4899
|
} else {
|
|
4458
4900
|
lines.push(`\u251C\u2500\u2500 \u{1F916} Sub-agents: ${pc.dim("None")}`);
|
|
4459
4901
|
}
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4902
|
+
const domainSkills = (bundle.skills || []).filter((s) => !s.startsWith("workflow-"));
|
|
4903
|
+
const workflowSkills = [
|
|
4904
|
+
...(bundle.skills || []).filter((s) => s.startsWith("workflow-")),
|
|
4905
|
+
...bundle.workflows || []
|
|
4906
|
+
];
|
|
4907
|
+
if (domainSkills.length > 0) {
|
|
4908
|
+
lines.push(`\u251C\u2500\u2500 \u26A1 Skills (${domainSkills.length}):`);
|
|
4909
|
+
if (domainSkills.length <= 5) {
|
|
4910
|
+
lines.push(`\u2502 \u2514\u2500\u2500 ${pc.yellow(domainSkills.join(", "))}`);
|
|
4464
4911
|
} else {
|
|
4465
|
-
lines.push(`\u2502 \u251C\u2500\u2500 ${pc.yellow(
|
|
4466
|
-
lines.push(`\u2502 \u2514\u2500\u2500 ${pc.dim(`(+${
|
|
4912
|
+
lines.push(`\u2502 \u251C\u2500\u2500 ${pc.yellow(domainSkills.slice(0, 5).join(", "))}`);
|
|
4913
|
+
lines.push(`\u2502 \u2514\u2500\u2500 ${pc.dim(`(+${domainSkills.length - 5} more: ${domainSkills.slice(5).join(", ")})`)}`);
|
|
4467
4914
|
}
|
|
4468
|
-
} else {
|
|
4915
|
+
} else if (!bundle.parentBundle && workflowSkills.length === 0) {
|
|
4916
|
+
lines.push(`\u251C\u2500\u2500 \u26A1 Skills: ${pc.dim("None")}`);
|
|
4917
|
+
} else if (bundle.parentBundle && domainSkills.length === 0) {
|
|
4469
4918
|
lines.push(`\u251C\u2500\u2500 \u26A1 Skills: ${pc.dim("Inherited from base bundle")}`);
|
|
4470
4919
|
}
|
|
4471
|
-
if (
|
|
4472
|
-
const wfNames =
|
|
4473
|
-
lines.push(`\u251C\u2500\u2500 \u{1F504} Workflows (${
|
|
4920
|
+
if (workflowSkills.length > 0) {
|
|
4921
|
+
const wfNames = workflowSkills.map((w) => w.replace(/^workflow-/, "").replace(/\.md$/, ""));
|
|
4922
|
+
lines.push(`\u251C\u2500\u2500 \u{1F504} Workflows (${workflowSkills.length}):`);
|
|
4474
4923
|
if (wfNames.length <= 4) {
|
|
4475
4924
|
lines.push(`\u2502 \u2514\u2500\u2500 ${pc.magenta(wfNames.join(", "))}`);
|
|
4476
4925
|
} else {
|
|
4477
4926
|
lines.push(`\u2502 \u251C\u2500\u2500 ${pc.magenta(wfNames.slice(0, 4).join(", "))}`);
|
|
4478
4927
|
lines.push(`\u2502 \u2514\u2500\u2500 ${pc.dim(`(+${wfNames.length - 4} more: ${wfNames.slice(4).join(", ")})`)}`);
|
|
4479
4928
|
}
|
|
4480
|
-
} else {
|
|
4929
|
+
} else if (bundle.parentBundle) {
|
|
4481
4930
|
lines.push(`\u251C\u2500\u2500 \u{1F504} Workflows: ${pc.dim("Inherited from base bundle")}`);
|
|
4482
4931
|
}
|
|
4483
4932
|
if (bundle.prerequisites) {
|
|
@@ -4569,15 +5018,20 @@ ${pc.bold(pc.magenta(header))} ${pc.dim(`(${items.length} bundle${items.length >
|
|
|
4569
5018
|
const displaySubs = subNames.length > 3 ? `${subNames.slice(0, 3).join(", ")} (+${subNames.length - 3} more)` : subNames.join(", ");
|
|
4570
5019
|
console.log(`${subIndent}\u251C\u2500\u2500 \u{1F916} Sub-agents: ${pc.blue(displaySubs)}`);
|
|
4571
5020
|
}
|
|
4572
|
-
|
|
4573
|
-
|
|
5021
|
+
const domainSkills = (b.skills || []).filter((s) => !s.startsWith("workflow-"));
|
|
5022
|
+
const workflowSkills = [
|
|
5023
|
+
...(b.skills || []).filter((s) => s.startsWith("workflow-")),
|
|
5024
|
+
...b.workflows || []
|
|
5025
|
+
];
|
|
5026
|
+
if (domainSkills.length > 0) {
|
|
5027
|
+
const displaySkills = domainSkills.length > 3 ? `${domainSkills.slice(0, 3).join(", ")} (+${domainSkills.length - 3} more)` : domainSkills.join(", ");
|
|
4574
5028
|
console.log(`${subIndent}\u251C\u2500\u2500 \u26A1 Skills: ${pc.yellow(displaySkills)}`);
|
|
4575
5029
|
}
|
|
4576
|
-
if (
|
|
4577
|
-
const wfNames =
|
|
5030
|
+
if (workflowSkills.length > 0) {
|
|
5031
|
+
const wfNames = workflowSkills.map((w) => w.replace(/^workflow-/, "").replace(/\.md$/, ""));
|
|
4578
5032
|
const displayWfs = wfNames.length > 3 ? `${wfNames.slice(0, 3).join(", ")} (+${wfNames.length - 3} more)` : wfNames.join(", ");
|
|
4579
5033
|
console.log(`${subIndent}\u2514\u2500\u2500 \u{1F504} Workflows: ${pc.magenta(displayWfs)}`);
|
|
4580
|
-
} else {
|
|
5034
|
+
} else if (b.parentBundle) {
|
|
4581
5035
|
console.log(`${subIndent}\u2514\u2500\u2500 \u{1F504} Workflows: ${pc.dim("Inherited from parent")}`);
|
|
4582
5036
|
}
|
|
4583
5037
|
if (!isLastBundle) {
|
|
@@ -4611,12 +5065,17 @@ ${pc.bold(pc.cyan("\u{1F3E2} Organization Bundles (Experimental / Cross-Functio
|
|
|
4611
5065
|
const displaySubs = subNames.length > 3 ? `${subNames.slice(0, 3).join(", ")} (+${subNames.length - 3} more)` : subNames.join(", ");
|
|
4612
5066
|
console.log(`${subIndent}\u251C\u2500\u2500 \u{1F916} Sub-agents: ${pc.blue(displaySubs)}`);
|
|
4613
5067
|
}
|
|
4614
|
-
|
|
4615
|
-
|
|
5068
|
+
const orgDomainSkills = (b.skills || []).filter((s) => !s.startsWith("workflow-"));
|
|
5069
|
+
const orgWorkflowSkills = [
|
|
5070
|
+
...(b.skills || []).filter((s) => s.startsWith("workflow-")),
|
|
5071
|
+
...b.workflows || []
|
|
5072
|
+
];
|
|
5073
|
+
if (orgDomainSkills.length > 0) {
|
|
5074
|
+
const displaySkills = orgDomainSkills.length > 3 ? `${orgDomainSkills.slice(0, 3).join(", ")} (+${orgDomainSkills.length - 3} more)` : orgDomainSkills.join(", ");
|
|
4616
5075
|
console.log(`${subIndent}\u251C\u2500\u2500 \u26A1 Skills: ${pc.yellow(displaySkills)}`);
|
|
4617
5076
|
}
|
|
4618
|
-
if (
|
|
4619
|
-
const wfNames =
|
|
5077
|
+
if (orgWorkflowSkills.length > 0) {
|
|
5078
|
+
const wfNames = orgWorkflowSkills.map((w) => w.replace(/^workflow-/, "").replace(/\.md$/, ""));
|
|
4620
5079
|
const displayWfs = wfNames.length > 3 ? `${wfNames.slice(0, 3).join(", ")} (+${wfNames.length - 3} more)` : wfNames.join(", ");
|
|
4621
5080
|
console.log(`${subIndent}\u251C\u2500\u2500 \u{1F504} Workflows: ${pc.magenta(displayWfs)}`);
|
|
4622
5081
|
}
|
|
@@ -5163,7 +5622,7 @@ cli.command("doctor", "Verify health of installed agents, frontmatter schemas, a
|
|
|
5163
5622
|
}
|
|
5164
5623
|
console.log(` \u{1F916} Installed Agents: ${pc.bold(report.agentsCount.toString())}`);
|
|
5165
5624
|
console.log(` \u26A1 Installed Skills: ${pc.bold(report.skillsCount.toString())}`);
|
|
5166
|
-
console.log(` \u{1F504} Installed
|
|
5625
|
+
console.log(` \u{1F504} Installed Workflow Skills: ${pc.bold(report.workflowsCount.toString())}
|
|
5167
5626
|
`);
|
|
5168
5627
|
if (report.clineCapability) {
|
|
5169
5628
|
console.log(pc.bold(pc.cyan("Cline Runtime & Native Discovery Audit:")));
|