Skip to content

automation — Repository automation is scripted capabilities over typed Rust, not shell

A capability may be scripted (ADR 0069): a Rhai script inside the Rust executable orchestrates typed capabilities through the one registry, reaches every surface by the projections that already exist, runs in a sandbox with a declared and enforced effect ceiling, and shell shrinks by migration under a gate that refuses new shell without a declared exemption.

ACTIVE 3 of 6 issues done

ready
2
blocked
1
active
0
verify
0
done
3
cancelled
0

Problem

Repository automation lives in shell, and every recurring defect class this repository has recorded about itself has a shell instance: a BSD/GNU flag that behaves differently on the runner, a pipeline whose count is lost in a subshell, a gate that cannot read its own pattern and reports clean, a sort whose order depends on the locale. An audit of 2026-09-15 classified 223 units: scripts/ci is 44 files and 6,017 lines, the other scripts and bin 82 files and 14,860 lines, lib 45 files and 19,513 lines, and 216 shell test cases 30,872 lines. By disposition 97 are domain logic that belongs in core Rust, 32 orchestration, 34 glue, 3 dead, 14 generated and 43 platform adaptors. A user of the tool needs Bash to run any of it, and Perl reaches the tree through shasum on macOS.

Outcome

A capability may be scripted (ADR 0069): a Rhai script inside the Rust executable orchestrates typed capabilities through the one registry, reaches every surface by the projections that already exist, runs in a sandbox with a declared and enforced effect ceiling, and shell shrinks by migration under a gate that refuses new shell without a declared exemption.

Current state

No interpreter is embedded. Every orchestration is a shell script, the baseline-ratchet logic is copied into ten scripts/ci gates, nothing refuses a new shell file, and Perl is reachable through shasum.

Desired state

The sandboxed engine is part of the executable; a scripted capability is a kind discovered by the index and registered in the one registry, runnable through majordomus run and projected like any capability; nothing runs Perl; new shell under governed paths is refused without an exemption and the migration inventory is tracked; the first shell gates are scripted capabilities over typed Rust.

Scope

  • apps/majordomus-cli
  • share
  • scripts
  • lib
  • bin
  • .ai/repo
  • docs
  • test
  • SECURITY.md

Out of scope

  • Transliterating shell scripts into Rhai. Domain logic moves to typed Rust capabilities; a script only orchestrates capabilities
  • A generic shell or exec capability, or any function that takes a command string
  • Perl, Python or Node as a portable layer

Acceptance criteria

  • A Rhai script runs only inside the sandbox engine, with eval disabled, no clock, bounded work and cancellation
  • A scripted capability declared in the layer appears in the registry, capabilities list, OpenAPI and MCP with no edit anywhere else
  • A script calling a capability whose effect exceeds its own declared effect is refused at run time
  • No tracked file invokes Perl, held by a gate
  • A new shell file under a governed path without an exemption entry is refused, and the migration inventory is machine-readable

Validation

  • majordomus plan validate
  • bin/majordomus-cli capabilities validate
  • bin/majordomus-cli generate --check
  • bash test/run.sh 383_a_scripted_capability_runs

Evidence required

  • sandbox_engine_proved
  • scripted_capability_projected_everywhere
  • effect_ceiling_enforced
  • no_perl
  • new_shell_refused

Issues

Each one is an execution contract with its own acceptance criteria, validation command and required evidence. The wave column is the layer of the dependency graph it sits in.

issuestatuswavedepends ontitle
I1800 DONE 0 — The sandboxed engine a scripted capability runs in
I1801 READY 1 I1800 A scripted capability is a kind, discovered and registered, runnable and projected like any capability
I1802 DONE 0 — Nothing runs Perl
I1803 DONE 0 — New shell is refused without a declared exemption, and the migration inventory is tracked
I1804 BLOCKED 2 I1801 The first shell scripts become scripted capabilities over typed Rust
I3160 READY 0 — A behavioural case can be written as a Rust integration test over a disposable repository, and the continuity cases are the first ported

The graph

automation dependency graphfrom .ai/repo/project
flowchart LR
    I1800["I1800<br/>The sandboxed engine a scripted capability runs in"]:::done
    I1801["I1801<br/>A scripted capability is a kind, discovered and registered, runnable and projected like any capability"]:::ready
    I1802["I1802<br/>Nothing runs Perl"]:::done
    I1803["I1803<br/>New shell is refused without a declared exemption, and the migration inventory is tracked"]:::done
    I1804["I1804<br/>The first shell scripts become scripted capabilities over typed Rust"]:::blocked
    I3160["I3160<br/>A behavioural case can be written as a Rust integration test over a disposable repository, and the continuity cases are the first ported"]:::ready
    I1800 --> I1801
    I1801 --> I1804
    classDef done stroke:#16a34a,fill:#dcfce7,color:#14532d,stroke-width:2px
    classDef active stroke:#2563eb,fill:#eff6ff,color:#1e3a8a,stroke-width:2px
    classDef verify stroke:#7c3aed,fill:#f5f3ff,color:#4c1d95,stroke-width:2px
    classDef ready stroke:#0891b2,fill:#ecfeff,color:#164e63,stroke-width:2px
    classDef planned stroke:#0891b2,fill:#ecfeff,color:#164e63,stroke-width:2px
    classDef blocked stroke:#b45309,fill:#fffbeb,color:#78350f,stroke-width:2px
    classDef cancelled stroke:#6b7280,fill:#f9fafb,color:#374151,stroke-width:2px
    classDef superseded stroke:#6b7280,fill:#f9fafb,color:#374151,stroke-width:2px

Canonical record: .ai/repo/project/milestones/automation.yaml. Read it back with majordomus plan show automation.

Searches the titles and descriptions of every page this site publishes.