PipeWhy CLI and Export Contract | CLI-1 version 1.0
October 30, 2026 | Q1 v1.0 applies to every implementation and verification task.
PW-12.01-.05 specification; commands become supported as their implementations land.
The executable supports the complete published scan/diff/lineage/why/report/export
grammar. Final all-command stream/error/install acceptance remains in progress.

PW-12.01 Command grammar and coordination

pipewhy [--help | --version]
pipewhy scan SOURCE --config FILE --source-version VERSION [scan options]
pipewhy diff BEFORE AFTER [selector] [query options]
pipewhy lineage SNAPSHOT selector [graph options] [query options]
pipewhy why BEFORE AFTER [selector] [incident options] [query options]
pipewhy report integrity BEFORE AFTER [report options] [query options]
pipewhy export snapshot SNAPSHOT --format FORMAT [selector] [query options]
pipewhy export diff BEFORE AFTER --format FORMAT [selector] [query options]
pipewhy export lineage SNAPSHOT --format FORMAT selector [graph/query options]
pipewhy export incidents BEFORE AFTER --format FORMAT [selector/incident/query options]
pipewhy export impact BEFORE AFTER --format FORMAT selector [query options]
pipewhy export report BEFORE AFTER --format FORMAT [report/query options]

BEFORE/AFTER/SNAPSHOT are exact lowercase 32-hex C5 IDs, never filesystem paths,
source versions or implicit latest aliases. SOURCE is an exact configured name.
A selector is at most one of --artifact-id UINT64, --artifact-name TEXT,
--artifact-path JSON_ARRAY. IDs exclude NULL_ID. Paths are literal root-first
JSON arrays of strings, preserving empty/slash/numeric labels; shell quoting is
the caller's responsibility. Commands marked selector require exactly one.
Name/path selection binds the captured snapshot (AFTER for pair commands); explicit
ID inspection can preserve removed facts without requiring an after-version label.
Typed C7 selectors retain unavailable results without first-match guesses. Derived
incident/impact exports require a resolved predicate/root and otherwise refuse the
input explicitly before producing an export, as detailed below.

Query options: exactly one of --store DIRECTORY or --config FILE; --limit N
(default1000, 1..100000); --cursor TOKEN; --max-label-bytes N (default1048576,
positive uint64); --format text|json where supported; --output FILE; --ascii;
--width N (default100, 40..240); --overwrite for explicitly replacing export files.
Text also accepts --max-output-bytes N (default8388608, positive uint64).
Output defaults to stdout. --ascii/--width are text-only. No arguments prints help
successfully; help/version require no configuration, optional backend or store access.
Machine format validation and malformed arguments precede source reads or publication.

Diff supports --resolution dataset|record|value (defaultdataset). The initial scan
producer materializes dataset observations. Finer retained C2 records can support
transform checks without a materialized fine C6 comparison; such requests preserve
C7 COMPARISON_DETAIL_NOT_SUPPLIED, rather than inventing record/value observations.
Unretained history reports DETAIL_NOT_RETAINED. A later fine-observation producer
requires its own stable artifact mapping and acceptance, not a renamed dataset view.

Graph options: --direction forward|reverse (defaultforward), --depth N (default1),
--all-depths (exclusive with --depth), --relations copy,transform,derived (defaultall).
Depth zero returns the selected root with no edges. An explicit empty relation
selection uses --relations none. Limits refer to edge rows, not complete paths.

Scan options: --snapshot-id ID (defaultnew UUID); --scope UINT64 (default0, fixture
root); --profile strict-v1|logical-v1 (defaultstrict-v1); --mode multiset|ordered
(defaultmultiset); --backend reference|cpu (defaultreference); --batch-size N
(default1024, 1..100000); --retain dataset|value (defaultdataset); --parent ID.
Reference works in a core-only installation. cpu explicitly requires the cpu extra
and never silently falls back. Unqualified CUDA/auto policies are not registered
as implemented backends. The earlier proposed --levels/auto grammar is superseded
for this initial qualified interface by explicit retention/resolution/backend options.

TOML configuration uses schema_version=1, [store] path="./snapshots", and named
[sources.NAME] entries with kind="local-fixture", path="./fixture". Store/source
paths resolve against the configuration file's directory, not the process cwd.
Reject unknown fields/kinds, wrong types and unsupported schema versions. Never
dynamically import an arbitrary configured adapter. The fixture directory is explicit
external input; installed code never discovers a repository test directory or relies
on test files bundled into the wheel. Query config loading resolves only the store;
historical query/why/export does not reconnect a configured source.

Source version is required for scan. Unknown versions/scopes fail visibly. Scan
captures C4 once, normalizes with the explicit C2 profile and computes C3 states via
the chosen backend. C5 publishes the validated inventory/names, dataset observations,
captured declarations/evidence/transforms and optional complete C2 retained records.
Failure/read accounting and source consistency remain in immutable metadata. Unknown
reads are not empty datasets. The receipt identifies snapshot/source/scope/profile/
algorithm/resolution/coverage. Existing snapshots are never overwritten. --parent
must bind an existing compatible source namespace/scope/fingerprint context.
The production array-role bundle is versioned separately from generic C5 storage;
reopening validates those roles rather than guessing semantic meaning from file names.

