ASIMOV Program Patterns Specification (PPS)

Living Standard,

This version:
https://asimov-specs.github.io/program-patterns/
Issue Tracking:
GitHub
Inline In Spec
Editor:
(ASIMOV Systems)

Abstract

Defines interoperable command-line contracts for ASIMOV programs that import, query, generate, transform, index, and export RDF datasets; resolve and retrieve resources; provide language-model inference; and execute program text. Specifies invocation, data transport, completion, and error handling, together with requirements for hosts that compose these programs.

This is an editor-maintained draft for community review. It expands the previously published pattern descriptions with explicit interoperability requirements and records issues requiring further agreement.

The document is intended to support future W3C Community Group work. It is not a W3C Standard or a published Community Group Report, and publication of this draft does not imply W3C endorsement or community consensus.

The implementation notes describe the Rust source reviewed while preparing this draft. They are informative and are not a claim that an implementation conforms to the expanded requirements. Feedback is welcome through the specification’s issue tracker.

1. Introduction

The [ASIMOV] Platform is a polyglot development platform for trustworthy, neurosymbolic AI. Its programs can be implemented in different languages and combined using operating-system processes, files, and standard streams.

This specification defines small, role-specific command-line interfaces. A reader imports data into RDF; an adapter queries an RDF dataset; a writer exports RDF; and the other patterns provide complementary operations. A host can select a program by role without depending on its implementation language.

The specification distinguishes a program’s semantic contract from the bytes used to carry it. An RDF result can contain many statements while occupying a single output stream. An SDK can expose that stream as a byte buffer without itself interpreting RDF. Neither buffering nor the choice of SDK return type changes the external program’s contract.

1.1. Scope

This specification defines:

Executable installation, module discovery, credential provisioning, and the choice of a particular RDF storage engine are outside this specification’s scope. These facilities can be supplied by the surrounding ASIMOV platform. This specification does not require a particular programming language, SDK, asynchronous runtime, or in-process type system.

2. Conformance

All of the text of this specification is normative except sections explicitly marked informative, examples, notes, and issues.

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

A program is an executable implementing one or more of the patterns defined in this specification. A host is software that invokes a program, supplies its input, handles its output, and observes its completion. An SDK process wrapper is one possible component of a host.

A profile is a documented set of additional choices needed to use a pattern interoperably, such as an RDF stream encoding, a supported URL scheme, an entailment regime, or a runtime language. A profile MUST NOT redefine a standard option to have an incompatible meaning. It MAY constrain optional features or add documented extensions.

A conforming program MUST satisfy the common program requirements and the requirements of each pattern for which it claims conformance. It MUST identify those patterns and document its supported formats and each applicable profile. A program need not implement every pattern. Where a table marks an option as optional to implement, conformance does not require support for that option.

A conforming host MUST satisfy the host requirements for the operations it offers. A host MAY support only a subset of the patterns. It MUST document that subset and any restrictions on formats, stream handling, or returned results. It MUST NOT claim to provide a pattern’s result when it merely runs the process and discards that result.

An implementation-defined behavior is one whose choice is left to the implementation. Such a choice MUST be documented when this specification requires it, and MUST NOT contradict another requirement of this specification.

The retained jsonl default does not yet identify a complete, shared RDF mapping. Until that mapping is standardized, conformance claims for RDF interchange need to identify a mutually supported profile as well as this specification. See RDF mapping. This draft does not claim that the format token alone establishes interoperability.

3. Common processing model

3.1. Invocations and logical data

An invocation consists of a program, an ordered sequence of argument strings, an execution environment, standard streams, and the resulting process termination. One invocation performs one pattern operation, although the operation MAY generate a stream of results over time.

The data types in the pattern overview describe logical payloads. They do not specify the number of reads, writes, lines, RDF statements, or operating-system processes used to carry those payloads. In particular:

An RDF payload MUST represent RDF graphs or datasets as defined by [RDF11-CONCEPTS], using the selected serialization and profile. A text payload MUST be UTF-8 unless an explicitly selected format or language profile specifies another encoding. UTF-8 is defined by [RFC3629].

3.2. Command-line syntax

The synopsis for each pattern uses square brackets for optional operands. Uppercase names such as INPUT-FILE and FORMAT are metavariables, not literal argument values. OPTIONS stands for zero or more supported options. Options precede positional operands in the portable invocation form.

For every supported option listed for its pattern, a program MUST accept the long spelling, including the --name=value form. It MUST also accept --name value. Where a short flag is listed, it MUST accept that flag followed by a separate value, for example -o jsonl. A program MAY additionally accept attached short values or other syntactic conveniences.

A program MUST recognize -- as the end of options. Arguments after -- MUST be interpreted as positional operands even if they begin with -. The single operand - retains its standard-stream meaning where specified below.

An option that is not declared repeatable SHOULD be supplied at most once. A host MUST NOT depend on a particular precedence rule for repeated singleton options unless that rule is defined by the program’s profile. Programs MUST document their handling of repeated options.

A program MUST reject an unknown option, a missing option value, an invalid value, or an unsupported number of operands with an unsuccessful exit. It MUST NOT silently ignore an option that changes the requested operation.

