SBCE: The Spec-Driven Boundary Control Entity 📎
SBCE (say "space"), short for Spec-Driven BCE, is a workflow: every capability is declared as a single spec, and the spec is the boundary contract (package-info.java or package-info.md for Web Components) of exactly one Boundary-Control-Entity business component (e.g. one Java package) with the same name. It ships as a AIrails skill: /sbce. No CLI, no dependencies.
BCE (skill: /bce) sets the architecture invariants: boundary/control/entity layering, package structure, naming rules. /sbce owns the workflow on top: declare a capability, then iterate on the code until it matches. SBCE provides the spec, BCE places the code, and a tech stack skill (java-cli-app, microprofile-server, web-components, web-static) adds code idioms and verification.
The spec lives in the BC's package doc: package-info.java as Markdown JavaDoc (JEP 467), co-located with the code it governs. No separate specs/ tree. The spec is just a better version of the JavaDoc a developer had to write anyway:
greetings package-info.java the spec: boundary ops + EARS requirements boundary/ one method per declared operation control/ implementation -- no spec section entity/ maps to ## Entities
For a greetings BC, the entire spec is the package-info.java:
/// # Greetings /// > Return a personalised greeting for a name. /// /// ## Boundary /// - `greet-visitor` — return a greeting for a name /// /// ## Requirements /// ### R1: Greet a visitor /// - R1.1 — When a name is submitted, the BC shall return a /// greeting containing that name. /// - R1.2 — If the name is blank, then the BC shall reject /// the request. /// /// ## Out of scope package airhacks.reception.greetings;
Everything in the spec is what, never how: the operation is verb-noun and transport-neutral (greet-visitor, not GET /greetings), and there is no frontmatter, because the BC name comes from the package. greet-visitor becomes the boundary's public method; each statement id (R1.1, R1.2) is stable and traces to at least one test that embeds it; the optional ## Entities section is simply omitted, because this BC owns no stateful domain nouns. Anything in the code without a spec counterpart is drift.
Every notation in SBCE is a stable, public standard: EARS for requirements, JavaDoc and package-info.java for placement, JEP 467 for the syntax, Mermaid for the generated BC map, and the decades-old Boundary-Control-Entity pattern itself. All of it is already in the LLM weights, so the skill never has to teach it: the complete workflow fits in roughly 4,000 tokens of SKILL.md. A self-invented spec DSL would burn thousands of extra tokens in every session.
Two modes drive the lifecycle:
/sbce new greetings declare: author the spec, scaffold the layers /sbce new "greet visitors" declare from free text (github issue, Jira ticket): carves one or several BCs, new or existing /sbce apply greetings converge: close the spec-code gap, run tests until green
new loops clarifying questions until no boundary operation or EARS requirement has to be guessed. apply reads the gap in both directions: missing methods and tests are generated from the spec; undeclared methods or orphan trace ids are surfaced as drift, never silently absorbed. "Done" is a green run of the stack's own test loop, never the model's opinion.
/bce tells the code where to live; /sbce tells it what to promise.