Incident options: --registry-snapshot ID to load a retained immutable registry;
--incident-window-ns N and --incident-clock TEXT are required together when making
a new registry. A loaded registry supplies its recorded policy; conflicting explicit
policy is an error. --event-limit N (default1000), --support-limit N (default1000)
and --max-key-bytes N (default1048576) follow C7 bounds. --save-registry NEW_ID
explicitly publishes the updated state to a new C5 snapshot; otherwise it is a
transient derived view. Output records its persistence state and optional base/saved
registry snapshot IDs. A registry UUID is not itself proof of durable publication.
Configuring an incident clock never asserts that a captured observation used it.
Without actual L1 data windows, earliest timing and temporal recurrence remain unknown.

why computes captured copy/qualified transform checks, direct divergence, original
earliest ambiguity and selected incident evidence; a selector focuses on that
artifact's candidate rows without reranking away competing scope candidates.
Potential/observed impact is a separate selected page, from the selected artifact
when supplied or the captured candidate set otherwise. A selected unchanged artifact
can have no observed incident while still having declared potential exposure.
No command labels a potential path, declaration or earliest candidate as a proven
physical cause. Persisted inputs alone supply historical explanations.

Report aggregates the full captured comparison scope, not just a displayed page.
--registry-snapshot ID supplies optional matching evidence counts; repeatable
--impact-from-id UINT64 options supply optional potential/observed impact roots.
No roots/registry means explicit unavailable optional metrics, not known zero.
Export impact uses its required selected artifact as the explicit traversal root.

PW-12.02 Exit codes and streams

0: successfully produced the requested result/receipt with no detected change.
1: produced a result with known change, presence/structure difference or failed
   qualified content condition, without a higher-priority failure below.
2: invalid command, option/value/combination or unsupported format/result pair.
3: operational failure: configuration/input/store/permission/checksum/publication/
   backend/output error. Do not issue a success receipt or partial machine result.
4: valid result reports required data/selection/detail unavailable, incomplete read/
   discovery/graph scope, or incomparable/unknown observed data needed for the view.

Precedence is usage2 before execution; operational3 before valid-result outcomes;
unavailable4 before detected1 before success0. A known change can coexist with exit4
and remains in the output. Determine full selected-source coverage/change before
pagination; displaying an early SAME row cannot suppress a later change or gap.
Unobserved structural containers alone are not failed data reads. Optional unsupplied
aggregate sources, ambiguous earliest ordering and unknown operation timing retain
explicit qualifiers; they do not by themselves invalidate an otherwise delivered
data view. A supplied but unreadable requested snapshot is operational failure.

Results only go to stdout (or --output), diagnostics only to stderr. No progress,
backend/JIT logging or extra banners contaminate machine output. Structured valid
unavailable results still serialize and return4. Failures before a result leave
stdout empty and explain the actual failed operation. Preserve exception context
in the library; the command boundary reports expected errors without swallowing them.

PW-12.03 JSON output version1.0

Envelope: {format:"pipewhy.result", version:"1.0", query_schema_version:"1.0",
family:NAME, result:OBJECT}. Query families map to the C7 page fields/properties;
why is a documented composition of incident and impact pages with shared capture/
registry persistence metadata. Scan uses family=scan and a validated C5 receipt.
No generic payload may omit original contexts, coverage, availability, reason,
totals, truncation, source identities or selected evidence qualifiers.

All uint64 scalar counts/IDs/times/offsets/limits and uint64 array entries are exact
decimal strings. Booleans remain JSON booleans; enum/uint8 and explicitly integer
format-version codes stay integers with C6/L1/C7 published mappings. Envelope/query
version strings retain the specified string representation. Null means unavailable/not applicable as
defined by the field, distinct from zero; NULL_ID references retain the sentinel's
decimal string. Scalar enum controls use their defined underlying values. Exported
SelectedNames uses {name_ids, payload_utf8, offsets, lengths}; offsets/lengths count
UTF-8 bytes, preserving captured dictionary IDs and exact Unicode identity. Other
flat tables are objects of equal-length integer arrays, without per-source-row objects.

Serialize dataclass/DTO metadata completely; no repr(), raw pointers, process hashes,
source adapters or original whole analysis owners. UTF-8, deterministic sorted object
keys and stable array order, allow_nan=false, one complete JSON document plus newline.
Escaping preserves quotes, backslashes, controls and Unicode; machine output does
not truncate identities or captured text. No float/Decimal serialization shortcuts.

When an actual fingerprint is exported, retain algorithm name/full ID, normalization
profile ID, schema ID, mode and exact C3 eight-word state as decimal strings. A short
display digest alone cannot establish equality. Snapshot inventory pages do not
claim to contain record/value states. Algorithm remains the explicitly experimental
accidental-drift profile; this schema grants no adversarial integrity guarantee.

PW-12.04 Format/result matrix and file policy

                     text     JSON      CSV       DOT
scan receipt         yes      yes       no        no
snapshot inventory   yes      yes       yes       no
diff                 yes      yes       yes       no
lineage edge page    yes      yes       yes       yes
incident page        yes      yes       yes       no
impact page          yes      yes       yes       no
integrity metrics    yes      yes       yes       no
why composition      yes      yes       no        no