Argument strings are values, not shell source. A host MUST preserve each argument’s boundary and contents when launching the process. It MUST NOT apply shell expansion to a URL, query, model name, definition, or other value merely because that value is supplied as a command-line argument.

Note: Shell quoting in examples is for the interactive shell. A host using a process API normally supplies each argument directly, without quote characters.

3.3. Resource identifiers

An INPUT-URI operand MUST be an absolute URI with a scheme, as defined by [RFC3986]. An INPUT-URL operand MUST additionally identify a resource location under the rules of a supported scheme. A relative pathname is not implicitly converted into a file URL, and this specification supplies no implicit base URI for relative references.

Programs MUST validate the identifiers they accept. A host MAY perform earlier validation, but transporting an identifier as a string does not establish its validity. Percent-encoding and fragment interpretation follow the identifier’s scheme and the program’s documented resource semantics. RDF payloads can contain IRIs as defined by the RDF data model; the command-line identifier requirements do not narrow that data model.

3.4. Files and standard streams

For an input-file operand, - denotes stdin. For an output-file operand, - denotes stdout. Where such an operand is optional, omitting it selects the default shown in the pattern’s argument table. Programs MUST support these stream defaults without requiring an explicit - operand.

The - convention is platform-independent. A program MUST NOT require callers to use /dev/stdin or /dev/stdout, which are not portable pathnames.

For patterns with both INPUT-FILE and OUTPUT-FILE:

  1. With no operands, input is stdin and output is stdout.

  2. With one operand, that operand is the input file and output is stdout.

  3. With two operands, the first is the input file and the second is the output file. A caller selecting stdin and a named output file supplies - first.

The indexer has a different operand rule because its index destination is required; see indexer arguments.

An explicitly selected input file replaces stdin as the operation’s payload source. An explicitly selected output file replaces stdout as the payload destination. A program MUST NOT duplicate that payload on stdout unless a documented extension explicitly requests duplication.

A program whose pattern has no stdin payload MUST NOT wait for data on stdin. Hosts SHOULD connect unused stdin to the platform’s null device. An EOF on an input stream means that no more input bytes are available; it is not an error by itself. Whether the resulting empty input is meaningful depends on the pattern and selected format.

3.5. Payload and diagnostic separation

Stdout, when it is the selected payload destination, MUST contain only the pattern’s output serialization. Programs MUST send diagnostics, progress messages, and logging to stderr. A program with no payload output, such as an indexer, MUST NOT emit progress messages on stdout.

Diagnostics SHOULD be UTF-8 text. Hosts SHOULD preserve diagnostic bytes even when they cannot decode them as UTF-8. Diagnostic wording is not a machine-readable error protocol and MAY change between implementations. Hosts MUST use the process termination result, rather than the presence or absence of stderr text, to determine whether an invocation succeeded.

Programs SHOULD honor a nonempty NO_COLOR environment variable by disabling optional ANSI color decoration in diagnostics. Machine-readable payloads MUST NOT contain terminal decoration regardless of that variable. [NO-COLOR]

3.6. Formats and defaults

--input=FORMAT selects the input serialization; it does not select a file. --output=FORMAT selects the output serialization; it does not select a file. File selection uses positional operands or host stream configuration.

Programs MUST implement the default format behavior listed for their pattern. When a format option is omitted, the program MUST use that default. Hosts MAY omit a format option to request the default; they MUST NOT assume that omitting an SDK field causes the SDK to transcode the payload.

A program MUST reject an explicitly requested format it does not support. It MUST NOT silently substitute another serialization. Programs MUST document supported format tokens, any aliases, and any required profiles.

The tokens used in this specification have the following meanings:

Token Meaning
text UTF-8 text; no structured chat-message envelope is implied.
jsonl Line-delimited JSON carrying RDF according to a documented RDF mapping profile; see RDF mapping.
auto Implementation-defined format selection or detection, subject to the requirements below; not a serialization in its own right.

For auto input, a program MUST document its detection procedure and fail when it cannot select a supported format. Detection MAY use content, a file extension, or other documented information. An explicit format selection MUST take precedence over automatic detection.

For auto output, a program MUST document how it selects a concrete format, including the case where output is stdout and no filename is available. It MUST NOT emit an unspecified mixture of serializations within one payload. Hosts requiring a specific output format SHOULD request it explicitly.

3.7. Counts and optional pagination

COUNT is a non-negative integer expressed using one or more ASCII decimal digits. Negative numbers, fractional numbers, and empty values are invalid. Programs MUST reject values outside their supported range instead of wrapping or silently truncating them.

--limit=COUNT sets the maximum number of logical results to emit. Omitting the option imposes no caller-requested limit; it does not guarantee that an underlying data source is unbounded. --limit=0 requests no results. Programs MAY still validate arguments, authorization, and resource availability.

A logical result for a lister is a listed entry, not an RDF statement or line of serialized output. A logical result for a resolver is one output URL. Programs MUST document how listed entries are represented in RDF.

