Capabilities are born in lib; co-locate only skill glue
Status: open/active
Summary
Section titled “Summary”- A capability — entity CRUD, policy checks, audits, anything general by nature — is born in
solutions/ontological/libregardless of caller count; only skill-specific glue co-locates with its skill, promoted to a shared home when a second real caller appears.
Placement is decided by what the code is, not by who calls it.
Capabilities are born in solutions/ontological/lib. Code that operates
on a domain entity or shared infrastructure — entity CRUD, policy checks,
audits, validation — is general by nature. It starts in
solutions/ontological/lib (with the entity it acts on per
D-0007-deterministic-op-substrate, or under services/ / util/) and is
exposed through an adapter. A single caller does not make it skill-local.
Skill glue co-locates. A helper that serves one skill’s own
presentation — rendering a prompt fragment for that skill, adapting a CLI
result into the shape the head narrates — lives in
solutions/ontological/skills/<skill>/. Promote it to a shared home only as a
deliberate refactor when a second real caller appears.
Caller count is a lagging signal; the nature of the code is known at birth. Entity CRUD written beside a skill is a capability hiding in a skill directory — undiscoverable, duplicated by the next skill, cut off from the op registry. Glue promoted early forces a generalized API before a second use case is real. Deciding by nature removes the judgment call both mistakes share.
How to apply
Section titled “How to apply”- Writing a script for a skill? Ask what it acts on. A domain entity
or shared infra →
solutions/ontological/lib(an op module or service), with the skill reaching it through an adapter or thin shim. The skill’s own presentation → co-locate. - The pattern to follow is the identifier gate:
lib/model/identifier.ts(findIdentifierViolations) andlib/model/authoring.ts(mintIdentity,schemaVersion) carry the capability; lefthook / project-check / scaffolder entry points are thin adapters. - Promoting glue when the second caller arrives:
git mvto the shared home, update every reference, tidy the API. The promotion is its own commit, separate from the second caller’s feature work.
Anti-examples
Section titled “Anti-examples”new_standard.tsliving insolutions/ontological/skills/standard-new/— entity CRUD beside a skill. CRUD is a capability; it is born inlib/model(T-0010 relocates it).- Keeping an audit or policy check skill-local because only one skill runs it today — checks are capabilities.
- Adding a glue helper to a shared bucket because “it might be reused later.” Glue without a second caller co-locates.
Generalizes beyond scripts: prose, fixtures, helper modules, configuration. For glue, treat the move into a shared dir as a positive event, not a default destination.
Sweep complete (2026-06-05): solutions/ontological/lib carries all
capabilities; solutions/ontological/skills/ is glue-only. The skill-prose
codemod (T-QL5F) re-pointed every skill from co-located scripts to
sdlc <path…> CLI verbs.
apps/ and packages/ (D-0012-monorepo-tooling): the
monorepo adds two consumer trees. Capabilities still come to life in the
substrate, never in an application. packages/<ecosystem>/ (partitioned by
language) holds code shared across applications — a UI kit, a generated typed
API client — and domain-blind components that never import the substrate; a
domain capability belongs in solutions/ontological/lib (later src/). How an
application reaches the substrate, and the arrow a domain-blind component may
not cross, are governed by
S-0008-apps-consume-substrate-through-published-surfaces.
The glue category shrinks. As sequencing moves out of prose and into process registrations the engine executes (D-VSLI-distributed-work-runner-architecture), the helpers that existed to serve a skill’s own sequencing — parsers for its intermediate output, mutators for its session state — lose their reason to exist: step results arrive over the step protocol and execution state lives on the lease. What remains is head-side presentation. The placement rule is unchanged; the set of things it governs gets smaller.