CSV is a genuine header/data table of the selected primary columns, with decimal
integer values, standard comma/double-quote/CRLF escaping and no comment preamble.
It requires a JSON metadata companion containing all non-primary C7 metadata,
related arrays/text/analysis, primary column types and SHA-256 of the exact CSV bytes.
For --output FILE, companion defaults to FILE.metadata.json; stdout CSV requires
an explicit --metadata FILE. Companion format/version are pipewhy.csv-metadata/1.0.
The pair is verified by checksum, not claimed as an atomic two-file transaction.
Never silently omit scope/evidence information to make a bare CSV look complete.

DOT contains only selected explicit lineage edges and related nodes, with stable
quoted IDs and correctly escaped labels. Preserve relation/evidence references,
selected graph context, query identity, counts and truncation as graph/edge metadata.
It cannot traverse a source graph or invent omitted connecting edges. Unsupported
pairs fail before writing. Build the bounded result before serialization; output
files use exclusive creation unless --overwrite was explicit. Failures remain errors,
and broken/partial output is never reported as a complete successful export.

PW-12.05 Text presentation

Default plain UTF-8 text: family/source/snapshot/scope header, full coverage and
availability qualifiers, primary table and selected related evidence, followed by
returned/total/page position/continuation and related-prefix counts. Distinguish
POTENTIAL, OBSERVED CHANGE, UNKNOWN and INCOMPARABLE in words. Retain different
artifact/episode/observation/metric units and original policy/version references.
Selected labels come only from the bounded C7 dictionaries. Missing names display
their stable ID plus unavailable qualification, never a guessed live name.

Escape terminal control characters and multiline labels. Width bounds presentation
with explicit wrapping/ellipsis, never silent data loss; machine formats retain full
values. --ascii substitutes ASCII tree/graph markers and escapes unsupported display
characters. No mandatory terminal/color dependency or ANSI control sequences.
Containment trees and lineage graphs are distinct; missing parents, cycles and
partial edge pages show explicit markers. Render only selected rows: a page cannot
claim complete ancestry/path coverage. Unknown clocks/operation timing and competing
earliest candidates remain visible beside any observed change or failed condition.

Verification: meaningful unit formatting/escaping/exit tests; clean stdout machine
parsing; text/JSON agreement; CSV+metadata checksum/round-trip and DOT parsing when
Graphviz is available; independently installed core/cpu wheel and rebuilt-sdist
help/version plus explicit fixture commands. PW-12.26 and PW-13 perform installed
workflow acceptance. Documentation specifications alone do not claim those gates.

Implemented Python export boundary (PW-12.14/.18)
pipewhy.export exposes OUTPUT_SCHEMA_VERSION=1.0, json_result(C7Page),
json_receipt(SnapshotMetadata), and json_fingerprint(FingerprintState). Each returns
one complete deterministic UTF-8-ready JSON document plus newline. json_result
accepts exactly the six selected page families, including both incident views;
original capture/adapter/graph/ranking/registry inputs are not accepted as roots.
It retains every tuple field and public page/prefix/analysis truncation property.
Evidence includes its declared kind/completeness/diagnostics, actual timing fields
and timing_known, independently of check status and raw content status.

SnapshotMetadata uses its existing C5 to_dict representation, including full
algorithm/context/profile/schema/mode, coverage accounting and failure diagnostics.
Comparison fingerprint contexts preserve schema/profile/mode plus context_id; their
outer source algorithm_id remains authoritative, including unsupported contexts.
Fingerprint export is a Python API family=fingerprint with algorithm name/full ID,
context and all eight state_words. No additional CLI command is implied.

Selected text reuses the C7 byte-budget projection and dictionary identity; there
is no second source/name resolver. UTF-8 payload, exact byte offsets and original
name IDs survive JSON escaping. Empty labels are not unavailable labels. Missing
explanation indices, null unavailable totals and zero denominators remain distinct.
Raw pointers/repr, floating control values, non-string metadata keys, out-of-range
scalar counts and noncontract array layouts fail explicitly. This encoder trusts
validated producer DTO semantics; encoding is not authentication or a separate proof
that an arbitrary caller-created DTO truthfully describes a source.

Tests parse all six families and incident observations, round-trip C5 metadata and
full multiset/ordered fingerprint states, preserve integer values above floating
precision, Unicode/quotes/backslashes/newlines, typed uint8 codes and uncertainty.
Native/reference saved C4/C5 integrations exercise real receipt/diff/incident exports.
Text/DOT, command parsing/dispatch and stream/file orchestration remain pending.

Implemented CSV bundles (PW-12.19)
pipewhy.export.csv_result(C7Page) returns CsvExport(text, metadata) without writing
files. All six families and incident views use an actual header/data primary CSV.
Columns sort lexically by field name; rows retain the C7 stable order. Integer
lexemes are exact decimal text and line endings are CRLF. Standard-library CSV
quoting covers delimiter/quote/newline field names. Unequal column lengths fail
rather than truncating to their shortest length.

The JSON companion uses pipewhy.csv-metadata version1.0, with query version/family,
primary encoding/line_ending/SHA256/row_count/column-name-and-dtype schema, and the
complete JSON result except its primary columns. Selected names, related arrays,
actual checks, context, null unknown totals and all truncation qualifiers remain
there. Recombining both parsed artifacts reconstructs the corresponding json_result
body exactly. Empty primary CSVs retain availability and zero-versus-null meaning
in the mandatory companion. Hash identity detects differing bytes; it is not an
authenticity certificate. File/stream orchestration is still command implementation.