The lister additionally defines optional --sort and --offset options. When supported and requested together, sorting is applied before the offset, and the limit is applied after the offset. Pagination MUST NOT split the RDF description of an entry merely to meet a statement or line count.

3.8. Completion and failure

An invocation succeeds only when its process terminates normally with exit status zero. A nonzero exit status or abnormal termination indicates failure. A host MUST distinguish failure to start a process from termination of a process that was successfully started. An absent numeric exit code, for example after termination by a signal, MUST NOT be treated as success.

Programs SHOULD use the conventional sysexits categories where applicable. The following table gives recommended categories; hosts MUST also support programs using other nonzero statuses. [SYSEXITS]

Status Name Typical use
64 EX_USAGE Invalid command-line syntax or option value.
65 EX_DATAERR Invalid input payload.
66 EX_NOINPUT Required input file is unavailable.
69 EX_UNAVAILABLE Required service or resource is unavailable.
70 EX_SOFTWARE Internal software failure.
73 EX_CANTCREAT Output file or index cannot be created.
74 EX_IOERR I/O failure while processing data.
75 EX_TEMPFAIL Temporary failure for which retry may be useful.
77 EX_NOPERM Insufficient permission.
78 EX_CONFIG Invalid or missing configuration.

A program can emit output before subsequently failing. Such output MUST NOT be represented by a host as a successfully completed result. A streaming host MUST provide a completion or failure indication in addition to the data stream. It MAY expose partial output together with the failure.

An unsuccessful invocation does not imply that external side effects were rolled back. Programs that modify an index, write files, or execute code MUST document their partial-update and retry behavior. Hosts MUST NOT infer idempotence solely from a pattern name or an exit-status category.

4. Patterns

The following table summarizes the logical contract of each pattern. RDF results are serialized graphs or datasets, not a count of individual output objects. Specific multiplicity requirements are stated in the pattern sections.

Pattern Role Logical input Logical output
Adapter RDF dataset proxy SPARQL query RDF
Compiler Prompt compiler Natural-language text SPARQL query
Emitter Value generator None RDF
Fetcher URL protocol client One URL RDF
Indexer Persistent RDF dataset indexer RDF None
Lister Directory iterator One URL RDF describing zero or more entries
Matcher Exact or approximate matcher RDF RDF describing matches
Prompter LLM inference provider Prompt text Response text
Reader RDF dataset importer Input document or byte stream RDF
Reasoner RDF dataset entailer RDF Entailed RDF
Resolver URI resolver One URI Zero or more URLs
Runner Language runtime engine Program text Execution result as text
Writer RDF dataset exporter RDF Output document or byte stream

4.1. Adapter

An adapter provides an RDF dataset proxy. It consumes a SPARQL query and emits RDF resulting from evaluation against the dataset made available by the program. SPARQL query syntax and query forms are defined in [SPARQL11-QUERY].

PROGRAM [OPTIONS] [QUERY-FILE]

4.1.1. Arguments

Operand Arity Default Meaning
QUERY-FILE 0..1 - (stdin) SPARQL query file.

4.1.2. Options

Option Flag Default Meaning
--output=FORMAT -o jsonl RDF output format.

The program MUST document the dataset being queried and the SPARQL features it supports. It MUST reject an unsupported query form rather than emit a non-RDF result under an RDF format token.

CONSTRUCT and DESCRIBE produce graph results. Support for SELECT or ASK requires a documented mapping of their results to RDF. This pattern does not implicitly authorize SPARQL Update or specify an update protocol.

4.2. Compiler

A compiler translates natural-language input into one SPARQL query intended for an adapter. The compiler does not execute that query as part of this pattern’s result contract.

PROGRAM [OPTIONS] [INPUT-FILE]

4.2.1. Arguments

Operand Arity Default Meaning
INPUT-FILE 0..1 - (stdin) Natural-language input file.

4.2.2. Options

This pattern defines no pattern-specific options. Additional options, if provided, are extensions subject to extension rules.

On success, stdout MUST contain a syntactically valid SPARQL query as UTF-8 text, without Markdown fences or explanatory prose outside the query. The query MUST use a graph-producing form, or a form for which the intended adapter profile defines an RDF result mapping. The program MUST document assumptions about the target dataset, vocabulary, and adapter capabilities.

Note: Syntactic validity does not guarantee that a generated query captures the author’s intent or is suitable for execution against every dataset.

4.3. Emitter

An emitter generates values represented as RDF. It takes no payload input. Its arguments, environment, configuration, or external sources can determine which values it emits.

PROGRAM [OPTIONS]

4.3.1. Arguments

This pattern defines no positional operands. The program MUST NOT wait for stdin as a payload source.

4.3.2. Options

Option Flag Default Meaning
--output=FORMAT -o jsonl RDF output format.

The program MUST document whether generation is finite or continuous and any conditions under which it terminates. A finite emitter MAY succeed with an empty RDF result. This pattern does not imply determinism across invocations.

4.4. Fetcher

A fetcher is a URL protocol client. It accepts one URL and produces an RDF representation or description of the identified resource. Raw retrieval of arbitrary response bytes is not, by itself, this pattern’s RDF output contract.

