Skip to content

Harness-agnostic

SDLC runs today inside Claude Code’s plugin mechanism. That’s a convenient bootstrap, not the destination.

The op registry is the system. The CLI is one adapter over it. The data (markdown + frontmatter on disk) and the deterministic ops are portable: they don’t depend on Claude Code, or on any single door, to be meaningful.

A future MCP server, HTTP service, or other agent harness operates on the same registry. Claude remains a front door — not the front door.

Every deterministic operation is declared once in the registry as a defineOp descriptor and projected into each door. The contract is restated nowhere: add a conforming module and the op appears in every adapter with no hand-wiring (D-0007-deterministic-op-substrate §2/§5).

solutions/ontological/lib/registry.ts
one defineOp descriptor
path · input · output · handler
│
┌───────────────┼───────────────┐
▼ ▼ ▼
CLI (sdlc) MCP HTTP
shipped derived derived
segments tool name = route =
verbatim underscore-join /<seg>/<seg>[/<seg>]
method by verb class

Adapter projection is a pure function of the path (D-H7FS-op-substrate-surface §5):

DoorProjectionExample
CLIpath segments verbatim; interior segments are description-only group subcommandssdlc quality baseline capture
MCPtool name = underscore-join, intra-segment hyphens kept; a forward map, uniqueness enforced by project-checkquality_baseline_capture, gate_worktree-scope
HTTP/<seg>/<seg>[/<seg>]; method by verb class (create/update/start → POST; get-schema/list/scan → GET)POST /quality/baseline/capture

The CLI is the one shipped door (solutions/ontological/cli/registry_adapter.ts); it builds a recursive command trie from the paths and dispatches each leaf through invokeOp. MCP and HTTP are bound to the rules above — tool names and routes are derived, never hand-assigned — but neither is built yet.

Tasks, milestones, decisions, standards, and the rest are plain markdown with YAML frontmatter under docs/planning/<plural>/. No database, no service, no Claude-specific format. Anything that can read a directory of markdown can read the data. The moment the canonical state lives in a proprietary store, the system is welded to whatever wrote it.

A handler runs against an injected ctx — { projectRoot, dryRun, io, git, gh } — and reads no ambient cwd or env (OpCtx in solutions/ontological/lib/registry.ts). That DI seam is exactly what makes an op callable off-process: an MCP or HTTP caller has no working directory to inherit. The same seam makes ops testable with fake io/git/gh, and lets --dry-run and --output be applied once by the adapter rather than re-coded per verb.

3. Long-running work has a lifecycle, not a request/response

Section titled “3. Long-running work has a lifecycle, not a request/response”

A server or a heartbeat loop never returns a single result object, so it can’t be a plain op — its handler would hang invokeOp’s await-then-validate. defineService is the registry sibling for these: same path-keyed index and help surface, but a lifecycle (start/stop?/list?) dispatched outside the output-parse pipeline (defineService in solutions/ontological/lib/registry.ts, §3). Lifecycle failures map to the SERVICE_ERROR exit tier — already-running, stale pidfile, port-in-use. The dashboard and the lease heartbeat loop are the two services shipped today.

defineService({ path, lifecycle })
│
┌───────────────────┼───────────────────┐
▼ ▼ ▼
start stop? list?
may never returns releases the reports running
(server / loop) pidfile/port instances
│
└─ dispatched OUTSIDE invokeOp's await-then-output.safeParse
(a non-returning loop would hang it) — exit via SERVICE_ERROR

It does not mean the LLM is interchangeable with a non-LLM today. The parts of the workflow that genuinely need judgment — readiness verification, backlog triage, semantic doc-drift — are LLM-shaped right now, and live in solutions/ontological/plugin/plugins/sdlc/skills/, outside the substrate. A pure-machine door reaches every op; it does not reach the skills that compose them with judgment.

The claim is narrower: the data and the deterministic ops don’t require the LLM. One registry, projected into many doors, means a capability is reachable identically from a shell, CI, a Claude session, or a non-Claude agent — with no per-adapter contract drift.