Implemented selected DOT (PW-12.20/.24)
pipewhy.export.dot_result(LineagePage) returns a non-strict directed graph with
stable quoted artifact IDs and exact selected edge IDs, relations and evidence/
transform references. It iterates only returned node/edge arrays; omitted connecting
edges are not reconstructed. Parallel edges, self edges and cycles remain distinct.
Visible graph labels retain availability/reason, source/scope, graph coverage,
returned/total counts, page position/continuation and name/evidence availability.
Missing names and known empty labels have different explicit presentations.

Captured display text uses escaped visible controls/quotes/backslashes and literal
Unicode, preventing source labels from becoming DOT statements or layout macros.
The graph attribute pipewhy_metadata_base64 contains the complete json_result page
as base64 UTF-8 JSON; pipewhy_metadata_encoding names that encoding. This preserves
all exact text/context/uncertainty across DOT lexical and label escape layers.
It is not a checksum/authentication certificate. Custom graph metadata remains
available to DOT/Graphviz JSON consumers; visual layout alone is not a full export.

Windows verifies source output, literal identities and all special graph cases.
Two separate installed-wheel tests pass in a clean Linux container with Graphviz
2.42.4: actual C4/C5 reopened selections plus synthetic parallel/cycle/self edges,
hostile quote/newline/macro labels, exact rendered labels and lossless metadata.
The Linux CI runner now installs Graphviz, records dot -V and runs these tests;
local Windows records the two unavailable-tool skips separately. No Graphviz Python
or runtime package dependency is added. Native instruction coverage is not claimed.

DOT syntax and escape references:
https://graphviz.org/doc/info/lang.html
https://graphviz.org/docs/attr-types/escString/

Implemented text tables (PW-12.15)
pipewhy.export.text_result(C7Page, width=100, ascii_only=False, max_bytes=8388608)
renders all six selected primary tables and complete non-primary context/evidence.
text_receipt(SnapshotMetadata, same options) presents the existing C5 receipt.
Stable row numbers associate column panels when a narrow display cannot fit all
fields at once. Cells/metadata wrap complete values, including full identities,
rather than silently abbreviating captured facts. Status/reason/relation/metric/
flag codes have readable names; unknown flag bits retain their numeric value.
Missing names differ from empty labels, unavailable totals from zero, and N/A
denominators from tested populations. All raw source qualifiers remain in metadata.

Only selected dictionaries resolve names. Unicode display widths account for wide
characters and combining marks without normalization. ASCII mode escapes non-ASCII
text; control/format characters, including bidi controls, have visible escapes.
These display escapes also protect DOT labels; embedded metadata still preserves
exact captured text. No terminal/color/formatting dependency is introduced.

The hard UTF8 byte budget includes wrapping/newlines and is checked before returning
any text. Exceeding it raises an explicit error, not a seemingly complete shortened
page. Invalid width/bool/budget/source types reject. Tests cover all family metadata,
actual saved receipt/diff output, partial graph/capture evidence, unknown timing/checks,
exact budgets, wide/combining Unicode, ASCII and unavailable optional metrics.
Dedicated containment/graph layouts are described below; CLI/file/stream dispatch remains downstream.

Implemented containment text (PW-12.16)
pipewhy.export.hierarchy_text(SnapshotPage, width=100, ascii_only=False,
max_bytes=8388608) renders only selected C1 containment rows, never lineage edges.
Root/sibling order follows stable IDs. Parents absent from the returned page are
explicitly outside the selected page, not inferred roots or fetched ancestors.
Every row retains artifact/name/kind/parent IDs and exact depth; indentation is
explicitly capped at depth8 to bound long-chain presentation. Unicode/ASCII branch
markers share the existing safe labels, display-width and byte-budget machinery.
All original non-primary context and coverage remains in the shared metadata view.

The traversal is iterative; a 1501-node chain renders without recursion or unbounded
indentation. Duplicate IDs, unequal columns and unrooted cycles in caller-constructed
invalid pages fail rather than loop or silently drop rows. Source containment is
already validated by C1/C7. Independent tests cover forests, stable siblings,
pagination/unknown ancestry, empty versus unavailable selection, control/Unicode
labels, incomplete capture outside selected rows and exact output limits. Stored
C4/C5 consumers verify actual selected root/dataset parent/kind/name identities.
Directed graph text is described next; command dispatch remains downstream.

Implemented directed graph text (PW-12.17; agreement PW-12.22)
pipewhy.export.graph_text(LineagePage, width=100, ascii_only=False,
max_bytes=8388608) lists selected nodes and original directed edge IDs/endpoints,
relation/evidence/transform references and quoted captured labels. Missing names,
known empty labels and absent evidence payloads remain explicit. Self loops and
parallel selected edges are labeled without coalescing their stable identities.

Cycle-closing markers are derived only from the selected subgraph. The renderer
shares the core CSR adjacency builder and performs iterative color-state traversal
over those selected arrays, never the original graph owner. A completed node reached
through a diamond is not mistaken for an active cycle. A cycle marker proves a cycle
in the returned subgraph; zero markers cannot establish that omitted graph scope is
acyclic. Page position/counts, incomplete graph coverage and original metadata remain
visible. The renderer never inserts omitted connecting edges or containment links.

Literal cycle/diamond/parallel/self fixtures and sixteen independent transitive-
closure oracles check the annotations, including every cyclic selected component.
A 1501-node cycle renders without recursion and identifies the actual closing edge.
Partial first/final pages, invalid caller-constructed layouts/endpoints, ASCII/
escaped/empty/missing labels, per-edge evidence gaps and exact byte limits are checked.
The adjacency refactor preserves all existing L1 index/reach/impact behavior.