PROGRAM [OPTIONS] INPUT-URL

4.4.1. Arguments

Operand Arity Default Meaning
INPUT-URL 1 None URL of the resource to retrieve.

4.4.2. Options

Option Flag Default Meaning
--output=FORMAT -o jsonl RDF output format.

The program MUST document supported URL schemes and its mapping from retrieved resources to RDF. A URL is supplied as one argument; it MUST NOT be split at spaces or interpreted as a shell command. Unsupported schemes MUST cause failure. Redirect handling, authentication, caching, and retrieval limits are implementation-defined and MUST be documented where supported.

4.5. Indexer

An indexer consumes RDF and maintains a persistent index at the selected destination. It has no payload output.

PROGRAM [OPTIONS] [INPUT-FILE] INDEX-FILE

4.5.1. Arguments

Operand Arity Default Meaning
INPUT-FILE 0..1 - (stdin) RDF input file.
INDEX-FILE 1 None Persistent index destination.

The operands MUST be interpreted as follows:

  1. With one operand, that operand is INDEX-FILE; input is stdin.

  2. With two operands, the first is INPUT-FILE and the second is INDEX-FILE.

  3. With no operands or more than two operands, invocation MUST fail.

INDEX-FILE is a program-defined persistent file or directory location. It does not use - to mean stdout. An indexer MUST reject - as an index destination; a literal relative pathname can instead be written as ./-.

4.5.2. Options

Option Flag Default Meaning
--input=FORMAT -i jsonl RDF input format.

The program MUST document its index format, creation behavior, update or replacement semantics, concurrency behavior, and guarantees on failure. A zero exit status indicates completion according to those documented guarantees; it does not independently specify transactional or crash-durability semantics. Stdout MUST contain no payload.

4.6. Lister

A lister iterates a directory or collection identified by a URL and produces RDF describing its entries. A directory need not be a local filesystem directory. A successful listing MAY contain no entries.

PROGRAM [OPTIONS] INPUT-URL

4.6.1. Arguments

Operand Arity Default Meaning
INPUT-URL 1 None URL of the directory or collection.

4.6.2. Options

Option Flag Default Support Meaning
--limit=COUNT -n No limit Required Maximum number of entries.
--output=FORMAT -o jsonl Required RDF output format.
--offset=COUNT None 0 Optional Number of entries to skip.
--sort=SORT None Program-defined order Optional Ordering requested using a documented sort expression.

The program MUST document supported URL schemes, the RDF description of an entry, and ordering guarantees. If sorting or offset is unsupported, supplying the corresponding option MUST cause failure. Supported sorting and pagination follow the common count rules. Hosts MUST use a sort expression supported by the selected program’s profile.

An offset is zero-based: --offset=0 skips no entries and --offset=1 skips the first entry. Without an explicit sort expression, pagination uses the program’s documented default order. Programs SHOULD provide a stable order for an unchanged collection when pagination is supported. This specification does not require a consistent snapshot across separate invocations.

The Rust wrapper forwards --sort and --offset, but the previous specification listed neither. This draft reserves their semantics as optional capabilities. The interoperable grammar for SORT, including keys, direction, and tie-breaking, remains to be agreed. An undocumented spelling such as asc cannot be assumed portable.

4.7. Matcher

A matcher performs exact or approximate matching over RDF input and emits RDF describing the matches. Output is not necessarily a subset of the input dataset: it can introduce statements identifying correspondences or scores.

PROGRAM [OPTIONS] [INPUT-FILE [OUTPUT-FILE]]

4.7.1. Arguments

Operand Arity Default Meaning
INPUT-FILE 0..1 - (stdin) RDF input file.
OUTPUT-FILE 0..1 - (stdout) RDF match-result file.

4.7.2. Options

Option Flag Default Meaning
--input=FORMAT -i jsonl RDF input format.
--output=FORMAT -o jsonl RDF output format.

The program MUST document the matching relation, the compared entities or external reference data, and the vocabulary used to describe matches. If it reports scores, it MUST document their interpretation. Exactness, thresholds, and approximation algorithms are profile-specific; this specification does not define a universal matching algorithm or score scale.

4.8. Prompter

A prompter provides language-model inference. It consumes a prompt and emits a response. The default input and output formats are UTF-8 text.

PROGRAM [OPTIONS] [INPUT-FILE [OUTPUT-FILE]]

4.8.1. Arguments

Operand Arity Default Meaning
INPUT-FILE 0..1 - (stdin) Prompt input file.
OUTPUT-FILE 0..1 - (stdout) Response output file.

4.8.2. Options

Option Flag Default Meaning
--input=FORMAT -i text Prompt format.
--model=MODEL -m auto Inference model selection.
--output=FORMAT -o text Response format.

For --model=auto, model selection is implementation-defined and MUST be documented. An explicitly selected model that is unavailable or unsupported MUST cause failure rather than an undocumented substitution.

The text format does not standardize role labels, conversation delimiters, tool calls, or a structured message envelope. A program that assigns such meaning to portions of the text MUST document that convention. Structured prompt or response formats MAY be provided using explicit format tokens and documented profiles.

