@raishin/vanguard-frontier-agentic 2.5.0 → 2.6.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/.agents/tasks/task-dynamic-kiro-powers/2025-01-24-120000-review.md +92 -0
- package/.agents/tasks/task-dynamic-kiro-powers/context.json +22 -0
- package/.agents/tasks/task-dynamic-kiro-powers/features/FEAT-001.json +34 -0
- package/.agents/tasks/task-dynamic-kiro-powers/task.json +14 -0
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +1 -1
- package/.github/plugin/marketplace.json +1 -1
- package/README.md +2 -0
- package/catalog/asset-integrity.json +129 -29
- package/package.json +3 -1
- package/plugins/vanguard-frontier-agentic/.codex-plugin/plugin.json +3 -2
- package/plugins/vanguard-frontier-agentic/skills/vanguard-frontier-agentic-install/SKILL.md +37 -0
- package/powers/README.md +28 -10
- package/powers/vanguard-argocd/POWER.md +40 -0
- package/powers/vanguard-backstage/POWER.md +40 -0
- package/powers/vanguard-cert-manager/POWER.md +40 -0
- package/powers/vanguard-cilium/POWER.md +40 -0
- package/powers/vanguard-dotnet/POWER.md +41 -0
- package/powers/vanguard-falco/POWER.md +40 -0
- package/powers/vanguard-fluxcd/POWER.md +40 -0
- package/powers/vanguard-generic/POWER.md +40 -0
- package/powers/vanguard-hr/POWER.md +41 -0
- package/powers/vanguard-istio/POWER.md +40 -0
- package/powers/vanguard-kyverno/POWER.md +40 -0
- package/powers/vanguard-legal/POWER.md +41 -0
- package/powers/vanguard-marketing/POWER.md +41 -0
- package/powers/vanguard-multi-cloud/POWER.md +41 -0
- package/powers/vanguard-opentelemetry/POWER.md +40 -0
- package/powers/vanguard-prometheus/POWER.md +40 -0
- package/powers/vanguard-sigstore/POWER.md +40 -0
- package/scripts/export-marketplace-agents.mjs +26 -0
- package/scripts/generate-kiro-powers.mjs +360 -5
- package/scripts/install-codex-home.mjs +95 -0
- package/tests/test-codex-plugin-marketplace-install.test.mjs +132 -0
- package/tests/test-vfa-export-coverage.test.mjs +108 -0
- package/tests/validate-codex-marketplace.py +23 -1
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "vanguard-multi-cloud"
|
|
3
|
+
displayName: "Vanguard Frontier — Multi-Cloud"
|
|
4
|
+
description: "Curated Multi-Cloud agents for ai economist, cloud price advisor. Routes via finops-maestro-agent to specialist agents based on task scope. Static review only; no live mutations."
|
|
5
|
+
keywords: ["finops", "cloud-pricing", "cost-optimization", "reserved-instances"]
|
|
6
|
+
author: "Raishin"
|
|
7
|
+
---
|
|
8
|
+
# Vanguard Frontier — Multi-Cloud
|
|
9
|
+
|
|
10
|
+
Curated Multi-Cloud agents for ai economist, cloud price advisor. Routes via finops-maestro-agent to specialist agents based on task scope. Static review only; no live mutations.
|
|
11
|
+
|
|
12
|
+
## When to engage this Power
|
|
13
|
+
|
|
14
|
+
Activate when the task references Multi-Cloud services, resources, or operations. Do not activate on unrelated requests — narrow keyword matching is required to avoid false activations (Kiro Powers convention).
|
|
15
|
+
|
|
16
|
+
## Routing pattern
|
|
17
|
+
|
|
18
|
+
- **`finops-maestro-agent`** — classifies and routes the task to the right specialist
|
|
19
|
+
|
|
20
|
+
Use the maestro as the entry point: classify the task, then dispatch to one specialist or a parallel team of specialists. Never have the maestro itself execute a live mutation.
|
|
21
|
+
|
|
22
|
+
## Live-guard agents (gate_mode only)
|
|
23
|
+
|
|
24
|
+
- *(none — this provider has no live-mutation guards in the catalog)*
|
|
25
|
+
|
|
26
|
+
Live-guard agents enforce approval, target confirmation, evidence capture, and rollback plans before executing a mutation. They are never auto-dispatched — the maestro must place them in `live-guard-gate` or `runtime-evidence-gate` mode.
|
|
27
|
+
|
|
28
|
+
## Invariants
|
|
29
|
+
|
|
30
|
+
- Route all tasks through finops-maestro-agent for proper classification and dispatch.
|
|
31
|
+
- Static review only -- agents analyze configuration and provide findings without mutating live systems.
|
|
32
|
+
- Cost recommendations are estimates based on public pricing; verify against actual billing before acting.
|
|
33
|
+
|
|
34
|
+
## Where the agents live
|
|
35
|
+
|
|
36
|
+
Agent specs and adapters are part of the [Vanguard Frontier Agentic](https://github.com/Raishin/vanguard-frontier-agentic) marketplace. For this provider, see `agents/multi-cloud/` in that repository. All 3 agents in this provider ship a Kiro adapter (`harnesses/kiro-ide.agent.md`, `kiro-cli.agent.json`).
|
|
37
|
+
|
|
38
|
+
## Companion install paths
|
|
39
|
+
|
|
40
|
+
- **Claude Code:** `/plugin marketplace add Raishin/vanguard-frontier-agentic` then `/plugin install vanguard-frontier-agentic@vanguard-frontier-agentic`
|
|
41
|
+
- **Codex / Copilot / Cursor / Gemini CLI / Kiro (file export):** `npx vfa-export-agents --platform <harness> --provider multi-cloud --repo .`
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "vanguard-opentelemetry"
|
|
3
|
+
displayName: "Vanguard Frontier — OpenTelemetry"
|
|
4
|
+
description: "Reviews openTelemetry Collector pipeline configuration — receiver/processor/exporter ordering, memory_limiter placement,... Static review only; no live mutations."
|
|
5
|
+
keywords: ["opentelemetry", "otel-collector", "tracing", "observability-pipeline"]
|
|
6
|
+
author: "Raishin"
|
|
7
|
+
---
|
|
8
|
+
# Vanguard Frontier — OpenTelemetry
|
|
9
|
+
|
|
10
|
+
Reviews openTelemetry Collector pipeline configuration — receiver/processor/exporter ordering, memory_limiter placement,... Static review only; no live mutations.
|
|
11
|
+
|
|
12
|
+
## When to engage this Power
|
|
13
|
+
|
|
14
|
+
Activate when the task references OpenTelemetry services, resources, or operations. Do not activate on unrelated requests — narrow keyword matching is required to avoid false activations (Kiro Powers convention).
|
|
15
|
+
|
|
16
|
+
## Routing pattern
|
|
17
|
+
|
|
18
|
+
- *(no maestro for this provider; reference agents directly under `agents/opentelemetry/`)*
|
|
19
|
+
|
|
20
|
+
Reference agents directly from agents/opentelemetry/ without maestro-based routing.
|
|
21
|
+
|
|
22
|
+
## Live-guard agents (gate_mode only)
|
|
23
|
+
|
|
24
|
+
- *(none — this provider has no live-mutation guards in the catalog)*
|
|
25
|
+
|
|
26
|
+
Live-guard agents enforce approval, target confirmation, evidence capture, and rollback plans before executing a mutation. They are never auto-dispatched — the maestro must place them in `live-guard-gate` or `runtime-evidence-gate` mode.
|
|
27
|
+
|
|
28
|
+
## Invariants
|
|
29
|
+
|
|
30
|
+
- Static review only -- agents analyze configuration and provide findings without mutating live systems.
|
|
31
|
+
- Collector pipeline changes affect observability for all instrumented services; review cardinality impact.
|
|
32
|
+
|
|
33
|
+
## Where the agents live
|
|
34
|
+
|
|
35
|
+
Agent specs and adapters are part of the [Vanguard Frontier Agentic](https://github.com/Raishin/vanguard-frontier-agentic) marketplace. For this provider, see `agents/opentelemetry/` in that repository. The single agent in this provider ships a Kiro adapter (`harnesses/kiro-ide.agent.md`, `kiro-cli.agent.json`).
|
|
36
|
+
|
|
37
|
+
## Companion install paths
|
|
38
|
+
|
|
39
|
+
- **Claude Code:** `/plugin marketplace add Raishin/vanguard-frontier-agentic` then `/plugin install vanguard-frontier-agentic@vanguard-frontier-agentic`
|
|
40
|
+
- **Codex / Copilot / Cursor / Gemini CLI / Kiro (file export):** `npx vfa-export-agents --platform <harness> --provider opentelemetry --repo .`
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "vanguard-prometheus"
|
|
3
|
+
displayName: "Vanguard Frontier — Prometheus"
|
|
4
|
+
description: "Reviews prometheus and AlertManager configuration for cardinality risks, alert correctness, scrape security, routing safety,... Static review only; no live mutations."
|
|
5
|
+
keywords: ["prometheus", "alertmanager", "metrics-cardinality", "scrape-config"]
|
|
6
|
+
author: "Raishin"
|
|
7
|
+
---
|
|
8
|
+
# Vanguard Frontier — Prometheus
|
|
9
|
+
|
|
10
|
+
Reviews prometheus and AlertManager configuration for cardinality risks, alert correctness, scrape security, routing safety,... Static review only; no live mutations.
|
|
11
|
+
|
|
12
|
+
## When to engage this Power
|
|
13
|
+
|
|
14
|
+
Activate when the task references Prometheus services, resources, or operations. Do not activate on unrelated requests — narrow keyword matching is required to avoid false activations (Kiro Powers convention).
|
|
15
|
+
|
|
16
|
+
## Routing pattern
|
|
17
|
+
|
|
18
|
+
- *(no maestro for this provider; reference agents directly under `agents/prometheus/`)*
|
|
19
|
+
|
|
20
|
+
Reference agents directly from agents/prometheus/ without maestro-based routing.
|
|
21
|
+
|
|
22
|
+
## Live-guard agents (gate_mode only)
|
|
23
|
+
|
|
24
|
+
- *(none — this provider has no live-mutation guards in the catalog)*
|
|
25
|
+
|
|
26
|
+
Live-guard agents enforce approval, target confirmation, evidence capture, and rollback plans before executing a mutation. They are never auto-dispatched — the maestro must place them in `live-guard-gate` or `runtime-evidence-gate` mode.
|
|
27
|
+
|
|
28
|
+
## Invariants
|
|
29
|
+
|
|
30
|
+
- Static review only -- agents analyze configuration and provide findings without mutating live systems.
|
|
31
|
+
- Alerting rule and scrape config changes affect monitoring coverage; review for metric-name collisions.
|
|
32
|
+
|
|
33
|
+
## Where the agents live
|
|
34
|
+
|
|
35
|
+
Agent specs and adapters are part of the [Vanguard Frontier Agentic](https://github.com/Raishin/vanguard-frontier-agentic) marketplace. For this provider, see `agents/prometheus/` in that repository. The single agent in this provider ships a Kiro adapter (`harnesses/kiro-ide.agent.md`, `kiro-cli.agent.json`).
|
|
36
|
+
|
|
37
|
+
## Companion install paths
|
|
38
|
+
|
|
39
|
+
- **Claude Code:** `/plugin marketplace add Raishin/vanguard-frontier-agentic` then `/plugin install vanguard-frontier-agentic@vanguard-frontier-agentic`
|
|
40
|
+
- **Codex / Copilot / Cursor / Gemini CLI / Kiro (file export):** `npx vfa-export-agents --platform <harness> --provider prometheus --repo .`
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: "vanguard-sigstore"
|
|
3
|
+
displayName: "Vanguard Frontier — Sigstore"
|
|
4
|
+
description: "Reviews cosign image signing, Kyverno imageVerify policy identity constraints, SBOM and SLSA provenance attestations, Rekor... Static review only; no live mutations."
|
|
5
|
+
keywords: ["sigstore", "cosign", "supply-chain-integrity", "image-signing"]
|
|
6
|
+
author: "Raishin"
|
|
7
|
+
---
|
|
8
|
+
# Vanguard Frontier — Sigstore
|
|
9
|
+
|
|
10
|
+
Reviews cosign image signing, Kyverno imageVerify policy identity constraints, SBOM and SLSA provenance attestations, Rekor... Static review only; no live mutations.
|
|
11
|
+
|
|
12
|
+
## When to engage this Power
|
|
13
|
+
|
|
14
|
+
Activate when the task references Sigstore services, resources, or operations. Do not activate on unrelated requests — narrow keyword matching is required to avoid false activations (Kiro Powers convention).
|
|
15
|
+
|
|
16
|
+
## Routing pattern
|
|
17
|
+
|
|
18
|
+
- *(no maestro for this provider; reference agents directly under `agents/sigstore/`)*
|
|
19
|
+
|
|
20
|
+
Reference agents directly from agents/sigstore/ without maestro-based routing.
|
|
21
|
+
|
|
22
|
+
## Live-guard agents (gate_mode only)
|
|
23
|
+
|
|
24
|
+
- *(none — this provider has no live-mutation guards in the catalog)*
|
|
25
|
+
|
|
26
|
+
Live-guard agents enforce approval, target confirmation, evidence capture, and rollback plans before executing a mutation. They are never auto-dispatched — the maestro must place them in `live-guard-gate` or `runtime-evidence-gate` mode.
|
|
27
|
+
|
|
28
|
+
## Invariants
|
|
29
|
+
|
|
30
|
+
- Static review only -- agents analyze configuration and provide findings without mutating live systems.
|
|
31
|
+
- Supply-chain policy changes can block valid deployments; verify cosign keyless trust roots before enforcement.
|
|
32
|
+
|
|
33
|
+
## Where the agents live
|
|
34
|
+
|
|
35
|
+
Agent specs and adapters are part of the [Vanguard Frontier Agentic](https://github.com/Raishin/vanguard-frontier-agentic) marketplace. For this provider, see `agents/sigstore/` in that repository. The single agent in this provider ships a Kiro adapter (`harnesses/kiro-ide.agent.md`, `kiro-cli.agent.json`).
|
|
36
|
+
|
|
37
|
+
## Companion install paths
|
|
38
|
+
|
|
39
|
+
- **Claude Code:** `/plugin marketplace add Raishin/vanguard-frontier-agentic` then `/plugin install vanguard-frontier-agentic@vanguard-frontier-agentic`
|
|
40
|
+
- **Codex / Copilot / Cursor / Gemini CLI / Kiro (file export):** `npx vfa-export-agents --platform <harness> --provider sigstore --repo .`
|
|
@@ -45,6 +45,7 @@ const PLATFORM_ALIASES = {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
const SKILLS_PLATFORM_CONFIG = {
|
|
48
|
+
codex: ".codex/skills",
|
|
48
49
|
"claude-code": ".claude/skills",
|
|
49
50
|
copilot: ".github/skills",
|
|
50
51
|
gemini: ".gemini/skills",
|
|
@@ -332,6 +333,14 @@ function copySkillTree(sourceDir, destDir, force) {
|
|
|
332
333
|
if (entry.isSymbolicLink()) {
|
|
333
334
|
throw new Error(`Refusing to copy symbolic link in skill tree: ${src}`);
|
|
334
335
|
}
|
|
336
|
+
let dstLstat = null;
|
|
337
|
+
try { dstLstat = fs.lstatSync(dst); } catch { /* dst does not exist – fine */ }
|
|
338
|
+
if (dstLstat && dstLstat.isSymbolicLink()) {
|
|
339
|
+
throw new Error(
|
|
340
|
+
`Refusing to write to symbolic link destination in skill tree: ${dst}. ` +
|
|
341
|
+
`Remove the symlink and retry.`
|
|
342
|
+
);
|
|
343
|
+
}
|
|
335
344
|
if (entry.isDirectory()) {
|
|
336
345
|
copySkillTree(src, dst, force);
|
|
337
346
|
continue;
|
|
@@ -420,6 +429,20 @@ function copyFile(source, destination, force) {
|
|
|
420
429
|
fs.copyFileSync(source, destination);
|
|
421
430
|
}
|
|
422
431
|
|
|
432
|
+
function rewriteCodexAgentSkillPaths(agentFile, targetRoot) {
|
|
433
|
+
const text = fs.readFileSync(agentFile, "utf8");
|
|
434
|
+
const rewritten = text.replace(
|
|
435
|
+
/^path = "skills\/[^"\n]+\/([^/"\n]+)\/SKILL\.md"$/gm,
|
|
436
|
+
(_match, skillName) => {
|
|
437
|
+
const skillDir = path.join(targetRoot, SKILLS_PLATFORM_CONFIG.codex, skillName);
|
|
438
|
+
return `path = ${JSON.stringify(skillDir)}`;
|
|
439
|
+
}
|
|
440
|
+
);
|
|
441
|
+
if (rewritten !== text) {
|
|
442
|
+
fs.writeFileSync(agentFile, rewritten);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
423
446
|
function loadRoles() {
|
|
424
447
|
const rolesPath = path.join(repoRoot, "catalog", "install-roles.json");
|
|
425
448
|
if (!fs.existsSync(rolesPath)) {
|
|
@@ -640,6 +663,9 @@ function main() {
|
|
|
640
663
|
for (const operation of operations) {
|
|
641
664
|
assertWithin(args.repo, operation.dest, "write destination");
|
|
642
665
|
copyFile(operation.source, operation.dest, args.force);
|
|
666
|
+
if (platform === "codex") {
|
|
667
|
+
rewriteCodexAgentSkillPaths(operation.dest, args.repo);
|
|
668
|
+
}
|
|
643
669
|
console.log(
|
|
644
670
|
`installed\t${operation.agentId}\t${operation.variantKey}\t${path.relative(args.repo, operation.dest)}`
|
|
645
671
|
);
|
|
@@ -212,6 +212,239 @@ const PROVIDERS = {
|
|
|
212
212
|
|
|
213
213
|
const catalog = JSON.parse(readFileSync(catalogPath, "utf8"));
|
|
214
214
|
|
|
215
|
+
// --- Dynamic provider discovery and derivation ---
|
|
216
|
+
|
|
217
|
+
/** Special-case display name mappings for providers not in PROVIDERS. */
|
|
218
|
+
const DISPLAY_NAME_OVERRIDES = {
|
|
219
|
+
dotnet: ".NET",
|
|
220
|
+
hr: "HR",
|
|
221
|
+
fluxcd: "FluxCD",
|
|
222
|
+
argocd: "ArgoCD",
|
|
223
|
+
opentelemetry: "OpenTelemetry",
|
|
224
|
+
"cert-manager": "Cert-Manager",
|
|
225
|
+
"multi-cloud": "Multi-Cloud",
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
/** Pre-authored keyword sets for derived providers. */
|
|
229
|
+
const DERIVED_KEYWORDS = {
|
|
230
|
+
argocd: ["argocd", "gitops", "progressive-delivery", "application-sync"],
|
|
231
|
+
dotnet: ["dotnet", "csharp", "aspnet-core", "ef-core", "nuget"],
|
|
232
|
+
marketing: ["marketing-governance", "consent-compliance", "advertising-fairness", "email-authentication"],
|
|
233
|
+
hr: ["hr-governance", "employment-risk", "compensation-equity", "recruiting"],
|
|
234
|
+
legal: ["legal-risk", "contract-review", "privacy-compliance", "regulatory"],
|
|
235
|
+
generic: ["test-quality", "ci-pipeline", "helm-chart", "manifest-review"],
|
|
236
|
+
"multi-cloud": ["finops", "cloud-pricing", "cost-optimization", "reserved-instances"],
|
|
237
|
+
backstage: ["backstage", "scaffolder", "software-templates", "developer-portal"],
|
|
238
|
+
"cert-manager": ["cert-manager", "x509", "certificate-lifecycle", "pki"],
|
|
239
|
+
cilium: ["cilium", "network-policy", "ebpf", "cluster-mesh"],
|
|
240
|
+
falco: ["falco", "runtime-threat", "syscall-rules", "container-security"],
|
|
241
|
+
fluxcd: ["fluxcd", "gitops", "kustomization", "helm-release"],
|
|
242
|
+
istio: ["istio", "service-mesh", "ambient-mesh", "mtls"],
|
|
243
|
+
kyverno: ["kyverno", "admission-policy", "cluster-policy", "policy-enforcement"],
|
|
244
|
+
opentelemetry: ["opentelemetry", "otel-collector", "tracing", "observability-pipeline"],
|
|
245
|
+
prometheus: ["prometheus", "alertmanager", "metrics-cardinality", "scrape-config"],
|
|
246
|
+
sigstore: ["sigstore", "cosign", "supply-chain-integrity", "image-signing"],
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Discover all unique providers from the catalog where at least one agent
|
|
251
|
+
* has 'kiro' in its harnesses array.
|
|
252
|
+
*/
|
|
253
|
+
function discoverKiroProviders() {
|
|
254
|
+
const providers = new Set();
|
|
255
|
+
for (const entry of catalog) {
|
|
256
|
+
if (
|
|
257
|
+
entry.type === "agent" &&
|
|
258
|
+
Array.isArray(entry.harnesses) &&
|
|
259
|
+
entry.harnesses.includes("kiro")
|
|
260
|
+
) {
|
|
261
|
+
providers.add(entry.provider);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
return [...providers].sort();
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Title-case a provider name, handling special cases.
|
|
269
|
+
*/
|
|
270
|
+
function titleCaseProvider(provider) {
|
|
271
|
+
if (DISPLAY_NAME_OVERRIDES[provider]) return DISPLAY_NAME_OVERRIDES[provider];
|
|
272
|
+
return provider
|
|
273
|
+
.split("-")
|
|
274
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
275
|
+
.join("-");
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Derive a topic summary from agent IDs for description generation.
|
|
280
|
+
*/
|
|
281
|
+
function deriveTopics(entries) {
|
|
282
|
+
const topics = entries
|
|
283
|
+
.map((e) => e.id)
|
|
284
|
+
.filter((id) => !id.endsWith("-maestro-agent"))
|
|
285
|
+
.map((id) => {
|
|
286
|
+
// Strip provider prefix and -agent / -review-agent suffix
|
|
287
|
+
let topic = id
|
|
288
|
+
.replace(/-review-agent$/, "")
|
|
289
|
+
.replace(/-agent$/, "")
|
|
290
|
+
.replace(/-run-agent$/, "");
|
|
291
|
+
// Remove known provider prefixes
|
|
292
|
+
const prefixes = [
|
|
293
|
+
"dotnet-", "hr-", "legal-", "marketing-", "finops-",
|
|
294
|
+
"argocd-", "backstage-", "cert-manager-", "cilium-",
|
|
295
|
+
"falco-", "fluxcd-", "istio-", "kyverno-",
|
|
296
|
+
"opentelemetry-", "prometheus-", "sigstore-",
|
|
297
|
+
];
|
|
298
|
+
for (const pfx of prefixes) {
|
|
299
|
+
if (topic.startsWith(pfx)) {
|
|
300
|
+
topic = topic.slice(pfx.length);
|
|
301
|
+
break;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
return topic.replace(/-/g, " ");
|
|
305
|
+
})
|
|
306
|
+
.slice(0, 4);
|
|
307
|
+
return topics.join(", ");
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Auto-generate steering content for a provider NOT in the hardcoded
|
|
312
|
+
* PROVIDERS object.
|
|
313
|
+
*/
|
|
314
|
+
function deriveProviderConfig(provider, catalogEntries) {
|
|
315
|
+
const displayLabel = titleCaseProvider(provider);
|
|
316
|
+
const displayName = `Vanguard Frontier \u2014 ${displayLabel}`;
|
|
317
|
+
|
|
318
|
+
const entries = catalogEntries.filter(
|
|
319
|
+
(e) => e.type === "agent" && e.provider === provider,
|
|
320
|
+
);
|
|
321
|
+
const maestro = entries.find((e) => e.id.endsWith("-maestro-agent"));
|
|
322
|
+
const liveGuards = entries.filter((e) => /-live-/.test(e.id));
|
|
323
|
+
|
|
324
|
+
// Build description (max 3 sentences)
|
|
325
|
+
let description;
|
|
326
|
+
if (maestro && entries.length > 2) {
|
|
327
|
+
const topics = deriveTopics(entries);
|
|
328
|
+
description = `Curated ${displayLabel} agents for ${topics}. Routes via ${maestro.id} to specialist agents based on task scope. Static review only; no live mutations.`;
|
|
329
|
+
} else if (entries.length === 1) {
|
|
330
|
+
// Single agent, no maestro
|
|
331
|
+
const summary = entries[0].summary || "";
|
|
332
|
+
// Split into sentences - skip "Agent for <id>." prefix if present
|
|
333
|
+
const sentences = summary.split(/(?<=[.!?])\s/);
|
|
334
|
+
let useSentence = sentences[0] || "";
|
|
335
|
+
if (/^Agent for\s/i.test(useSentence) && sentences.length > 1) {
|
|
336
|
+
useSentence = sentences[1];
|
|
337
|
+
}
|
|
338
|
+
// Remove trailing period for reassembly
|
|
339
|
+
useSentence = useSentence.replace(/\.$/, "");
|
|
340
|
+
// Strip leading "Static review of" / "Review" prefix to avoid doubling
|
|
341
|
+
let core = useSentence
|
|
342
|
+
.replace(/^Static,?\s+evidence-gated\s+review\s+of\s+/i, "")
|
|
343
|
+
.replace(/^Static\s+review\s+of\s+/i, "")
|
|
344
|
+
.replace(/^Review\s+(a\s+)?/i, "");
|
|
345
|
+
// Truncate if too long, respecting word boundaries
|
|
346
|
+
if (core.length > 120) {
|
|
347
|
+
const truncated = core.substring(0, 117);
|
|
348
|
+
const lastSpace = truncated.lastIndexOf(" ");
|
|
349
|
+
core = (lastSpace > 0 ? truncated.substring(0, lastSpace) : truncated) + "...";
|
|
350
|
+
}
|
|
351
|
+
const sep = core.endsWith("...") ? " " : ". ";
|
|
352
|
+
description = `Reviews ${core.charAt(0).toLowerCase() + core.slice(1)}${sep}Static review only; no live mutations.`;
|
|
353
|
+
} else {
|
|
354
|
+
// Multiple agents, no maestro
|
|
355
|
+
const topics = deriveTopics(entries);
|
|
356
|
+
description = `Curated ${displayLabel} review agents covering ${topics}. Reference agents directly under agents/${provider}/. Static review only; no live mutations.`;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Keywords
|
|
360
|
+
const keywords = DERIVED_KEYWORDS[provider] || [
|
|
361
|
+
provider,
|
|
362
|
+
"static-review",
|
|
363
|
+
"configuration-audit",
|
|
364
|
+
"best-practices",
|
|
365
|
+
];
|
|
366
|
+
|
|
367
|
+
// Invariants
|
|
368
|
+
const invariants = [];
|
|
369
|
+
if (liveGuards.length > 0) {
|
|
370
|
+
invariants.push(
|
|
371
|
+
`Live-guard agents (${provider}-live-*) must never be auto-dispatched; require explicit approval and rollback plan.`,
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
if (maestro) {
|
|
375
|
+
invariants.push(
|
|
376
|
+
`Route all tasks through ${maestro.id} for proper classification and dispatch.`,
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
invariants.push(
|
|
380
|
+
"Static review only -- agents analyze configuration and provide findings without mutating live systems.",
|
|
381
|
+
);
|
|
382
|
+
// Add domain-specific invariants
|
|
383
|
+
if (provider === "dotnet") {
|
|
384
|
+
invariants.push("Review covers language runtime, frameworks, data access, testing, and supply-chain integrity.");
|
|
385
|
+
} else if (provider === "hr") {
|
|
386
|
+
invariants.push("All findings must respect employee privacy and data-minimization principles.");
|
|
387
|
+
} else if (provider === "legal") {
|
|
388
|
+
invariants.push("Agents provide risk-flagging only; output is not legal advice and does not create attorney-client privilege.");
|
|
389
|
+
} else if (provider === "marketing") {
|
|
390
|
+
invariants.push("Review covers consent, privacy, fairness, and regulatory compliance for marketing systems.");
|
|
391
|
+
} else if (provider === "multi-cloud") {
|
|
392
|
+
invariants.push("Cost recommendations are estimates based on public pricing; verify against actual billing before acting.");
|
|
393
|
+
} else if (provider === "generic") {
|
|
394
|
+
invariants.push("Agents are provider-agnostic and focus on CI, Helm, manifest, and test-quality patterns.");
|
|
395
|
+
} else if (provider === "argocd") {
|
|
396
|
+
invariants.push("Sync and rollout strategies must be validated against the target cluster GitOps workflow.");
|
|
397
|
+
} else if (provider === "backstage") {
|
|
398
|
+
invariants.push("Template parameters and scaffolder actions must be reviewed for injection and secret-exposure risks.");
|
|
399
|
+
} else if (provider === "cert-manager") {
|
|
400
|
+
invariants.push("Certificate renewal windows and issuer trust chains must be validated before any policy change.");
|
|
401
|
+
} else if (provider === "cilium") {
|
|
402
|
+
invariants.push("Network policies must be reviewed for unintended traffic blocking across namespaces and cluster-mesh endpoints.");
|
|
403
|
+
} else if (provider === "falco") {
|
|
404
|
+
invariants.push("Rule changes must be evaluated for false-positive rate impact on production alerting.");
|
|
405
|
+
} else if (provider === "fluxcd") {
|
|
406
|
+
invariants.push("Kustomization and HelmRelease reconciliation intervals must align with the GitOps change cadence.");
|
|
407
|
+
} else if (provider === "istio") {
|
|
408
|
+
invariants.push("Service mesh policies affect traffic routing cluster-wide; review blast radius before changes.");
|
|
409
|
+
} else if (provider === "kyverno") {
|
|
410
|
+
invariants.push("Cluster-scoped policies can reject legitimate workloads; validate against existing deployments before applying.");
|
|
411
|
+
} else if (provider === "opentelemetry") {
|
|
412
|
+
invariants.push("Collector pipeline changes affect observability for all instrumented services; review cardinality impact.");
|
|
413
|
+
} else if (provider === "prometheus") {
|
|
414
|
+
invariants.push("Alerting rule and scrape config changes affect monitoring coverage; review for metric-name collisions.");
|
|
415
|
+
} else if (provider === "sigstore") {
|
|
416
|
+
invariants.push("Supply-chain policy changes can block valid deployments; verify cosign keyless trust roots before enforcement.");
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return { displayName, description, keywords, invariants };
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Build a merged map combining hand-authored PROVIDERS with auto-derived
|
|
424
|
+
* entries for all kiro-enabled providers in the catalog.
|
|
425
|
+
*/
|
|
426
|
+
function buildMergedProviders() {
|
|
427
|
+
const kiroProviders = discoverKiroProviders();
|
|
428
|
+
const merged = {};
|
|
429
|
+
|
|
430
|
+
for (const provider of kiroProviders) {
|
|
431
|
+
if (PROVIDERS[provider]) {
|
|
432
|
+
merged[provider] = PROVIDERS[provider];
|
|
433
|
+
} else {
|
|
434
|
+
merged[provider] = deriveProviderConfig(provider, catalog);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Sort alphabetically for deterministic output
|
|
439
|
+
const sorted = {};
|
|
440
|
+
for (const key of Object.keys(merged).sort()) {
|
|
441
|
+
sorted[key] = merged[key];
|
|
442
|
+
}
|
|
443
|
+
return sorted;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const allProviders = buildMergedProviders();
|
|
447
|
+
|
|
215
448
|
function summarize(provider) {
|
|
216
449
|
const entries = catalog.filter(
|
|
217
450
|
(e) => e.type === "agent" && e.provider === provider,
|
|
@@ -254,7 +487,9 @@ function renderPower(provider, cfg) {
|
|
|
254
487
|
|
|
255
488
|
const adapterNote =
|
|
256
489
|
kiroAvailable === total
|
|
257
|
-
?
|
|
490
|
+
? total === 1
|
|
491
|
+
? `The single agent in this provider ships a Kiro adapter (\`harnesses/kiro-ide.agent.md\`, \`kiro-cli.agent.json\`).`
|
|
492
|
+
: `All ${total} agents in this provider ship a Kiro adapter (\`harnesses/kiro-ide.agent.md\`, \`kiro-cli.agent.json\`).`
|
|
258
493
|
: kiroAvailable === 0
|
|
259
494
|
? `This provider's ${total} agents do not yet ship Kiro adapters — this Power supplies steering content only. Use \`npx vfa-export-agents --platform kiro --provider ${provider}\` from the npm package once Kiro adapters land.`
|
|
260
495
|
: `${kiroAvailable} of ${total} agents in this provider ship a Kiro adapter; the rest provide steering context only.`;
|
|
@@ -273,7 +508,9 @@ function renderPower(provider, cfg) {
|
|
|
273
508
|
"",
|
|
274
509
|
maestroLine,
|
|
275
510
|
"",
|
|
276
|
-
|
|
511
|
+
maestro
|
|
512
|
+
? "Use the maestro as the entry point: classify the task, then dispatch to one specialist or a parallel team of specialists. Never have the maestro itself execute a live mutation."
|
|
513
|
+
: "Reference agents directly from agents/" + provider + "/ without maestro-based routing.",
|
|
277
514
|
"",
|
|
278
515
|
"## Live-guard agents (gate_mode only)",
|
|
279
516
|
"",
|
|
@@ -299,10 +536,114 @@ function renderPower(provider, cfg) {
|
|
|
299
536
|
return frontmatter + body;
|
|
300
537
|
}
|
|
301
538
|
|
|
539
|
+
function renderReadme() {
|
|
540
|
+
const providerKeys = Object.keys(allProviders);
|
|
541
|
+
const count = providerKeys.length;
|
|
542
|
+
const tree = providerKeys
|
|
543
|
+
.map((p, i) => {
|
|
544
|
+
const prefix = i < count - 1 ? "├──" : "└──";
|
|
545
|
+
return `${prefix} vanguard-${p}/POWER.md`;
|
|
546
|
+
})
|
|
547
|
+
.join("\n");
|
|
548
|
+
|
|
549
|
+
return `# \`powers/\` — Kiro Powers
|
|
550
|
+
|
|
551
|
+
This directory holds **${count} Kiro Powers** for \`vanguard-frontier-agentic\`, one
|
|
552
|
+
per cloud/platform/IaC provider. Each Power is a directory containing a
|
|
553
|
+
\`POWER.md\` file with strict-5 frontmatter and steering content.
|
|
554
|
+
|
|
555
|
+
## What's in here
|
|
556
|
+
|
|
557
|
+
\`\`\`
|
|
558
|
+
powers/
|
|
559
|
+
${tree}
|
|
560
|
+
\`\`\`
|
|
561
|
+
|
|
562
|
+
Each \`POWER.md\` declares:
|
|
563
|
+
|
|
564
|
+
- **Frontmatter (strict-5):** \`name\`, \`displayName\`, \`description\` (≤ 3
|
|
565
|
+
sentences), \`keywords\` (specific, non-broad), \`author\`. **No other fields
|
|
566
|
+
permitted** by Kiro spec.
|
|
567
|
+
- **Body steering:** when to engage, routing pattern (\`<provider>-maestro\`),
|
|
568
|
+
live-mutation discipline, provider-specific invariants (e.g. MLPS 2.0 for
|
|
569
|
+
Alibaba/Huawei, Enterprise Project vs IAM scope for Huawei, account-ID
|
|
570
|
+
/region confirmation for AWS).
|
|
571
|
+
|
|
572
|
+
## How users install
|
|
573
|
+
|
|
574
|
+
Kiro Powers don't have a one-command marketplace install — the Powers panel
|
|
575
|
+
is per-Power directory add. Users clone the repo and add each Power they
|
|
576
|
+
need via the Kiro UI:
|
|
577
|
+
|
|
578
|
+
\`\`\`bash
|
|
579
|
+
# 1. Clone the repo
|
|
580
|
+
git clone https://github.com/Raishin/vanguard-frontier-agentic
|
|
581
|
+
cd vanguard-frontier-agentic
|
|
582
|
+
\`\`\`
|
|
583
|
+
|
|
584
|
+
\`\`\`text
|
|
585
|
+
2. In Kiro:
|
|
586
|
+
Open the Powers panel → "Add Custom Power" → "Local Directory"
|
|
587
|
+
Paste the absolute path to the Power(s) you need:
|
|
588
|
+
/absolute/path/to/vanguard-frontier-agentic/powers/vanguard-aws
|
|
589
|
+
/absolute/path/to/vanguard-frontier-agentic/powers/vanguard-kubernetes
|
|
590
|
+
Repeat for each provider you work with.
|
|
591
|
+
\`\`\`
|
|
592
|
+
|
|
593
|
+
## How to update
|
|
594
|
+
|
|
595
|
+
\`\`\`bash
|
|
596
|
+
# Regenerate the ${count} Powers from catalog/agents.json + per-provider config:
|
|
597
|
+
npm run kiro-powers:write
|
|
598
|
+
|
|
599
|
+
# Then verify everything is in sync:
|
|
600
|
+
npm run validate:kiro-powers
|
|
601
|
+
\`\`\`
|
|
602
|
+
|
|
603
|
+
The \`validate\` chain runs \`validate:kiro-powers\` automatically. The
|
|
604
|
+
validator enforces:
|
|
605
|
+
|
|
606
|
+
- strict-5 frontmatter (any extra field fails)
|
|
607
|
+
- lowercase kebab-case names
|
|
608
|
+
- name matches directory name
|
|
609
|
+
- description ≤ 3 sentences (decimal-aware — "MLPS 2.0" doesn't count as a
|
|
610
|
+
sentence break)
|
|
611
|
+
- non-empty keywords list, no broad terms (\`cloud\`, \`devops\`, \`code\`,
|
|
612
|
+
\`agent\`, \`ml\`, etc.) per Kiro's anti-false-activation guidance
|
|
613
|
+
- generator in sync (\`--check\`)
|
|
614
|
+
|
|
615
|
+
## Schema references (official Kiro docs)
|
|
616
|
+
|
|
617
|
+
- **Kiro Powers repo:** <https://github.com/kirodotdev/powers>
|
|
618
|
+
- **POWER.md frontmatter spec:**
|
|
619
|
+
<https://github.com/kirodotdev/powers/blob/main/power-builder/POWER.md>
|
|
620
|
+
- **Interactive power builder:**
|
|
621
|
+
<https://github.com/kirodotdev/powers/blob/main/power-builder/steering/interactive.md>
|
|
622
|
+
- **Testing a power locally:**
|
|
623
|
+
<https://github.com/kirodotdev/powers/blob/main/power-builder/steering/testing.md>
|
|
624
|
+
- **Kiro IDE:** <https://kiro.dev/>
|
|
625
|
+
|
|
626
|
+
## Design notes
|
|
627
|
+
|
|
628
|
+
- **One Power per provider, not one mega-Power** — Kiro docs warn that
|
|
629
|
+
broad keywords trigger false activations across unrelated tasks. One
|
|
630
|
+
narrowly-scoped Power per provider keeps activation precise:
|
|
631
|
+
\`vanguard-alibaba\` activates on Alibaba Cloud work only; \`vanguard-aws\`
|
|
632
|
+
never activates on Azure questions.
|
|
633
|
+
- **Hetzner and Contabo Powers exist** even though their agents don't yet
|
|
634
|
+
ship Kiro adapter files (their \`harnesses: [codex, claude-code]\`). Powers
|
|
635
|
+
are steering-first — the steering content stands alone. When their Kiro
|
|
636
|
+
adapter files land, the Powers will gain agent-routing as well.
|
|
637
|
+
- **No \`version\`, \`repository\`, \`license\`, or \`tags\`** — Kiro spec
|
|
638
|
+
explicitly forbids these fields in frontmatter. The validator fails on
|
|
639
|
+
any extra field.
|
|
640
|
+
`;
|
|
641
|
+
}
|
|
642
|
+
|
|
302
643
|
const errors = [];
|
|
303
644
|
const written = [];
|
|
304
645
|
|
|
305
|
-
for (const [provider, cfg] of Object.entries(
|
|
646
|
+
for (const [provider, cfg] of Object.entries(allProviders)) {
|
|
306
647
|
const dir = join(powersRoot, `vanguard-${provider}`);
|
|
307
648
|
const file = join(dir, "POWER.md");
|
|
308
649
|
const next = renderPower(provider, cfg);
|
|
@@ -322,15 +663,29 @@ for (const [provider, cfg] of Object.entries(PROVIDERS)) {
|
|
|
322
663
|
}
|
|
323
664
|
}
|
|
324
665
|
|
|
666
|
+
// Generate/check README.md
|
|
667
|
+
const readmePath = join(powersRoot, "README.md");
|
|
668
|
+
const nextReadme = renderReadme();
|
|
669
|
+
if (check) {
|
|
670
|
+
if (!existsSync(readmePath)) {
|
|
671
|
+
errors.push(`${relative(repoRoot, readmePath)} is missing`);
|
|
672
|
+
} else if (readFileSync(readmePath, "utf8") !== nextReadme) {
|
|
673
|
+
errors.push(`${relative(repoRoot, readmePath)} is stale; run npm run kiro-powers:write`);
|
|
674
|
+
}
|
|
675
|
+
} else {
|
|
676
|
+
writeFileSync(readmePath, nextReadme);
|
|
677
|
+
written.push(relative(repoRoot, readmePath));
|
|
678
|
+
}
|
|
679
|
+
|
|
325
680
|
if (check) {
|
|
326
681
|
if (errors.length) {
|
|
327
682
|
errors.forEach((e) => console.error(`ERROR: ${e}`));
|
|
328
683
|
process.exit(1);
|
|
329
684
|
}
|
|
330
685
|
console.log(
|
|
331
|
-
`OK: ${Object.keys(
|
|
686
|
+
`OK: ${Object.keys(allProviders).length} Kiro Powers are in sync`,
|
|
332
687
|
);
|
|
333
688
|
} else {
|
|
334
|
-
console.log(`OK: wrote ${written.length} Kiro Powers`);
|
|
689
|
+
console.log(`OK: wrote ${written.length} Kiro Powers (+ README.md)`);
|
|
335
690
|
written.forEach((f) => console.log(` ${f}`));
|
|
336
691
|
}
|