PW-12.22 library agreement covers all six selected families and both incident views:
JSON retains full typed facts; CSV plus companion reconstructs that body exactly;
tabular/tree/directed text retain original primary identities and full non-primary
metadata with readable code names. Real saved C4/C5 consumers assert literal expected
statuses/parents/edges/names and original failures across complete/mutated/missing
reads. Machine exports retain full precise values; text wraps complete identities,
and all variants preserve scope uncertainty and explicit page/related-prefix limits.
Command dispatch, stdout/stderr and installed-command acceptance remain downstream.

Parser/configuration component (PW-12.06/.07 in progress)
pipewhy.cli.parser.build_parser()/parse_command() implement the full pure grammar
for Python callers, including generated help, canonical integer/snapshot selectors,
literal paths/names, resource bounds and format/incident-policy combinations. They
perform no source/store execution. At this component's original delivery the entry
point retained help/version behavior. Current executable scan support is documented
below; read-command handlers remain in progress.

pipewhy.cli.config.load_configuration(FILE) validates TOML schema_version1, exact
store/source field sets and supported local-fixture kinds. Returned configuration
and source maps are immutable. Paths are absolute relative to the config file;
source paths normalize lexically without probing offline configured inputs. Missing,
malformed, duplicate-key, non-UTF8, wrong-type and unknown-field configs fail clearly,
without dumping unrecognized values. Empty source maps support store-only queries.
SOURCE_VERSIONS is shared with the actual local adapter, avoiding a second version
policy. Moving cli.py into the cli package preserves pipewhy.cli:main and installed
import/entry-point identity. Configured scan acceptance is delivered below.

Capture component (PW-12.08 in progress)
pipewhy.cli.capture.scan_fixture(source, store, source_version, ...) now performs
actual C4 discovery/read/lineage capture and publishes a verified immutable C5
snapshot. Strict-v1/multiset/reference/dataset retention are defaults; logical-v1,
ordered mode, explicit CPU execution and value retention are selectable. There is
no backend fallback. Unknown versions/options, incompatible parent namespace/scope/
fingerprint context and unexpected source errors fail without publishing a snapshot.
Known read failures publish explicit ERROR observations and PARTIAL or UNAVAILABLE
coverage with expected/returned counts; their empty payload is never an empty-data
fingerprint. Capture times use epoch nanoseconds and do not establish operation
intervals, clock compatibility or an earliest physical cause.

The version1 pipewhy.local-capture semantic bundle contains captured c1_* inventory,
names_payload/names_offsets/names_lengths, c6_* dataset observations and fingerprint
words, discovery_complete, lineage_* explicit edges, declarations (UTF8 JSON of
captured evidence/transform rules) and capture_metadata (UTF8 JSON format/version,
backend, normalization_descriptor, observation_resolution and lineage_coverage).
record_artifact_id/record_words/record_offsets/record_lengths retain C2 key/amount
records only with value retention, otherwise all four arrays are empty. The exact
normalization descriptor is retained alongside its full profile hash. Declared
edges remain declarations, never claimed execution proof. Parent captures must
have matching namespace, scope and fingerprint context. Scoped datasets preserve
their outside-scope containment parent without importing its inventory or edges.

C4 scalar-to-C2 framing now lives in adapters.local.records and is shared by capture
and existing adapter/transform acceptance tests. It copies normalized uint64 words
without decoding them through float or reinterpreting Decimal representations.
This Python API is now connected to installed scan dispatch. Offline reopening is
delivered below; executable read/query command acceptance remains in progress.

Offline capture reopening (PW-12.08/.09 component)
pipewhy.cli.bundle.load_capture(snapshot) validates the versioned semantic array
inventory and control metadata after C5 verification, then supplies the captured
ArtifactCatalog, dataset ArtifactObservations, LineageIndex, declared Evidence,
TransformRule records and retained(artifact_id) C2 slices. It opens no adapter and
works after the configured source directory is unavailable. Known failed reads
have no retained-record result. Dataset retention similarly returns None rather
than re-reading history. Selected retained slices share the captured word pool;
check_retained_records/check_transform independently verify their observed C3 state.

Validation binds C1/C6 identities, parents/levels, capture timestamp bounds, packed
fingerprint state/counts, explicit read status/failure accounting, retained record
packing/owner order/counts and all graph declaration references. Unknown inventories,
versions, dtypes, profiles with mismatched descriptors and malformed/duplicate-key
declarations fail explicitly. Historical profile descriptors remain as captured;
current profile eligibility can return INCOMPARABLE instead of relabeling them.

The declaration version is sha256:<full content identity>, using the existing framed
content_identity mechanism over namespace/scope/coverage, full captured declaration
payloads, artifact IDs and edge columns. It is stable across data versions, profile,
backend and retention changes, and changes when declaration content changes. This
identity is distinct from source data version and is not an authentication claim.
Capture epoch timestamps are never supplied as operation windows or execution proof.

