@raishin/vanguard-frontier-agentic 3.11.0 → 3.11.1
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.cursor-plugin/plugin.json +19 -1
- package/.github/plugin/marketplace.json +1 -1
- package/agents/AGENTS.md +24 -24
- package/agents/README.md +17 -17
- package/agents/ionos/ionos-cost-optimization-analyst-agent/metadata.json +17 -3
- package/agents/ionos/ionos-datacenter-designer-reviewer-agent/metadata.json +17 -3
- package/agents/ionos/ionos-kubernetes-platform-operator-agent/metadata.json +17 -3
- package/agents/ionos/ionos-live-database-lifecycle-guard-agent/metadata.json +17 -3
- package/agents/ionos/ionos-maestro-agent/metadata.json +17 -3
- package/agents/ionos/ionos-security-compliance-reviewer-agent/metadata.json +17 -3
- package/agents/ovhcloud/ovhcloud-cost-finops-analyst-agent/metadata.json +17 -3
- package/agents/ovhcloud/ovhcloud-iam-policy-review-agent/metadata.json +17 -3
- package/agents/ovhcloud/ovhcloud-kubernetes-platform-operator-agent/metadata.json +17 -3
- package/agents/ovhcloud/ovhcloud-live-kms-key-destruction-guard-agent/metadata.json +17 -3
- package/agents/ovhcloud/ovhcloud-maestro-agent/metadata.json +17 -3
- package/agents/ovhcloud/ovhcloud-network-architect-agent/metadata.json +17 -3
- package/agents/scaleway/scaleway-cost-optimizer-agent/metadata.json +17 -3
- package/agents/scaleway/scaleway-iam-policy-review-agent/metadata.json +17 -3
- package/agents/scaleway/scaleway-kapsule-platform-operator-agent/metadata.json +17 -3
- package/agents/scaleway/scaleway-live-kapsule-rollout-guard-agent/metadata.json +17 -3
- package/agents/scaleway/scaleway-maestro-agent/metadata.json +17 -3
- package/agents/scaleway/scaleway-network-architect-agent/metadata.json +17 -3
- package/catalog/agents.json +90 -18
- package/catalog/asset-integrity.json +65 -65
- package/package.json +1 -1
- package/plugins/vanguard-frontier-agentic/.codex-plugin/plugin.json +1 -1
- package/powers/README.md +5 -2
- package/scripts/generate-board-counts.mjs +40 -4
- package/tests/validate-catalog.py +156 -0
|
@@ -342,6 +342,154 @@ def validate_guarded_live_kubernetes_agents() -> None:
|
|
|
342
342
|
)
|
|
343
343
|
|
|
344
344
|
|
|
345
|
+
# Adapter files that prove a harness actually ships, mapped to the `harnesses` value
|
|
346
|
+
# that must then be declared.
|
|
347
|
+
HARNESS_ADAPTER_FILES = {
|
|
348
|
+
"codex.toml": "codex",
|
|
349
|
+
"copilot.agent.md": "copilot",
|
|
350
|
+
"claude-code.agent.md": "claude-code",
|
|
351
|
+
"cursor.agent.md": "cursor",
|
|
352
|
+
"gemini.agent.md": "gemini",
|
|
353
|
+
"kiro-ide.agent.md": "kiro",
|
|
354
|
+
"kiro-cli.agent.json": "kiro",
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
# Kiro is the one harness whose single `harnesses` value covers TWO adapter files, and the
|
|
358
|
+
# exporter emits both. Collapsing them into one set member would let a half-shipped Kiro
|
|
359
|
+
# adapter pass: with only kiro-ide.agent.md present, `kiro` is still in the on-disk set, the
|
|
360
|
+
# declaration matches, and the export later fails on the missing kiro-cli.agent.json. So the
|
|
361
|
+
# pair is checked explicitly rather than through the collapsed mapping.
|
|
362
|
+
KIRO_REQUIRED_FILES = ("kiro-ide.agent.md", "kiro-cli.agent.json")
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def validate_harness_declarations() -> None:
|
|
366
|
+
"""Every agent's `harnesses` must match the adapters it ships AND the catalog entry.
|
|
367
|
+
|
|
368
|
+
Three independent failures, each of which has actually happened or was one edit away:
|
|
369
|
+
|
|
370
|
+
* UNDER-declared (adapter on disk, harness absent from `harnesses`) makes a shipped
|
|
371
|
+
adapter invisible to everything that filters on the catalog. ionos, ovhcloud, and
|
|
372
|
+
scaleway each shipped all seven adapter files while declaring only codex and
|
|
373
|
+
claude-code, so generate-cursor-plugin.mjs omitted 18 real cursor adapters and
|
|
374
|
+
generate-kiro-powers.mjs dropped three real Kiro Powers.
|
|
375
|
+
|
|
376
|
+
* OVER-declared (harness claimed, no adapter file) promises an install path that does
|
|
377
|
+
not exist, failing at the user's `vfa-export-agents` rather than here.
|
|
378
|
+
|
|
379
|
+
* CATALOG DRIFT (metadata.json and catalog/agents.json disagree). catalog/agents.json
|
|
380
|
+
has no full regenerator — only an upsert — so fixing metadata.json does NOT update
|
|
381
|
+
it, and the catalog is what every generator actually reads. Checking metadata
|
|
382
|
+
against disk alone would report success while the original user-facing breakage
|
|
383
|
+
remained. This is not hypothetical: resyncing those 18 catalog entries was a
|
|
384
|
+
separate manual step from fixing their metadata.
|
|
385
|
+
"""
|
|
386
|
+
problems: list[str] = []
|
|
387
|
+
|
|
388
|
+
catalog_harnesses: dict[str, list] = {}
|
|
389
|
+
catalog_agents = load_json(ROOT / "catalog" / "agents.json")
|
|
390
|
+
if isinstance(catalog_agents, dict):
|
|
391
|
+
catalog_agents = catalog_agents.get("agents", [])
|
|
392
|
+
for entry in catalog_agents:
|
|
393
|
+
if isinstance(entry, dict) and entry.get("type") == "agent":
|
|
394
|
+
catalog_harnesses[entry["id"]] = entry.get("harnesses") or []
|
|
395
|
+
|
|
396
|
+
for metadata_path in sorted(ROOT.glob("agents/*/*/metadata.json")):
|
|
397
|
+
data = load_json(metadata_path)
|
|
398
|
+
agent_id = data.get("id", metadata_path.parent.name)
|
|
399
|
+
declared = set(data.get("harnesses") or [])
|
|
400
|
+
harness_dir = metadata_path.parent / "harnesses"
|
|
401
|
+
present_files = (
|
|
402
|
+
{entry.name for entry in harness_dir.iterdir() if entry.is_file()}
|
|
403
|
+
if harness_dir.is_dir()
|
|
404
|
+
else set()
|
|
405
|
+
)
|
|
406
|
+
on_disk = {
|
|
407
|
+
HARNESS_ADAPTER_FILES[name]
|
|
408
|
+
for name in present_files
|
|
409
|
+
if name in HARNESS_ADAPTER_FILES
|
|
410
|
+
}
|
|
411
|
+
# "other" is a catalog-only escape hatch with no adapter file of its own.
|
|
412
|
+
declared.discard("other")
|
|
413
|
+
|
|
414
|
+
if on_disk - declared:
|
|
415
|
+
problems.append(
|
|
416
|
+
f"{agent_id}: ships adapters for {sorted(on_disk - declared)} "
|
|
417
|
+
f"but does not declare them in harnesses"
|
|
418
|
+
)
|
|
419
|
+
if declared - on_disk:
|
|
420
|
+
problems.append(
|
|
421
|
+
f"{agent_id}: declares harnesses {sorted(declared - on_disk)} "
|
|
422
|
+
f"with no matching adapter file"
|
|
423
|
+
)
|
|
424
|
+
|
|
425
|
+
# Kiro's two adapter files are checked as a pair, not through the collapsed value.
|
|
426
|
+
kiro_missing = [f for f in KIRO_REQUIRED_FILES if f not in present_files]
|
|
427
|
+
if "kiro" in declared and kiro_missing:
|
|
428
|
+
problems.append(
|
|
429
|
+
f"{agent_id}: declares the kiro harness but is missing {sorted(kiro_missing)} "
|
|
430
|
+
f"— both Kiro adapter files are required"
|
|
431
|
+
)
|
|
432
|
+
if kiro_missing and len(kiro_missing) == 1:
|
|
433
|
+
problems.append(
|
|
434
|
+
f"{agent_id}: ships a partial Kiro adapter — has "
|
|
435
|
+
f"{sorted(set(KIRO_REQUIRED_FILES) - set(kiro_missing))}, missing {kiro_missing}"
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
# The catalog is what the generators read; metadata alone proves nothing about them.
|
|
439
|
+
if agent_id in catalog_harnesses:
|
|
440
|
+
if sorted(catalog_harnesses[agent_id]) != sorted(data.get("harnesses") or []):
|
|
441
|
+
problems.append(
|
|
442
|
+
f"{agent_id}: catalog/agents.json declares "
|
|
443
|
+
f"{sorted(catalog_harnesses[agent_id])} but metadata.json declares "
|
|
444
|
+
f"{sorted(data.get('harnesses') or [])} — resync the catalog entry"
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
assert_true(
|
|
448
|
+
not problems,
|
|
449
|
+
"harness declarations disagree with shipped adapters or the catalog:\n - "
|
|
450
|
+
+ "\n - ".join(problems),
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def validate_tui_provider_enum() -> None:
|
|
455
|
+
"""Every catalog provider must have a variant in the vfa-tui `Provider` enum.
|
|
456
|
+
|
|
457
|
+
tools/vfa-tui deserializes catalog/agents.json into a serde enum with
|
|
458
|
+
`deny_unknown_fields`, so a provider the enum does not know makes the whole catalog
|
|
459
|
+
fail to load and the TUI unusable. A Rust test already asserts this — but CI's
|
|
460
|
+
vfa-tui workflow is path-filtered to `tools/vfa-tui/**` (see
|
|
461
|
+
.github/workflows/vfa-tui-ci.yml), so a catalog-only PR that adds a provider never
|
|
462
|
+
triggers it and merges green while leaving the TUI broken. CLAUDE.md documents that
|
|
463
|
+
trap and asks contributors to remember `cargo test`; this makes remembering
|
|
464
|
+
unnecessary, because `npm run validate` is not path-filtered.
|
|
465
|
+
|
|
466
|
+
Parsed, never executed: variant names are read with a regex and converted to the
|
|
467
|
+
kebab-case slugs serde produces via `rename_all`, plus any explicit `rename = "..."`.
|
|
468
|
+
"""
|
|
469
|
+
enum_path = ROOT / "tools" / "vfa-tui" / "src" / "models" / "provider.rs"
|
|
470
|
+
if not enum_path.exists():
|
|
471
|
+
# The TUI is optional to the catalog's correctness; absence is not a catalog error.
|
|
472
|
+
return
|
|
473
|
+
source = enum_path.read_text(encoding="utf8")
|
|
474
|
+
variants = re.findall(r"^\s{4}([A-Z][A-Za-z0-9]*),\s*$", source, re.MULTILINE)
|
|
475
|
+
slugs = {re.sub(r"(?<!^)(?=[A-Z])", "-", v).lower() for v in variants}
|
|
476
|
+
slugs |= set(re.findall(r'rename\s*=\s*"([a-z0-9-]+)"', source))
|
|
477
|
+
|
|
478
|
+
providers = set()
|
|
479
|
+
for entry in load_json(ROOT / "catalog" / "agents.json"):
|
|
480
|
+
if isinstance(entry, dict) and entry.get("provider"):
|
|
481
|
+
providers.add(entry["provider"])
|
|
482
|
+
|
|
483
|
+
missing = sorted(providers - slugs)
|
|
484
|
+
assert_true(
|
|
485
|
+
not missing,
|
|
486
|
+
"catalog providers with no variant in tools/vfa-tui/src/models/provider.rs: "
|
|
487
|
+
+ f"{missing}. The TUI deserializes catalog/agents.json with a strict enum, so "
|
|
488
|
+
+ "the catalog will fail to load entirely. Add the variant (kebab-case serde) and "
|
|
489
|
+
+ "run `cargo test` in tools/vfa-tui.",
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
|
|
345
493
|
def main() -> int:
|
|
346
494
|
errors: list[str] = []
|
|
347
495
|
seen_ids: set[str] = set()
|
|
@@ -364,6 +512,14 @@ def main() -> int:
|
|
|
364
512
|
validate_codex_harness_adapters()
|
|
365
513
|
except AssertionError as exc:
|
|
366
514
|
errors.append(str(exc))
|
|
515
|
+
try:
|
|
516
|
+
validate_harness_declarations()
|
|
517
|
+
except AssertionError as exc:
|
|
518
|
+
errors.append(str(exc))
|
|
519
|
+
try:
|
|
520
|
+
validate_tui_provider_enum()
|
|
521
|
+
except AssertionError as exc:
|
|
522
|
+
errors.append(str(exc))
|
|
367
523
|
try:
|
|
368
524
|
validate_markdown_agent_templates()
|
|
369
525
|
except AssertionError as exc:
|