A host presenting the response as text MUST preserve its whitespace and newlines unless it exposes a separate, explicitly requested transformation. The program MUST document whether it can stream output and whether repeated invocations can produce different results for the same prompt.

4.9. Reader

A reader imports a document or byte stream into an RDF graph or dataset. The input can use a non-RDF format; interpretation and mapping are performed by the reader program.

PROGRAM [OPTIONS] [INPUT-FILE [OUTPUT-FILE]]

4.9.1. Arguments

Operand Arity Default Meaning
INPUT-FILE 0..1 - (stdin) Source input file.
OUTPUT-FILE 0..1 - (stdout) RDF output file.

4.9.2. Options

Option Flag Default Meaning
--input=FORMAT -i auto Source format or automatic detection.
--output=FORMAT -o jsonl RDF output format.

The program MUST document supported input formats and their RDF mappings, including any base-IRI, vocabulary, or identifier-generation conventions. The auto behavior MUST follow the format-selection rules.

4.10. Reasoner

A reasoner consumes RDF and emits RDF entailed under a documented entailment regime or rule system.

PROGRAM [OPTIONS] [INPUT-FILE [OUTPUT-FILE]]

4.10.1. Arguments

Operand Arity Default Meaning
INPUT-FILE 0..1 - (stdin) RDF input file.
OUTPUT-FILE 0..1 - (stdout) Entailed RDF output file.

4.10.2. Options

Option Flag Default Meaning
--input=FORMAT -i jsonl RDF input format.
--output=FORMAT -o jsonl RDF output format.

The program MUST document its entailment regime, whether output includes the input statements or only additional consequences, and how it handles named graphs and inconsistent input. This specification does not require a particular rule language, completeness guarantee, or reasoning algorithm.

4.11. Resolver

A resolver maps one URI, including a URN or URL, to zero or more resolved URLs. The URI syntax is defined by [RFC3986]. Resolution identifies locations; it does not imply retrieval of the resources at those locations.

PROGRAM [OPTIONS] INPUT-URI

4.11.1. Arguments

Operand Arity Default Meaning
INPUT-URI 1 None URI to resolve.

The input URI is REQUIRED. There is no implicit stdin or environment source for an omitted operand. Programs MUST document the URI schemes they support and MUST reject unsupported schemes. The input is passed as one argument.

4.11.2. Options

Option Flag Default Meaning
--limit=COUNT -n No limit Maximum number of output URLs.

4.11.3. Output framing

On success, stdout MUST contain zero or more absolute URLs, encoded as UTF-8, with one URL followed by a line feed (U+000A) per result. There is no header, JSON envelope, quoting, or shell escaping. A successful resolution with no results produces zero output bytes. A program MUST NOT emit blank result lines.

A host parsing resolver output MUST preserve result order. It MUST treat each line as one URL rather than split it on whitespace or commas. It MUST accept CRLF line endings and a final nonempty line without a terminating line feed for compatibility with existing text producers. Removing a line terminator does not authorize other whitespace trimming or percent-decoding.

Each result MUST be an absolute URI usable as a locator under its scheme’s rules. Embedded line-feed or carriage-return characters are not permitted in a result. A program MUST document ordering, duplicate-result behavior, and any network or local lookup used in resolution.

Note: The line-oriented framing is made explicit in this draft to enable hosts to return a list of URLs. The reviewed Rust wrapper’s unfinished line parsing is evidence of the need for this contract, not an implementation of it.

4.12. Runner

A runner is a language runtime engine. It consumes text conforming to a documented grammar, executes it, and emits the execution result as text. This pattern is distinct from a host’s generic process-launching facility.

PROGRAM [OPTIONS] [INPUT-FILE]

4.12.1. Arguments

Operand Arity Default Meaning
INPUT-FILE 0..1 - (stdin) Program text input file.

4.12.2. Options

Option Flag Default Meaning
--define=VAR=VAL -D No definitions Repeatable variable definition.

The --define option is repeatable. Its argument is split at the first = into a variable name and value; additional = characters belong to the value. A missing separator or empty variable name is invalid. An empty value is permitted. Programs MUST document variable-name constraints, value interpretation, and the policy for repeated definitions of the same variable.

The program MUST document its language and version, how definitions are made available to the executed program, how the execution result is represented, and what external side effects are possible. Accepting arbitrary input bytes in an SDK does not remove the requirement that program input conform to the selected language’s syntax and encoding.

4.13. Writer

A writer exports an RDF graph or dataset to a supported output format. The output can be an RDF serialization or a non-RDF representation.

PROGRAM [OPTIONS] [INPUT-FILE [OUTPUT-FILE]]

4.13.1. Arguments

Operand Arity Default Meaning
INPUT-FILE 0..1 - (stdin) RDF input file.
OUTPUT-FILE 0..1 - (stdout) Exported output file.

4.13.2. Options

Option Flag Default Meaning
--input=FORMAT -i jsonl RDF input format.
--output=FORMAT -o auto Export format or automatic selection.