Executable scan delivery (PW-12.07/.08)
The installed pipewhy entry point now registers the implemented scan command only,
in addition to help/version. The pure parser still exposes the full specified
grammar for command integration. No not-yet-implemented command is advertised as
executable. scan uses the selected named source, config-relative paths and explicit
version/options; it publishes a capture and emits only the text/JSON receipt on
stdout or to the chosen file. COMPLETE exits0, PARTIAL/UNAVAILABLE exits4, expected
operational failures emit one escaped diagnostic on stderr and exit3. Invalid
arguments exit2 before configuration access. Unknown source names and incompatible
scope/parent/version controls do not masquerade as successful empty scans.

File destinations are validated before capture: parent directory must exist;
existing outputs require --overwrite; configured inputs and snapshot-store paths
are protected, including resolved directory aliases. New files use exclusive create;
explicit replacements are written to a sibling temporary and replace the directory
entry so other hard links to an input inode remain unchanged. Replacement failure
keeps the old destination and cleans its temporary. Output uses UTF8 bytes when
stdout exposes a binary stream, including Windows redirected output. Text-only
capture streams are supported without changing the result. No progress is mixed
into machine stdout. Read-family/CSV stream acceptance remains PW-12.21/.23.

Snapshot publication and receipt delivery are separate operations: a subsequent
rendering/output error exits3 without rolling back an already published immutable
snapshot. The supplied --snapshot-id allows explicit recovery/inspection. New-file
I/O failure can leave a partial output file and is reported as an operational error;
there is no claim of a joint transaction between store and export destination.
examples/local-fixture.toml is an executable checkout example, with ignored store
data under .artifacts. Installed distributions require externally configured fixture
files; no repository fixture lookup is hidden in the package.

Executable offline diff/lineage (PW-12.09/.10)
The installed entry point now also registers diff and lineage. Both validate output
destinations, verify an existing store and reopen versioned captures without C4
connections. A missing/incomplete store is not created by a read command. Captured
checksums/semantic-role errors produce an operational diagnostic and no result.
--config is supported for query-only coordination even when its source is offline.

Diff materializes the existing dataset comparison, applies exact captured selectors
and C7 bounds/cursors, and preserves full source/scope/resolution/coverage metadata.
Its exit code evaluates the whole matching selection before paging: all pages of a
changed scope exit1, and all pages requiring an unknown read exit4, including a page
that displays only SAME. Selecting a known complete SAME dataset can exit0 while
unrelated wider-scope changes/read failures remain in scope_status/capture_failures.
Incomplete discovery and incompatible contexts remain exit4. Unknown ID in complete
diff scope is a known empty match. Finer retained history is not silently relabeled
as fine observations; C7 detail-unavailable reasons remain exact and exit4.

Lineage uses captured declaration content versions, names and payloads. Direction,
minimum-hop depth/all-depths, explicit relation sets and selected edge paging are
forwarded to C7. Unknown start differs from an isolated known node. Dataset read
failures remain visible in names_source metadata but do not invalidate a complete
declared-graph query. Declared payload availability never establishes operation
execution, equality, timing or physical cause.

Diff emits selected tables; lineage emits directed selected-edge text. JSON/CSV work
for both, and DOT is restricted to lineage by argument validation. CSV file output
defaults its companion to FILE.metadata.json; stdout requires --metadata FILE. Both
paths are preflighted and must differ. Serialization completes before writing, and
the companion is written before primary output; its checksum binds exact UTF8 CSV
bytes/CRLF. This is not a joint atomic transaction. Companion write errors emit no
CSV stdout and return3. A later primary-write error can leave a companion alone.

Shared decode_cursor validates canonical token structure without source/store I/O;
malformed/zero-position tokens are usage2. A structurally valid cursor still requires
the captured query identity and bounds; stale/wrong-query tokens are runtime input
errors (exit3), never continuation into a different query. Why/export dispatch and
final all-command stream/install acceptance remain separate; report is delivered below.

Executable integrity reports (PW-12.12)
report integrity reopens the supplied capture pair and counts direct C6 observation
facts, independently of metric pagination. Unlike diff's containment roll-up, a
structural container with no direct observation remains UNKNOWN/NOT_CAPTURED in
the metric population; this is untested content, not a failed dataset read, and
alone does not force exit4. Baseline fixture totals are four SAME datasets and one
unobserved container, with four content-comparable artifacts. Mutation totals add
one direct changed B; missing C reduces comparable content to three. Direct status
counts reconcile to the five captured artifacts, including the container.

Optional --registry-snapshot loads verified derived grouping state; matching incident
episode/evidence-observation counts use the exact capture pair/context. Report
does not register incidents or modify the saved registry. Optional --impact-from-id
roots invoke explicit declared reachability with direct observed changes attached.
Roots are deduplicated; starts are excluded collectively and no containment edges
are inferred. Potential exposure and observed downstream changes remain separate.
No optional source means unavailable metrics, not observed zero, and does not alone
force exit4. An explicitly requested unreadable registry or out-of-inventory root
is an operational input error (exit3), never substituted with known-zero metrics.
Text/JSON/CSV use the shared output and companion rules. Every metric page retains
the same complete comparison exit assessment; changing sources invalidates cursors.

Derived registry boundary (PW-12.11 foundation)
pipewhy.cli.registry.load_registry(snapshot), bind_registry(registry, metadata) and
save_registry(registry, store, source_metadata, new_snapshot_id, parent_id=...) support
immutable derived C5 state. The envelope uses incident-registry-v1 and immutable-
derived-registry, dataset resolution and COMPLETE coverage of the serialized registry
observation count. This coverage describes the saved registry state, not source-data
read completeness or proven physical events. IncidentRegistry.from_arrays performs
the existing full replay validation; local envelope checks bind its namespace/scope/
algorithm/profile/schema/mode and observation count. This initial CLI envelope holds
one such source policy; the general library's wider grouping capability is unchanged.

