@raishin/vanguard-frontier-agentic 2.5.0 → 2.7.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/.agents/tasks/task-jekyll-docs-site/2025-07-17-review.md +118 -0
- package/.agents/tasks/task-jekyll-docs-site/context.json +30 -0
- package/.agents/tasks/task-jekyll-docs-site/features/FEAT-001.json +28 -0
- package/.agents/tasks/task-jekyll-docs-site/features/FEAT-002.json +44 -0
- package/.agents/tasks/task-jekyll-docs-site/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
|
@@ -35,6 +35,8 @@
|
|
|
35
35
|
* 16. --dry-run --no-skills omits skill lines.
|
|
36
36
|
* 17. cursor --dry-run emits agent lines but no skill lines (unsupported platform).
|
|
37
37
|
* 18. --dry-run stderr summary reports skill count on skill-capable platform.
|
|
38
|
+
* 19. codex --all --dry-run emits both agent and skill lines.
|
|
39
|
+
* 20. codex --dry-run --no-skills omits skill lines.
|
|
38
40
|
*
|
|
39
41
|
* F. Full CLI flag surface
|
|
40
42
|
* 19. --list exits 0 and prints all agents.
|
|
@@ -46,6 +48,8 @@
|
|
|
46
48
|
* 25. --platform claude (alias) resolves to claude-code.
|
|
47
49
|
* 26. --no-skills writes agent file but no skills directory.
|
|
48
50
|
* 27. --force overwrites existing agent files without error.
|
|
51
|
+
* 28. codex export writes agent + companion skill and rewrites skill path.
|
|
52
|
+
* 29. two-stage Codex installer dry-run plans all agents and skills.
|
|
49
53
|
*
|
|
50
54
|
* G. Error / rejection cases
|
|
51
55
|
* 28. No args → usage text printed, non-zero exit.
|
|
@@ -65,6 +69,7 @@ import { fileURLToPath } from "node:url";
|
|
|
65
69
|
|
|
66
70
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
67
71
|
const exporter = path.join(repoRoot, "scripts", "export-marketplace-agents.mjs");
|
|
72
|
+
const installer = path.join(repoRoot, "scripts", "install-codex-home.mjs");
|
|
68
73
|
|
|
69
74
|
const agents = JSON.parse(fs.readFileSync(path.join(repoRoot, "catalog/agents.json"), "utf8"));
|
|
70
75
|
const skills = JSON.parse(fs.readFileSync(path.join(repoRoot, "catalog/skills.json"), "utf8"));
|
|
@@ -133,6 +138,12 @@ function run(args) {
|
|
|
133
138
|
return { stdout: r.stdout ?? "", stderr: r.stderr ?? "", exitCode: r.status ?? 0 };
|
|
134
139
|
}
|
|
135
140
|
|
|
141
|
+
function runInstaller(args) {
|
|
142
|
+
const r = spawnSync(process.execPath, [installer, ...args], { encoding: "utf8", timeout: 30000 });
|
|
143
|
+
if (r.signal === "SIGTERM") fail(`installer timed out (30s) for: ${args.join(" ")}`);
|
|
144
|
+
return { stdout: r.stdout ?? "", stderr: r.stderr ?? "", exitCode: r.status ?? 0 };
|
|
145
|
+
}
|
|
146
|
+
|
|
136
147
|
// 5. --provider <p> --all should list the same count as the catalog says.
|
|
137
148
|
{
|
|
138
149
|
const r = run(["--platform", "claude-code", "--provider", "nvidia", "--all", "--dry-run"]);
|
|
@@ -518,6 +529,31 @@ function findLeakedSkills(skillNames, expectedProvider) {
|
|
|
518
529
|
}
|
|
519
530
|
}
|
|
520
531
|
|
|
532
|
+
// E19: codex --all --dry-run emits both agents and companion skills.
|
|
533
|
+
{
|
|
534
|
+
const r = run(["--platform", "codex", "--all", "--dry-run"]);
|
|
535
|
+
const agentCount = (r.stdout.match(/^export agent:/gm) || []).length;
|
|
536
|
+
const skillCount = (r.stdout.match(/^export skill:/gm) || []).length;
|
|
537
|
+
const codexAgents = agents.filter((a) => Array.isArray(a.harnesses) && a.harnesses.includes("codex"));
|
|
538
|
+
if (r.exitCode === 0 && agentCount === codexAgents.length && skillCount === skills.length && /\d+ skill\(s\)/.test(r.stderr)) {
|
|
539
|
+
ok(`E19 codex --all --dry-run emits agents (${agentCount}) and skills (${skillCount})`);
|
|
540
|
+
} else {
|
|
541
|
+
fail(`E19 codex dry-run expected ${codexAgents.length} agents and ${skills.length} skills, got agents=${agentCount} skills=${skillCount}; exit=${r.exitCode}; stderr=${r.stderr.slice(0, 300)}`);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// E20: codex --dry-run --no-skills emits agent lines but no skill lines.
|
|
546
|
+
{
|
|
547
|
+
const r = run(["--platform", "codex", "--agents", "aws-iam-least-privilege-review-agent", "--dry-run", "--no-skills"]);
|
|
548
|
+
const agentCount = (r.stdout.match(/^export agent:/gm) || []).length;
|
|
549
|
+
const skillCount = (r.stdout.match(/^export skill:/gm) || []).length;
|
|
550
|
+
if (r.exitCode === 0 && agentCount === 1 && skillCount === 0) {
|
|
551
|
+
ok("E20 codex --dry-run --no-skills: 1 agent line, 0 skill lines");
|
|
552
|
+
} else {
|
|
553
|
+
fail(`E20 expected 1 agent and 0 skills, got agents=${agentCount} skills=${skillCount}; exit=${r.exitCode}`);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
|
|
521
557
|
// ── F. Full CLI flag surface ──────────────────────────────────────────────────
|
|
522
558
|
|
|
523
559
|
// F19: --list exits 0 and emits one line per agent.
|
|
@@ -638,6 +674,78 @@ function findLeakedSkills(skillNames, expectedProvider) {
|
|
|
638
674
|
}
|
|
639
675
|
}
|
|
640
676
|
|
|
677
|
+
// F28: codex real write installs agent + companion skill and rewrites skill path.
|
|
678
|
+
{
|
|
679
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vfa-test-codex-skills-"));
|
|
680
|
+
try {
|
|
681
|
+
const r = run(["--platform", "codex", "--agents", "aws-iam-least-privilege-review-agent", "--repo", tmpDir]);
|
|
682
|
+
const agentFile = path.join(tmpDir, ".codex", "agents", "aws-iam-least-privilege-review-agent.toml");
|
|
683
|
+
const skillDir = path.join(tmpDir, ".codex", "skills", "aws-iam-least-privilege-review");
|
|
684
|
+
const skillFile = path.join(skillDir, "SKILL.md");
|
|
685
|
+
const agentText = fs.existsSync(agentFile) ? fs.readFileSync(agentFile, "utf8") : "";
|
|
686
|
+
const expectedPathLine = `path = ${JSON.stringify(skillDir)}`;
|
|
687
|
+
if (
|
|
688
|
+
r.exitCode === 0 &&
|
|
689
|
+
fs.existsSync(agentFile) &&
|
|
690
|
+
fs.existsSync(skillFile) &&
|
|
691
|
+
agentText.includes(expectedPathLine) &&
|
|
692
|
+
!agentText.includes('path = "skills/aws/aws-iam-least-privilege-review/SKILL.md"')
|
|
693
|
+
) {
|
|
694
|
+
ok("F28 codex export writes agent + skill and rewrites skill path to installed folder");
|
|
695
|
+
} else {
|
|
696
|
+
fail(`F28 codex export invalid: exit=${r.exitCode} agent=${fs.existsSync(agentFile)} skill=${fs.existsSync(skillFile)} hasExpectedPath=${agentText.includes(expectedPathLine)} stderr=${r.stderr.slice(0, 300)}`);
|
|
697
|
+
}
|
|
698
|
+
} finally {
|
|
699
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
// F28b: skill bundling refuses destination symlinks even with --force.
|
|
704
|
+
{
|
|
705
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vfa-test-skill-symlink-"));
|
|
706
|
+
const outsideDir = fs.mkdtempSync(path.join(os.tmpdir(), "vfa-test-outside-"));
|
|
707
|
+
const outsideFile = path.join(outsideDir, "OUTSIDE_SENTINEL");
|
|
708
|
+
try {
|
|
709
|
+
const skillDir = path.join(tmpDir, ".codex", "skills", "aws-iam-least-privilege-review");
|
|
710
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
711
|
+
fs.writeFileSync(outsideFile, "ORIGINAL_OUTSIDE_SENTINEL\n");
|
|
712
|
+
fs.symlinkSync(outsideFile, path.join(skillDir, "SKILL.md"));
|
|
713
|
+
const r = run([
|
|
714
|
+
"--platform", "codex",
|
|
715
|
+
"--agents", "aws-iam-least-privilege-review-agent",
|
|
716
|
+
"--repo", tmpDir,
|
|
717
|
+
"--force",
|
|
718
|
+
]);
|
|
719
|
+
const outsideText = fs.readFileSync(outsideFile, "utf8");
|
|
720
|
+
if (r.exitCode !== 0 && /symbolic link destination in skill tree/i.test(r.stderr) && outsideText === "ORIGINAL_OUTSIDE_SENTINEL\n") {
|
|
721
|
+
ok("F28b codex skill export rejects destination symlink and preserves outside file");
|
|
722
|
+
} else {
|
|
723
|
+
fail(`F28b expected symlink rejection without outside overwrite; exit=${r.exitCode} preserved=${outsideText === "ORIGINAL_OUTSIDE_SENTINEL\n"} stderr=${r.stderr.slice(0, 300)}`);
|
|
724
|
+
}
|
|
725
|
+
} finally {
|
|
726
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
727
|
+
fs.rmSync(outsideDir, { recursive: true, force: true });
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// F29: two-stage installer dry-run composes marketplace-safe export path.
|
|
732
|
+
{
|
|
733
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "vfa-test-two-stage-"));
|
|
734
|
+
try {
|
|
735
|
+
const r = runInstaller(["--dry-run", "--skip-marketplace", "--repo", tmpDir]);
|
|
736
|
+
const combined = `${r.stdout}
|
|
737
|
+
${r.stderr}`;
|
|
738
|
+
const planMatch = /(\d+) agent\(s\), (\d+) skill\(s\) planned/.exec(combined);
|
|
739
|
+
if (r.exitCode === 0 && planMatch && parseInt(planMatch[1], 10) > 0 && parseInt(planMatch[2], 10) > 0) {
|
|
740
|
+
ok(`F29 two-stage Codex installer dry-run plans all agents and skills (${planMatch[1]} agents, ${planMatch[2]} skills)`);
|
|
741
|
+
} else {
|
|
742
|
+
fail(`F29 installer dry-run did not plan expected agents/skills; exit=${r.exitCode} output=${combined.slice(-500)}`);
|
|
743
|
+
}
|
|
744
|
+
} finally {
|
|
745
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
|
|
641
749
|
// ── G. Error / rejection cases ────────────────────────────────────────────────
|
|
642
750
|
|
|
643
751
|
// G28: No args → usage text printed to stderr, non-zero exit.
|
|
@@ -116,12 +116,34 @@ def main() -> int:
|
|
|
116
116
|
f"{prefix} ({name}): plugin.json name {manifest.get('name')!r} must equal marketplace entry name {name!r}",
|
|
117
117
|
)
|
|
118
118
|
|
|
119
|
-
# Version parity for the primary plugin
|
|
119
|
+
# Version parity and install-surface checks for the primary plugin.
|
|
120
120
|
if name == "vanguard-frontier-agentic":
|
|
121
121
|
if manifest.get("version") != pkg.get("version"):
|
|
122
122
|
errors.append(
|
|
123
123
|
f"{prefix} ({name}): plugin.json version {manifest.get('version')!r} != package.json {pkg.get('version')!r}",
|
|
124
124
|
)
|
|
125
|
+
if manifest.get("skills") != "./skills/":
|
|
126
|
+
errors.append(
|
|
127
|
+
f"{prefix} ({name}): plugin.json must declare skills './skills/' for the bundled Codex install skill",
|
|
128
|
+
)
|
|
129
|
+
install_skill = plugin_dir / "skills" / "vanguard-frontier-agentic-install" / "SKILL.md"
|
|
130
|
+
if not install_skill.is_file():
|
|
131
|
+
errors.append(
|
|
132
|
+
f"{prefix} ({name}): bundled install skill is missing at {install_skill.relative_to(REPO)}",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
skills_path = manifest.get("skills")
|
|
136
|
+
if skills_path is not None:
|
|
137
|
+
if not isinstance(skills_path, str) or not skills_path.startswith("./"):
|
|
138
|
+
errors.append(f"{prefix} ({name}): plugin.json skills path must be a './'-prefixed string")
|
|
139
|
+
else:
|
|
140
|
+
skills_dir = (plugin_dir / skills_path).resolve()
|
|
141
|
+
if not skills_dir.is_relative_to(plugin_dir.resolve()):
|
|
142
|
+
errors.append(f"{prefix} ({name}): plugin.json skills path must stay inside plugin root")
|
|
143
|
+
elif not skills_dir.is_dir():
|
|
144
|
+
errors.append(f"{prefix} ({name}): plugin.json skills directory {skills_path!r} is missing")
|
|
145
|
+
elif not any(skills_dir.glob("*/SKILL.md")):
|
|
146
|
+
errors.append(f"{prefix} ({name}): plugin.json skills directory has no */SKILL.md entries")
|
|
125
147
|
|
|
126
148
|
policy = plugin.get("policy") or {}
|
|
127
149
|
install = policy.get("installation")
|