The program MUST document its supported output formats, mappings, and any loss of RDF information, including named-graph or datatype information. A writer’s auto output selection MUST be defined for stdout as well as for named files. An application requiring a particular representation SHOULD select it explicitly.

5. Host requirements

5.1. Preparing an invocation

A host MUST keep executable selection separate from payload interpretation. It MAY locate programs through a configured installation directory, an explicit pathname, a module registry, or the operating system’s search path. No particular lookup order is required by this specification.

A host MUST preserve argument boundaries and MUST pass a URL or URI as one operand where required. Additional arguments supplied by an application are still argument strings, not shell snippets. Hosts SHOULD provide a way to set required operands that are not represented by convenience API parameters, such as an indexer’s INDEX-FILE.

A host that supplies input through stdin MUST create a writable child stdin stream, deliver the intended bytes, and close its write end when input ends. A host selecting a named input file instead MUST NOT assume that the child will also consume bytes sent to stdin.

5.2. Output handling and progress

A host MAY discard output, inherit the parent’s stream, capture bytes, or forward bytes to another destination. Its API MUST distinguish these choices. If a host claims to forward output to a destination, it MUST actually transfer the bytes and report transfer failure; creating a pipe alone is insufficient.

For every piped stdout or stderr stream, a host MUST arrange for reads to make progress while it writes input and waits for the child. A program MAY produce output before consuming all input. Hosts MUST NOT require a program to fit all output in an operating-system pipe buffer before that host starts reading it.

A host MAY buffer the complete output before returning a result, or expose incremental output. It MUST document which behavior its API provides and any size limits. Output bytes MUST be preserved unless a documented format parser or an explicitly requested transformation is applied. Decoding failure MUST NOT be silently reported as an empty successful value.

A host MUST observe failures while supplying input or forwarding output. It MUST NOT report an overall successful transfer merely because the child’s exit status is zero when a required host-side transfer failed.

Note: A host may need concurrent tasks to feed stdin and drain stdout and stderr. Full-duplex progress is an I/O requirement, not a requirement to use threads, Tokio, or any other particular execution mechanism.

5.3. Repeated execution and cancellation

Hosts MUST document whether repeated execution reuses configuration, replays input, or consumes input from its current position. A host MUST NOT imply that a consumed stream is rewound unless it actually provides replay.

Hosts MUST document ownership of running child processes, cancellation behavior, and how exit status is collected. Cancellation or dropping an API handle MUST NOT be presented as successful completion. Killing a child does not establish that a previously initiated remote operation or persistent index update was rolled back.

5.4. Composition

A host composing programs MUST ensure that the producer’s output format and profile are accepted by the consumer. Matching names such as GraphOutput and GraphInput in an SDK do not establish serialization compatibility.

A host claiming successful completion of a pipeline MUST account for every required stage’s exit status and every required inter-stage transfer. Success of the last stage alone is insufficient. The policy for stopping other stages after failure or cancellation MUST be documented.

Note: Shell examples illustrate data flow, but ordinary shell pipelines may report only the final command’s status. Applications needing the host guarantees in this section must also monitor upstream stages.

6. RDF mapping

RDF is the semantic model of the graph-oriented patterns. A byte stream that parses as JSON is not necessarily an RDF graph or dataset. An RDF stream profile MUST specify:

For jsonl, each nonempty record MUST be one complete JSON value on a single line, encoded as UTF-8. JSON syntax is defined by [RFC8259]. Producers MUST terminate each record with a line feed and MUST NOT emit blank records or pretty-printed JSON spanning multiple lines. A profile MUST define how each JSON value represents RDF and whether state or context is shared across records. The token jsonl alone does not imply JSON-LD or a particular object shape such as subject/predicate/object members.

Programs and hosts MUST NOT assume that an RDF record is synonymous with a listed entry or an independently scoped dataset. In particular, they MUST respect the profile’s blank-node scope when splitting or combining streams.

A shared RDF jsonl profile, its identifier, and a normative reference must be selected before this default can provide plug-and-play RDF interchange. The reviewed Rust wrappers forward the token and raw bytes; they do not define the wire representation. This draft deliberately does not invent a JSON shape from those wrappers. A standards-defined RDF serialization can also be selected explicitly when both programs support it.

This specification does not define an RDF vocabulary for describing installed programs, invocation metadata, error objects, or pipeline topology. Such a vocabulary can be defined separately. Payload RDF and metadata describing a program are distinct uses of RDF.

7. Extensions

A program MAY provide additional options, format tokens, model identifiers, resource schemes, and profile-specific behavior. It MUST document such extensions and MUST retain the semantics of the standard options it supports. Extensions MUST NOT cause an otherwise valid standard invocation to require additional operands or options.

A host MUST NOT infer support for an extension merely because its SDK exposes a field or an untyped additional-argument list. Support has to be established through program documentation, configuration, or a separately defined capability-discovery mechanism.

This specification does not define a capability-discovery command or a registry of extension names. Implementations SHOULD use descriptive long option names and avoid short-option assignments that conflict with their pattern’s standard flags.

8. Examples