Registry UUID and snapshot ID are distinct. Saving never overwrites a snapshot.
A parent must have the same source context, registry identity and recurrence policy;
all old observations/timing/incident assignments/flags remain an unchanged prefix.
Appending new captured evidence creates a new snapshot; exact repeats leave counts
unchanged. Publication timestamps are derived-state save times, not operation windows.
Why registration/persistence is delivered below, with explicit --save-registry
required to publish; report remains strictly read-only.

Qualified captured analysis coordinator (PW-12.11 foundation)
pipewhy.cli.analysis.analyze_captures(before_bundle, after_bundle) evaluates the
saved after-graph's explicit conditions in edge-ID order. Copy checks use captured
dataset states; the versioned cents/dollars transform uses captured rule metadata,
declared provenance and retained historical C2 values. Dataset-only retention never
opens a source to fill missing detail. Missing values/rules and unsupported relations
remain UNKNOWN/INCOMPARABLE checks, rather than silently disappearing.

The coordinator joins these qualified checks to direct historical content changes
and calls the existing earliest-ranking engine without supplying invented operation
windows. Actual capture epoch timestamps do not establish clock domains, execution
order or physical cause. A lone B change still has UNKNOWN earliest timing. Scoped
isolated changes do not acquire omitted upstream edges or checks. Full source
incomparability and missing read qualifiers remain in the comparison even with no
eligible candidate. Actual saved strict/logical and ordered/multiset fixtures verify
copy/transform truth under dataset/value retention for baseline/mutation/missing
versions; unsupported declared relations remain explicit incomparable conditions.
Executable why composition/persistence is delivered below.

Selected why output boundary (PW-12.11 foundation)
pipewhy.export.WhyResult composes selected C7 DiffPage, optional IncidentPage and
optional ImpactPage with explicit selection availability/reason, scope candidate/
possibly-earliest counts, original RankingStatus, qualified ConditionCounts and
RegistryState. It contains no capture/graph/registry owners. Condition counts name
passed/failed/unknown/incomparable separately and identify their selection scope.
analysis_scope explicitly identifies current-capture-pair evidence; it does not
pretend a registry's other historical references have been reopened or explained.

RegistryState separates registry_id from base_snapshot_id/saved_snapshot_id and
persistence transient/derived-unsaved/saved, carrying episode/evidence-observation
counts and the full input identity. An allocated registry UUID alone never implies
durable storage. An unresolved selection uses absent incident/impact/condition
projections with UNAVAILABLE, rather than a misleading successful empty explanation.

json_why_result uses the existing pipewhy.result/1.0 envelope with family why and
preserves each nested C7 page exactly, including its family/schema/cursors, precise
integers, selected related evidence, context gaps and all original qualifiers. This
CLI-1 composition does not add a new C7 query family or change its schema version.
text_why_result uses the shared bounded table/metadata renderer and applies one
UTF8 byte budget to the complete composition, including all three pages and control
metadata. Exact byte-boundary and width/ASCII cases are verified; failure returns
no shortened explanation. The executable why delivery is described below.

Executable captured why (PW-12.11)
why coordinates the saved analysis, explicit incident policy, immutable registration
and selected comparison/incident/impact output. Scope ranking/candidate counts stay
original when a selector focuses the view. Qualified condition counts cover the
whole selected incident-edge population; the bounded root checks tuple also shows
conditions touching an unchanged selected artifact that has no content incident.
check_limit/checks_truncated expose that prefix. --support-limit independently bounds
this root condition prefix and C7 incident support projection. Limits never change
the complete selected-condition exit assessment. Unknown/incomparable required reads
or conditions exit4; known content/condition differences exit1; complete matches
exit0. Missing operation timing alone retains UNKNOWN ranking without forcing exit4.

The nested comparison uses direct C6 observations. --limit bounds each selected
page, and --cursor continues the incident page; comparison and impact retain bounded
prefixes. The loaded registry can contain older capture references. Only the supplied
pair's current analysis is attached: older selected references remain explicitly
unexplained, with analysis_scope=current-capture-pair. This optional historical
analysis gap does not erase current condition evidence or alone force exit4.

Without --registry-snapshot, an explicit window/clock is required. A transient UUIDv5
namespaces the full framed input identity (captured metadata/observations, declaration
version, policy and canonical incident payload), making repeated transient queries
and their cursors reproducible. The full input_identity is retained; event deduplication
continues to use complete canonical observation/timing keys, not a shortened digest.
Loaded registry UUID/policy and source namespace/scope/fingerprint context must match;
an explicitly conflicting policy is an operational input error. Clock text must be
valid UTF8 and malformed policy/argument combinations fail before store access.

No save option means transient or derived-unsaved output with saved_snapshot_id null.
--save-registry publishes a new verified registry snapshot, preserving an optional
base registry as its immutable parent. Exact repeats retain counts. Selection/key/
label-budget unavailability does not publish, and reports no saved snapshot. Rendering
finishes before publication, so a text-budget failure creates no registry. After an
explicit successful publication, a later output I/O failure can leave the requested
new snapshot available for inspection while returning3; no rollback/combined store-
output transaction is claimed. Existing snapshot IDs are never overwritten.

