Audience: advanced application and PTC-Lisp authors who need the complete component, dependency, visibility, and shipped-library contract.
A component is one immutable PTC-Lisp module with one namespace. Its declared component dependencies define the only namespaces it may call while compiling. Components compile into a frozen bundle; shipped components are selected as libraries instead of copied into an application.
A project names its components in the manifest:
"components": [
{"id": "math", "path": "math.clj"}
](ns math "Small arithmetic helpers." {:visibility :prompt})
(defn double [x] (* x 2))Public defn and def forms become qualified exports. defn- remains private
to its namespace. A cross-component call needs both a declared dependency and
a public export in that dependency.
Dependencies are composition boundaries, not authority grants. Once a bundle
is installed, evaluated PTC-Lisp can call every public export in it.
:visibility :discoverable removes an export from prompt inventory, not from
the callable surface. Code can find it with dir or apropos and inspect it
with doc or export-meta. Use this visibility for support APIs that remain
available without consuming prompt space.
Public exports may declare contracts in their ordinary metadata map:
(defn search
"Search the configured document source."
{:signature "(query :string, limit :int?) -> {items [:string]}"
:effect :read}
[query limit]
...)
(def default-limit
"Default number of results."
{:type ":int"}
10)The compiler parses contracts and rejects malformed declarations,
signature/arity mismatches, invalid effects, and incompatible constants. A
signed function validates arguments before its body and validates every
successful result, including an export-local return. fail is not a
successful result, so its payload is not output-validated. Unsigned exports
remain dynamic.
The contract is a string in its own type grammar, not Clojure reader metadata.
Signatures cover fixed arity only. A nullable type such as :int? accepts
nil; it does not make a positional argument optional.
See Signature syntax for the complete grammar and the PTC-Lisp specification for normative behavior. The manifest guide links to a credential-free rejection and correction example.
Every tool/name used by an export is recorded as tool:name, including calls
through private helpers and dependencies. Environment assembly rejects a bundle
unless the destination environment grants every requirement. Requirements
validate authority; they never create it.
Shipped libraries such as runtime, cap, kernel, llm, analysis, and
the agent and result libraries are selected by ID:
"components": [
{"id": "my.agent", "path": "agent.clj", "dependencies": ["agent.core"]},
{"library": "agent.core"}
]Transitive library dependencies join local components in the same frozen bundle. Unknown IDs, repeated selections, and local/library ID collisions are rejected. Workflow and mission bundles remain separate.
Manifests expand shipped dependencies into a closed component graph. Hosts that assemble bundles through another supported interface have the same responsibility.
Shipped components use the same dependency rules. For example:
| Component | Purpose |
|---|---|
cap |
Fail-safe capability-envelope handling and bounded cursor traversal |
analysis |
Three bounded public/private run-evidence navigation operations |
The generated shipped prelude reference groups every installed component by purpose and lists its visibility, direct and transitive dependencies, reverse dependents, public functions, contracts, effects, and backing capability requirements.
analysis depends on cap. Adding an installed dependency widens the callable
surface, so fixed profiles pin the complete resolved component list and must
version public surface changes.
cap/fold-pages is the single shipped traversal helper. It reduces page items
into caller-owned bounded state, stops at max_pages, and returns the opaque
next_cursor plus snapshot_hash needed to resume in another evaluation.
Callers must keep the reducer state bounded; collecting every item merely moves
the source-size heap problem into the accumulator. Cursor-cycle detection covers
each bounded invocation; the helper deliberately does not retain an unbounded
history across resumptions.
Building agents covers the agent.core loop and the
agent.prompt policy seam these libraries provide.
Local components use new IDs; they cannot shadow a selected shipped library ID. A hash-checked component override can evaluate replacement source for one selected component on a run, but it is an invocation option rather than a permanent manifest library installation.
The manifest selects component sources and trusted provider aliases; executable callbacks stay in the host-owned provider registry. New provider types must preserve this boundary: manifests must not introduce endpoints, credentials, SQL, commands, or callbacks.
Private inspection is a separate host-selected artifact, described in Running and debugging. An active bundle is immutable; any changed component must be compiled into a new bundle.
Hosts that compile bundles directly rather than through a manifest use the same compiler and dependency rules.