The executable names below are illustrative. These examples assume that connected programs support the same documented RDF jsonl profile. Shell redirection and pipes configure streams; they are not arguments passed to the programs. Error handling is omitted for readability.

Compile a natural-language request and query a dataset:

asimov-example-compiler request.txt | asimov-example-adapter --output=jsonl

The compiler emits SPARQL. The adapter reads it from stdin and emits RDF. A host observes both processes' completion before declaring success.

Fetch RDF and index it using the single-operand indexer form:

asimov-example-fetcher --output=jsonl https://example.com/resource | asimov-example-indexer --input=jsonl ./catalog.index

The equivalent explicit-stdin indexer invocation is:

asimov-example-indexer --input=jsonl - ./catalog.index

In both forms, the indexer reads RDF from stdin and treats ./catalog.index as the persistent destination.

Resolve a URI to at most two URLs:

asimov-example-resolver --limit=2 urn:example:document:42

An illustrative successful stdout payload is:

https://example.com/documents/42
https://mirror.example.com/documents/42

The host parses two URL records. It does not interpret the lines as RDF or execute them as shell commands.

Read a text prompt from stdin and write the text response to a file:

asimov-example-prompter --input=text --output=text --model=auto - response.txt

The first operand is needed because a single filename would select the input file, not the output file.

Pass two runtime definitions, including a value containing an equals sign:

asimov-example-runner --define=mode=preview --define=expression=a=b program.txt

The second definition has the variable name expression and value a=b. Its interpretation belongs to the selected runtime.

9. Security and privacy considerations

Programs and hosts operate on potentially untrusted arguments, payloads, resources, and generated text. Conformance to an input/output contract does not establish trust in the program, its data source, or its output.

Hosts MUST preserve argument boundaries as specified in command-line syntax. Concatenating a resource identifier or model-supplied value into a shell command can introduce command injection. Executable lookup policy SHOULD prevent an untrusted directory from unexpectedly substituting a program selected by name.

Fetchers, listers, resolvers, and programs using remote services SHOULD enforce the application’s restrictions on network destinations and URI schemes, including after redirects. Dereferencing input can expose local resources, credentials, or internal network services. Programs MUST document when payloads or identifiers are transmitted to third parties.

Programs accepting untrusted RDF or other structured data SHOULD bound parsing resources and document external-reference resolution. Hosts SHOULD provide limits for runtime, input size, captured output, and diagnostic retention. Exceeding a resource limit that prevents completion of the requested operation MUST result in an observable failure or cancellation rather than a silently truncated successful payload. This does not apply to a requested result count such as --limit, which is part of the operation itself. Hosts MAY abbreviate retained diagnostics if they indicate that the diagnostic record is incomplete.

Prompts and RDF literals can contain instructions intended for a model. Such content is data under this specification; it does not by itself authorize additional host actions. Compiled queries and runtime program text can cause expensive computation or external effects. Applications determine whether and with what authority those outputs are subsequently executed.

Index destinations, output files, environment variables, prompts, and stderr can contain sensitive information. Programs SHOULD avoid unnecessary secret disclosure in diagnostics. Hosts SHOULD apply the application’s retention and access-control policy to captured output and diagnostics.

Process cancellation is not a transaction boundary. Implementations MUST NOT claim that killing a process undoes filesystem, network, or index changes unless they implement and document such a guarantee.

10. IANA considerations

This specification requests no IANA registrations. Format tokens and option names defined here are local to these program interfaces; this document does not register media types, URI schemes, or protocol parameters.

11. Implementation notes

This section is informative. It records observations from the asimov-runner Rust crate, version 25.4.0, reviewed for this draft. The paths below are relative to its src/ directory. These are implementation observations, not requirements for other SDKs or endorsements of conformance to this expanded draft.

11.1. Pattern coverage and argument construction

programs.rs exports wrappers for twelve patterns: adapter, emitter, fetcher, indexer, lister, matcher, prompter, reader, reasoner, resolver, runner, and writer. There is no compiler wrapper in the reviewed crate. The compiler remains part of the specification.

Constructors prepare commands; execution methods start new child processes. Wrappers translate configured option fields into individual --name=value arguments, append their other argument list, and then append the dedicated URL or URI operand where present. They re-export option types and implement the corresponding pattern and execution traits from asimov-patterns.

The indexer wrapper has no dedicated index-destination parameter; its required operand can be supplied through options.other. The lister wrapper forwards --sort and --offset in addition to the limit and output-format options previously listed in the specification.

11.2. Process defaults

executor.rs checks the ASIMOV root’s libexec directory before falling back to the supplied program name or path. It sets NO_COLOR=1, initially connects all standard streams to the null device, and enables Tokio’s child-handle kill-on-drop behavior. Wrappers subsequently configure the streams required for their pattern.

These lookup, environment, and ownership policies are choices of this host implementation. They are not universal program requirements. Process-backed APIs are gated on the crate’s std feature and use Tokio. Optional tracing records child exit statuses.

11.3. Input and output representations

input.rs represents either ignored input or an owned asynchronous reader. output.rs represents ignored, inherited, captured, or asynchronous-writer output. Content-specific aliases such as GraphInput and TextOutput do not validate or transcode the stream. The unit-type aliases NoInput and NoOutput describe the absence of a pattern value.

