Decisions

ADR-0003: Taskfile as Contract

Decision to use Taskfile as the mandatory operational contract for repository operations.

ApprovedNo MCP

Status: Accepted

Date: 2025-12-16

Deciders: Engineering Leadership


Context

Ontopix repositories vary in language, framework, and tooling. Without standardization:

For Humans:

  • New engineers don't know how to run repositories
  • Operations differ across repositories (npm scripts, Make, bash scripts, etc.)
  • Onboarding requires learning each repository's specific tooling
  • Documentation of operations is often missing or outdated

For AI Agents:

  • Agents don't know which commands are safe to run
  • No standard interface to discover operations
  • Risk of running dangerous commands (e.g., rm -rf, production deployments)
  • Ad-hoc tool invocation leads to errors

For the Organization:

  • No consistency across repositories
  • Hard to enforce operational patterns
  • Difficult to automate cross-repository operations
  • CI/CD pipelines differ unnecessarily

We need a single, standard interface for all repository operations that works for humans, agents, and automation.

Decision

We will use Taskfile as the mandatory operational contract for every Ontopix repository.

Core Principle

Taskfile is the single interface for all repository operations.

If an operation exists as a Taskfile task, it MUST be used. Tools MUST NOT be invoked directly when a Taskfile task exists.

Requirements

Every Ontopix repository MUST:

  1. Have a Taskfile.yaml at the repository root
  2. Expose all common operations as tasks
  3. Use standard task namespaces (dev, test, lint, sandbox, infra, build, deploy)
  4. Document tasks with desc: field
  5. Define task dependencies with deps: where appropriate

Standard Namespaces

Repositories SHOULD organize tasks into standard namespaces:

  • dev:* — Development operations (run, watch, migrate, seed)
  • test:* — Testing operations (unit, integration, e2e, all)
  • lint:* — Code quality operations (check, fix, types)
  • sandbox:* — Sandbox management (start, stop, reset)
  • infra:* — Infrastructure operations (plan, apply, destroy)
  • build:* — Build operations (docker, dist, docs)
  • deploy:* — Deployment operations (dev, staging, prod)

Agent Contract

Agents MUST:

  • Use Taskfile tasks when they exist
  • Run task --list to discover operations
  • Never invoke tools directly if a task exists

Agents MUST NOT:

  • Run pytest instead of task test:unit
  • Run terraform apply instead of task infra:apply
  • Skip tasks because they "know better"

Rationale

Why Taskfile Over Alternatives?

vs Make:

  • YAML syntax more readable than Makefile syntax
  • Better support for cross-platform (Windows, macOS, Linux)
  • No tab-vs-space issues
  • Built-in features (variables, includes, status checks)

vs npm scripts (in package.json):

  • Not language-specific (works for Python, Go, Terraform, etc.)
  • More powerful (dependencies, preconditions, status)
  • Consistent across all repository types
  • Not tied to JavaScript ecosystem

vs bash scripts:

  • Self-documenting (task --list)
  • Structured and consistent
  • Built-in dependency management
  • Easier to maintain

vs Just, Mage, or other task runners:

  • Taskfile is mature and widely adopted
  • Good documentation
  • Active maintenance
  • YAML-based (familiar format)

Why a Contractual Interface?

Discoverability:

  • task --list shows all available operations
  • Engineers immediately see what's possible
  • No need to read documentation or scripts

Consistency:

  • Same command structure across repositories
  • task test:all works everywhere
  • task sandbox:start works everywhere
  • Reduces cognitive load

Safety:

  • Tasks encode safe operations
  • Preconditions prevent dangerous actions
  • Agents have safe interface
  • Production deployments require explicit confirmation

Maintainability:

  • Tool changes don't break workflows
  • Tasks encapsulate complexity
  • Easier to update than scattered scripts

Automation:

  • CI/CD can use same tasks as developers
  • Cross-repository automation simplified
  • Consistent interface for orchestration

Why Standard Namespaces?

Predictability:

  • Engineers know test:unit runs unit tests
  • Agents know sandbox:start starts sandbox
  • No guessing required

Pattern Enforcement:

  • Standard operations are standard tasks
  • Organizational patterns encoded
  • Deviations are visible

Tooling:

  • Build tools on top of standard tasks
  • Cross-repository scripts simplified
  • Easier to create meta-automation

Consequences

Positive

Developer Experience:

  • Immediate operational clarity
  • Fast onboarding
  • Consistent across repositories

Agent Effectiveness:

  • Clear, safe interface
  • Reduced risk of errors
  • Pattern adherence

Organizational Consistency:

  • Standard operations everywhere
  • Easier to enforce patterns
  • Simplified automation

Maintenance:

  • Tasks encapsulate complexity
  • Tool changes isolated
  • Self-documenting

Negative

Additional Tooling:

  • Engineers must install Taskfile
  • Another tool to learn
  • Potential version compatibility issues

Abstraction Overhead:

  • Simple commands wrapped in tasks
  • Potential for over-abstraction
  • Learning curve for task syntax

Migration Effort:

  • Existing repositories need Taskfile
  • Scripts need to be converted
  • Patterns need standardization

Mitigations

Easy Installation:

  • Taskfile available via package managers
  • Single binary, no dependencies
  • Installation documented

Pragmatic Abstraction:

  • Don't wrap trivial commands unnecessarily
  • Tasks add value (safety, dependencies, documentation)
  • Direct tool usage acceptable when no task exists

Incremental Migration:

  • Add Taskfile wrapping existing tools
  • Migrate scripts over time
  • Templates provided for new repositories

Alternatives Considered

Alternative 1: No Standard (Ad-hoc Scripts)

Rejected because:

  • No consistency
  • No discoverability
  • Unsafe for agents
  • Poor onboarding experience

Alternative 2: Make (Makefile)

Rejected because:

  • Syntax is less readable
  • Tab vs space issues
  • Less cross-platform support
  • Lacks modern features

Alternative 3: Language-Specific (npm scripts, poetry scripts)

Rejected because:

  • Not language-agnostic
  • Doesn't work for infrastructure repos
  • Inconsistent across repository types
  • Tied to specific ecosystems

Alternative 4: Bash Scripts in scripts/

Rejected because:

  • No self-documentation
  • No standard structure
  • Hard to discover operations
  • Difficult to enforce patterns

Alternative 5: Just, Mage, or Other Runners

Rejected because:

  • Less mature ecosystem
  • Smaller community
  • Taskfile already established in industry

References

Success Criteria

This decision is successful if:

  • Every repository has Taskfile.yaml
  • Engineers use task --list to discover operations
  • Agents consistently use tasks instead of direct tools
  • CI/CD uses tasks for operations
  • Onboarding time reduced
  • Cross-repository automation simplified