@raishin/vanguard-frontier-agentic 1.3.0 → 1.4.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 +23 -1
- package/agents/kubernetes/kubernetes-live-admission-policy-guard-agent/metadata.json +2 -1
- package/agents/kubernetes/kubernetes-live-argocd-sync-guard-agent/metadata.json +2 -1
- package/agents/kubernetes/kubernetes-live-mesh-policy-guard-agent/metadata.json +2 -1
- package/agents/kubernetes/kubernetes-live-network-policy-guard-agent/metadata.json +2 -1
- package/agents/kubernetes/kubernetes-live-velero-restore-guard-agent/metadata.json +2 -1
- package/agents/kubernetes/kubernetes-psa-review-agent/metadata.json +2 -1
- package/agents/terraform/terraform-reviewer/AGENT.md +2 -1
- package/catalog/skill-manifest.json +414 -414
- package/package.json +23 -4
- package/schemas/AGENTS.md +14 -0
- package/schemas/agent.frontmatter.schema.json +89 -0
- package/schemas/agent.schema.json +8 -0
- package/schemas/skill.frontmatter.schema.json +95 -0
- package/scripts/apply-skill-allowed-tools.py +142 -0
- package/scripts/backfill-skill-metadata.py +410 -0
- package/scripts/export-marketplace-agents.mjs +175 -0
- package/skills/argocd/argo-rollouts-progressive-delivery-review/SKILL.md +3 -0
- package/skills/argocd/argocd-gitops-review/SKILL.md +3 -0
- package/skills/aws/aws-agentcore/SKILL.md +3 -0
- package/skills/aws/aws-api-edge-delivery-review/SKILL.md +3 -0
- package/skills/aws/aws-bedrock-agent-security-governor/SKILL.md +3 -0
- package/skills/aws/aws-change-impact-advisor/SKILL.md +3 -0
- package/skills/aws/aws-ci-cd-release-engineer/SKILL.md +3 -0
- package/skills/aws/aws-compliance-evidence-mapper/SKILL.md +3 -0
- package/skills/aws/aws-cost-anomaly-watch-coordinator/SKILL.md +3 -0
- package/skills/aws/aws-cost-optimization-governor/SKILL.md +3 -0
- package/skills/aws/aws-daily-operations-briefing-coordinator/SKILL.md +3 -0
- package/skills/aws/aws-data-protection-backup-steward/SKILL.md +3 -0
- package/skills/aws/aws-deployment-hotfix-operator/SKILL.md +3 -0
- package/skills/aws/aws-devops-agent-skill-designer/SKILL.md +3 -0
- package/skills/aws/aws-dynamodb-data-modeling-performance-review/SKILL.md +3 -0
- package/skills/aws/aws-ec2-compute-operations-steward/SKILL.md +3 -0
- package/skills/aws/aws-ecs-fargate-platform-operator/SKILL.md +3 -0
- package/skills/aws/aws-ecs-service-remediation-operator/SKILL.md +3 -0
- package/skills/aws/aws-eks-platform-operator/SKILL.md +3 -0
- package/skills/aws/aws-event-driven-architecture-review/SKILL.md +3 -0
- package/skills/aws/aws-generative-ai-developer/SKILL.md +3 -0
- package/skills/aws/aws-iac-change-safety-review/SKILL.md +3 -0
- package/skills/aws/aws-iac-patch-executor/SKILL.md +3 -0
- package/skills/aws/aws-iam-least-privilege-review/SKILL.md +3 -0
- package/skills/aws/aws-kms-secrets-lifecycle-steward/SKILL.md +3 -0
- package/skills/aws/aws-landing-zone-governor/SKILL.md +3 -0
- package/skills/aws/aws-live-deployment-guarded-operator/SKILL.md +3 -0
- package/skills/aws/aws-live-ecs-rollout-guard/SKILL.md +3 -0
- package/skills/aws/aws-live-iac-change-guard/SKILL.md +3 -0
- package/skills/aws/aws-live-pipeline-approval-operator/SKILL.md +3 -0
- package/skills/aws/aws-live-serverless-release-guard/SKILL.md +3 -0
- package/skills/aws/aws-maestro/SKILL.md +3 -0
- package/skills/aws/aws-migration-cutover-architect/SKILL.md +3 -0
- package/skills/aws/aws-network-architect/SKILL.md +3 -0
- package/skills/aws/aws-non-destructive-task-automation-advisor/SKILL.md +3 -0
- package/skills/aws/aws-observability-incident-responder/SKILL.md +3 -0
- package/skills/aws/aws-pipeline-fix-operator/SKILL.md +3 -0
- package/skills/aws/aws-private-ca-issuer-review/SKILL.md +3 -0
- package/skills/aws/aws-rds-aurora-performance-investigator/SKILL.md +3 -0
- package/skills/aws/aws-resilience-bcdr-review/SKILL.md +3 -0
- package/skills/aws/aws-s3-data-perimeter-governor/SKILL.md +3 -0
- package/skills/aws/aws-security-posture-hardening/SKILL.md +3 -0
- package/skills/aws/aws-serverless-production-readiness/SKILL.md +3 -0
- package/skills/aws/aws-serverless-rollout-corrector/SKILL.md +3 -0
- package/skills/aws/aws-solution-architect/SKILL.md +3 -0
- package/skills/aws/aws-ticket-triage-escalation-coordinator/SKILL.md +3 -0
- package/skills/azure/azure-ai-foundry-ops-governor/SKILL.md +3 -0
- package/skills/azure/azure-aks-platform-operator/SKILL.md +3 -0
- package/skills/azure/azure-app-service-production-readiness/SKILL.md +3 -0
- package/skills/azure/azure-cosmosdb-application-developer/SKILL.md +3 -0
- package/skills/azure/azure-cosmosdb-performance-investigator/SKILL.md +3 -0
- package/skills/azure/azure-cosmosdb-platform-operator/SKILL.md +3 -0
- package/skills/azure/azure-cost-estimation-review/SKILL.md +3 -0
- package/skills/azure/azure-cost-optimization-governor/SKILL.md +3 -0
- package/skills/azure/azure-entra-id-specialist/SKILL.md +3 -0
- package/skills/azure/azure-governance-policy-guardrails/SKILL.md +3 -0
- package/skills/azure/azure-identity-governance-review/SKILL.md +3 -0
- package/skills/azure/azure-key-vault-secret-lifecycle-auditor/SKILL.md +3 -0
- package/skills/azure/azure-keyvault-certificate-issuer-review/SKILL.md +3 -0
- package/skills/azure/azure-landing-zone-architect/SKILL.md +3 -0
- package/skills/azure/azure-live-aks-rollout-guard/SKILL.md +3 -0
- package/skills/azure/azure-live-app-service-slot-swap-guard/SKILL.md +3 -0
- package/skills/azure/azure-live-arm-deployment-stack-guard/SKILL.md +3 -0
- package/skills/azure/azure-live-cost-budget-action-guard/SKILL.md +3 -0
- package/skills/azure/azure-live-entra-role-assignment-guard/SKILL.md +3 -0
- package/skills/azure/azure-live-keyvault-rotation-purge-guard/SKILL.md +3 -0
- package/skills/azure/azure-live-pim-jit-activation-guard/SKILL.md +3 -0
- package/skills/azure/azure-maestro/SKILL.md +3 -0
- package/skills/azure/azure-migrate-landing-zone-cutover/SKILL.md +3 -0
- package/skills/azure/azure-network-topology-review/SKILL.md +3 -0
- package/skills/azure/azure-observability-investigator/SKILL.md +3 -0
- package/skills/azure/azure-platform-automation-devops/SKILL.md +3 -0
- package/skills/azure/azure-private-endpoint-adoption-planner/SKILL.md +3 -0
- package/skills/azure/azure-rbac-review/SKILL.md +3 -0
- package/skills/azure/azure-resilience-bcdr-review/SKILL.md +3 -0
- package/skills/azure/azure-resource-health-incident-triage/SKILL.md +3 -0
- package/skills/azure/azure-role-selector/SKILL.md +3 -0
- package/skills/azure/azure-security-posture-hardening/SKILL.md +3 -0
- package/skills/azure/azure-subscription-resource-organization/SKILL.md +3 -0
- package/skills/backstage/backstage-scaffolder-template-review/SKILL.md +3 -0
- package/skills/cert-manager/cert-manager-issuer-trust-review/SKILL.md +3 -0
- package/skills/cilium/cilium-network-policy-review/SKILL.md +3 -0
- package/skills/falco/falco-runtime-threat-rules-review/SKILL.md +3 -0
- package/skills/finops/finops-cloud-price-advisor/SKILL.md +3 -0
- package/skills/fluxcd/fluxcd-kustomization-helmrelease-review/SKILL.md +3 -0
- package/skills/istio/istio-ambient-mesh-review/SKILL.md +3 -0
- package/skills/kubernetes/external-secrets-operator-review/SKILL.md +3 -0
- package/skills/kubernetes/kubecost-chargeback-allocation-review/SKILL.md +3 -0
- package/skills/kubernetes/kubernetes-live-rbac-mutation-guard/SKILL.md +3 -0
- package/skills/kubernetes/kubernetes-maestro/SKILL.md +3 -0
- package/skills/kubernetes/kubernetes-pod-security-admission-review/SKILL.md +3 -0
- package/skills/kubernetes/kubernetes-pod-spec-review/SKILL.md +3 -0
- package/skills/kubernetes/kubernetes-rbac-review/SKILL.md +3 -0
- package/skills/kubernetes/kubernetes-workload-identity-review/SKILL.md +3 -0
- package/skills/kyverno/kyverno-policy-review/SKILL.md +3 -0
- package/skills/oci/oci-autonomous-database-architect/SKILL.md +3 -0
- package/skills/oci/oci-certificates-issuer-review/SKILL.md +3 -0
- package/skills/oci/oci-cloud-guard-responder/SKILL.md +3 -0
- package/skills/oci/oci-compute-instance-agent-operator/SKILL.md +3 -0
- package/skills/oci/oci-compute-platform-operator/SKILL.md +3 -0
- package/skills/oci/oci-cost-finops-analyst/SKILL.md +3 -0
- package/skills/oci/oci-database-platform-dba/SKILL.md +3 -0
- package/skills/oci/oci-dbtools-sql-analyst/SKILL.md +3 -0
- package/skills/oci/oci-devops-container-platform-engineer/SKILL.md +3 -0
- package/skills/oci/oci-exadata-database-architect/SKILL.md +3 -0
- package/skills/oci/oci-exadata-platform-architect/SKILL.md +3 -0
- package/skills/oci/oci-fusion-apps-environment-operator/SKILL.md +3 -0
- package/skills/oci/oci-goldengate-replication-operator/SKILL.md +3 -0
- package/skills/oci/oci-identity-access-governor/SKILL.md +3 -0
- package/skills/oci/oci-iot-digital-twin-engineer/SKILL.md +3 -0
- package/skills/oci/oci-limits-capacity-planner/SKILL.md +3 -0
- package/skills/oci/oci-live-autonomous-db-lifecycle-guard/SKILL.md +3 -0
- package/skills/oci/oci-live-cost-budget-runaway-guard/SKILL.md +3 -0
- package/skills/oci/oci-live-iam-policy-compartment-guard/SKILL.md +3 -0
- package/skills/oci/oci-live-network-security-rule-guard/SKILL.md +3 -0
- package/skills/oci/oci-live-oke-rollout-guard/SKILL.md +3 -0
- package/skills/oci/oci-live-resource-manager-stack-guard/SKILL.md +3 -0
- package/skills/oci/oci-live-vault-key-destruction-guard/SKILL.md +3 -0
- package/skills/oci/oci-load-balancer-traffic-engineer/SKILL.md +3 -0
- package/skills/oci/oci-maestro/SKILL.md +3 -0
- package/skills/oci/oci-migration-cutover-architect/SKILL.md +3 -0
- package/skills/oci/oci-multi-cloud-architect/SKILL.md +3 -0
- package/skills/oci/oci-mysql-heatwave-ai-specialist/SKILL.md +3 -0
- package/skills/oci/oci-network-architect/SKILL.md +3 -0
- package/skills/oci/oci-observability-incident-responder/SKILL.md +3 -0
- package/skills/oci/oci-recovery-service-operator/SKILL.md +3 -0
- package/skills/oci/oci-registry-artifact-governor/SKILL.md +3 -0
- package/skills/oci/oci-resource-search-inventory-analyst/SKILL.md +3 -0
- package/skills/oci/oci-security-compliance-reviewer/SKILL.md +3 -0
- package/skills/oci/oci-solution-architect/SKILL.md +3 -0
- package/skills/oci/oci-storage-backup-steward/SKILL.md +3 -0
- package/skills/oci/oci-support-incident-coordinator/SKILL.md +3 -0
- package/skills/oci/oracle-oci-mcp-grounded-advisor/SKILL.md +3 -0
- package/skills/opentelemetry/opentelemetry-collector-config-review/SKILL.md +3 -0
- package/skills/prometheus/prometheus-alerting-cardinality-review/SKILL.md +3 -0
- package/skills/sigstore/sigstore-cosign-supply-chain-review/SKILL.md +3 -0
- package/skills/terraform/terraform-maestro/SKILL.md +3 -0
- package/skills/velero/velero-backup-restore-guard/SKILL.md +3 -0
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Backfill `metadata.updated` and `metadata.category` on every SKILL.md.
|
|
3
|
+
|
|
4
|
+
`updated` is derived from the last git commit date that touched the SKILL.md.
|
|
5
|
+
`category` is classified deterministically from the skill name using a keyword
|
|
6
|
+
rules table with a fixed precedence order.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 scripts/backfill-skill-metadata.py --dry-run
|
|
10
|
+
python3 scripts/backfill-skill-metadata.py
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from __future__ import annotations
|
|
14
|
+
|
|
15
|
+
import argparse
|
|
16
|
+
import re
|
|
17
|
+
import subprocess
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
ROOT = Path(__file__).resolve().parents[1]
|
|
22
|
+
SKILLS_DIR = ROOT / "skills"
|
|
23
|
+
|
|
24
|
+
# Precedence order: earlier categories win when multiple keyword groups match.
|
|
25
|
+
# security > networking > resilience > observability > delivery > compliance
|
|
26
|
+
# > finops > ai > data > platform
|
|
27
|
+
CATEGORY_RULES: list[tuple[str, list[str]]] = [
|
|
28
|
+
(
|
|
29
|
+
"security",
|
|
30
|
+
[
|
|
31
|
+
"iam", "rbac", "secret", "kms", "vault", "perimeter", "policy",
|
|
32
|
+
"psa", "pod-security", "guard", "supply-chain", "falco", "cosign",
|
|
33
|
+
"sigstore", "kyverno", "security", "hardening", "cert-manager",
|
|
34
|
+
"certificate", "private-ca", "issuer", "trust", "workload-identity",
|
|
35
|
+
"entra", "pim", "external-secrets", "keyvault", "key-vault",
|
|
36
|
+
"ambient-mesh", "network-policy", "rotation", "purge", "destruction",
|
|
37
|
+
"cloud-guard", "threat",
|
|
38
|
+
],
|
|
39
|
+
),
|
|
40
|
+
(
|
|
41
|
+
"networking",
|
|
42
|
+
[
|
|
43
|
+
"network", "mesh", "cilium", "istio", "vpc", "endpoint", "topology",
|
|
44
|
+
"load-balancer", "traffic", "private-endpoint", "api-edge", "edge",
|
|
45
|
+
],
|
|
46
|
+
),
|
|
47
|
+
(
|
|
48
|
+
"resilience",
|
|
49
|
+
[
|
|
50
|
+
"backup", "recovery", "bcdr", "resilience", "velero",
|
|
51
|
+
"data-protection", "restore",
|
|
52
|
+
],
|
|
53
|
+
),
|
|
54
|
+
(
|
|
55
|
+
"observability",
|
|
56
|
+
[
|
|
57
|
+
"observability", "monitor", "incident", "responder", "investigator",
|
|
58
|
+
"prometheus", "opentelemetry", "alerting", "resource-health",
|
|
59
|
+
"triage", "health",
|
|
60
|
+
],
|
|
61
|
+
),
|
|
62
|
+
(
|
|
63
|
+
"delivery",
|
|
64
|
+
[
|
|
65
|
+
"ci-cd", "release", "pipeline", "rollout", "deployment", "gitops",
|
|
66
|
+
"argocd", "argo-rollouts", "flux", "scaffolder", "registry",
|
|
67
|
+
"rollout-corrector", "hotfix", "slot-swap", "approval", "devops",
|
|
68
|
+
"platform-automation", "agent-skill-designer", "stack-guard",
|
|
69
|
+
"iac", "arm-deployment", "resource-manager-stack", "migration",
|
|
70
|
+
"cutover", "fix-operator", "patch-executor", "change-impact",
|
|
71
|
+
"change-safety", "deployment-stack",
|
|
72
|
+
],
|
|
73
|
+
),
|
|
74
|
+
(
|
|
75
|
+
"compliance",
|
|
76
|
+
[
|
|
77
|
+
"compliance", "evidence", "audit", "governance", "landing-zone",
|
|
78
|
+
"guardrail", "subscription-resource", "identity-governance",
|
|
79
|
+
"role-selector", "entra-id-specialist", "access-governor",
|
|
80
|
+
"limits-capacity", "resource-search", "ticket-triage",
|
|
81
|
+
],
|
|
82
|
+
),
|
|
83
|
+
(
|
|
84
|
+
"finops",
|
|
85
|
+
[
|
|
86
|
+
"cost", "finops", "budget", "kubecost", "anomaly", "price",
|
|
87
|
+
"chargeback", "estimation",
|
|
88
|
+
],
|
|
89
|
+
),
|
|
90
|
+
(
|
|
91
|
+
"ai",
|
|
92
|
+
[
|
|
93
|
+
"bedrock", "agentcore", "generative", "ai-foundry", "heatwave-ai",
|
|
94
|
+
"iot-digital-twin", "maestro", "grounded-advisor",
|
|
95
|
+
],
|
|
96
|
+
),
|
|
97
|
+
(
|
|
98
|
+
"data",
|
|
99
|
+
[
|
|
100
|
+
"rds", "dynamodb", "cosmos", "aurora", "database", "dba",
|
|
101
|
+
"autonomous-db", "autonomous-database", "exadata", "goldengate",
|
|
102
|
+
"mysql", "dbtools", "sql-analyst", "fusion-apps",
|
|
103
|
+
],
|
|
104
|
+
),
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
# Keywords whose presence forces a re-route override. Some names contain
|
|
108
|
+
# substrings that would mismatch precedence; codify hard overrides here.
|
|
109
|
+
HARD_OVERRIDES: list[tuple[re.Pattern, str]] = [
|
|
110
|
+
# Solution / network / multi-cloud architects are platform/networking design
|
|
111
|
+
(re.compile(r"network-architect$"), "networking"),
|
|
112
|
+
(re.compile(r"network-topology"), "networking"),
|
|
113
|
+
(re.compile(r"multi-cloud-architect$"), "platform"),
|
|
114
|
+
(re.compile(r"solution-architect$"), "platform"),
|
|
115
|
+
(re.compile(r"landing-zone"), "compliance"),
|
|
116
|
+
(re.compile(r"governance-policy-guardrails$"), "compliance"),
|
|
117
|
+
# Live-guard skills with policy/iam/rbac stay security
|
|
118
|
+
(re.compile(r"iam-policy-compartment-guard$"), "security"),
|
|
119
|
+
(re.compile(r"rbac-mutation-guard$"), "security"),
|
|
120
|
+
(re.compile(r"role-assignment-guard$"), "security"),
|
|
121
|
+
(re.compile(r"pim-jit-activation-guard$"), "security"),
|
|
122
|
+
(re.compile(r"vault-key-destruction-guard$"), "security"),
|
|
123
|
+
(re.compile(r"keyvault-rotation-purge-guard$"), "security"),
|
|
124
|
+
(re.compile(r"network-security-rule-guard$"), "security"),
|
|
125
|
+
# Cost-budget guards remain finops despite "guard"
|
|
126
|
+
(re.compile(r"cost-budget-runaway-guard$"), "finops"),
|
|
127
|
+
(re.compile(r"cost-budget-action-guard$"), "finops"),
|
|
128
|
+
# Live IaC change guards are delivery
|
|
129
|
+
(re.compile(r"iac-change-guard$"), "delivery"),
|
|
130
|
+
(re.compile(r"resource-manager-stack-guard$"), "delivery"),
|
|
131
|
+
(re.compile(r"arm-deployment-stack-guard$"), "delivery"),
|
|
132
|
+
# Rollout / deployment guards are delivery
|
|
133
|
+
(re.compile(r"rollout-guard$"), "delivery"),
|
|
134
|
+
(re.compile(r"deployment-guarded-operator$"), "delivery"),
|
|
135
|
+
(re.compile(r"pipeline-approval-operator$"), "delivery"),
|
|
136
|
+
(re.compile(r"serverless-release-guard$"), "delivery"),
|
|
137
|
+
(re.compile(r"slot-swap-guard$"), "delivery"),
|
|
138
|
+
(re.compile(r"app-service-production-readiness$"), "platform"),
|
|
139
|
+
(re.compile(r"app-service.*$"), "platform"),
|
|
140
|
+
(re.compile(r"serverless-production-readiness$"), "platform"),
|
|
141
|
+
(re.compile(r"event-driven-architecture-review$"), "platform"),
|
|
142
|
+
# AKS / EKS / OKE / ECS / Fargate platform operators
|
|
143
|
+
(re.compile(r"aks-platform-operator$"), "platform"),
|
|
144
|
+
(re.compile(r"eks-platform-operator$"), "platform"),
|
|
145
|
+
(re.compile(r"oke.*$"), "platform"),
|
|
146
|
+
(re.compile(r"ecs-fargate-platform-operator$"), "platform"),
|
|
147
|
+
(re.compile(r"ecs-service-remediation-operator$"), "platform"),
|
|
148
|
+
(re.compile(r"compute-platform-operator$"), "platform"),
|
|
149
|
+
(re.compile(r"compute-instance-agent-operator$"), "platform"),
|
|
150
|
+
(re.compile(r"ec2-compute-operations-steward$"), "platform"),
|
|
151
|
+
(re.compile(r"cosmosdb-platform-operator$"), "platform"),
|
|
152
|
+
(re.compile(r"container-platform-engineer$"), "platform"),
|
|
153
|
+
(re.compile(r"environment-operator$"), "platform"),
|
|
154
|
+
# Cosmos / DB performance/dev/audit are data
|
|
155
|
+
(re.compile(r"cosmosdb-application-developer$"), "data"),
|
|
156
|
+
(re.compile(r"cosmosdb-performance-investigator$"), "data"),
|
|
157
|
+
(re.compile(r"keyvault-secret-lifecycle-auditor$"), "security"),
|
|
158
|
+
(re.compile(r"key-vault-secret-lifecycle-auditor$"), "security"),
|
|
159
|
+
(re.compile(r"keyvault-certificate-issuer-review$"), "security"),
|
|
160
|
+
# Pod spec review = platform
|
|
161
|
+
(re.compile(r"pod-spec-review$"), "platform"),
|
|
162
|
+
# Backstage scaffolder = delivery
|
|
163
|
+
(re.compile(r"scaffolder-template-review$"), "delivery"),
|
|
164
|
+
# OCI registry = delivery
|
|
165
|
+
(re.compile(r"registry-artifact-governor$"), "delivery"),
|
|
166
|
+
# Storage backup steward = resilience
|
|
167
|
+
(re.compile(r"storage-backup-steward$"), "resilience"),
|
|
168
|
+
(re.compile(r"data-protection-backup-steward$"), "resilience"),
|
|
169
|
+
(re.compile(r"recovery-service-operator$"), "resilience"),
|
|
170
|
+
# Observability investigators
|
|
171
|
+
(re.compile(r"observability-investigator$"), "observability"),
|
|
172
|
+
(re.compile(r"observability-incident-responder$"), "observability"),
|
|
173
|
+
(re.compile(r"resource-health-incident-triage$"), "observability"),
|
|
174
|
+
(re.compile(r"support-incident-coordinator$"), "observability"),
|
|
175
|
+
(re.compile(r"daily-operations-briefing-coordinator$"), "observability"),
|
|
176
|
+
(re.compile(r"performance-investigator$"), "observability"),
|
|
177
|
+
(re.compile(r"rds-aurora-performance-investigator$"), "data"),
|
|
178
|
+
# Maestros are routing skills — bucket as ai (router/judgment)
|
|
179
|
+
(re.compile(r"-maestro$"), "ai"),
|
|
180
|
+
(re.compile(r"^terraform-maestro$"), "delivery"),
|
|
181
|
+
# Migration cutover architects = delivery
|
|
182
|
+
(re.compile(r"migration-cutover-architect$"), "delivery"),
|
|
183
|
+
(re.compile(r"migrate-landing-zone-cutover$"), "delivery"),
|
|
184
|
+
# Skill designer
|
|
185
|
+
(re.compile(r"agent-skill-designer$"), "delivery"),
|
|
186
|
+
# Identity / RBAC reviews
|
|
187
|
+
(re.compile(r"rbac-review$"), "security"),
|
|
188
|
+
(re.compile(r"identity-governance-review$"), "compliance"),
|
|
189
|
+
(re.compile(r"identity-access-governor$"), "compliance"),
|
|
190
|
+
(re.compile(r"entra-id-specialist$"), "security"),
|
|
191
|
+
# Generative AI dev
|
|
192
|
+
(re.compile(r"generative-ai-developer$"), "ai"),
|
|
193
|
+
(re.compile(r"ai-foundry-ops-governor$"), "ai"),
|
|
194
|
+
(re.compile(r"heatwave-ai-specialist$"), "ai"),
|
|
195
|
+
(re.compile(r"iot-digital-twin-engineer$"), "ai"),
|
|
196
|
+
(re.compile(r"agentcore$"), "ai"),
|
|
197
|
+
(re.compile(r"oracle-oci-mcp-grounded-advisor$"), "ai"),
|
|
198
|
+
(re.compile(r"bedrock-agent-security-governor$"), "security"),
|
|
199
|
+
# Network architect / load balancer
|
|
200
|
+
(re.compile(r"load-balancer-traffic-engineer$"), "networking"),
|
|
201
|
+
(re.compile(r"private-endpoint-adoption-planner$"), "networking"),
|
|
202
|
+
(re.compile(r"api-edge-delivery-review$"), "networking"),
|
|
203
|
+
# Cost
|
|
204
|
+
(re.compile(r"cost-anomaly-watch-coordinator$"), "finops"),
|
|
205
|
+
(re.compile(r"cost-optimization-governor$"), "finops"),
|
|
206
|
+
(re.compile(r"cost-finops-analyst$"), "finops"),
|
|
207
|
+
(re.compile(r"cost-estimation-review$"), "finops"),
|
|
208
|
+
(re.compile(r"cloud-price-advisor$"), "finops"),
|
|
209
|
+
(re.compile(r"chargeback-allocation-review$"), "finops"),
|
|
210
|
+
# Compliance / security posture
|
|
211
|
+
(re.compile(r"security-posture-hardening$"), "security"),
|
|
212
|
+
(re.compile(r"compliance-evidence-mapper$"), "compliance"),
|
|
213
|
+
(re.compile(r"security-compliance-reviewer$"), "compliance"),
|
|
214
|
+
(re.compile(r"cloud-guard-responder$"), "security"),
|
|
215
|
+
# Resilience
|
|
216
|
+
(re.compile(r"resilience-bcdr-review$"), "resilience"),
|
|
217
|
+
# Subscription / governance
|
|
218
|
+
(re.compile(r"subscription-resource-organization$"), "compliance"),
|
|
219
|
+
(re.compile(r"governance-policy-guardrails$"), "compliance"),
|
|
220
|
+
(re.compile(r"limits-capacity-planner$"), "platform"),
|
|
221
|
+
(re.compile(r"resource-search-inventory-analyst$"), "platform"),
|
|
222
|
+
# Platform automation / DevOps
|
|
223
|
+
(re.compile(r"platform-automation-devops$"), "delivery"),
|
|
224
|
+
(re.compile(r"ci-cd-release-engineer$"), "delivery"),
|
|
225
|
+
(re.compile(r"non-destructive-task-automation-advisor$"), "delivery"),
|
|
226
|
+
(re.compile(r"ticket-triage-escalation-coordinator$"), "observability"),
|
|
227
|
+
# Pipeline / hotfix / serverless rollout corrector
|
|
228
|
+
(re.compile(r"pipeline-fix-operator$"), "delivery"),
|
|
229
|
+
(re.compile(r"deployment-hotfix-operator$"), "delivery"),
|
|
230
|
+
(re.compile(r"serverless-rollout-corrector$"), "delivery"),
|
|
231
|
+
(re.compile(r"iac-patch-executor$"), "delivery"),
|
|
232
|
+
(re.compile(r"iac-change-safety-review$"), "delivery"),
|
|
233
|
+
(re.compile(r"change-impact-advisor$"), "delivery"),
|
|
234
|
+
# DynamoDB / RDS modeling = data
|
|
235
|
+
(re.compile(r"dynamodb-data-modeling-performance-review$"), "data"),
|
|
236
|
+
(re.compile(r"dbtools-sql-analyst$"), "data"),
|
|
237
|
+
(re.compile(r"goldengate-replication-operator$"), "data"),
|
|
238
|
+
(re.compile(r"database-platform-dba$"), "data"),
|
|
239
|
+
(re.compile(r"autonomous-database-architect$"), "data"),
|
|
240
|
+
(re.compile(r"autonomous-db-lifecycle-guard$"), "data"),
|
|
241
|
+
(re.compile(r"exadata-platform-architect$"), "platform"),
|
|
242
|
+
(re.compile(r"exadata-database-architect$"), "data"),
|
|
243
|
+
(re.compile(r"fusion-apps-environment-operator$"), "platform"),
|
|
244
|
+
# Architects (broad)
|
|
245
|
+
(re.compile(r"^aws-solution-architect$"), "platform"),
|
|
246
|
+
(re.compile(r"^oci-solution-architect$"), "platform"),
|
|
247
|
+
(re.compile(r"^oci-multi-cloud-architect$"), "platform"),
|
|
248
|
+
(re.compile(r"^azure-landing-zone-architect$"), "compliance"),
|
|
249
|
+
(re.compile(r"^aws-landing-zone-governor$"), "compliance"),
|
|
250
|
+
(re.compile(r"^aws-network-architect$"), "networking"),
|
|
251
|
+
(re.compile(r"^oci-network-architect$"), "networking"),
|
|
252
|
+
]
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def classify(skill_name: str) -> str:
|
|
256
|
+
# Apply hard overrides first.
|
|
257
|
+
for pat, cat in HARD_OVERRIDES:
|
|
258
|
+
if pat.search(skill_name):
|
|
259
|
+
return cat
|
|
260
|
+
|
|
261
|
+
name_l = skill_name.lower()
|
|
262
|
+
for cat, keywords in CATEGORY_RULES:
|
|
263
|
+
for kw in keywords:
|
|
264
|
+
# match whole word-ish on hyphen boundaries
|
|
265
|
+
if kw in name_l:
|
|
266
|
+
return cat
|
|
267
|
+
return "platform"
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def git_last_date(path: Path) -> str | None:
|
|
271
|
+
try:
|
|
272
|
+
out = subprocess.check_output(
|
|
273
|
+
["git", "log", "-1", "--format=%cs", "--", str(path)],
|
|
274
|
+
cwd=ROOT,
|
|
275
|
+
text=True,
|
|
276
|
+
).strip()
|
|
277
|
+
if out and re.match(r"^\d{4}-\d{2}-\d{2}$", out):
|
|
278
|
+
return out
|
|
279
|
+
except subprocess.CalledProcessError:
|
|
280
|
+
return None
|
|
281
|
+
return None
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def find_frontmatter_bounds(text: str) -> tuple[int, int] | None:
|
|
285
|
+
"""Return (start_after_open_fence, end_before_close_fence) line indices."""
|
|
286
|
+
lines = text.splitlines(keepends=True)
|
|
287
|
+
if not lines or lines[0].rstrip("\n") != "---":
|
|
288
|
+
return None
|
|
289
|
+
for i in range(1, len(lines)):
|
|
290
|
+
if lines[i].rstrip("\n") == "---":
|
|
291
|
+
return (1, i)
|
|
292
|
+
return None
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def update_skill_md(path: Path, dry_run: bool) -> tuple[bool, str, str | None, str | None]:
|
|
296
|
+
"""Returns (changed, skill_name, applied_updated, applied_category)."""
|
|
297
|
+
text = path.read_text(encoding="utf-8")
|
|
298
|
+
bounds = find_frontmatter_bounds(text)
|
|
299
|
+
if bounds is None:
|
|
300
|
+
return (False, path.parent.name, None, None)
|
|
301
|
+
|
|
302
|
+
lines = text.splitlines(keepends=True)
|
|
303
|
+
fm_start, fm_end = bounds # fm_end is the closing '---' index
|
|
304
|
+
|
|
305
|
+
# Locate metadata block
|
|
306
|
+
meta_idx = None
|
|
307
|
+
for i in range(fm_start, fm_end):
|
|
308
|
+
if lines[i].startswith("metadata:"):
|
|
309
|
+
meta_idx = i
|
|
310
|
+
break
|
|
311
|
+
if meta_idx is None:
|
|
312
|
+
return (False, path.parent.name, None, None)
|
|
313
|
+
|
|
314
|
+
# Find end of metadata block (next non-indented line within frontmatter)
|
|
315
|
+
meta_block_end = fm_end
|
|
316
|
+
for i in range(meta_idx + 1, fm_end):
|
|
317
|
+
line = lines[i]
|
|
318
|
+
if line.strip() == "":
|
|
319
|
+
continue
|
|
320
|
+
if not (line.startswith(" ") or line.startswith("\t")):
|
|
321
|
+
meta_block_end = i
|
|
322
|
+
break
|
|
323
|
+
|
|
324
|
+
meta_lines = lines[meta_idx + 1 : meta_block_end]
|
|
325
|
+
|
|
326
|
+
has_updated = any(
|
|
327
|
+
re.match(r"^\s+updated\s*:", ln) for ln in meta_lines
|
|
328
|
+
)
|
|
329
|
+
has_category = any(
|
|
330
|
+
re.match(r"^\s+category\s*:", ln) for ln in meta_lines
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
skill_name = path.parent.name
|
|
334
|
+
new_updated = None
|
|
335
|
+
new_category = None
|
|
336
|
+
insertions: list[str] = []
|
|
337
|
+
|
|
338
|
+
if not has_updated:
|
|
339
|
+
date = git_last_date(path) or "2026-05-05"
|
|
340
|
+
new_updated = date
|
|
341
|
+
insertions.append(f' updated: "{date}"\n')
|
|
342
|
+
|
|
343
|
+
if not has_category:
|
|
344
|
+
# Read declared name from frontmatter if available; fall back to dir
|
|
345
|
+
name_in_fm = None
|
|
346
|
+
for i in range(fm_start, fm_end):
|
|
347
|
+
m = re.match(r"^name:\s*(.+)$", lines[i].rstrip("\n"))
|
|
348
|
+
if m:
|
|
349
|
+
name_in_fm = m.group(1).strip().strip('"').strip("'")
|
|
350
|
+
break
|
|
351
|
+
cat = classify(name_in_fm or skill_name)
|
|
352
|
+
new_category = cat
|
|
353
|
+
insertions.append(f" category: {cat}\n")
|
|
354
|
+
|
|
355
|
+
if not insertions:
|
|
356
|
+
return (False, skill_name, None, None)
|
|
357
|
+
|
|
358
|
+
# Insert after the last existing metadata sub-line (keep ordering stable).
|
|
359
|
+
# Find the last non-blank line within meta_lines.
|
|
360
|
+
insert_at = meta_block_end
|
|
361
|
+
# walk back over trailing blank lines
|
|
362
|
+
while insert_at - 1 > meta_idx and lines[insert_at - 1].strip() == "":
|
|
363
|
+
insert_at -= 1
|
|
364
|
+
|
|
365
|
+
new_lines = lines[:insert_at] + insertions + lines[insert_at:]
|
|
366
|
+
|
|
367
|
+
if not dry_run:
|
|
368
|
+
path.write_text("".join(new_lines), encoding="utf-8")
|
|
369
|
+
|
|
370
|
+
return (True, skill_name, new_updated, new_category)
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
def main() -> int:
|
|
374
|
+
ap = argparse.ArgumentParser()
|
|
375
|
+
ap.add_argument("--dry-run", action="store_true")
|
|
376
|
+
args = ap.parse_args()
|
|
377
|
+
|
|
378
|
+
skill_files = sorted(SKILLS_DIR.glob("*/*/SKILL.md"))
|
|
379
|
+
if not skill_files:
|
|
380
|
+
print("ERROR: no SKILL.md files found", file=sys.stderr)
|
|
381
|
+
return 2
|
|
382
|
+
|
|
383
|
+
changed = 0
|
|
384
|
+
cat_counts: dict[str, int] = {}
|
|
385
|
+
rows: list[tuple[str, str | None, str | None]] = []
|
|
386
|
+
|
|
387
|
+
for sf in skill_files:
|
|
388
|
+
ch, name, upd, cat = update_skill_md(sf, args.dry_run)
|
|
389
|
+
if ch:
|
|
390
|
+
changed += 1
|
|
391
|
+
if cat:
|
|
392
|
+
cat_counts[cat] = cat_counts.get(cat, 0) + 1
|
|
393
|
+
rows.append((name, upd, cat))
|
|
394
|
+
|
|
395
|
+
mode = "DRY-RUN" if args.dry_run else "APPLIED"
|
|
396
|
+
print(f"{mode}: {changed} of {len(skill_files)} SKILL.md files updated")
|
|
397
|
+
print("Category distribution:")
|
|
398
|
+
for c in sorted(cat_counts):
|
|
399
|
+
print(f" {c}: {cat_counts[c]}")
|
|
400
|
+
|
|
401
|
+
if args.dry_run:
|
|
402
|
+
print("\nPer-skill assignments:")
|
|
403
|
+
for name, upd, cat in rows:
|
|
404
|
+
print(f" {name}: updated={upd} category={cat}")
|
|
405
|
+
|
|
406
|
+
return 0
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
if __name__ == "__main__":
|
|
410
|
+
sys.exit(main())
|
|
@@ -43,6 +43,53 @@ const PLATFORM_ALIASES = {
|
|
|
43
43
|
kirocli: "kiro-cli",
|
|
44
44
|
};
|
|
45
45
|
|
|
46
|
+
const SKILLS_PLATFORM_CONFIG = {
|
|
47
|
+
"claude-code": ".claude/skills",
|
|
48
|
+
copilot: ".github/skills",
|
|
49
|
+
gemini: ".gemini/skills",
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Platforms that will NEVER support skill bundling because they have no native
|
|
54
|
+
* skill primitive. The value is an explicit notice that replaces the generic
|
|
55
|
+
* "not yet supported" fallback for these platforms.
|
|
56
|
+
*
|
|
57
|
+
* Design rationale: docs/cross-harness-skills.md
|
|
58
|
+
* Cursor — uses Project Rules (.cursor/rules/*.mdc), not skills.
|
|
59
|
+
* Kiro — uses Steering files (.kiro/steering/*.md), not skills.
|
|
60
|
+
* Both mismatches are large enough that skill export is intentionally omitted
|
|
61
|
+
* as a permanent design decision, not a pending TODO.
|
|
62
|
+
*/
|
|
63
|
+
const SKIP_SKILLS_PLATFORM_NOTICES = {
|
|
64
|
+
cursor:
|
|
65
|
+
"[vfa] Skill export is not supported on Cursor. Cursor uses Project Rules " +
|
|
66
|
+
"(.cursor/rules/*.mdc), not skills. The semantics (style guides, glob-based " +
|
|
67
|
+
"triggers) differ significantly from our multi-section operating playbooks; " +
|
|
68
|
+
"this is a permanent design decision, not a pending TODO. " +
|
|
69
|
+
"See docs/cross-harness-skills.md for the full rationale.\n",
|
|
70
|
+
kiro:
|
|
71
|
+
"[vfa] Skill export is not supported on Kiro. Kiro uses Steering files " +
|
|
72
|
+
"(.kiro/steering/*.md), not skills. Steering is single-file guidance with " +
|
|
73
|
+
"plural-by-default inclusion; our SKILL packages bundle scripts/ and " +
|
|
74
|
+
"references/ siblings that Steering cannot accommodate. " +
|
|
75
|
+
"This is a permanent design decision, not a pending TODO. " +
|
|
76
|
+
"See docs/cross-harness-skills.md for the full rationale.\n",
|
|
77
|
+
"kiro-ide":
|
|
78
|
+
"[vfa] Skill export is not supported on Kiro. Kiro uses Steering files " +
|
|
79
|
+
"(.kiro/steering/*.md), not skills. Steering is single-file guidance with " +
|
|
80
|
+
"plural-by-default inclusion; our SKILL packages bundle scripts/ and " +
|
|
81
|
+
"references/ siblings that Steering cannot accommodate. " +
|
|
82
|
+
"This is a permanent design decision, not a pending TODO. " +
|
|
83
|
+
"See docs/cross-harness-skills.md for the full rationale.\n",
|
|
84
|
+
"kiro-cli":
|
|
85
|
+
"[vfa] Skill export is not supported on Kiro. Kiro uses Steering files " +
|
|
86
|
+
"(.kiro/steering/*.md), not skills. Steering is single-file guidance with " +
|
|
87
|
+
"plural-by-default inclusion; our SKILL packages bundle scripts/ and " +
|
|
88
|
+
"references/ siblings that Steering cannot accommodate. " +
|
|
89
|
+
"This is a permanent design decision, not a pending TODO. " +
|
|
90
|
+
"See docs/cross-harness-skills.md for the full rationale.\n",
|
|
91
|
+
};
|
|
92
|
+
|
|
46
93
|
function usage(exitCode = 0) {
|
|
47
94
|
const message = `
|
|
48
95
|
Export selected marketplace agents into a consumer repository.
|
|
@@ -61,12 +108,21 @@ Roles:
|
|
|
61
108
|
cloud-security-engineer, cloud-platform-engineer, cloud-dba,
|
|
62
109
|
cloud-finops-analyst, cloud-solutions-architect, cloud-devops-engineer
|
|
63
110
|
|
|
111
|
+
Companion skills:
|
|
112
|
+
By default, when --platform supports skill bundling (claude-code, copilot, gemini),
|
|
113
|
+
each agent's same-named SKILL.md companion is also exported into the
|
|
114
|
+
platform skill directory (e.g. <repo>/.claude/skills/, <repo>/.github/skills/,
|
|
115
|
+
or <repo>/.gemini/skills/).
|
|
116
|
+
Pairing rule: agent id '<name>-agent' bundles skill '<name>' if it exists.
|
|
117
|
+
Use --no-skills to export agents only.
|
|
118
|
+
|
|
64
119
|
Examples:
|
|
65
120
|
vfa-export-agents --list
|
|
66
121
|
vfa-export-agents --list-roles
|
|
67
122
|
vfa-export-agents --platform claude-code --agents azure-cosmosdb-platform-operator-agent
|
|
68
123
|
vfa-export-agents --platform claude-code --role cloud-security-engineer
|
|
69
124
|
vfa-export-agents --platform claude-code --role cloud-security-engineer --provider azure
|
|
125
|
+
vfa-export-agents --platform claude-code --all --no-skills --repo /path/to/project
|
|
70
126
|
vfa-export-agents --platform kiro --agents azure-cosmosdb-platform-operator-agent --repo ../consumer-repo
|
|
71
127
|
vfa-export-agents --platform copilot --all --repo /path/to/project --force
|
|
72
128
|
`.trim();
|
|
@@ -85,6 +141,7 @@ function parseArgs(argv) {
|
|
|
85
141
|
platform: null,
|
|
86
142
|
role: null,
|
|
87
143
|
provider: null,
|
|
144
|
+
noSkills: false,
|
|
88
145
|
};
|
|
89
146
|
|
|
90
147
|
for (let i = 0; i < argv.length; i += 1) {
|
|
@@ -106,6 +163,10 @@ function parseArgs(argv) {
|
|
|
106
163
|
args.all = true;
|
|
107
164
|
continue;
|
|
108
165
|
}
|
|
166
|
+
if (arg === "--no-skills") {
|
|
167
|
+
args.noSkills = true;
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
109
170
|
if (arg === "--repo") {
|
|
110
171
|
args.repo = path.resolve(argv[++i] ?? "");
|
|
111
172
|
continue;
|
|
@@ -161,6 +222,7 @@ function loadAgents() {
|
|
|
161
222
|
provider: metadata.provider,
|
|
162
223
|
summary: metadata.summary,
|
|
163
224
|
harness_variants: metadata.harness_variants ?? {},
|
|
225
|
+
companion_skills: Array.isArray(metadata.companion_skills) ? metadata.companion_skills : undefined,
|
|
164
226
|
metadataPath,
|
|
165
227
|
};
|
|
166
228
|
});
|
|
@@ -197,6 +259,76 @@ function assertWithin(parent, child, label) {
|
|
|
197
259
|
}
|
|
198
260
|
}
|
|
199
261
|
|
|
262
|
+
function loadSkills() {
|
|
263
|
+
const skillsRoot = path.join(repoRoot, "skills");
|
|
264
|
+
if (!fs.existsSync(skillsRoot)) return new Map();
|
|
265
|
+
const byName = new Map();
|
|
266
|
+
for (const provider of fs.readdirSync(skillsRoot, { withFileTypes: true })) {
|
|
267
|
+
if (!provider.isDirectory()) continue;
|
|
268
|
+
const providerDir = path.join(skillsRoot, provider.name);
|
|
269
|
+
for (const skill of fs.readdirSync(providerDir, { withFileTypes: true })) {
|
|
270
|
+
if (!skill.isDirectory()) continue;
|
|
271
|
+
const skillDir = path.join(providerDir, skill.name);
|
|
272
|
+
if (fs.existsSync(path.join(skillDir, "SKILL.md"))) {
|
|
273
|
+
byName.set(skill.name, skillDir);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return byName;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function copySkillTree(sourceDir, destDir, force) {
|
|
281
|
+
assertWithin(repoRoot, sourceDir, "read skill source");
|
|
282
|
+
for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
283
|
+
const src = path.join(sourceDir, entry.name);
|
|
284
|
+
const dst = path.join(destDir, entry.name);
|
|
285
|
+
if (entry.isSymbolicLink()) {
|
|
286
|
+
throw new Error(`Refusing to copy symbolic link in skill tree: ${src}`);
|
|
287
|
+
}
|
|
288
|
+
if (entry.isDirectory()) {
|
|
289
|
+
copySkillTree(src, dst, force);
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
292
|
+
if (!entry.isFile()) continue;
|
|
293
|
+
if (!force && fs.existsSync(dst)) {
|
|
294
|
+
throw new Error(`Refusing to overwrite existing file without --force: ${dst}`);
|
|
295
|
+
}
|
|
296
|
+
fs.mkdirSync(path.dirname(dst), { recursive: true });
|
|
297
|
+
fs.copyFileSync(src, dst);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function resolveCompanionSkills(selectedAgents, skillsByName, role, includeAll) {
|
|
302
|
+
const skillNames = new Set();
|
|
303
|
+
if (includeAll) {
|
|
304
|
+
for (const name of skillsByName.keys()) skillNames.add(name);
|
|
305
|
+
}
|
|
306
|
+
if (role && Array.isArray(role.skills)) {
|
|
307
|
+
for (const id of role.skills) skillNames.add(id);
|
|
308
|
+
}
|
|
309
|
+
const orphans = [];
|
|
310
|
+
for (const agent of selectedAgents) {
|
|
311
|
+
// Prefer explicit companion_skills if declared (even if empty — that means intentional no-pair)
|
|
312
|
+
if (Array.isArray(agent.companion_skills)) {
|
|
313
|
+
for (const skillId of agent.companion_skills) {
|
|
314
|
+
if (skillsByName.has(skillId)) skillNames.add(skillId);
|
|
315
|
+
}
|
|
316
|
+
// companion_skills: [] is intentional no-pair — do NOT count as orphan
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
// Fall back to name-stripping convention
|
|
320
|
+
const skillName = agent.id.endsWith("-agent")
|
|
321
|
+
? agent.id.slice(0, -"-agent".length)
|
|
322
|
+
: agent.id;
|
|
323
|
+
if (skillsByName.has(skillName)) {
|
|
324
|
+
skillNames.add(skillName);
|
|
325
|
+
} else if (!role) {
|
|
326
|
+
orphans.push(agent.id);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return { skillNames: [...skillNames].sort(), orphans };
|
|
330
|
+
}
|
|
331
|
+
|
|
200
332
|
function copyFile(source, destination, force) {
|
|
201
333
|
const sourceStat = fs.lstatSync(source);
|
|
202
334
|
if (sourceStat.isSymbolicLink()) {
|
|
@@ -292,9 +424,11 @@ function main() {
|
|
|
292
424
|
const platform = ensurePlatform(args.platform);
|
|
293
425
|
|
|
294
426
|
let selectedAgents;
|
|
427
|
+
let selectedRole = null;
|
|
295
428
|
if (args.role) {
|
|
296
429
|
const rolesData = loadRoles();
|
|
297
430
|
const role = Object.hasOwn(rolesData.roles, args.role) ? rolesData.roles[args.role] : undefined;
|
|
431
|
+
selectedRole = role;
|
|
298
432
|
if (!role) {
|
|
299
433
|
const validRoles = Object.keys(rolesData.roles).join(", ");
|
|
300
434
|
throw new Error(`Unknown role: ${args.role}. Valid roles: ${validRoles}`);
|
|
@@ -353,6 +487,47 @@ function main() {
|
|
|
353
487
|
`installed\t${operation.agentId}\t${operation.variantKey}\t${path.relative(args.repo, operation.dest)}`
|
|
354
488
|
);
|
|
355
489
|
}
|
|
490
|
+
|
|
491
|
+
const skillsDestRoot = SKILLS_PLATFORM_CONFIG[platform];
|
|
492
|
+
if (args.noSkills) {
|
|
493
|
+
process.stderr.write(`[vfa] --no-skills: companion skills not bundled.\n`);
|
|
494
|
+
} else if (!skillsDestRoot) {
|
|
495
|
+
const specificNotice = SKIP_SKILLS_PLATFORM_NOTICES[platform];
|
|
496
|
+
if (specificNotice) {
|
|
497
|
+
process.stderr.write(specificNotice);
|
|
498
|
+
} else {
|
|
499
|
+
process.stderr.write(
|
|
500
|
+
`[vfa] Note: skills bundling is not yet supported on platform '${platform}'. ` +
|
|
501
|
+
`Agents exported only. Pass --no-skills to silence.\n`
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
} else {
|
|
505
|
+
const skillsByName = loadSkills();
|
|
506
|
+
const { skillNames, orphans } = resolveCompanionSkills(
|
|
507
|
+
selectedAgents,
|
|
508
|
+
skillsByName,
|
|
509
|
+
selectedRole,
|
|
510
|
+
args.all
|
|
511
|
+
);
|
|
512
|
+
let bundled = 0;
|
|
513
|
+
for (const skillName of skillNames) {
|
|
514
|
+
const sourceDir = skillsByName.get(skillName);
|
|
515
|
+
if (!sourceDir) continue;
|
|
516
|
+
const destDir = path.join(args.repo, skillsDestRoot, skillName);
|
|
517
|
+
assertWithin(args.repo, destDir, "write skill destination");
|
|
518
|
+
copySkillTree(sourceDir, destDir, args.force);
|
|
519
|
+
console.log(`installed\tskill:${skillName}\t${platform}\t${path.relative(args.repo, destDir)}`);
|
|
520
|
+
bundled += 1;
|
|
521
|
+
}
|
|
522
|
+
process.stderr.write(
|
|
523
|
+
`[vfa] Bundled ${bundled} companion skill(s) alongside ${selectedAgents.length} agent(s)` +
|
|
524
|
+
(orphans.length ? ` (no-skill agents: ${orphans.length})` : "") +
|
|
525
|
+
`. Use --no-skills to opt out.\n`
|
|
526
|
+
);
|
|
527
|
+
if (orphans.length && orphans.length <= 10) {
|
|
528
|
+
process.stderr.write(`[vfa] Agents without companion skill: ${orphans.join(", ")}\n`);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
356
531
|
}
|
|
357
532
|
|
|
358
533
|
try {
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: argo-rollouts-progressive-delivery-review
|
|
3
3
|
description: Use this skill when reviewing Argo Rollouts progressive delivery configuration. Trigger when the user asks about canary or blue-green Rollout strategy correctness, AnalysisTemplate success/failure conditions, traffic weighting provider alignment, canaryService isolation, PDB deadlock risk with Rollout maxSurge settings, automated rollback posture, or manual vs automated promotion configuration.
|
|
4
|
+
allowed-tools: Read Grep Glob
|
|
4
5
|
metadata:
|
|
5
6
|
author: "github: Raishin"
|
|
6
7
|
version: "0.1.0"
|
|
8
|
+
updated: "2026-05-05"
|
|
9
|
+
category: delivery
|
|
7
10
|
---
|
|
8
11
|
|
|
9
12
|
# Argo Rollouts Progressive Delivery Review
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: argocd-gitops-review
|
|
3
3
|
description: Use this skill for Argo CD GitOps review across Application, AppProject, ApplicationSet, sync windows, RBAC, sync impersonation, and Argo CD Agent multi-cluster topologies. Trigger when the user asks whether an Argo CD configuration is safe for production, whether automated sync should be enabled, whether prune+selfHeal is appropriate, whether AppProject scope is too wide, or how to enforce least-privilege sync identity.
|
|
4
|
+
allowed-tools: Read Grep Glob
|
|
4
5
|
metadata:
|
|
5
6
|
author: "github: Raishin"
|
|
6
7
|
version: "0.1.0"
|
|
8
|
+
updated: "2026-05-05"
|
|
9
|
+
category: delivery
|
|
7
10
|
---
|
|
8
11
|
|
|
9
12
|
# Argo CD GitOps Review
|