Converting these values to Stdio configures null, inherited, or piped streams; it does not transfer data. The consuming conversion drops an owned reader or writer. The borrowed as_stdio() method preserves that object for subsequent use.

The stream-input execution path copies the remaining input to child stdin, closes that pipe, and only then collects stdout and stderr. Reusing an input reader does not rewind it. Copying input before draining output can deadlock with a child that fills an output pipe before consuming all input. The host progress requirements therefore describe a stronger contract than this implementation currently provides.

Most wrappers buffer captured stdout in memory and return a byte cursor positioned at zero. Ignored or inherited stdout produces an empty capture. Although Output::AsyncWrite requests a pipe, the reviewed wrappers do not forward the captured bytes to its stored writer. This does not satisfy the draft’s forwarding contract.

11.4. Pattern-specific return values

programs/indexer.rs discards stdout and returns a unit value on success, consistent with the indexer’s lack of a payload output.

programs/prompter.rs always captures stdout regardless of its output argument. It clones a stored prompt, writes its display representation to stdin in a separate task, and decodes the complete stdout as UTF-8 without trimming. The write task is not awaited; write failures panic in that task rather than being returned through the execution result. A formatter’s role-prefixed prompt representation does not establish a standard chat grammar.

programs/resolver.rs has a list-of-strings result type, but its stdout-to-lines conversion is unfinished. It currently discards captured stdout and returns an empty list on success. The resolver contract in this draft requires the actual URL results to be available to a host that claims to return them.

pipeline.rs contains a zero-sized placeholder with no stages, connections, or execution API. The composition requirements specify observable host behavior, not an existing Rust pipeline implementation.

11.5. Error representation

executor_error.rs distinguishes a not-found spawn error, other spawn failures, recognized sysexits failures, other unsuccessful terminations, and miscellaneous I/O failures. A termination without a numeric exit code is represented separately from a numeric nonzero status.

When converting process output into an error, the implementation keeps stderr only if it is valid UTF-8; empty stderr becomes an empty string, while invalid UTF-8 becomes absent diagnostic text. Captured stdout is not retained in those errors. Successful execution returns stdout and discards captured stderr. These representation choices motivate the distinction between process status, diagnostic bytes, and partial payloads in the common processing model.

12. Acknowledgments

The editors thank the ASIMOV Platform community for its contributions and feedback. This revision was informed by a cross-review of the published Program Patterns Specification, its Bikeshed section sources, and the Rust asimov-runner implementation.

13. Changes

This draft expands the living standard dated 10 September 2026. The following changes are proposed for review; they are not a statement of deployed consensus.

13.1. Corrections and clarifications

13.2. Expanded draft requirements

This file incorporates the pattern sections directly and uses textual examples instead of external diagrams, so it can be reviewed as a single Bikeshed source without the original sections/ and img/ directories.

Index

Terms defined by this specification

References

Normative References

[RDF11-CONCEPTS]
Richard Cyganiak; David Wood; Markus Lanthaler. RDF 1.1 Concepts and Abstract Syntax. URL: https://w3c.github.io/rdf-concepts/spec/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[RFC3629]
F. Yergeau. UTF-8, a transformation format of ISO 10646. November 2003. Internet Standard. URL: https://www.rfc-editor.org/info/rfc3629/
[RFC3986]
T. Berners-Lee; R. Fielding; L. Masinter. Uniform Resource Identifier (URI): Generic Syntax. January 2005. Internet Standard. URL: https://www.rfc-editor.org/info/rfc3986/
[RFC8174]
B. Leiba. Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/info/rfc8174/
[RFC8259]
T. Bray, Ed.. The JavaScript Object Notation (JSON) Data Interchange Format. December 2017. Internet Standard. URL: https://www.rfc-editor.org/info/rfc8259/
[SPARQL11-QUERY]
Steven Harris; Andy Seaborne. SPARQL 1.1 Query Language. URL: https://w3c.github.io/sparql-query/spec/

Non-Normative References

[ASIMOV]
Arto Bendiken; et al. ASIMOV Platform Documentation. URL: https://asimov.sh
[NO-COLOR]
Disabling ANSI color output in various Unix commands. URL: https://no-color.org/
[SYSEXITS]
sysexits(3): Preferable exit codes for programs. URL: https://man.freebsd.org/cgi/man.cgi?query=sysexits&sektion=3

Issues Index

The Rust wrapper forwards --sort and --offset, but the previous specification listed neither. This draft reserves their semantics as optional capabilities. The interoperable grammar for SORT, including keys, direction, and tie-breaking, remains to be agreed. An undocumented spelling such as asc cannot be assumed portable.
A shared RDF jsonl profile, its identifier, and a normative reference must be selected before this default can provide plug-and-play RDF interchange. The reviewed Rust wrappers forward the token and raw bytes; they do not define the wire representation. This draft deliberately does not invent a JSON shape from those wrappers. A standards-defined RDF serialization can also be selected explicitly when both programs support it.