diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..5a318c6 --- /dev/null +++ b/.mcp.json @@ -0,0 +1,16 @@ +{ + "servers": { + "workiq": { + "command": "npx", + "args": ["-y", "@microsoft/workiq", "mcp"], + "tools": ["*"] + }, + "github": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" + } + } + } +} diff --git a/docs/prototype-marketplace-plan.md b/docs/prototype-marketplace-plan.md new file mode 100644 index 0000000..f6a0cb6 --- /dev/null +++ b/docs/prototype-marketplace-plan.md @@ -0,0 +1,264 @@ +# Prototype Marketplace — Inner Loop / Outer Loop System Plan + +> **Issue:** [#1 — Shyam's Crazy Idea](https://github.com/All-The-Vibes/atv-platform/issues/1) +> **Vision:** Idea-to-Prototype generator — curate ideas from ATV channels and build a catalog of prototypes (Prototype Marketplace) +> **Insight from @sachaa:** Focus on identifying **problems** that need solving, not just ideas. Inspired by [ideabrowser.com/database](https://www.ideabrowser.com/database). + +--- + +## 1. Overview + +This document describes a comprehensive plan for the **Prototype Marketplace** — a system that discovers problems and ideas across All-The-Vibes (ATV) channels, curates them into a structured catalog, and enables rapid prototyping through an **inner loop / outer loop** workflow powered by [WorkIQ](https://learn.microsoft.com/en-us/azure/devops/mcp-server/mcp-server-overview). + +### Core Concept + +``` +ATV Channels ──► Problem/Idea Curation ──► Prototype Catalog ──► Marketplace + │ │ + (Outer Loop) (Inner Loop) + Discovery & Rapid Build & + Prioritization Iteration +``` + +--- + +## 2. Inner Loop / Outer Loop Model + +### 2.1 Inner Loop — Rapid Prototyping + +The **inner loop** is where individual developers or small teams take a curated problem/idea and rapidly build a working prototype. This loop is optimized for speed, creativity, and immediate feedback. + +| Stage | Activity | Tools | +|-------|----------|-------| +| **Pick** | Select a problem/idea from the catalog | Prototype Catalog, GitHub Issues | +| **Scaffold** | Generate project structure from templates | Copilot, VS Code, project templates | +| **Build** | Write code with AI assistance | GitHub Copilot, VS Code, MCP servers | +| **Test** | Validate locally with fast feedback | Local dev environment, hot reload | +| **Demo** | Show working prototype | Local preview, screenshots, recordings | + +**Key characteristics:** +- Individual or pair development +- Minutes-to-hours cycle time +- Local environment with AI assistance +- Immediate feedback through hot reload and local testing +- Low friction — pick a problem, start building + +### 2.2 Outer Loop — Discovery, Curation & Delivery + +The **outer loop** manages the broader lifecycle: discovering problems, curating the catalog, reviewing prototypes, and publishing to the marketplace. + +| Stage | Activity | Tools | +|-------|----------|-------| +| **Discover** | Monitor ATV channels for problems/ideas | WorkIQ MCP, channel integrations | +| **Curate** | Structure, deduplicate, and categorize | WorkIQ MCP, AI-assisted triage | +| **Prioritize** | Community voting, problem scoring | GitHub Reactions, discussions | +| **Review** | Code review, prototype evaluation | GitHub PRs, peer review | +| **Publish** | Add to marketplace catalog | GitHub Actions, catalog automation | +| **Promote** | Share with community, gather feedback | ATV channels, discussions | + +**Key characteristics:** +- Community-driven and collaborative +- Hours-to-days cycle time +- Automated pipelines for consistency +- Quality gates and peer review +- Continuous feedback from the community + +### 2.3 How the Loops Connect + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ OUTER LOOP │ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ ┌──────────┐ │ +│ │ Discover │──►│ Curate │──►│ Prioritize │──►│ Review │ │ +│ │ Problems │ │ Catalog │ │ & Vote │ │ & Merge │ │ +│ └──────────┘ └────┬─────┘ └─────────────┘ └─────┬────┘ │ +│ │ │ │ +│ ▼ │ │ +│ ┌───────────────┐ │ │ +│ │ PROTOTYPE │ │ │ +│ │ CATALOG │◄─────────────────────────┘ │ +│ └───────┬───────┘ │ +│ │ │ +│ ┌───────────────────┼───────────────────────────────────────┐ │ +│ │ ▼ INNER LOOP │ │ +│ │ ┌──────┐ ┌──────────┐ ┌───────┐ ┌──────┐ ┌──────┐ │ │ +│ │ │ Pick │─►│ Scaffold │─►│ Build │─►│ Test │─►│ Demo │ │ │ +│ │ └──────┘ └──────────┘ └───────┘ └──────┘ └──┬───┘ │ │ +│ │ │ │ │ +│ └───────────────────────────────────────────────────┼──────┘ │ +│ │ │ +│ ┌──────────┐ │ │ +│ │ Publish │◄───────────────────┘ │ +│ │ to Mktpl │ │ +│ └──────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 3. WorkIQ Integration + +[WorkIQ](https://learn.microsoft.com/en-us/azure/devops/mcp-server/mcp-server-overview) is Microsoft's MCP server for workplace intelligence. It gives AI agents secure access to M365 and Azure DevOps data. + +### 3.1 Role in the Outer Loop + +WorkIQ powers the **discovery** and **curation** stages of the outer loop: + +- **Channel Monitoring:** WorkIQ connects to Teams channels, emails, and documents where ATV community members discuss problems and ideas. It surfaces relevant conversations for curation. +- **Content Extraction:** Using WorkIQ's document intelligence, raw discussions are parsed into structured problem/idea entries with title, description, source, and context. +- **Deduplication:** WorkIQ helps identify when a newly surfaced problem overlaps with an existing catalog entry, preventing duplicates. +- **Backlog Sync:** Through integration with Azure DevOps (see [Issue #4 — ADO Flow](https://github.com/All-The-Vibes/atv-platform/issues/4)), curated problems can be synchronized to ADO work items for tracking. + +### 3.2 Role in the Inner Loop + +WorkIQ enhances the **build** stage of the inner loop: + +- **Context Retrieval:** When a developer picks a problem from the catalog, WorkIQ can pull related documents, past discussions, and prior art from M365 to provide rich context. +- **Collaboration Discovery:** WorkIQ can identify who in the ATV community has relevant expertise or has discussed the problem before. +- **Progress Tracking:** As prototypes are built, WorkIQ helps track progress against the original problem statement. + +### 3.3 MCP Configuration + +```json +{ + "servers": { + "workiq": { + "command": "npx", + "args": ["-y", "@microsoft/workiq", "mcp"], + "tools": ["*"] + }, + "github": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" + } + } + } +} +``` + +--- + +## 4. Prototype Catalog — Data Model + +Each entry in the catalog represents a **problem** (per @sachaa's suggestion) that can be prototyped. + +### 4.1 Catalog Entry Schema + +```yaml +id: "unique-identifier" +title: "Short descriptive title" +type: "problem" # problem | idea | enhancement +status: "open" # open | in-progress | prototyped | archived +description: "Detailed description of the problem" +source: + channel: "ATV channel name" + author: "GitHub username or display name" + url: "Link to original discussion" + date: "ISO 8601 date" +tags: ["category", "technology", "domain"] +votes: 0 +prototypes: [] # List of prototype references +related_issues: [] # Links to GitHub issues +created_at: "ISO 8601" +updated_at: "ISO 8601" +``` + +### 4.2 Prototype Reference Schema + +```yaml +id: "prototype-identifier" +catalog_entry_id: "parent-catalog-entry-id" +title: "Prototype name" +description: "What this prototype demonstrates" +author: "GitHub username" +repo_url: "Link to prototype repository" +demo_url: "Link to live demo (if available)" +tech_stack: ["python", "react", "azure"] +status: "draft" # draft | demo-ready | published +created_at: "ISO 8601" +updated_at: "ISO 8601" +``` + +--- + +## 5. Implementation Phases + +### Phase 1: Foundation (Current) +- [x] Define inner loop / outer loop model +- [x] Design catalog data model (YAML-based for simplicity) +- [x] Create initial directory structure +- [ ] Create sample catalog entries from existing ATV issues +- [ ] Set up MCP configuration for WorkIQ and GitHub + +### Phase 2: Catalog & Discovery +- [ ] Build script to extract problems/ideas from GitHub issues +- [ ] Implement catalog validation (schema enforcement) +- [ ] Create catalog index/summary generator +- [ ] Integrate WorkIQ for M365 channel monitoring +- [ ] Set up automated PR creation for new catalog entries + +### Phase 3: Inner Loop Tooling +- [ ] Create project scaffolding templates for common prototype types +- [ ] Build VS Code extension or MCP tool for browsing the catalog +- [ ] Integrate Copilot for AI-assisted prototyping from catalog entries +- [ ] Add prototype submission workflow (PR-based) + +### Phase 4: Marketplace & Outer Loop +- [ ] Build web-based prototype marketplace UI +- [ ] Implement community voting and feedback +- [ ] Add automated prototype evaluation (tests, demos) +- [ ] Connect to ADO Flow for enterprise backlog integration +- [ ] Set up continuous discovery pipeline from ATV channels + +--- + +## 6. Integration with Other ATV Projects + +| Project | Integration Point | +|---------|------------------| +| [ADO Flow (#4)](https://github.com/All-The-Vibes/atv-platform/issues/4) | Sync catalog entries to ADO work items; use WorkIQ MCP for backlog management | +| [Natural Language Compiler (#2)](https://github.com/All-The-Vibes/atv-platform/issues/2) | Use requirement-to-code generation for rapid prototyping in the inner loop | +| [Consumer MCP App Harness (#3)](https://github.com/All-The-Vibes/atv-platform/issues/3) | Marketplace as a consumer MCP app; prototype catalog as an extension point | +| [shai-hulud](https://github.com/All-The-Vibes/shai-hulud) | Vibe-coding starter kit as default scaffold for prototypes | +| [skills-catalog](https://github.com/All-The-Vibes/skills-catalog) | Reusable agent skills for catalog automation and discovery | +| [Agent-Harness](https://github.com/All-The-Vibes/Agent-Harness) | Orchestrate multi-agent workflows for outer loop automation | + +--- + +## 7. Success Metrics + +| Metric | Target | Loop | +|--------|--------|------| +| Time from problem discovery to catalog entry | < 1 day | Outer | +| Time from catalog entry to first prototype | < 1 week | Inner | +| Catalog entries per month | 10+ | Outer | +| Prototypes published per month | 5+ | Inner | +| Community votes per catalog entry | 3+ average | Outer | +| Duplicate detection accuracy | > 80% | Outer | + +--- + +## 8. Getting Started + +### Prerequisites +- Node.js 18+ +- VS Code with GitHub Copilot +- GitHub account with access to All-The-Vibes org +- (Optional) M365 account for WorkIQ integration + +### Quick Start +1. Clone the repository +2. Browse the catalog: `prototype-catalog/catalog/` +3. Pick a problem to prototype +4. Create a new branch: `git checkout -b prototype/` +5. Build your prototype +6. Submit a PR linking to the catalog entry + +### Adding a New Problem/Idea +1. Create a YAML file in `prototype-catalog/catalog/` +2. Follow the schema in `prototype-catalog/schemas/catalog-entry.schema.json` +3. Submit a PR for community review diff --git a/prototype-catalog/README.md b/prototype-catalog/README.md new file mode 100644 index 0000000..3d67d34 --- /dev/null +++ b/prototype-catalog/README.md @@ -0,0 +1,62 @@ +# Prototype Catalog + +The **Prototype Catalog** is the structured registry of problems and ideas curated from ATV community channels. Each entry represents a real problem that can be prototyped. + +## Directory Structure + +``` +prototype-catalog/ +├── catalog/ # YAML files — one per problem/idea +├── schemas/ # JSON Schema for validation +└── scripts/ # Automation scripts +``` + +## How It Works + +### Browse Problems +Look through the `catalog/` directory. Each `.yaml` file describes a problem with its context, source, and current status. + +### Pick a Problem to Prototype +1. Find an entry with `status: open` +2. Create a branch: `git checkout -b prototype/` +3. Build your prototype with AI assistance +4. Submit a PR linking to the catalog entry + +### Add a New Problem/Idea +1. Create a new `.yaml` file in `catalog/` following the schema +2. Use the entry ID as the filename (e.g., `my-problem.yaml`) +3. Validate: `python prototype-catalog/scripts/validate_catalog.py` +4. Submit a PR for community review + +### Validate Entries +```bash +pip install pyyaml jsonschema +python prototype-catalog/scripts/validate_catalog.py +``` + +## Schema + +See [`schemas/catalog-entry.schema.json`](schemas/catalog-entry.schema.json) for the full schema definition. + +### Required Fields +- `id` — Unique identifier (lowercase, hyphens) +- `title` — Short descriptive title +- `type` — `problem`, `idea`, or `enhancement` +- `status` — `open`, `in-progress`, `prototyped`, or `archived` +- `description` — Detailed description +- `source` — Where this was discovered (channel, author, date) +- `tags` — Categories and technology tags +- `created_at` / `updated_at` — Timestamps + +## Current Catalog + +| Entry | Type | Status | Source | +|-------|------|--------|--------| +| [Idea to Prototype Generator](catalog/idea-to-prototype-generator.yaml) | problem | open | Issue #1 | +| [Natural Language Compiler](catalog/natural-language-compiler.yaml) | problem | open | Issue #2 | +| [Consumer MCP App Harness](catalog/consumer-mcp-app-harness.yaml) | idea | open | Issue #3 | +| [ADO Flow](catalog/ado-flow.yaml) | problem | open | Issue #4 | + +## Related Documentation + +- [Prototype Marketplace Plan](../docs/prototype-marketplace-plan.md) — Full inner loop / outer loop system design diff --git a/prototype-catalog/catalog/ado-flow.yaml b/prototype-catalog/catalog/ado-flow.yaml new file mode 100644 index 0000000..d3a5a8f --- /dev/null +++ b/prototype-catalog/catalog/ado-flow.yaml @@ -0,0 +1,29 @@ +id: ado-flow +title: "ADO Flow — AI-Powered Azure DevOps Backlog Generator" +type: problem +status: open +description: > + Converting documentation, transcripts, SoWs, and other sources into a + structured Azure DevOps backlog (epics, features, user stories, tasks) is + a manual, time-consuming process. There is no MCP app that orchestrates + this digestion, supports custom ADO template fields, and maintains + synchronization between ADO and local markdown files. We need an MCP app + for VS Code that automates backlog creation from unstructured sources and + keeps ADO and local project files in sync. +source: + channel: "GitHub Issues" + author: "softwaresalt" + url: "https://github.com/All-The-Vibes/atv-platform/issues/4" + date: "2026-03-02" +tags: + - mcp + - azure-devops + - backlog + - workiq + - automation +votes: 0 +prototypes: [] +related_issues: + - "https://github.com/All-The-Vibes/atv-platform/issues/4" +created_at: "2026-03-02T05:13:09Z" +updated_at: "2026-03-09T20:00:00Z" diff --git a/prototype-catalog/catalog/consumer-mcp-app-harness.yaml b/prototype-catalog/catalog/consumer-mcp-app-harness.yaml new file mode 100644 index 0000000..c0b1515 --- /dev/null +++ b/prototype-catalog/catalog/consumer-mcp-app-harness.yaml @@ -0,0 +1,29 @@ +id: consumer-mcp-app-harness +title: "Consumer MCP App Harness — Extension Marketplace for M365" +type: idea +status: open +description: > + There is no consumer-friendly harness for MCP Apps — think of an + extension/plugin market for M365. Today, solving complex personal + scheduling problems (like planning summer camps for children across + multiple schedules, availability, and friend groups) requires enormous + manual effort. An agentic app with access to calendar and email context + could research, plan, and coordinate automatically. We need a consumer + harness that makes MCP apps accessible and useful for everyday scenarios. +source: + channel: "GitHub Issues" + author: "softwaresalt" + url: "https://github.com/All-The-Vibes/atv-platform/issues/3" + date: "2026-03-02" +tags: + - mcp + - consumer + - m365 + - agentic + - scheduling +votes: 0 +prototypes: [] +related_issues: + - "https://github.com/All-The-Vibes/atv-platform/issues/3" +created_at: "2026-03-02T00:00:00Z" +updated_at: "2026-03-09T20:00:00Z" diff --git a/prototype-catalog/catalog/idea-to-prototype-generator.yaml b/prototype-catalog/catalog/idea-to-prototype-generator.yaml new file mode 100644 index 0000000..0b0e73e --- /dev/null +++ b/prototype-catalog/catalog/idea-to-prototype-generator.yaml @@ -0,0 +1,30 @@ +id: idea-to-prototype-generator +title: "Idea to Prototype Generator — Prototype Marketplace" +type: problem +status: open +description: > + There is no structured way to discover, curate, and act on the many ideas + and problems discussed across ATV community channels. Great ideas get lost + in chat threads and meeting notes. We need a system that continuously + monitors ATV channels, extracts actionable problems, catalogs them, and + enables rapid prototyping through an inner loop / outer loop workflow. + The end result is a Prototype Marketplace where the community can browse + problems, pick one, and build a working prototype with AI assistance. +source: + channel: "GitHub Issues" + author: "shyamsridhar123" + url: "https://github.com/All-The-Vibes/atv-platform/issues/1" + date: "2026-02-27" +tags: + - marketplace + - discovery + - curation + - mcp + - workiq + - ai-assisted +votes: 1 +prototypes: [] +related_issues: + - "https://github.com/All-The-Vibes/atv-platform/issues/1" +created_at: "2026-02-27T22:17:56Z" +updated_at: "2026-03-09T20:00:00Z" diff --git a/prototype-catalog/catalog/natural-language-compiler.yaml b/prototype-catalog/catalog/natural-language-compiler.yaml new file mode 100644 index 0000000..713263a --- /dev/null +++ b/prototype-catalog/catalog/natural-language-compiler.yaml @@ -0,0 +1,29 @@ +id: natural-language-compiler +title: "Natural Language Compiler — Requirements as Source of Truth" +type: problem +status: open +description: > + Software requirements and source code exist as disconnected artifacts. + When requirements change, there is no automated way to detect what changed, + determine which code is affected, and generate or modify code accordingly. + This leads to requirement-code drift, stale documentation, and massive + manual effort. We need a system that treats requirements as the source of + truth that compiles down to code, maintaining bidirectional traceability + between requirements and code at the granular level. +source: + channel: "GitHub Issues" + author: "jnPiyush" + url: "https://github.com/All-The-Vibes/atv-platform/issues/2" + date: "2026-02-27" +tags: + - ai + - compiler + - requirements + - traceability + - code-generation +votes: 0 +prototypes: [] +related_issues: + - "https://github.com/All-The-Vibes/atv-platform/issues/2" +created_at: "2026-02-27T22:41:45Z" +updated_at: "2026-03-09T20:00:00Z" diff --git a/prototype-catalog/schemas/catalog-entry.schema.json b/prototype-catalog/schemas/catalog-entry.schema.json new file mode 100644 index 0000000..48c78e6 --- /dev/null +++ b/prototype-catalog/schemas/catalog-entry.schema.json @@ -0,0 +1,147 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Prototype Catalog Entry", + "description": "Schema for a problem or idea entry in the ATV Prototype Marketplace catalog", + "type": "object", + "required": ["id", "title", "type", "status", "description", "source", "tags", "created_at", "updated_at"], + "properties": { + "id": { + "type": "string", + "pattern": "^[a-z0-9-]+$", + "description": "Unique identifier (lowercase, hyphens only)" + }, + "title": { + "type": "string", + "minLength": 5, + "maxLength": 200, + "description": "Short descriptive title" + }, + "type": { + "type": "string", + "enum": ["problem", "idea", "enhancement"], + "description": "Entry type — prefer 'problem' to focus on what needs solving" + }, + "status": { + "type": "string", + "enum": ["open", "in-progress", "prototyped", "archived"], + "description": "Current status of the catalog entry" + }, + "description": { + "type": "string", + "minLength": 20, + "description": "Detailed description of the problem or idea" + }, + "source": { + "type": "object", + "required": ["channel", "author", "date"], + "properties": { + "channel": { + "type": "string", + "description": "ATV channel or source where this was discovered" + }, + "author": { + "type": "string", + "description": "GitHub username or display name of the originator" + }, + "url": { + "type": "string", + "format": "uri", + "description": "Link to the original discussion or source" + }, + "date": { + "type": "string", + "format": "date", + "description": "Date when the problem/idea was first identified" + } + } + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "description": "Categories, technologies, or domain tags" + }, + "votes": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "Community vote count" + }, + "prototypes": { + "type": "array", + "items": { + "$ref": "#/definitions/prototype" + }, + "default": [], + "description": "List of prototypes built for this entry" + }, + "related_issues": { + "type": "array", + "items": { + "type": "string", + "format": "uri" + }, + "default": [], + "description": "Links to related GitHub issues" + }, + "created_at": { + "type": "string", + "format": "date-time", + "description": "When this catalog entry was created" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "description": "When this catalog entry was last updated" + } + }, + "definitions": { + "prototype": { + "type": "object", + "required": ["id", "title", "author", "status"], + "properties": { + "id": { + "type": "string", + "pattern": "^[a-z0-9-]+$" + }, + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "author": { + "type": "string" + }, + "repo_url": { + "type": "string", + "format": "uri" + }, + "demo_url": { + "type": "string", + "format": "uri" + }, + "tech_stack": { + "type": "array", + "items": { + "type": "string" + } + }, + "status": { + "type": "string", + "enum": ["draft", "demo-ready", "published"] + }, + "created_at": { + "type": "string", + "format": "date-time" + }, + "updated_at": { + "type": "string", + "format": "date-time" + } + } + } + } +} diff --git a/prototype-catalog/scripts/validate_catalog.py b/prototype-catalog/scripts/validate_catalog.py new file mode 100644 index 0000000..135046c --- /dev/null +++ b/prototype-catalog/scripts/validate_catalog.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python3 +"""Validate catalog entries against the JSON schema. + +Usage: + python prototype-catalog/scripts/validate_catalog.py + +Validates all YAML files in prototype-catalog/catalog/ against the +catalog-entry.schema.json schema. Exits with code 1 if any entry is invalid. +""" + +import json +import sys +from pathlib import Path + +try: + import jsonschema +except ImportError: + print("jsonschema package is required. Install with: pip install jsonschema") + sys.exit(1) + +try: + import yaml +except ImportError: + print("pyyaml package is required. Install with: pip install pyyaml") + sys.exit(1) + + +def load_schema(): + """Load the catalog entry JSON schema.""" + schema_path = Path(__file__).parent.parent / "schemas" / "catalog-entry.schema.json" + with open(schema_path) as f: + return json.load(f) + + +def validate_entry(entry_path, schema): + """Validate a single catalog entry against the schema. + + Returns a list of validation error messages (empty if valid). + """ + errors = [] + try: + with open(entry_path) as f: + entry = yaml.safe_load(f) + except yaml.YAMLError as e: + return [f"YAML parse error: {e}"] + + validator = jsonschema.Draft7Validator(schema) + for error in validator.iter_errors(entry): + path = " -> ".join(str(p) for p in error.absolute_path) if error.absolute_path else "(root)" + errors.append(f" {path}: {error.message}") + + return errors + + +def main(): + """Validate all catalog entries.""" + catalog_dir = Path(__file__).parent.parent / "catalog" + schema = load_schema() + + yaml_files = sorted(catalog_dir.glob("*.yaml")) + sorted(catalog_dir.glob("*.yml")) + + if not yaml_files: + print("No catalog entries found.") + return 0 + + total_errors = 0 + for entry_path in yaml_files: + errors = validate_entry(entry_path, schema) + if errors: + print(f"INVALID: {entry_path.name}") + for error in errors: + print(error) + total_errors += len(errors) + else: + print(f" VALID: {entry_path.name}") + + print(f"\n{len(yaml_files)} entries checked, {total_errors} errors found.") + return 1 if total_errors > 0 else 0 + + +if __name__ == "__main__": + sys.exit(main())