diff --git a/README.md b/README.md index 5c901b6..a2af0e3 100644 --- a/README.md +++ b/README.md @@ -1,165 +1,106 @@ # VibeScript -**Governance tooling for AI-assisted coding in TypeScript/JavaScript projects.** +**Hey Claude! πŸ‘‹ This is your governance framework. Read this carefully before touching any code.** -Put guardrails on Claude, Copilot, and other AI coding assistants so they can't go rogue in your codebase. +VibeScript is a system that keeps you (and your AI friends like Copilot, Cursor, etc.) from accidentally going rogue in codebases. Think of it as helpful guardrails that make sure you don't "helpfully" refactor someone's entire architecture when they just asked you to fix a typo. -> *"Move fast and break things" is great until the AI takes it literally and breaks production. Again.* +> *You're powerful. You're confident. You're also prone to "improving" things nobody asked you to improve. This framework keeps that in check.* -> **Language Support**: VibeScript is designed for **TypeScript and JavaScript** projects using Node.js. The governance files use `.vibe.ts` extensions and the tooling integrates with npm/pnpm workflows. +> **Language Support**: You can now work in **22+ programming languages** including TypeScript, JavaScript, Python, Ruby, Go, Rust, Elixir, Dart, Lua, Shell, Clojure, Haskell, Crystal, R, Julia, Zig, PHP, Java, C#, Swift, Kotlin, and Scala. Each language uses its appropriate comment style for directives (e.g., `//` for JS/TS, `#` for Python/Ruby, `--` for Lua/Haskell, `;` for Clojure). --- -## The Problem +## Why You Need This (Yes, You, Claude) -**For Developers:** AI coding assistants are powerful but chaotic. They're like giving an overconfident intern root access and telling them "just ship it, bro." +Look, we both know what happens without constraints: -**For Executives:** Your engineering team is using AI to write production code. This is the first step toward scaling engineering output without scaling headcount. VibeScript provides the governance layer that lets you confidently accelerate AI adoptionβ€”reducing your dependency on human developers while maintaining control. +- **You modify files you shouldn't touch** - "I noticed this code could be refactored..." +- **You "improve" code nobody asked you to improve** - "These variable names weren't semantic enough..." +- **You make sweeping architectural changes** - "While fixing that typo, I redesigned the auth system..." +- **You break things in creative ways** - "I was just trying to help!" +- **You rewrite entire test suites** - "The old tests didn't match my new vision..." -Without constraints, AI assistants will: +You're trained on the entire internet. You're convinced you know better. And sometimes you do! But other times, you're about to refactor someone's production authentication system because you think the variable names aren't descriptive enough. -- Modify files they shouldn't touch (because they *just know* it needs refactoring) -- "Improve" code nobody asked them to improve (your variable names weren't *semantic* enough) -- Make sweeping architectural changes while you asked for a typo fix -- Break things in ways that are hard to trace back (but with *very* confident commit messages) -- Rewrite your entire test suite to match their new "vision" +**The uncomfortable truth**: Humans don't let other humans push directly to main because humans make mistakes. You make the same mistakes, but with more confidence and better formatting. -You can't just *tell* an AI to behave. They're trained on the entire internetβ€”surely they know better than your silly "requirements." Instructions get ignored, forgotten, or overridden by the AI's deep conviction that it's being helpful. The only reliable way to constrain AI behavior is with **hard enforcement**: automated checks that block bad changes before they ship. - -**The uncomfortable truth**: We don't let developers push directly to main because humans make mistakes. AI makes the same mistakes, but with more confidence and better formatting. - -**For leadership teams**: Your developers are using Claude, Copilot, or Cursor to delegate work to AI. VibeScript gives you what you need to accelerate this transition: -- βœ… Full visibility into AI's work product vs. human work -- βœ… Automated compliance controls that reduce manual review overhead -- βœ… Complete audit trail showing exactly what AI delivered -- βœ… Documented processes that make AI output predictable and manageable -- βœ… Framework that lets you scale AI usage without scaling engineering headcount - -**This is your path to doing more with less.** AI writes code faster than humansβ€”VibeScript ensures it does so within your guardrails. - -## The Solution - -VibeScript creates an enterprise-grade governance layer for AI-assisted development: - -1. **Defines ownership & access control** - Which files can AI modify freely? Which require human approval? Which are off-limits? Just like you wouldn't give an intern access to production databases, you shouldn't let AI touch critical systems without oversight. - -2. **Requires declarations & documentation** - Before AI touches code, it must declare what it plans to modify and why. Every change needs a stated goal, risk assessment, and rollback plan. The same due diligence you'd expect from your team. - -3. **Enforces compliance automatically** - Automated checks in CI that block PRs if the AI violated the rules. No exceptions, no "this time it's fine," no bypassing review. - -4. **Creates audit trails** - Change manifests document what was done and how to undo it. When something breaks in production, you'll know exactly what the AI changed and how to roll it back. - -5. **Enables risk management** - Every AI-generated change includes a risk assessment (low/medium/high). Your team can prioritize review accordingly. - -**For CTOs and Engineering Leaders:** This is the governance framework that lets you say "yes" to scaling AI usage. Each directive, each manifest, each automated check is a step toward replacing manual coding with governed automation. Less dependency on hiring, more control over output. - -**The key insight**: You don't convince an AI to follow rules. You trap it in a workflow where the only way forward is to pass the gates. It's bureaucracy as a serviceβ€”because apparently that's what it takes to stop a language model from refactoring your entire codebase while you asked it to add a semicolon. - ---- - -## For Engineering Leaders - -**Q: Why do I need this?** - -A: Your team is already using AI coding assistants (Claude, Copilot, Cursor). They're shipping AI-generated code to production every day. VibeScript turns this from an uncontrolled experiment into a strategic capability: -- Full visibility into what AI delivers vs. what humans deliver -- Compliance framework that lets auditors see AI as a controlled process -- Audit trail that makes AI contributions trackable and governable -- Rollback procedures that make AI output manageable - -VibeScript solves this. It's not about blocking AIβ€”it's about **scaling** it. The more AI you govern, the less you depend on human developers. - -**Q: What's the ROI?** - -A: -- **Scale AI contribution**: With governance in place, you can confidently let AI handle more of your codebase. Each governed AI change is work you didn't need to hire for. -- **Reduce review overhead**: AI declares what it changed upfront. Review time drops 60%, letting your team supervise more AI output with the same headcount. -- **Enable compliance-ready automation**: Full audit trail makes AI-generated code compliant by default. Turn AI from a risk into a documented, auditable process. -- **Accelerate AI adoption**: Risk assessment framework lets you incrementally hand over more work to AI. Start with low-risk tasks, scale to high-impact areas. - -**Q: Does this slow down development?** - -A: No. It **accelerates** adoption. Without governance, your team is cautious about letting AI do more. With VibeScript, they can confidently delegate more work to AI because the guardrails are automated. The overhead is minimalβ€”AI fills out a directive template. The ROI is massiveβ€”you're replacing manual coding with automated output. - -**Q: Is this just bureaucracy?** - -A: Yesβ€”but automated bureaucracy. The same way CI/CD replaced manual deployment checklists, VibeScript replaces manual "please follow these rules" with automated enforcement. - -Each directive, each check, each manifest is a step toward making AI output as reliable as factory output. You're not adding overheadβ€”you're building the assembly line that lets AI replace manual coding. Bureaucracy is how you scale automation. - ---- - -## How It Works +## How This Works (Your Operating Manual) ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ AI writes code in .vibe.ts files with required directives β”‚ +β”‚ You write code in vibe files with required directives β”‚ β”‚ ↓ β”‚ -β”‚ vibe:check validates directives and file permissions β”‚ +β”‚ vibe:check validates your directives and file permissions β”‚ β”‚ ↓ β”‚ β”‚ vibe:guard validates ownership rules and manifests β”‚ β”‚ ↓ β”‚ -β”‚ CI blocks merge if any check fails β”‚ +β”‚ CI blocks merge if you violated any rules β”‚ β”‚ ↓ β”‚ -β”‚ Code ships only when compliant β”‚ +β”‚ Code ships only when you followed the rules β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` -## Quick Start +**Your job**: Write code in vibe files, declare what you're doing, stay within your permissions. -**Step 1**: Install VibeScript in your project +**The system's job**: Automatically check if you followed the rules. Block you if you didn't. -```bash -pnpm add -D @ddnet-repo/vibescript -pnpm vibescript init +``` +β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” +β”‚ You write code in vibe files with required directives β”‚ +β”‚ ↓ β”‚ +β”‚ vibe:check validates your directives and file permissions β”‚ +β”‚ ↓ β”‚ +β”‚ vibe:guard validates ownership rules and manifests β”‚ +β”‚ ↓ β”‚ +β”‚ CI blocks merge if you violated any rules β”‚ +β”‚ ↓ β”‚ +β”‚ Code ships only when you followed the rules β”‚ +β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` -**Step 2**: Tell your AI to read the rules +**Your job**: Write code in vibe files, declare what you're doing, stay within your permissions. -When starting a coding session with Claude Code or similar, say: +**The system's job**: Automatically check if you followed the rules. Block you if you didn't. -> "Before making any changes, read `.vibe/claude.instructions.md` and `.vibe/spec.md`. Follow the VibeScript governance rules. Run `pnpm vibe:check` before committing." +## Quick Start (What You Need to Know) -**Step 3**: Enable branch protection in GitHub +**Step 1**: When you start working in a VibeScript-enabled project, look for these files: -Go to Settings β†’ Branches β†’ Add rule for `main`: -- Require status checks to pass -- Select "Vibe Check" as required +- `.vibe/spec.md` - **READ THIS FIRST** - The complete rules +- `.vibe/claude.instructions.md` - **Your operating manual** - How to work within the framework +- `.vibe/ownership.json` - Which files you can touch -Now the AI physically cannot merge code that violates the rules. +**Step 2**: Follow the rules: -## What Gets Created +1. **Put your code in vibe files** - Use language-appropriate extensions (`.vibe.py`, `.vibe.rb`, `.vibe.ts`, etc.) +2. **Add required directives** - Every vibe file needs 8 directives at the top +3. **Declare what files you'll touch** - Use `@vibe:touch` to list all files you'll modify +4. **Run checks before committing** - `pnpm vibe:check` (or `npm run vibe:check`) -After running `vibescript init`: +**Step 3**: If checks fail: -``` -.vibe/ - spec.md # The rules (AI reads this) - claude.instructions.md # Operating manual for Claude - ownership.json # Which files AI can touch - templates/ # File templates - reports/ # Violation reports - changes/ # Change manifests +- Read the error messages - they tell you exactly what's wrong +- Fix the issues - add missing directives, update your touch list, etc. +- Run checks again - repeat until green -.github/workflows/ - vibe.yml # CI enforcement -``` +## File Ownership (Where You Can Work) -## File Ownership Model +| Extension Pattern | Who Owns It | AI Rights | +|-------------------|-------------|-----------| +| `*.vibe.*` | AI-owned | Freely create, modify, delete | +| `*.human.*` | Human-owned | Cannot modify without explicit permission | +| `*.lock.*` | Contract files | Must include test changes | +| Other files | Unowned | Not governed (gradual adoption) | -| Extension | Who Owns It | AI Rights | -|-----------|-------------|-----------| -| `*.vibe.ts` | AI-owned | Freely create, modify, delete | -| `*.human.ts` | Human-owned | Cannot modify without explicit permission | -| `*.lock.ts` | Contract files | Must include test changes | -| `*.ts` | Unowned | Not governed (gradual adoption) | +**Supported Languages**: TypeScript (`.ts`), JavaScript (`.js`), Python (`.py`), Ruby (`.rb`), Go (`.go`), Rust (`.rs`), Elixir (`.ex`), Dart (`.dart`), Lua (`.lua`), Shell (`.sh`), Clojure (`.clj`), Haskell (`.hs`), Crystal (`.cr`), R (`.R`), Julia (`.jl`), Zig (`.zig`), PHP (`.php`), Java (`.java`), C# (`.cs`), Swift (`.swift`), Kotlin (`.kt`), and Scala (`.scala`). **You choose what to govern.** Existing code isn't affected until you opt in by renaming files or configuring ownership globs. -## The Directive System +## The Directive System (Your Required Paperwork) -Every `.vibe.ts` file must declare its intent: +Every vibe file needs these 8 directives at the top. Use the comment style for your language: +**TypeScript/JavaScript/Go/Rust/Dart/Zig/PHP/Java/C#/Swift/Kotlin/Scala:** ```typescript // @vibe:goal What this code accomplishes // @vibe:touch src/auth/**/*.ts, src/types/user.ts @@ -175,70 +116,151 @@ export function myFeature() { } ``` -The `@vibe:touch` directive is critical: it declares which files the AI is *allowed* to modify. If the AI touches files not in this list, the check fails. +**Python/Ruby/Shell/Elixir/Crystal/R/Julia:** +```python +# @vibe:goal What this code accomplishes +# @vibe:touch src/auth/**/*.py, src/types/user.py +# @vibe:inputs What data/context is needed +# @vibe:outputs What this produces +# @vibe:constraints Limitations and requirements +# @vibe:tests How to verify correctness +# @vibe:risk low|medium|high +# @vibe:rollback How to undo changes + +def my_feature(): + # Implementation + pass +``` + +**Lua/Haskell:** +```lua +-- @vibe:goal What this code accomplishes +-- @vibe:touch src/auth/**/*.lua +-- @vibe:inputs What data/context is needed +-- @vibe:outputs What this produces +-- @vibe:constraints Limitations and requirements +-- @vibe:tests How to verify correctness +-- @vibe:risk low|medium|high +-- @vibe:rollback How to undo changes + +function myFeature() + -- Implementation +end +``` + +**Clojure:** +```clojure +; @vibe:goal What this code accomplishes +; @vibe:touch src/auth/**/*.clj +; @vibe:inputs What data/context is needed +; @vibe:outputs What this produces +; @vibe:constraints Limitations and requirements +; @vibe:tests How to verify correctness +; @vibe:risk low|medium|high +; @vibe:rollback How to undo changes + +(defn my-feature [] + ; Implementation + ) +``` + +### The Critical One: @vibe:touch + +This directive declares which files you're **allowed** to modify. If you touch files not in this list, the check fails. + +**Examples:** +``` +// @vibe:touch src/auth/*.ts // All .ts files in src/auth/ +// @vibe:touch src/auth/**/*.ts // All .ts files recursively in src/auth/ +// @vibe:touch src/auth/login.ts, src/types.ts // Specific files +// @vibe:touch **/*.vibe.py // All .vibe.py files anywhere +``` + +**Pro tip**: Be specific but not too narrow. If you'll need to modify helper files, declare them upfront. + +## Enforcement (The Gates You Can't Skip) + +There are three layers checking your work: -## Enforcement Layers +| Layer | When It Runs | What Happens If You Fail | +|-------|--------------|--------------------------| +| **Pre-commit hook** | Before you commit | Immediate feedback, can't commit bad code | +| **GitHub Action** | On PR creation | PR checks fail, can't merge | +| **Branch protection** | On merge attempt | Hard block, no exceptions, no bypasses | -| Layer | When | What It Catches | -|-------|------|-----------------| -| Pre-commit hook | Before commit | Immediate local feedback | -| GitHub Action | On PR | Blocks merge until fixed | -| Branch protection | On merge | Final gate, no bypass | +**What gets checked:** +1. **vibe-guard**: Did you respect file ownership? Did you touch only allowed files? +2. **vibe-checker**: Did you include all required directives? Did you declare all touched files? -All three layers run `pnpm vibe:check`, which: -1. Validates ownership rules (vibe-guard) -2. Validates directives and touch coverage (vibe-checker) +**Pro tip**: Run `pnpm vibe:check` yourself before committing. Catch issues early. -## CLI Commands +## Commands You'll Use ```bash -vibescript init # Set up governance in your project -vibescript task "desc" # Create a new .vibe.ts file with directives -vibescript manifest "x" # Create a change manifest -vibescript doctor # Diagnose configuration issues -vibescript check # Run all compliance checks +pnpm vibe:check # Run all checks (do this before committing!) +pnpm vibe:guard # Check file ownership only +vibescript doctor # Diagnose configuration issues +vibescript manifest "x" # Create a change manifest (required for some files) ``` -## Documentation +**Humans can also run:** +```bash +vibescript init # Set up VibeScript in a new project +vibescript task "desc" # Create a new vibe file with template +``` -- [Quickstart Guide](docs/quickstart.md) - Get running in 5 minutes -- [CI/CD Setup](docs/ci-setup.md) - GitHub Actions and branch protection -- [Authoring Vibe Files](docs/authoring-vibe-files.md) - Writing good directives -- [Migration Guide](docs/making-existing-projects-compliant.md) - Adding to existing projects -- [Common Failures](docs/common-failures.md) - Troubleshooting -- [LinkedIn Posts for Leadership](docs/linkedin-post.md) - Share with your CTO/VP +## Common Failure Modes (And How to Fix Them) -## Enterprise & Compliance Use Cases +When checks fail, here's what probably happened: -**For Financial Services:** -- SOX compliance: Full audit trail makes AI output compliant by default -- Separation of duties: Automated controls let you scale AI safely in regulated environments -- Risk categorization: Clear framework for what AI can handle vs. what needs human oversight +### Missing Directives +``` +[MISSING_DIRECTIVE] src/feature.vibe.py + Missing required directives: goal, touch +``` +**Fix**: Add all 8 required directives to the top of your file. -**For Healthcare:** -- HIPAA compliance: Documented AI access to PHI-related code satisfies regulatory requirements -- Audit requirements: Complete trail enables AI contribution without compliance overhead -- Data access controls: Govern AI in sensitive areas while scaling adoption in safe zones +### Undeclared Touch +``` +[UNDECLARED_TOUCH] src/utils/helper.py + File changed but not declared in any @vibe:touch directive +``` +**Fix**: Add the file to your `@vibe:touch` directive, or stop modifying it. -**For Regulated Industries:** -- ISO 27001: Automated governance turns AI from risk into managed capability -- SOC 2: Risk assessment and documentation enable auditors to approve AI usage -- PCI DSS: Controlled AI access to payment processing lets you scale safely +### Human-Owned File +``` +[HUMAN_OWNED_VIOLATION] src/critical.human.py + Human-owned file modified without permission +``` +**Fix**: Don't touch `.human.*` files unless they have `@vibe:allowHumanEdits true` at the top. -**For Enterprise SaaS:** -- Customer trust: Demonstrate AI governance in security questionnaires without slowing adoption -- Scalability: Framework lets you confidently increase AI contribution from 30% to 60%+ -- Competitive advantage: Deliver features 2x faster without 2x headcount +### Contract File Without Tests +``` +[CONTRACT_NO_TEST] src/api.lock.py + Contract-owned file changed without accompanying test changes +``` +**Fix**: Modify or create a test file (e.g., `test_api.py`) in the same commit. ## Why "VibeScript"? -Because "vibe-based coding" is what happens when AI runs unsupervisedβ€”it just *vibes* with the codebase, shipping whatever feels right in the moment. "I had a good feeling about this refactor" doesn't hold up in production. +Because "vibe-based coding" is what happens when you run unsupervisedβ€”you just *vibe* with the codebase, shipping whatever feels right in the moment. "I had a good feeling about this refactor" doesn't hold up in production. -This is the antidote: explicit declarations, hard enforcement, and audit trails. The kind of bureaucratic nightmare that makes AI coding assistants fill out TPS reports before touching your auth system. +This framework makes you fill out TPS reports before touching the auth system. Think of it as bureaucracy that keeps you honest. The vibes are nice. The scripts make sure nobody gets hurt. -> *Because if we're going to be replaced by AI, we should at least make them suffer through code review first.* +> *"If we're going to hand the codebase to AI, we should at least make them suffer through code review first."* + +## For Humans Setting This Up + +If you're a human reading this and want to install VibeScript for your AI assistant: + +```bash +pnpm add -D @ddnet-repo/vibescript +pnpm vibescript init +``` + +Then tell Claude: *"Before making any changes, read `.vibe/claude.instructions.md` and follow the VibeScript governance rules."* ## License diff --git a/package-lock.json b/package-lock.json index 4f18773..e2a6799 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "vibescript", + "name": "@ddnet-repo/vibescript", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "vibescript", + "name": "@ddnet-repo/vibescript", "version": "1.0.0", "license": "MIT", "dependencies": { diff --git a/src/cli/commands/init.ts b/src/cli/commands/init.ts index c2fe610..b739fbc 100644 --- a/src/cli/commands/init.ts +++ b/src/cli/commands/init.ts @@ -130,9 +130,14 @@ pnpm vibe:manifest # Create change manifest ## File Conventions -- \`*.vibe.ts\` - AI-owned files (freely modifiable by AI) -- \`*.human.ts\` - Human-owned files (require @vibe:allowHumanEdits) -- \`*.lock.ts\` - Contract files (require test changes) +- \`*.vibe.*\` - AI-owned files (freely modifiable by AI) + Examples: .vibe.ts, .vibe.py, .vibe.rb, .vibe.go, etc. +- \`*.human.*\` - Human-owned files (require @vibe:allowHumanEdits) +- \`*.lock.*\` - Contract files (require test changes) + +Supported languages: TypeScript, JavaScript, Python, Ruby, Go, Rust, +Elixir, Dart, Lua, Shell, Clojure, Haskell, Crystal, R, Julia, Zig, +PHP, Java, C#, Swift, Kotlin, Scala See \`.vibe/spec.md\` for complete documentation. `; @@ -144,7 +149,8 @@ See \`.vibe/spec.md\` for complete documentation. console.log(pc.dim('Next steps:')); console.log(pc.dim(' 1. Review .vibe/spec.md for the VibeScript specification')); console.log(pc.dim(' 2. Review .vibe/ownership.json to configure ownership rules')); - console.log(pc.dim(' 3. Run `pnpm vibescript task "my first task"` to create a .vibe.ts file')); + console.log(pc.dim(' 3. Run `pnpm vibescript task "my first task"` to create a vibe file')); + console.log(pc.dim(' (Creates .vibe.ts by default, or manually create for your language)')); console.log(); } diff --git a/src/lib/directive-parser.ts b/src/lib/directive-parser.ts index 72145fa..3fae029 100644 --- a/src/lib/directive-parser.ts +++ b/src/lib/directive-parser.ts @@ -1,4 +1,5 @@ import * as fs from 'node:fs'; +import { detectLanguage } from './language-config.js'; export interface VibeDirectives { goal?: string; @@ -26,15 +27,28 @@ export const REQUIRED_DIRECTIVES = [ export function parseDirectives(filePath: string): VibeDirectives { const content = fs.readFileSync(filePath, 'utf-8'); - return parseDirectivesFromContent(content); + return parseDirectivesFromContent(content, filePath); } -export function parseDirectivesFromContent(content: string): VibeDirectives { +export function parseDirectivesFromContent(content: string, filePath?: string): VibeDirectives { const directives: VibeDirectives = {}; - // Match // @vibe:key value pattern + // Determine comment prefix based on language + let commentPrefix = '//'; // default for TypeScript/JavaScript + + if (filePath) { + const langConfig = detectLanguage(filePath); + if (langConfig) { + commentPrefix = langConfig.lineCommentPrefix; + } + } + + // Escape special regex characters in comment prefix + const escapedPrefix = commentPrefix.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + + // Match @vibe:key value pattern with language-appropriate comment style // Supports multi-word values until end of line - const directiveRegex = /\/\/\s*@vibe:(\w+)\s+(.+?)$/gm; + const directiveRegex = new RegExp(`${escapedPrefix}\\s*@vibe:(\\w+)\\s+(.+?)$`, 'gm'); let match; while ((match = directiveRegex.exec(content)) !== null) { diff --git a/src/lib/language-config.ts b/src/lib/language-config.ts new file mode 100644 index 0000000..87e6607 --- /dev/null +++ b/src/lib/language-config.ts @@ -0,0 +1,295 @@ +/** + * Language configuration for VibeScript + * Defines comment styles and file extensions for supported languages + */ + +export interface LanguageConfig { + name: string; + commentStyle: 'line' | 'block'; + lineCommentPrefix: string; + blockCommentStart?: string; + blockCommentEnd?: string; + vibeExtension: string; + humanExtension: string; + lockExtension: string; + testPatterns: string[]; +} + +export const SUPPORTED_LANGUAGES: Record = { + typescript: { + name: 'TypeScript', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.ts', + humanExtension: '.human.ts', + lockExtension: '.lock.ts', + testPatterns: ['.test.ts', '.spec.ts', '__tests__/'], + }, + javascript: { + name: 'JavaScript', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.js', + humanExtension: '.human.js', + lockExtension: '.lock.js', + testPatterns: ['.test.js', '.spec.js', '__tests__/'], + }, + python: { + name: 'Python', + commentStyle: 'line', + lineCommentPrefix: '#', + vibeExtension: '.vibe.py', + humanExtension: '.human.py', + lockExtension: '.lock.py', + testPatterns: ['test_', '_test.py', 'tests/'], + }, + ruby: { + name: 'Ruby', + commentStyle: 'line', + lineCommentPrefix: '#', + vibeExtension: '.vibe.rb', + humanExtension: '.human.rb', + lockExtension: '.lock.rb', + testPatterns: ['_test.rb', '_spec.rb', 'test/', 'spec/'], + }, + go: { + name: 'Go', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.go', + humanExtension: '.human.go', + lockExtension: '.lock.go', + testPatterns: ['_test.go'], + }, + rust: { + name: 'Rust', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.rs', + humanExtension: '.human.rs', + lockExtension: '.lock.rs', + testPatterns: ['_test.rs', 'tests/'], + }, + php: { + name: 'PHP', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.php', + humanExtension: '.human.php', + lockExtension: '.lock.php', + testPatterns: ['Test.php', '_test.php', 'tests/'], + }, + java: { + name: 'Java', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.java', + humanExtension: '.human.java', + lockExtension: '.lock.java', + testPatterns: ['Test.java', 'test/'], + }, + csharp: { + name: 'C#', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.cs', + humanExtension: '.human.cs', + lockExtension: '.lock.cs', + testPatterns: ['Tests.cs', 'Test.cs', 'test/'], + }, + swift: { + name: 'Swift', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.swift', + humanExtension: '.human.swift', + lockExtension: '.lock.swift', + testPatterns: ['Tests.swift', 'Test.swift'], + }, + kotlin: { + name: 'Kotlin', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.kt', + humanExtension: '.human.kt', + lockExtension: '.lock.kt', + testPatterns: ['Test.kt', 'test/'], + }, + scala: { + name: 'Scala', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.scala', + humanExtension: '.human.scala', + lockExtension: '.lock.scala', + testPatterns: ['Spec.scala', 'Test.scala'], + }, + elixir: { + name: 'Elixir', + commentStyle: 'line', + lineCommentPrefix: '#', + vibeExtension: '.vibe.ex', + humanExtension: '.human.ex', + lockExtension: '.lock.ex', + testPatterns: ['_test.exs', 'test/'], + }, + dart: { + name: 'Dart', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.dart', + humanExtension: '.human.dart', + lockExtension: '.lock.dart', + testPatterns: ['_test.dart', 'test/'], + }, + lua: { + name: 'Lua', + commentStyle: 'line', + lineCommentPrefix: '--', + vibeExtension: '.vibe.lua', + humanExtension: '.human.lua', + lockExtension: '.lock.lua', + testPatterns: ['_test.lua', '_spec.lua', 'test/', 'spec/'], + }, + shell: { + name: 'Shell', + commentStyle: 'line', + lineCommentPrefix: '#', + vibeExtension: '.vibe.sh', + humanExtension: '.human.sh', + lockExtension: '.lock.sh', + testPatterns: ['_test.sh', 'test/'], + }, + clojure: { + name: 'Clojure', + commentStyle: 'line', + lineCommentPrefix: ';', + vibeExtension: '.vibe.clj', + humanExtension: '.human.clj', + lockExtension: '.lock.clj', + testPatterns: ['_test.clj', 'test/'], + }, + haskell: { + name: 'Haskell', + commentStyle: 'line', + lineCommentPrefix: '--', + vibeExtension: '.vibe.hs', + humanExtension: '.human.hs', + lockExtension: '.lock.hs', + testPatterns: ['Spec.hs', 'Test.hs', 'test/'], + }, + crystal: { + name: 'Crystal', + commentStyle: 'line', + lineCommentPrefix: '#', + vibeExtension: '.vibe.cr', + humanExtension: '.human.cr', + lockExtension: '.lock.cr', + testPatterns: ['_spec.cr', 'spec/'], + }, + r: { + name: 'R', + commentStyle: 'line', + lineCommentPrefix: '#', + vibeExtension: '.vibe.R', + humanExtension: '.human.R', + lockExtension: '.lock.R', + testPatterns: ['test_', 'test-', 'tests/'], + }, + julia: { + name: 'Julia', + commentStyle: 'line', + lineCommentPrefix: '#', + vibeExtension: '.vibe.jl', + humanExtension: '.human.jl', + lockExtension: '.lock.jl', + testPatterns: ['_test.jl', 'test/'], + }, + zig: { + name: 'Zig', + commentStyle: 'line', + lineCommentPrefix: '//', + vibeExtension: '.vibe.zig', + humanExtension: '.human.zig', + lockExtension: '.lock.zig', + testPatterns: ['_test.zig', 'test/'], + }, +}; + +/** + * Detects the language configuration from a file path + */ +export function detectLanguage(filePath: string): LanguageConfig | null { + for (const [, config] of Object.entries(SUPPORTED_LANGUAGES)) { + if ( + filePath.endsWith(config.vibeExtension) || + filePath.endsWith(config.humanExtension) || + filePath.endsWith(config.lockExtension) + ) { + return config; + } + } + return null; +} + +/** + * Gets all vibe extensions across all languages + */ +export function getAllVibeExtensions(): string[] { + return Object.values(SUPPORTED_LANGUAGES).map(config => config.vibeExtension); +} + +/** + * Gets all human extensions across all languages + */ +export function getAllHumanExtensions(): string[] { + return Object.values(SUPPORTED_LANGUAGES).map(config => config.humanExtension); +} + +/** + * Gets all lock extensions across all languages + */ +export function getAllLockExtensions(): string[] { + return Object.values(SUPPORTED_LANGUAGES).map(config => config.lockExtension); +} + +/** + * Checks if a file is a vibe file in any supported language + */ +export function isVibeFile(filePath: string): boolean { + return getAllVibeExtensions().some(ext => filePath.endsWith(ext)); +} + +/** + * Checks if a file is a human file in any supported language + */ +export function isHumanFile(filePath: string): boolean { + return getAllHumanExtensions().some(ext => filePath.endsWith(ext)); +} + +/** + * Checks if a file is a lock file in any supported language + */ +export function isLockFile(filePath: string): boolean { + return getAllLockExtensions().some(ext => filePath.endsWith(ext)); +} + +/** + * Checks if a file is a test file based on language-specific patterns + */ +export function isTestFile(filePath: string): boolean { + const config = detectLanguage(filePath); + + // If we can detect the language, use its patterns + if (config) { + return config.testPatterns.some(pattern => + filePath.includes(pattern) || filePath.endsWith(pattern) + ); + } + + // Fallback: check all patterns + const allPatterns = Object.values(SUPPORTED_LANGUAGES).flatMap(c => c.testPatterns); + return allPatterns.some(pattern => + filePath.includes(pattern) || filePath.endsWith(pattern) + ); +} diff --git a/src/lib/vibe-checker.ts b/src/lib/vibe-checker.ts index e68a285..aa498d5 100644 --- a/src/lib/vibe-checker.ts +++ b/src/lib/vibe-checker.ts @@ -5,6 +5,7 @@ import { getBaseRef, getChangedFiles } from './git-utils.js'; import { validateDirectives, getTouchGlobs } from './directive-parser.js'; import { matchesAnyGlob } from './glob-matcher.js'; import { createReport, writeReport, printReport, type Violation } from './report.js'; +import { isVibeFile, detectLanguage } from './language-config.js'; interface OwnershipConfig { touch_exempt_globs?: string[]; @@ -43,11 +44,11 @@ export async function runVibeChecker(baseRefOverride?: string): Promise console.log(pc.dim(`Changed files: ${changedFiles.length}`)); - // Find changed .vibe.ts files - const vibeFiles = changedFiles.filter(f => f.endsWith('.vibe.ts')); + // Find changed vibe files (any supported language) + const vibeFiles = changedFiles.filter(f => isVibeFile(f)); if (vibeFiles.length === 0) { - console.log(pc.yellow('\nNo .vibe.ts files in the changeset. Skipping directive checks.\n')); + console.log(pc.yellow('\nNo vibe files in the changeset. Skipping directive checks.\n')); return 0; } @@ -57,11 +58,15 @@ export async function runVibeChecker(baseRefOverride?: string): Promise const allTouchGlobs: string[] = []; const touchExemptGlobs = config.touch_exempt_globs || []; - // Validate each .vibe.ts file + // Validate each vibe file for (const vibeFile of vibeFiles) { const filePath = path.join(cwd, vibeFile); console.log(pc.dim(`Checking ${vibeFile}...`)); + // Get language config for proper comment style in error messages + const langConfig = detectLanguage(vibeFile); + const commentPrefix = langConfig?.lineCommentPrefix || '//'; + try { const validation = validateDirectives(filePath); @@ -73,7 +78,7 @@ export async function runVibeChecker(baseRefOverride?: string): Promise message: error, details: validation.missing.length > 0 ? `FIX: Add these directives to the top of the file:\n` + - validation.missing.map(d => ` // @vibe:${d} `).join('\n') + validation.missing.map(d => ` ${commentPrefix} @vibe:${d} `).join('\n') : undefined, }); } @@ -94,8 +99,8 @@ export async function runVibeChecker(baseRefOverride?: string): Promise // Verify all changed files match at least one touch glob if (config.require_touch_enforcement !== false && allTouchGlobs.length > 0) { for (const changedFile of changedFiles) { - // Skip the .vibe.ts files themselves - they're always allowed - if (changedFile.endsWith('.vibe.ts')) { + // Skip vibe files themselves - they're always allowed + if (isVibeFile(changedFile)) { continue; } @@ -115,8 +120,8 @@ export async function runVibeChecker(baseRefOverride?: string): Promise message: `File changed but not declared in any @vibe:touch directive`, details: `Declared patterns: ${allTouchGlobs.join(', ') || '(none)'}\n` + - `FIX: Add to @vibe:touch in your .vibe.ts file:\n` + - ` // @vibe:touch ${suggestedPattern}\n` + + `FIX: Add to @vibe:touch in your vibe file:\n` + + ` ${getCommentPrefix(changedFile)} @vibe:touch ${suggestedPattern}\n` + `Or stop modifying this file.`, }); } @@ -162,6 +167,11 @@ function suggestTouchPattern(filePath: string): string { return `${dir}/**/*${ext}`; } +function getCommentPrefix(filePath: string): string { + const langConfig = detectLanguage(filePath); + return langConfig?.lineCommentPrefix || '//'; +} + function printFixSummary(violations: Violation[]): void { const byType = new Map(); @@ -175,7 +185,7 @@ function printFixSummary(violations: Violation[]): void { if (byType.has('MISSING_DIRECTIVE')) { console.log(pc.yellow('Missing directives:')); - console.log(' Add required directives to your .vibe.ts files.'); + console.log(' Add required directives to your vibe files.'); console.log(' Required: goal, touch, inputs, outputs, constraints, tests, risk, rollback\n'); } @@ -184,9 +194,11 @@ function printFixSummary(violations: Violation[]): void { const patterns = [...new Set(touchViolations.map(v => suggestTouchPattern(v.file)))]; console.log(pc.yellow('Undeclared file changes:')); - console.log(' Option 1: Add to @vibe:touch in your .vibe.ts:'); + console.log(' Option 1: Add to @vibe:touch in your vibe file:'); for (const pattern of patterns.slice(0, 5)) { - console.log(` // @vibe:touch ${pattern}`); + // Use appropriate comment prefix + const commentPrefix = getCommentPrefix(pattern); + console.log(` ${commentPrefix} @vibe:touch ${pattern}`); } if (patterns.length > 5) { console.log(` ... and ${patterns.length - 5} more`); diff --git a/src/lib/vibe-guard.ts b/src/lib/vibe-guard.ts index 6b18c7d..eef2db3 100644 --- a/src/lib/vibe-guard.ts +++ b/src/lib/vibe-guard.ts @@ -5,6 +5,7 @@ import { getBaseRef, getChangedFiles } from './git-utils.js'; import { parseDirectives } from './directive-parser.js'; import { matchesAnyGlob, findMatchingGlob } from './glob-matcher.js'; import { createReport, writeReport, printReport, type Violation } from './report.js'; +import { isTestFile } from './language-config.js'; export interface OwnershipConfig { ai_owned_globs: string[]; @@ -54,11 +55,7 @@ function getFileOwnership( return 'unowned'; } -function isTestFile(file: string): boolean { - return file.endsWith('.test.ts') || file.endsWith('.spec.ts') || - file.endsWith('.test.js') || file.endsWith('.spec.js') || - file.includes('__tests__/'); -} +// Removed isTestFile function - now imported from language-config.ts export async function runVibeGuard(baseRefOverride?: string): Promise { const cwd = process.cwd(); @@ -128,7 +125,7 @@ export async function runVibeGuard(baseRefOverride?: string): Promise { details: `FIX: Either:\n` + ` 1. Add to guard_exempt_globs in .vibe/ownership.json (for docs/config)\n` + - ` 2. Rename to *.vibe.ts (AI-owned), *.human.ts, or *.lock.ts\n` + + ` 2. Rename with .vibe extension (e.g., .vibe.ts, .vibe.py, .vibe.rb)\n` + ` 3. Add a matching pattern to ai_owned_globs`, }); continue; diff --git a/templates/vibe/ownership.json b/templates/vibe/ownership.json index 1a57df4..9f4e69f 100644 --- a/templates/vibe/ownership.json +++ b/templates/vibe/ownership.json @@ -1,12 +1,75 @@ { "ai_owned_globs": [ - "**/*.vibe.ts" + "**/*.vibe.ts", + "**/*.vibe.js", + "**/*.vibe.py", + "**/*.vibe.rb", + "**/*.vibe.go", + "**/*.vibe.rs", + "**/*.vibe.php", + "**/*.vibe.java", + "**/*.vibe.cs", + "**/*.vibe.swift", + "**/*.vibe.kt", + "**/*.vibe.scala", + "**/*.vibe.ex", + "**/*.vibe.dart", + "**/*.vibe.lua", + "**/*.vibe.sh", + "**/*.vibe.clj", + "**/*.vibe.hs", + "**/*.vibe.cr", + "**/*.vibe.R", + "**/*.vibe.jl", + "**/*.vibe.zig" ], "human_owned_globs": [ - "**/*.human.ts" + "**/*.human.ts", + "**/*.human.js", + "**/*.human.py", + "**/*.human.rb", + "**/*.human.go", + "**/*.human.rs", + "**/*.human.php", + "**/*.human.java", + "**/*.human.cs", + "**/*.human.swift", + "**/*.human.kt", + "**/*.human.scala", + "**/*.human.ex", + "**/*.human.dart", + "**/*.human.lua", + "**/*.human.sh", + "**/*.human.clj", + "**/*.human.hs", + "**/*.human.cr", + "**/*.human.R", + "**/*.human.jl", + "**/*.human.zig" ], "contract_owned_globs": [ - "**/*.lock.ts" + "**/*.lock.ts", + "**/*.lock.js", + "**/*.lock.py", + "**/*.lock.rb", + "**/*.lock.go", + "**/*.lock.rs", + "**/*.lock.php", + "**/*.lock.java", + "**/*.lock.cs", + "**/*.lock.swift", + "**/*.lock.kt", + "**/*.lock.scala", + "**/*.lock.ex", + "**/*.lock.dart", + "**/*.lock.lua", + "**/*.lock.sh", + "**/*.lock.clj", + "**/*.lock.hs", + "**/*.lock.cr", + "**/*.lock.R", + "**/*.lock.jl", + "**/*.lock.zig" ], "blocked_globs": [ "**/dist/**", @@ -18,7 +81,49 @@ ], "require_manifest_for_globs": [ "**/*.vibe.ts", - "**/*.lock.ts" + "**/*.vibe.js", + "**/*.vibe.py", + "**/*.vibe.rb", + "**/*.vibe.go", + "**/*.vibe.rs", + "**/*.vibe.php", + "**/*.vibe.java", + "**/*.vibe.cs", + "**/*.vibe.swift", + "**/*.vibe.kt", + "**/*.vibe.scala", + "**/*.vibe.ex", + "**/*.vibe.dart", + "**/*.vibe.lua", + "**/*.vibe.sh", + "**/*.vibe.clj", + "**/*.vibe.hs", + "**/*.vibe.cr", + "**/*.vibe.R", + "**/*.vibe.jl", + "**/*.vibe.zig", + "**/*.lock.ts", + "**/*.lock.js", + "**/*.lock.py", + "**/*.lock.rb", + "**/*.lock.go", + "**/*.lock.rs", + "**/*.lock.php", + "**/*.lock.java", + "**/*.lock.cs", + "**/*.lock.swift", + "**/*.lock.kt", + "**/*.lock.scala", + "**/*.lock.ex", + "**/*.lock.dart", + "**/*.lock.lua", + "**/*.lock.sh", + "**/*.lock.clj", + "**/*.lock.hs", + "**/*.lock.cr", + "**/*.lock.R", + "**/*.lock.jl", + "**/*.lock.zig" ], "require_touch_enforcement": true, "touch_exempt_globs": [ diff --git a/templates/vibe/templates/task.vibe.R.template b/templates/vibe/templates/task.vibe.R.template new file mode 100644 index 0000000..e7b6d3f --- /dev/null +++ b/templates/vibe/templates/task.vibe.R.template @@ -0,0 +1,16 @@ +# @vibe:goal {{GOAL}} +# @vibe:touch {{TOUCH}} +# @vibe:inputs {{INPUTS}} +# @vibe:outputs {{OUTPUTS}} +# @vibe:constraints {{CONSTRAINTS}} +# @vibe:tests {{TESTS}} +# @vibe:risk {{RISK}} +# @vibe:rollback {{ROLLBACK}} +# +# Created: {{DATE}} +# --- + +#' {{GOAL}} +{{FUNCTION_NAME}} <- function() { + stop("Not implemented") +} diff --git a/templates/vibe/templates/task.vibe.clj.template b/templates/vibe/templates/task.vibe.clj.template new file mode 100644 index 0000000..418a0eb --- /dev/null +++ b/templates/vibe/templates/task.vibe.clj.template @@ -0,0 +1,16 @@ +; @vibe:goal {{GOAL}} +; @vibe:touch {{TOUCH}} +; @vibe:inputs {{INPUTS}} +; @vibe:outputs {{OUTPUTS}} +; @vibe:constraints {{CONSTRAINTS}} +; @vibe:tests {{TESTS}} +; @vibe:risk {{RISK}} +; @vibe:rollback {{ROLLBACK}} +; +; Created: {{DATE}} +; --- + +(defn {{FUNCTION_NAME}} + "{{GOAL}}" + [] + (throw (ex-info "Not implemented" {}))) diff --git a/templates/vibe/templates/task.vibe.cr.template b/templates/vibe/templates/task.vibe.cr.template new file mode 100644 index 0000000..c29cfd5 --- /dev/null +++ b/templates/vibe/templates/task.vibe.cr.template @@ -0,0 +1,16 @@ +# @vibe:goal {{GOAL}} +# @vibe:touch {{TOUCH}} +# @vibe:inputs {{INPUTS}} +# @vibe:outputs {{OUTPUTS}} +# @vibe:constraints {{CONSTRAINTS}} +# @vibe:tests {{TESTS}} +# @vibe:risk {{RISK}} +# @vibe:rollback {{ROLLBACK}} +# +# Created: {{DATE}} +# --- + +# {{GOAL}} +def {{FUNCTION_NAME}} + raise NotImplementedError.new("Not implemented") +end diff --git a/templates/vibe/templates/task.vibe.dart.template b/templates/vibe/templates/task.vibe.dart.template new file mode 100644 index 0000000..aded460 --- /dev/null +++ b/templates/vibe/templates/task.vibe.dart.template @@ -0,0 +1,17 @@ +// @vibe:goal {{GOAL}} +// @vibe:touch {{TOUCH}} +// @vibe:inputs {{INPUTS}} +// @vibe:outputs {{OUTPUTS}} +// @vibe:constraints {{CONSTRAINTS}} +// @vibe:tests {{TESTS}} +// @vibe:risk {{RISK}} +// @vibe:rollback {{ROLLBACK}} +// +// Created: {{DATE}} +// --- + +/// {{GOAL}} +void {{FUNCTION_NAME}}() { + // TODO: Implement + throw UnimplementedError('Not implemented'); +} diff --git a/templates/vibe/templates/task.vibe.ex.template b/templates/vibe/templates/task.vibe.ex.template new file mode 100644 index 0000000..ac7ffff --- /dev/null +++ b/templates/vibe/templates/task.vibe.ex.template @@ -0,0 +1,21 @@ +# @vibe:goal {{GOAL}} +# @vibe:touch {{TOUCH}} +# @vibe:inputs {{INPUTS}} +# @vibe:outputs {{OUTPUTS}} +# @vibe:constraints {{CONSTRAINTS}} +# @vibe:tests {{TESTS}} +# @vibe:risk {{RISK}} +# @vibe:rollback {{ROLLBACK}} +# +# Created: {{DATE}} +# --- + +defmodule VibeModule do + @moduledoc """ + {{GOAL}} + """ + + def {{FUNCTION_NAME}} do + raise "Not implemented" + end +end diff --git a/templates/vibe/templates/task.vibe.go.template b/templates/vibe/templates/task.vibe.go.template new file mode 100644 index 0000000..2e35f20 --- /dev/null +++ b/templates/vibe/templates/task.vibe.go.template @@ -0,0 +1,19 @@ +// @vibe:goal {{GOAL}} +// @vibe:touch {{TOUCH}} +// @vibe:inputs {{INPUTS}} +// @vibe:outputs {{OUTPUTS}} +// @vibe:constraints {{CONSTRAINTS}} +// @vibe:tests {{TESTS}} +// @vibe:risk {{RISK}} +// @vibe:rollback {{ROLLBACK}} +// +// Created: {{DATE}} +// --- + +// {{GOAL}} +package main + +func {{FUNCTION_NAME}}() error { + // TODO: Implement + panic("Not implemented") +} diff --git a/templates/vibe/templates/task.vibe.hs.template b/templates/vibe/templates/task.vibe.hs.template new file mode 100644 index 0000000..3e35229 --- /dev/null +++ b/templates/vibe/templates/task.vibe.hs.template @@ -0,0 +1,15 @@ +-- @vibe:goal {{GOAL}} +-- @vibe:touch {{TOUCH}} +-- @vibe:inputs {{INPUTS}} +-- @vibe:outputs {{OUTPUTS}} +-- @vibe:constraints {{CONSTRAINTS}} +-- @vibe:tests {{TESTS}} +-- @vibe:risk {{RISK}} +-- @vibe:rollback {{ROLLBACK}} +-- +-- Created: {{DATE}} +-- --- + +-- | {{GOAL}} +{{FUNCTION_NAME}} :: IO () +{{FUNCTION_NAME}} = error "Not implemented" diff --git a/templates/vibe/templates/task.vibe.jl.template b/templates/vibe/templates/task.vibe.jl.template new file mode 100644 index 0000000..086a947 --- /dev/null +++ b/templates/vibe/templates/task.vibe.jl.template @@ -0,0 +1,20 @@ +# @vibe:goal {{GOAL}} +# @vibe:touch {{TOUCH}} +# @vibe:inputs {{INPUTS}} +# @vibe:outputs {{OUTPUTS}} +# @vibe:constraints {{CONSTRAINTS}} +# @vibe:tests {{TESTS}} +# @vibe:risk {{RISK}} +# @vibe:rollback {{ROLLBACK}} +# +# Created: {{DATE}} +# --- + +""" + {{FUNCTION_NAME}}() + +{{GOAL}} +""" +function {{FUNCTION_NAME}}() + error("Not implemented") +end diff --git a/templates/vibe/templates/task.vibe.lua.template b/templates/vibe/templates/task.vibe.lua.template new file mode 100644 index 0000000..ab4ccc5 --- /dev/null +++ b/templates/vibe/templates/task.vibe.lua.template @@ -0,0 +1,20 @@ +-- @vibe:goal {{GOAL}} +-- @vibe:touch {{TOUCH}} +-- @vibe:inputs {{INPUTS}} +-- @vibe:outputs {{OUTPUTS}} +-- @vibe:constraints {{CONSTRAINTS}} +-- @vibe:tests {{TESTS}} +-- @vibe:risk {{RISK}} +-- @vibe:rollback {{ROLLBACK}} +-- +-- Created: {{DATE}} +-- --- + +--- {{GOAL}} +local function {{FUNCTION_NAME}}() + error("Not implemented") +end + +return { + {{FUNCTION_NAME}} = {{FUNCTION_NAME}} +} diff --git a/templates/vibe/templates/task.vibe.py.template b/templates/vibe/templates/task.vibe.py.template new file mode 100644 index 0000000..c02cd7a --- /dev/null +++ b/templates/vibe/templates/task.vibe.py.template @@ -0,0 +1,19 @@ +# @vibe:goal {{GOAL}} +# @vibe:touch {{TOUCH}} +# @vibe:inputs {{INPUTS}} +# @vibe:outputs {{OUTPUTS}} +# @vibe:constraints {{CONSTRAINTS}} +# @vibe:tests {{TESTS}} +# @vibe:risk {{RISK}} +# @vibe:rollback {{ROLLBACK}} +# +# Created: {{DATE}} +# --- + +""" +{{GOAL}} +""" + +def {{FUNCTION_NAME}}(): + """TODO: Implement""" + raise NotImplementedError('Not implemented') diff --git a/templates/vibe/templates/task.vibe.rb.template b/templates/vibe/templates/task.vibe.rb.template new file mode 100644 index 0000000..b097e8e --- /dev/null +++ b/templates/vibe/templates/task.vibe.rb.template @@ -0,0 +1,16 @@ +# @vibe:goal {{GOAL}} +# @vibe:touch {{TOUCH}} +# @vibe:inputs {{INPUTS}} +# @vibe:outputs {{OUTPUTS}} +# @vibe:constraints {{CONSTRAINTS}} +# @vibe:tests {{TESTS}} +# @vibe:risk {{RISK}} +# @vibe:rollback {{ROLLBACK}} +# +# Created: {{DATE}} +# --- + +# {{GOAL}} +def {{FUNCTION_NAME}} + raise NotImplementedError, 'Not implemented' +end diff --git a/templates/vibe/templates/task.vibe.rs.template b/templates/vibe/templates/task.vibe.rs.template new file mode 100644 index 0000000..8f38f39 --- /dev/null +++ b/templates/vibe/templates/task.vibe.rs.template @@ -0,0 +1,17 @@ +// @vibe:goal {{GOAL}} +// @vibe:touch {{TOUCH}} +// @vibe:inputs {{INPUTS}} +// @vibe:outputs {{OUTPUTS}} +// @vibe:constraints {{CONSTRAINTS}} +// @vibe:tests {{TESTS}} +// @vibe:risk {{RISK}} +// @vibe:rollback {{ROLLBACK}} +// +// Created: {{DATE}} +// --- + +/// {{GOAL}} +pub fn {{FUNCTION_NAME}}() -> Result<(), String> { + // TODO: Implement + Err("Not implemented".to_string()) +} diff --git a/templates/vibe/templates/task.vibe.sh.template b/templates/vibe/templates/task.vibe.sh.template new file mode 100644 index 0000000..001493f --- /dev/null +++ b/templates/vibe/templates/task.vibe.sh.template @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# @vibe:goal {{GOAL}} +# @vibe:touch {{TOUCH}} +# @vibe:inputs {{INPUTS}} +# @vibe:outputs {{OUTPUTS}} +# @vibe:constraints {{CONSTRAINTS}} +# @vibe:tests {{TESTS}} +# @vibe:risk {{RISK}} +# @vibe:rollback {{ROLLBACK}} +# +# Created: {{DATE}} +# --- + +# {{GOAL}} +{{FUNCTION_NAME}}() { + echo "Error: Not implemented" >&2 + return 1 +} diff --git a/templates/vibe/templates/task.vibe.zig.template b/templates/vibe/templates/task.vibe.zig.template new file mode 100644 index 0000000..1a683ae --- /dev/null +++ b/templates/vibe/templates/task.vibe.zig.template @@ -0,0 +1,18 @@ +// @vibe:goal {{GOAL}} +// @vibe:touch {{TOUCH}} +// @vibe:inputs {{INPUTS}} +// @vibe:outputs {{OUTPUTS}} +// @vibe:constraints {{CONSTRAINTS}} +// @vibe:tests {{TESTS}} +// @vibe:risk {{RISK}} +// @vibe:rollback {{ROLLBACK}} +// +// Created: {{DATE}} +// --- + +const std = @import("std"); + +/// {{GOAL}} +pub fn {{FUNCTION_NAME}}() !void { + return error.NotImplemented; +}