PtcRunner.Lisp.Prelude (PtcRunner v0.13.0)

Copy Markdown View Source

Compiled, stateless deployment prelude artifact (Capability Prelude V1).

A deployment loads curated PTC-Lisp prelude source that declares protected namespaces (e.g. crm) and exports functions/constants. The compiler (PtcRunner.Lisp.Prelude.Compiler) turns that source into one of these artifacts, which is then attached to a run and consulted — unchanged — across direct Lisp execution, SubAgent execution, and the REPL (plan §1A).

Fields

  • namespaces — sorted list of declared namespace-name strings. These are the prelude-protected namespaces (host-boundary string-backed).
  • exports — list of %PtcRunner.Lisp.Prelude.Export{} public export records (:prompt + :discoverable). Private helpers are NOT here.
  • private_env — the captured private prelude environment, keyed by namespace then bare symbol: %{namespace => %{symbol => callable}} ({:closure, ...} for defn). Namespace-scoping keeps same-named definitions in different namespaces distinct (e.g. crm/who vs hr/who). Public exports call their own namespace's private helpers through this env; user code cannot resolve private helpers by qualified symbol (plan §5). The CALLABLE values are the contract slice 2 (evaluator threading) depends on.
  • source_hash — sha256 hex digest of the prelude source (plan §12 traceability).
  • source_index — precomputed %{full-ref => rendered-source} map for the (source ns/name) discovery form (issue #1095). Keyed by full ref for public exports PLUS the private helpers transitively reachable from some public export; unreferenced privates stay out. Values are rendered strings (a labeled effective-metadata header + the Formatter-rendered defining form), so this cache leaks no captured closure or raw parser AST. NOTE: it exposes export IMPLEMENTATION, not just contract — deployments must keep secrets/credentials out of prelude bodies, not just docstrings.
  • metadata — small map of namespace-level facts for traces/debugging, e.g. per-namespace docstring and default visibility.

Private-env capture seam (fact #6)

defn/defn- in the prelude desugar through the existing analyze+eval pipeline to {:closure, params, body, captured_env, turn_history, meta} tuples stored under their bare symbol in a user_ns-shaped map. The compiler captures that whole map as private_env. Sibling helpers are NOT folded into each closure's captured_env — they resolve by name through user_ns at call time, and private_env is exactly that namespace. P2 therefore threads private_env as the user_ns layer (resolver position between the mutable user namespace and built-ins) when invoking exports: a public export resolves qualified (crm/get-user) to private_env[symbol] and runs its body against private_env, so private helpers resolve, while private symbols stay absent from exports and so are unreachable by qualified user calls. Proven end-to-end during P0.

Validation errors

Compile-time failures are returned as {:error, %PtcRunner.Lisp.Prelude.ValidationError{}}, never raised.

Summary

Types

Trace/debug summary of a compiled prelude (plan §12 Traceability).

t()

Functions

The typed-tool names a public export invokes (transitively over same-namespace helpers), or [] when ref is not a public export.

Looks up a public export by its Lisp-facing ref (e.g. "crm/get-user").

The declared (protected) namespace names, sorted.

Public export records visible in the prompt inventory (:prompt only).

Builds the trace/debug summary for prelude (plan §12).

Types

export_summary()

@type export_summary() :: %{
  ref: String.t(),
  namespace: String.t(),
  symbol: String.t(),
  arity: non_neg_integer() | :variadic,
  params: [String.t()],
  visibility: PtcRunner.Lisp.Prelude.Export.visibility(),
  effect: PtcRunner.Lisp.Prelude.Export.effect(),
  provider_ref: String.t() | nil,
  requires: [String.t()]
}

Trace/debug summary of a compiled prelude (plan §12 Traceability).

String/atom/list-only, JSON-serializable, and credential-free: it carries enough to REPRODUCE the V1 capability environment without leaking captured closures, the private prelude env, or any host secret.

  • source_hash — sha256 hex of the prelude source.
  • artifact_hash — sha256 hex over the compiled artifact's protected facts (namespaces + public export records). Lets a trace consumer tell whether two runs used the same compiled prelude even when source text is unavailable.
  • protected_namespaces — the selected protected namespace names (sorted).
  • host_policy_hash — host policy hash/id when available; nil in V1 (no first-class host policy yet).
  • exports — one export_summary per PUBLIC export (no callables/env).
  • components — selected source component provenance when the artifact was produced by PtcRunner.Lisp.Prelude.Bundle; otherwise [].

t()

@type t() :: %PtcRunner.Lisp.Prelude{
  exports: [PtcRunner.Lisp.Prelude.Export.t()],
  metadata: map(),
  namespaces: [String.t()],
  private_env: %{required(String.t()) => %{required(String.t()) => term()}},
  source_hash: String.t(),
  source_index: %{required(String.t()) => String.t()}
}

trace_summary()

@type trace_summary() :: %{
  source_hash: String.t(),
  artifact_hash: String.t(),
  protected_namespaces: [String.t()],
  host_policy_hash: String.t() | nil,
  exports: [export_summary()],
  components: [map()]
}

Functions

export_tool_refs(prelude, ref)

@spec export_tool_refs(t(), String.t()) :: [String.t()]

The typed-tool names a public export invokes (transitively over same-namespace helpers), or [] when ref is not a public export.

The pre-execution tool guard unions these in so a prelude-wrapped (tool/call ...) is validated before any side effect runs (plan §6/§7).

fetch_export(prelude, ref)

@spec fetch_export(t(), String.t()) ::
  {:ok, PtcRunner.Lisp.Prelude.Export.t()} | :error

Looks up a public export by its Lisp-facing ref (e.g. "crm/get-user").

namespaces(prelude)

@spec namespaces(t()) :: [String.t()]

The declared (protected) namespace names, sorted.

prompt_exports(prelude)

@spec prompt_exports(t()) :: [PtcRunner.Lisp.Prelude.Export.t()]

Public export records visible in the prompt inventory (:prompt only).

trace_summary(prelude)

@spec trace_summary(t() | nil) :: trace_summary() | nil

Builds the trace/debug summary for prelude (plan §12).

Returns nil for nil (no prelude attached). The result is JSON-serializable and contains NO captured closures, private prelude env, or credentials — only the protected facts needed to reproduce the capability environment.

The host_policy_hash slot is nil in V1; it is reserved for when a host policy hash/id becomes available.