Read coordination protects actual config/store inputs and verifies an existing store.
Unused configured source paths remain lexical and unresolved, including with file
output; no passive offline-source probes or adapter connections are performed. Scan
additionally protects its explicitly selected source directory. Actual console tests
cover capture, offline why, save/reload/repeat and matching integrity registry counts
for mutated and missing reads, with clean JSON stdout and preserved uncertainty.

Executable export dispatch (PW-12.13)
export snapshot/diff/lineage/incidents/impact/report dispatch all six selected C7
families with an explicit supported format. Diff, lineage and report share existing
read coordinators. Snapshot text uses the selected containment renderer; lineage
text uses selected directed edges and also supports DOT. All six support JSON/CSV.
Unsupported or missing format combinations fail as usage2 before opening inputs.
Inventory availability is independent of dataset read coverage: a captured C remains
an inspectable artifact even when its data read failed, with failure metadata retained.

Impact resolves a known captured root, traverses declared edges and joins direct
historical changes. Its exit assessment includes the relevant root and full reachable
population before paging, without importing unrelated read failures or changes into
a selected isolated view. Complete source/graph qualifiers remain in the page.
An unknown/ambiguous/unavailable impact root is an operational input error (exit3),
as for report impact roots. Incident names/paths likewise must resolve uniquely
before constructing their qualified registry predicate; failures produce exit3 and
no guessed match, partial export or registry save. Explicit incident IDs can inspect
registry history independently of whether the artifact is in current inventory.

Incident export reuses qualified analysis, exact registration and explicit save rules.
The C7 incident result remains unchanged. Its JSON envelope and CSV companion add a
coordination object, schema_version=cli-export-context-v1, containing the full C5
before/after source receipts, selected integrity input_summary, explicit RegistryState,
optional name/path selection diagnostics and analysis_scope=current-capture-pair.
Thus an actually empty registry table does not hide a missing source read or imply
complete tested data. Input summaries retain exact expected/returned records and
the original capture failures. Optional older reference evidence remains unavailable
without inventing historical analyses. Grouping state availability and source-data
qualification stay separate; a missing read returns4 even if the exported table is
empty. Unchanged selected data can have zero matching incidents while the wider
registry and input summary retain unrelated observations.

CSV primary bytes/checksum/dtypes and C7 result reconstruction remain exact; the
coordination extension is only in the companion. Text appends the same qualifiers
under one complete-output byte budget. Rendering precedes optional registry save;
key-budget unavailability does not save. No save option creates no snapshot. Explicit
save/reload/repeat preserves counts and parent history through the shared registry
boundary. All shared protected/exclusive output and operational-error rules apply.

Full-width declaration words emitted as JSON decimal strings are parsed by the same
C4 word decoder when reconstructing typed evidence/transform IDs and rule field IDs.
Raw captured declaration content remains unchanged for version hashing. Regression
capture/export tests preserve edge/evidence/transform IDs above 2^63, including
2^64-2, and validate actual qualified incident checks after reopening those captures.

Installed workflow qualification (PW-12.21/.23/.25/.26)
tools/cli_smoke.py is a supported direct verification entry point. It takes expected
distribution version, installed console path and an explicit external fixture directory;
--backend reference|cpu chooses the producer. It creates its own temporary store and
configures the source explicitly, captures baseline/mutation/missing versions with
value retention, then removes the original config from the command path and queries
only saved inputs. No development-tool imports or repository sys.path are required.

The independent fixture oracle checks all five diff statuses, exact B candidate,
three failed conditions, unknown operation timing, explicit registry save and repeat
count1, all six export families/primary IDs, full JSON/CSV reconstruction and exact
CSV companion hashes/coordination. Integrity checks distinguish four tested datasets,
one episode/observation, three potential descendants and one observed downstream
change. Help/version and usage2/operational3 diagnostics are exercised, in addition
to valid success0/known-change1/unavailable4 outputs. Every valid command must have
clean stderr; failed pre-result commands must have empty stdout and real diagnostics.

Unit isolation replaces only the subprocess boundary while running actual handlers;
separate fault injections alter version/capture counts, diff status, candidate ID,
repeat count, export dispatch, checksum or metadata. Each plausible failure rejects.
Wrong exit status, logging contamination and unsupported envelopes similarly fail.
Real fresh installed Windows core and CPU environments pass the complete checker.
CI now repeats it for both wheel origins (direct wheel and wheel rebuilt from
sdist), in core and CPU phases, alongside pip check/import/module/native checks.
Native completion of this expanded workflow is recorded separately from local passes.
Enron source/export extension, November2,2026
The scan grammar also accepts a full lowercase40-character Git revision. Source
kind enron uses explicit cache/offline/source_limit/metadata_limit configuration;
local-fixture retains its known version labels. Source loading is side-effect free.
E1/ENRON_ACCEPTANCE.txt specify source mapping, consistency, history and limits.
Incident export coordination is cli-export-context-v2 and includes the captured
lineage_context. UNKNOWN/PARTIAL graph coverage keeps its failures in JSON, CSV
companions and text and forces incident-export exit4; it cannot become a complete
empty-incident claim. Data-only snapshot/diff/report exports keep their existing
semantics. DOT continues to preserve complete JSON metadata in its base64 attribute.
