mix ptc repl provides deliberately different PTC-Lisp session modes:
- direct and manifest-backed sessions are workflow scratchpads;
run-analysis-v1is a fixed mission session for querying an immutable capture of canonical traces; andprivate-run-analysis-v1is a fixed private mission session for correlating canonical traces with exact private inspection evidence.
All modes retain successful definitions and exact *1, *2, and *3
history for one command. Failed forms preserve the previously committed state.
A successful evaluation is installed before its terminal event is recorded; if
that fail-closed event write fails, the returned session reflects the committed
continuation and is terminally closed instead of exposing a competing stale
copy.
They do not share authority: selecting a profile is mutually exclusive with a
manifest.
Start an interactive session, repeat expressions, load setup code, or evaluate one script:
mix ptc repl
mix ptc repl -e '(def x 40)' -e '(+ x 2)' -e '(+ *1 1)'
mix ptc repl -l setup.clj
mix ptc repl script.clj
mix ptc repl - < script.cljUse the same strict manifest as mix ptc run to attach a frozen workflow
bundle, workflow capabilities, limits, input, labels, and event policy:
mix ptc repl --manifest ptc.json
mix ptc repl --manifest ptc.json --host-config ptc-host.json
mix ptc repl --manifest ptc.json -e '(workflow/helper data/input)'The direct REPL does not accept an ambient capability catalog or arbitrary profile configuration. Providers and component sources are selected only by the manifest and trusted provider registry.
Manifest mode resolves --host-config HOST.json through the same bounded
trusted-installation path as mix ptc run. A manifest that selects a provider
requires this option; a provider-free manifest may omit it. Direct sessions and
code-owned profile modes reject it. Provider-backed startup runs the shared
audited-local checks before marking activity, then acquires one provider
session which every evaluation reuses until the REPL closes.
An interactive session also accepts a few meta-commands:
:doc <name> Show core function documentation
:find <pattern> Search the available function surface
:help List the session commands
The full language surface is in the PTC-Lisp specification and function reference.
Every workflow session emits canonical Kernel events. Persist them as bounded, append-only JSONL with:
mix ptc repl --trace trace.jsonl
mix ptc repl --manifest ptc.json --trace trace.jsonlPrivate event policies require an explicit private manifest selection; the
REPL requires the reserved .private.jsonl suffix and restricts the file to
owner read/write permissions before appending event data. Normal directory
grants and the Viewer do not discover private-suffixed traces.
A private manifest result is interactive authority, not ordinary unattended
stdout. Manifest mode requires an attached terminal and the explicit
--private-terminal grant during destination preflight, after manifest
classification but before audited-local checks or opening a provider session.
It rejects --eval, --load, positional scripts, stdin, --format jsonl, and
detached execution at that boundary with provider activity false and no
provider work. Returned private values and prints may reach only that
authorized terminal; they never enter the JSONL stream or an unauthorized
stdout sink.
The session owner is the only terminalization path for direct and manifest
workflow sessions. It retains the trace grant, run state, and the manifest
opening handle; that handle owns the active provider session and its acquired
resources. Normal close, abort, caller death, evaluation-worker failure, and
deadline failure converge on bounded cleanup. Provider cleanup precedes the
single terminal event batch, trace persistence follows that batch, and sinks
are stopped last. If trace persistence fails after finalization, programmatic
close/1 and abort/2 return the frozen events alongside
:trace_persistence_failed so an embedding host can retain or recover that
evidence.
Select the code-owned profile and supply its required trace resource:
mix ptc repl \
--profile run-analysis-v1 \
--resource traces=tmp/tutorial-tracesThe traces value must name one normal directory of canonical sanitized JSONL
files. The task captures it immutably when the session starts. The caller
cannot select the profile's component, capabilities, limits, mission data,
labels, persistence policy, or result projection.
Capture is one directory level deep. A resource directory whose artifacts sit in subdirectories admits nothing, so the session refuses to start rather than answering every query with an empty page:
ptc repl profile setup failed: the traces resource directory contains no
*.jsonl trace files at its own level; artifacts in subdirectories are not
captured
A session that does start reports what it admitted, one line per resource, so a partial match is visible before the first query:
Captured traces: 12 files, 12 runs
With --format jsonl the same counts appear under capture in the
session-started record.
run-analysis-v1 installs one analysis namespace with six question-shaped
functions:
(analysis/runs {"limit" 50})
(analysis/overview "run-id")
(analysis/activity "run-id" {"limit" 100})
(analysis/failure "run-id" {"limit" 100})Public captures can answer those four questions from sanitized canonical
traces. analysis/conversation and analysis/source require the private
recipe and return an evidence-unavailable error here. Results are bounded and
carry complete?; a false value means the caller must narrow the question or
raise the bound, never that omitted evidence did not exist.
Ordinary bounded mission introspection such as (tool/runtime-usage {}) and
(tool/cap-list {}) is also available. Filesystem, network, LLM, agent,
workflow, MCP, private-inspection, and nested evaluation authority is absent.
If an attached workflow kernel component calls kernel/check-source, the
standalone REPL reports :busy without charging the check quota: the outer
interactive form already holds the sole continuation lease.
One session can build up an investigation interactively:
(def runs (analysis/runs {"limit" 50}))
(def items (get runs "items"))
(def ok-runs (filter #(= "ok" (get % "status")) items))
(map #(select-keys % ["run_id" "duration_ms" "mission_capability_calls"])
ok-runs)
(def slowest (first (sort-by #(get % "duration_ms") > items)))
(analysis/activity (get slowest "run_id") {"limit" 100})Loaded files, repeated --eval forms, positional scripts, stdin, and
interactive forms all use the same mission continuation and aggregate budget.
Each of those source inputs is bounded by the profile's
subordinate_source_bytes limit before evaluation. Oversized load files,
scripts, stdin, and accumulated interactive forms are rejected without first
reading an unbounded source into the Mix task.
mix ptc repl \
--profile run-analysis-v1 \
--resource traces=tmp/tutorial-traces \
-e '(def runs (analysis/runs {}))' \
-e '(count (get runs "items"))'return and fail are per-form outcomes in this human session. They do not
close it. A terminal deadline or Kernel budget prevents later forms; normal
close still finalizes the session trace with the authoritative terminal reason.
Use the private profile only on an attached terminal, and explicitly authorize that terminal as the private result sink:
mix ptc repl \
--profile private-run-analysis-v1 \
--resource traces=tmp/tutorial-traces \
--resource inspection=tmp/tutorial-inspection \
--session-trace-dir tmp/analysis-traces \
--private-terminalThe profile checks both terminal attachment and --private-terminal before it
opens either source directory. Its traces, inspection, and analysis-trace
directories must be physically separate, including through ancestors and
symlink aliases. Inspection capture validates every private artifact against
the corresponding run in the immutable canonical trace capture; malformed,
replaced, uncorrelated, or oversized input rejects the whole private source.
An artifact from an unsupported inspection schema also rejects the whole
source, and setup reports both the artifact's declared version and the version
supported by the running build. Use a matching PtcRunner build to inspect the
retained artifact, or regenerate it with the current build.
For a deliberately unattended private analysis, authorize the command's own
streams instead with --private-unattended. That destination permits --eval,
--load, a positional script or stdin, and --format jsonl; it is mutually
exclusive with --private-terminal. Because private values may then reach the
caller-controlled stdout sink, redirect it only to an owner-authorized private
destination and do not treat it as an ordinary public command channel:
In a repository checkout, set MIX_QUIET=1 for machine-readable output so
Mix and dependency build progress do not share stdout. The packaged ptc
executable and container entry point do not have that Mix build stream.
MIX_QUIET=1 mix ptc repl \
--profile private-run-analysis-v1 \
--resource traces=tmp/tutorial-traces \
--resource inspection=tmp/tutorial-inspection \
--session-trace-dir tmp/analysis-traces \
--private-unattended \
--format jsonl \
-e '(analysis/conversation "run-id" {"limit" 1000})' \
>tmp/private-analysis.jsonlprivate-run-analysis-v1 installs the same analysis namespace and reads both
ordinary and .private.jsonl canonical traces, still excluding inspection
files from the trace resource. Private authority enriches the same result
shapes instead of requiring another vocabulary:
(def runs (analysis/runs {"limit" 20}))
(def run-id (get (first (get runs "items")) "run_id"))
(analysis/overview run-id)
(analysis/conversation run-id {"limit" 1000})
(analysis/failure run-id {"limit" 1000})
(analysis/source run-id {"limit" 1000})conversation reconstructs cumulative model requests into ordered streams and
preserves the terminal response, generated programs, feedback, system prompt,
and token usage without exposing inspection record shapes. Independent model
calls remain separate streams; an equal maximal predecessor is reported as
ambiguous. failure returns the private evaluator diagnostic and relevant
programs with an explicit direct, same_workflow_evaluation, preceding, or
unknown relationship. overview includes the exact strictly JSON terminal
value when V5 captured one. activity includes exact non-LLM capability,
provider, print, and error facets.
For the flagship dialogue journey, avoid a REPL entirely:
ptc transcript run-id \
--traces tmp/tutorial-traces \
--inspection tmp/tutorial-inspection \
--private-unattended \
--private-output tmp/transcript.private.jsonThe destination is reserved with owner-only permissions before either source is captured. An incomplete or ambiguous conversation fails without publishing the file.
Exact model messages, generated source, capability arguments/results, effective preludes, MCP request/response bodies, execution prints, execution error details, and terminal result values may appear on the authorized terminal. They are private data: do not paste or redirect them to a public sink.
The attached-terminal check is an accident guard, not access control. It
cannot distinguish a human terminal from a pseudo-terminal allocated by
script(1), tmux, or ssh -t, and a same-UID caller can already read the
inspection artifact directly. --private-unattended makes deliberate
non-interactive use explicit and greppable. Exact private values then become
part of whatever consumes this command's output, including a coding agent's
conversation transcript and potentially that agent's provider logs. Treat that
destination with the same care as the private data itself.
The separate canonical analysis trace records only safe profile identity, hashes, sizes, timing, outcomes, and usage. It never records the evaluated REPL source, returned private value, prints, or retained REPL history.
A private session never forwards evaluator message text, because that text can quote a captured record. It does rebuild the diagnostics that describe nothing but the operator's own input: an undefined-variable failure reports the names from the submitted source, each checked to appear verbatim in it.
(defn- g [x] (* x 3)) (return (g 14))
;=> Error (unbound_var): Undefined variables: defn-, g, x. Hint: 'defn-'
; defines a private helper in component source only; use defn in dynamic
; source [continuation preserved]A name that is not in the submitted source is dropped, and the message says so
rather than presenting a short list as the whole cause. Every other failure
answers with a fixed string and message_redacted? set, so a withheld
diagnostic is visibly withheld rather than silently absent:
("some-string" 1)
;=> Error (not_callable): private evaluation failed; diagnostic withheld by
; the private result policy [continuation preserved]The fault kind, the continuation effect, and every usage counter stay exact
in both cases.
Terminal profile sessions never write their analysis trace into the captured input tree. Supply an existing physically separate output directory:
mix ptc repl \
--profile run-analysis-v1 \
--resource traces=tmp/tutorial-traces \
--session-trace-dir tmp/analysis-traces \
-e '(analysis/overview "run-id")'Without --session-trace-dir, the task creates a private 0700 directory
under the operating system temporary directory. On close it reports the
absolute <run-analysis-id>.jsonl path. The file is published atomically,
never appended, and contains the profile ID and effective digest. Evaluated
source and exact trace-query payloads are not copied into canonical events.
The output directory cannot be the input directory, an ancestor or descendant of it, or the same physical directory through symlinked parents.
Coding agents can avoid PTY and prompt handling by repeating -e with
--format jsonl:
MIX_QUIET=1 mix ptc repl \
--profile run-analysis-v1 \
--resource traces=tmp/tutorial-traces \
--session-trace-dir tmp/analysis-traces \
--format jsonl \
-e '(def runs (analysis/runs {}))' \
-e '(count (get runs "items"))'Every task-emitted stdout line is one JSON object. Records use schema version 1 and, when their corresponding lifecycle stage is reached, appear in this order:
- one
session-startedrecord after successful session construction; - one
evaluationrecord per accepted source, containingindex,input_kind, and the boundedAnalysisSessionresult projection; - one
session-closedrecord only after successful close and persistence, containing the persistedtrace_path; - a final
command-errorfor an unsuccessful command, with categorycli,setup,evaluation,lifecycle,persistence, orfrontend.
Validation and setup failures can therefore produce only command-error;
persistence failure follows any started/evaluation records without claiming a
successful session-closed record.
The task adds no raw source field or independent source copy. Returned values, prints, and bounded evaluator messages remain intentional public feedback and may naturally contain text also present in a program.
JSONL is non-interactive only. Any command error makes the Mix process
unsuccessful. To collect feedback from later expressions after a recoverable
form error, use --continue-on-error with at least two -e arguments:
MIX_QUIET=1 mix ptc repl \
--profile run-analysis-v1 \
--resource traces=tmp/tutorial-traces \
--format jsonl \
--continue-on-error \
-e '(def runs (analysis/runs {}))' \
-e 'missing-name' \
-e '(count (get runs "items"))'Later forms see the state committed before the failed form. The session closes and persists normally, but the final process status remains non-zero because a requested evaluation failed.
Inspect the safe static contract without capturing traces or starting a session:
mix ptc repl --describe-profile run-analysis-v1
MIX_QUIET=1 mix ptc repl --describe-profile run-analysis-v1 --format jsonlThe description lists the required resources, complete component closure, callable namespaces, capabilities, fixed limits, and policies. It contains no path, snapshot, callback, process identifier, source, or credential.
- Running and debugging owns the run command,
result shape, trace capture, private inspection capture, and the Viewer. For
a manifest entry run rather than a REPL session, use
mix ptc run MANIFEST --trace-dir DIR. - Manifests and capabilities documents the
manifest that
--manifestsessions attach to, and the trace and inspection snapshot providers these profiles read. - Components and preludes explains the core and analysis components these profiles install, dependency closure, and how to package your own analysis functions the same way.
- Hosts driving
PtcRunner.Kernel.ReplSessionprogrammatically should read Embedding in Elixir for its ownership rules.