Repository documentation
The framework flow
The operator golden path is adopt, then prove the dev workflow, then cut a
release. You do not need every framework contract to start.
flowchart LR Adopt["litai onboard create / adopt"] --> Status[litai status] Status --> Verify[litai verify] Verify --> LockPlan["lock then plan"] LockPlan --> Rebuild["litai rebuild (dev)"] Rebuild --> ReleaseCut["release plan / prepare / check / publish"]
Staging and production workflow catalogs exist as opt-in nested directories; they are not scaffolded into new projects by default and stay organization- convention-dependent.
The diagram below is the current external-driver rebuild path. litai rebuild
validates project authority and selects the lifecycle binding declared by the project.
A Standard-bound project runs the provider-neutral in-process lifecycle as an exact
per-Component graph. This repository instead declares a content-pinned external driver
that uses the host lifecycle facade for its existing sample build and test work.
flowchart TD
O[Onboard and validate] --> A[Specify behavior]
A --> B[Plan specs + Flavors + skills]
B --> C{BUILD_DIR exact accepted source?}
C -->|no| D[Major rebuild: source + tests + source SBOM]
C -->|yes| E[Materialize untrusted exact candidate]
D --> F[Index, validate, classify, authorize]
E --> F
F --> Q{OBJ_DIR exact build result?}
Q -->|no| G[Resolve dependencies + compile]
Q -->|yes| H
G --> H[Verify resolved SBOM]
H --> I[Run generated checks]
I --> J[Execute + independently verify]
J --> K[Accept exact tree]
K --> L[Driver writes provisional assertion]
L --> V[Outer validates lifecycle membership]
V --> N{Publication configured?}
N -->|yes| P[Validate offer + publish immutable entries]
N -->|no| C[Outer writes finalized candidate envelope]
P --> C
C --> M[Extract raw receipt + commit current receipt]The two implementations should not be mentally collapsed:
flowchart LR
CLI[litai rebuild] --> BIND{Manifest lifecycle binding}
BIND -->|external| OUTER[Trusted outer rebuild protocol]
OUTER --> DRIVER[Content-pinned project driver]
DRIVER --> HOST[Current host lifecycle facade]
HOST --> TOOLS[Sample builders, runners, and verifiers]
BIND -->|standard| STANDARD[Implemented Standard lifecycle core]
PLAN[Exact Component execution plan] --> STANDARD
STANDARD --> NODES[Parallel per-Component source candidates]
NODES --> GRAPH[Declared exports and dependency assembly]
GRAPH --> ADMIT[Project admission and receipt]
STANDARD -. sample adoption pending .-> HOSTThe host facade is a compatibility and integration surface, not the architectural definition of the framework. The Standard core already provides typed per-node generation, invalidation, source-only scheduling, build-intent, authorization, artifact assembly, execution, acceptance, accepted-source cache membership, and project-admission seams. The filesystem composition can now publish a complete accepted-source entry and restore it in a newly assembled runtime. Restored hits remain untrusted: they receive new final-path source-intelligence evidence, authorization, build/test/execution, and acceptance, and are never republished as if newly generated. The ordinary CLI now reaches that composition for Standard-bound projects. Replacing the remaining sample facade and completing link/package and root-integration coverage are explicit integration work. A separate durable Standard checkpoint journal now records each attempt before source exists and each later successful or failed node boundary with append-only lineage and CAS-backed source bytes. Source-generation-internal failures remain in the generation checkpoint journal. After process restart it restores only source custody; current indexing, authorization, build, generated tests, execution, and acceptance always run again. This bounds recovery cost without treating historical authority as current authority.
If a flow diagram, tutorial, or tool presents a different order, it should explain why. This is the repository's golden path. The arrows express required dependencies, not a globally fixed set of implementation stages: a pinned workflow may add or parallelize work where those dependencies still hold.
Target selects intent; worker selects execution
Explicitly retained source (local development)
For an operator-authorized repair of generated source, the local Standard lifecycle can review and qualify that exact tree under its existing Component:
litai rebuild components/example --retained-source path/to/source --retained-source-plan
litai rebuild components/example --retained-source path/to/source \
--authorize-retained-source sha256:REVIEWED_PLAN_ID --allow-host-execution
Use the same project, target and Flavor selectors in both commands. The review
identity binds exact UTF-8 file bytes, the current Component lock, project
authority and target. The source directory is placed under the normal source/
workspace envelope without rewriting its bytes. It must already contain valid,
current test metadata and source SBOM; stale metadata is rejected, not repaired.
No model is invoked, no specifications are inferred, and the input is never
edited. Current dependency, payload, source/resolved SBOM, build, test, execution,
independent acceptance, packaging and cleanup gates remain mandatory.
This path supports one locked Component, without separately materialized binary
assets, on the local target. It rejects links, nonportable paths and oversized
or non-UTF-8 input. Keep interpreter caches outside the reviewed source tree.
Retained provenance is distinct from model generation. Retained runs do not
restore checkpoints or prior source, and their checkpoints cannot become
ordinary generated-source inputs. Accepted cache entries remain bound to the
retained review identity rather than a regenerative source key. A passing run
does not establish regenerative equivalence. --update-receipt still requires
the complete Standard lifecycle to pass; the read-only plan grants no admission.
Retained whole projects (qualification in progress)
For an existing source tree whose hierarchy must remain in place, first author
and validate its canonical project metadata, then commit the source and metadata.
litai project adopt-original --project PATH produces a read-only plan binding
the validated project authority and clean Git commit/tree. Review its identity,
then repeat with --apply --acknowledge --expected-plan-identity sha256:....
Apply writes only original-adoption evidence and conversion-authority metadata;
it does not move source, build, contact a model, or qualify execution. Dirty
trees, stale plans, unsafe roots and existing authority refuse. Preserve failed
evidence for diagnosis rather than overwriting it.
The independent initial original stage keeps release authority with original
source. It has no successor in the legacy wrapped/retained/drafted/qualified
conversion chain. After current locks exist, use explicit retained-project
manifest/profile planning. Regenerative rebuild and unqualified retained
execution remain blocked; this adoption record is not a build or test receipt.
Whole-project retained planning uses a streaming binary-capable manifest and an
explicit command profile, separately from the small UTF-8 source mode above. Its
test-policy input must bind the configured project receipt policy's identity,
every original case and owning test action, any exact permitted skip reason, and
the report path sealed by each test action. Action inventories name the actual
cases; a suite label or successful command exit does not establish coverage.
The same original-source protocol is available on build, test and rebuild.
For example, review the exact locked selection with:
litai build --project path/to/project \
--retained-project manifest.json --retained-project-profile profile.json \
--retained-project-plan
Execution uses the same manifest/profile, the returned
--authorize-retained-project sha256:REVIEWED_PLAN_ID and explicit
--allow-host-execution. test runs the same complete retained lifecycle,
including build, original tests, documentation and independent acceptance.
Both verbs return retained admission/custody evidence, not an ordinary generated
artifact or a litai run export. Package and release qualification remain
separate. --build-dir and --obj-dir select the retained custody/object roots.
Selected secondary-account tests additionally
require an operator-private live allocation inspector. Their private execution
sessions live under the inspected allocation prefix, and admission requires
successful delegated-access cleanup retained with the run.
Target configuration, Flavors, toolchain and command capacity come from the
locked profile; generation/model/source-cache and --jobs overrides are refused
instead of being silently ignored. A partial Component selector cannot narrow a
whole-project retained plan. Planning output says read-only and grants no build
or publication authority.
The sole release-policy input must be the configured literate.release.json,
with the profile binding its exact bytes. Planning reuses the existing release
policy parser and repository-branch checks. An alternative hashed file cannot
replace the project's release gates or grant publication permission.
Retained managed SBOM graphs use the retained-project root kind and
literate-ai:retained-project binding instead of a Component-revision claim. The
root identifies the reviewed plan, including the original manifest and complete
Component-lock inventory. Shared locked dependencies keep their identities and
edge authority. The existing CycloneDX source/resolved transition checks preserve
this distinction. A managed graph describes authority; it does not establish the
observed native SDK/toolchain closure or issue an acceptance receipt.
The read-only retained planning response includes managed_sbom_graph alongside
the plan and authorization identity. It derives that graph from the same verified
persisted Component locks, not supplied graph metadata or unlocked catalog entries.
Current project definitions and lock inputs must remain unchanged. This response
does not authorize execution or attest a resolved runtime dependency closure.
The internal command workspace freezes host-native dependency observations for captured tools and inputs using its sanitized command environment. It rechecks that graph and the command context before and after each process, and binds the observation identity to the command record. Dependency drift refuses even after a zero exit. Returned observation dictionaries cannot mutate the frozen record. This does not qualify SDK products or establish the native closure of built exports.
The internal command workspace reads bounded, identity-checked reports using
literate-ai/retained-project-test-report@1. Each report names its action and
the complete case outcomes (passed, failed, or explicitly permitted skipped).
Missing, extra or duplicate cases, unknown outcomes, failed cases and unauthorized
skips stop later work. Only actual passes satisfy the project's minimum; baseline
exceptions cannot be relabeled as passing tests.
Development profiles can explicitly select runtime_library_paths, an ordered
list of up to 32 captured input directories. Every directory must contain only
SDK, toolchain or dependency members. The command owner projects these paths to
the POSIX loader variable and passes the same context to native dependency
inspection, SDK scopes and acceptance. It never inherits loader variables from
the caller. Missing, redirected, source/output or empty directories refuse;
unsupported hosts refuse the opt-in. Omission preserves legacy identities and
default environments. This selects captured runtime libraries for native tools;
it does not suppress system fallback or establish complete compiler/sysroot
provenance. Native/installed qualification remains open under RETAINED-LOADER-001.
When selected SDKs are present, each SDK command also binds the complete captured
runtime context and preserves SDK-owned placements and the native code/dependency
graph. Reviewed external byte copies may relocate with equivalent native edges;
ambient import/preload injection and SDK shadowing remain refusals. Captured
context records do not establish compiler SDK or product release admission.
Development profiles can also select output_command_paths: up to 32 ordered
output-relative directories at or below declared build products. These precede
captured tool directories so original tests can find the newly built programs.
Missing future directories are permitted before their producer runs; existing
redirected or non-directory ancestors refuse. Export custody still guards the
produced bytes. The profile and environment bind the selection, and caller PATH
is never inherited. Omission preserves the captured-tools-only default and legacy
profile identities. This prepares original-suite execution; it grants no public
execution or acceptance on its own.
Development retained independent acceptance can opt in to a filesystem case.
It binds private input bytes, expected file lengths and SHA-256 values, optional
permission checks, directory/absence expectations and explicit resource limits.
The sealed product runs in a fresh case directory; {case_root} is substituted
only for opted-in cases. Fixtures are rechecked after SDK authorization and before
launch. Actual bounded file states are observed without following links and kept
with the process evidence. Wrong contents or size fail even after a zero exit;
extra output, unsafe nodes, changed fixtures and resource overruns also refuse.
The ordinary run and private case environments retain separate native dependency
bindings, so private HOME/temporary paths do not weaken final source/export checks.
Legacy cases keep their wire identities. Native/installed filesystem qualification
remains open under RETAINED-FS-001; this is cooperative custody, not a hostile-code
filesystem sandbox or permission to execute with greater privileges.
The development local route joins the existing command workspace, complete
original-test coverage, independent acceptance, both BOMs and live retained
receipt admission. It requires the exact reviewed plan authorization plus
--allow-host-execution and reopens current manifest/profile/project/worker
authority throughout execution. Planning stays read-only. Explicit worker health
policy uses the existing preflight and active-job polling owner.
Local execution keeps its run under OBJ_DIR/retained-project-runs and immutable
receipt/payload custody under BUILD_DIR/retained-project-cas. The run's separate
command-diagnostics.json index points to actual stdout/stderr and command
observations, including failed commands; that diagnostic index grants no admission.
Fresh local worker observations enforce authored capacity requirements and the
selected OS/architecture Flavors across all current Component locks. The local
probe follows the actual host OS; architecture aliases use the shared host
normalizer. OS family, OS version or architecture drift refuses continued execution.
The current-plan guards recheck that context, and live admission retains the
plan-bound initial/final observations in receipt records. Those records are data;
decoding them grants no execution or admission. Existing receipt wire identities
are preserved for callers that omit this optional context.
The returned retained receipt preserves original authority and cannot replace an
ordinary generated receipt. Package construction and publication remain separate.
Remote workers and selected SDK inputs without their required live producer bindings refuse; this entry never falls back to local execution or ambient SDK discovery. Full canonical-project/installed CLI, native and package/release qualification remain open under RETAINED-PROJECT-001. The development handler checks use the real execution/admission owners but fixture project discovery, so they do not qualify those remaining boundaries.
Target and worker selection
litai build, litai test, and litai run keep two independent choices explicit.
--target NAME resolves the target profile and selected Flavors used to derive source.
--worker ID resolves the private execution endpoint used for lifecycle work. Omitting
--worker selects the exact implicit local worker.
flowchart LR
T[--target profile] --> P[Exact generation plan]
F[Selected Flavors] --> P
P --> R[Typed execution request]
W[--worker catalog entry] --> R
Q[Declared worker parameters] --> R
R --> L[Local lifecycle]
R --> C[Synchronous command dispatcher]
L --> X[Content-bound artifact export]
C --> X
X --> B[Build, test, or run result]Local, synchronous command, and bounded SSH workers implement this single-component
lifecycle. SSH transfers one request-bound source archive into an attempt-scoped
workspace, verifies its accepted manifest and transport bytes, runs the installed
Standard receiver, and retains accepted artifacts in the worker CAS. Before any attempt
cleanup, the receiver emits a digest-bound manifest and deterministic bundle containing
the available source, object, artifact, receipt, lifecycle-result, and redacted failure
evidence. The coordinator downloads that bundle, verifies its outer digest, embedded
manifest, complete path set, per-file sizes/digests/executable intent, and then imports
the bytes into its own content-addressed evidence root. Only that imported custody can
form the per-cell receipt; a worker-local path cannot. The coordinator then acknowledges
the exact manifest and bundle identities, after which bounded idempotent worker cleanup
may run. Transfer or acknowledgement failure leaves the lifecycle failed closed and the
attempt available for retry. Archive
executable intent remains part of the accepted manifest even on Windows, where the
filesystem cannot reproduce POSIX mode bits; content and path drift still fail closed,
while POSIX materialization reapplies only canonical 0644 or 0755 modes.
A worker that lacks the project's exact Standard distribution is not authorized to use an ambient installation or package index. The coordinator first exports a target-specific binary dependency closure:
litai worker wheelhouse export \
--framework-wheel dist/literate_ai-0.3.0-py3-none-any.whl \
--distribution-identity sha256:<project-pinned-installed-payload> \
--platform manylinux_2_17_x86_64 \
--python-version 3.12 --implementation cp --abi cp312 \
--output _build/worker-wheelhouse-linux
After staging the complete output directory, invoke:
litai worker bootstrap \
--wheelhouse worker-wheelhouse-linux \
--manifest worker-wheelhouse-linux/worker-wheelhouse.json \
--closure-identity sha256:<exported-canonical-manifest> \
--distribution-identity sha256:<project-pinned-installed-payload> \
--install-root "$HOME/.local/share/literate-ai/venv" \
--replace-existing
Use --platform win_amd64 for the corresponding Windows export. The SSH receiver
discovers the conventional isolated root on POSIX and its Scripts/litai.cmd
equivalent on Windows. The manifest identity binds target selectors and every wheel's
filename, distribution name/version, size, SHA-256, and declared requirements. The
project pin continues to bind only Literate AI's logical installed payload.
Worker bootstrap does not pin a companion indexer when
a worker will run opted-in source-intelligence commands; it is not part of the
required bootstrap.
Bootstrap verifies the canonical manifest and every wheel before creating a movable
no-index installation, invokes pip only with the verified wheelhouse, verifies every
installed RECORD, and records both identities before atomic activation. Existing
mismatched environments fail closed unless the operator explicitly supplies
--replace-existing; replacement keeps the old directory until the verified new
environment is ready and rolls back if activation fails. A coordinator may upload the
stdlib-only
literate_ai.remote_worker_bootstrap module when the compatible verb is not installed;
this is a fixed capability, not arbitrary remote shell. Worker secrets
enter only through declared environment bindings. The request, worker identity,
non-secret parameters, artifact export, and lifecycle result are content-bound evidence.
There are only two authoring directions to remember. The forward path is the normal product lifecycle. The inverse path is an onboarding tool for an existing codebase. It can produce a complete, reviewable specification project today, but release authority stays with the original source until a future lifecycle-backed verifier proves the replacement:
flowchart LR
S[Specs + Flavors + skills] -->|litai rebuild| A[Runnable, tested application]
O[Existing source] -->|litai spec derive| D[Reviewable specs + Flavor drafts]
D --> H[Human acceptance]
H --> P[component.md + exact target lock; no source]
P -->|litai spec qualify today| Q[Historical clean runs + parity measurements]
Q --> R[Source baseline remains release authority]
P -.->|trusted v2 lifecycle adapter| V[Verified-current decision]
V -.->|only after verification| Slitai spec derive --translator coding-cli --allow-model-egress is the semantic inverse
path. It inventories an inert classified mirror, invokes one exact
language-conversion skill and coding-agent call per detected language, and preserves a
complete versioned call journal. It never executes the analyzed source. The separate
qualification verifier may execute the exact baseline only after forward generation and
only with explicit host authorization. See
source to specification for the promotion workflow.
Current qualification writers use v2 wire schemas, but their evaluator is deliberately
the historical v1 measurement model: every result carries
qualification-v2-required. Current qualification records persist separate
claimed_authority and effective_authority fields: a historical producer claim may
say specification, but effective authority is schema-constrained to source-baseline.
The local measurement path never creates that projection. A trusted lifecycle adapter
must supply complete typed evidence bound to the exact current Component lock; only the
locked admission service can append the distinct verified-current Component authority
projection and transfer authority.
litai rebuild is the public full-lifecycle front door. It delegates the project-specific
work to a manifest-declared lifecycle driver whose sorted implementation files, aggregate
content identity, argument template, allowed environment, timeout, and ordered phases are
project authority. The CLI verifies the driver and project before and after execution,
then validates the provisional assertion, current lifecycle membership, and any outer
publication before it exposes a finalized candidate envelope. Individual plan,
generate, project, and source-to-specification commands remain useful phase-specific
surfaces. See the
constraint classification decision
for the line between invariant behavior, current policy, and delivery goals.
What an application author does
An author has five jobs:
- Start at the project root
SKILL.md, keep the linked documentation graph reviewed, and keeplitai project validategreen. Validation is non-mutating and does not require a source-graph indexer. fail-closed only when a project has opted into that provider.litai build,litai run, andlitai rebuilddo not fail closed on a missing or stale optional index. - Describe observable behavior and known acceptance examples in OpenSpec.
- Declare the Component's logical entrypoint and variation slots.
- Choose concrete Flavors, such as macOS + C++, Linux + Python, standalone Rust, or Rust backend + JavaScript frontend. The Component and those Flavors select their exact specification-to-source skills.
- Inspect the resolved plan, run the full rebuild, and inspect the built result and provenance. After a complete passing test run, replace and commit the one current project receipt; a failure or skipped test leaves the prior receipt untouched.
The Component remains a description of the application. It does not need to embed model commands, compiler flags, cache algorithms, security decisions, or publication logic.
For a project whose lifecycle driver accepts one Component, the practical commands are:
litai project source-intelligence sync
litai project validate
litai lock path/to/component --target linux-host --flavor=+flavor://literate-ai/lang-cpp --flavor=+flavor://literate-ai/os-linux
litai plan path/to/component --target linux-host --flavor=+flavor://literate-ai/lang-cpp --flavor=+flavor://literate-ai/os-linux
litai rebuild path/to/component \
--project . \
--runtime-root /tmp/generated-app \
--candidate-receipt /tmp/generated-app-receipt.json \
--flavor=+flavor://literate-ai/lang-cpp \
--flavor=+flavor://literate-ai/os-linux \
--allow-host-execution
litai project test-receipt update /tmp/generated-app-receipt.json --project .
Use . instead of a Component when the pinned driver has project scope, as this
repository does. litai rebuild compiles and executes generated host code, so it fails
without the explicit acknowledgement. It writes but never commits the external
finalized candidate envelope. The separate update command validates that envelope
and performs the policy-gated raw-receipt replacement;
the user or CI decides whether to commit it.
Fresh generation is a clean major-rebuild: a new empty output receives the complete
implementation, source/tests/manifest.json, and
source/.literate/sbom.cdx.json. After full acceptance it may enter the derived
BUILD_DIR cache, never an authority catalog. Exact OBJ_DIR artifacts may bypass
compilation while all tests and execution still run. litai generate exposes only that source-generation phase. For this repository's complete
compile-and-run matrix, use litai rebuild . or the make samples convenience target.
What the framework does
| Stage | Plain-language question | Durable result |
|---|---|---|
| Onboard | Which project contract and authority boundaries apply? | Validated project root, provider-neutral agent skill, and reviewed documentation graph |
| Specify | What must the application do? | Content-identified behavior and acceptance contract |
| Plan | Which Flavors, skills, workflow, routing policy, model mappings, and lifecycle will apply? | Verified, inspectable generation preflight |
| Resolve source cache | Is there an exact reusable result for this request? | Zero or one structurally verified candidate; still acceptance-untrusted |
| Generate or materialize | What complete source tree implements that recipe now? | Coding-CLI implementation or immutable cache tree, plus current tests and the pre-build SBOM |
| Derive source intelligence | What symbols and relationships does the configured provider infer for this exact generated tree? | Detached source-tree-bound evidence when a provider is selected |
| Validate source and authorize | Is this exact tree internally valid, is every manifest/lock/import represented by its source SBOM, and is it allowed to build? | Dependency admission, findings, classification, and expiring build authorization |
| Compile | Does the selected host toolchain produce the requested artifact? | Bytecode, native executable, checked script bundle, or composite artifact with build provenance |
| Verify dependencies | What exact direct and transitive binary closure did the build resolve? | Strict CycloneDX 1.7 post-build SBOM bound to the managed Component graph |
| Test generated | Does every admitted generated case pass against that exact artifact? | Suite-, source-, and artifact-bound case results; failure prevents workspace preparation and commit |
| Verify independently | Does the candidate artifact satisfy the verifier-only known result contract? | Pinned-oracle and post-build entropy results with typed observation requests and execution authorizations |
| Accept | Which generated tree became the workspace truth? | Atomically committed, content-identified source tree |
| Record | Which exact all-passing result is current for this complete project authority revision? | One canonical replaceable receipt; Git retains earlier committed versions |
| Publish | Should an immutable result leave the local cache? | Exact policy-authorized publication manifest and destination record |
| Import | Is this published result currently trusted for this local destination? | Exact local import policy decision, authorization, and receipt |
At the new per-node boundary, “generate” has a deliberately narrower meaning. A
successful node returns one immutable GeneratedSourceCandidate, its
SourceGenerationProvenance, and an explicit runtime observation. It has not indexed,
classified, authorized, built, tested, executed, accepted, admitted, or published that
candidate. The scheduler may run independent nodes concurrently, but retains the full
output for each successful node so later stages do not reconstruct evidence from
summaries.
After all nodes terminate, the Standard core creates one canonical membership table. Its Component set must equal the execution-plan set, its cache-decision set, and its lifecycle-result set exactly. Successful admission produces a typed aggregate receipt over that same membership identity and ordered result identities. A failed run retains the complete table for diagnosis but cannot receive admission or a receipt.
A failure stops at its stage. The one repository-specific exception is the sample
driver's bounded replacement pilot. It admits exactly four categories: a static Bzlmod
source rejection with an exact terminal validate event, matching
DependencyObservationError, generated tree/source-bundle/suite identities, one code
from the closed finite allowlist, and no admitted lifecycle result; an exact terminal
test-generated behavior mismatch with complete run/build/suite/result bindings; an
application/backend host_execution.nonzero_exit occurring only during a
generated implementation case, with a nonzero integer return code and exact stdout and
stderr digests; or an exact terminal C++ generated-source rejection after validation,
classification, and authorization. The latter must have exact generated
tree/source-bundle/suite identities,
no build output or downstream step, and an event-matching
builder.cpp_generated_source_rejected BuildError. The C++ builder emits that code only
when the candidate compile/link fails but a second compile-and-link canary succeeds with
the same pinned toolchain. A failed canary remains terminal
builder.cpp_compile_failed. Python, Rust, JavaScript, generic native, Bazel
build/resolve/analyze, toolchain, authorization, other dependency, malformed-suite, and
independent-verifier failures remain fail-stop. So do execution timeouts, launch or
authorization failures, invalid output, and missing or malformed process evidence. An
unknown Bzlmod code, resolver or evidence failure, toolchain/framework failure, or any
failure after a lifecycle result is admitted also remains terminal. An
admitted failure discards the whole candidate and repeats the same recipe in a fresh
empty root, for no more than three total attempts. No prior source, generated
expectation, or verifier-only fact is feedback to the next coding-CLI call. A repair
receives only the prior attempt's sanitized typed rejection record, never its source tree
or private acceptance values. The framework does not quietly select another
Flavor, source revision, or privilege level. A pinned routing policy may permit model
fallback, but the chosen route and fallback decision are recorded. Test receipt
candidates are stricter still: the contract permits only a non-empty run with every test
passed and none failed or skipped.
Three test artifacts, three jobs
The word “test” crosses three trust boundaries. Keeping them separate prevents a model from grading its own work and prevents a tracked test tree from becoming stale source authority.
flowchart LR
subgraph Authority[Tracked authority]
S[Current specs]
F[Selected Flavors]
K[Exact skills]
end
subgraph Rebuild[Disposable major rebuild]
I[Generated implementation]
T[source/tests/manifest.json]
end
subgraph Verifier[Independent verification]
O[Hidden verifier oracle]
B[Bounded exact build]
G[Generated-case result]
R[Independent run result]
end
subgraph History[Tracked projection]
C[verification/current.json]
H[Git history]
end
S --> I
F --> I
K --> I
S --> T
F --> T
K --> T
I --> V{Static source validation passes?}
V -->|yes| B
V -->|closed static Bzlmod rejection and budget remains| N
V -->|other rejection| X
B --> D{Build completes?}
D -->|yes| G
D -->|canary-proven C++ source rejection| N
D -->|other build failure| X
T --> A[Generated-suite admission]
A --> G
G --> Q{Generated cases pass?}
Q -->|yes| R
Q -->|exact behavior mismatch or typed application/backend nonzero; budget remains| N[Fresh complete candidate attempt]
N --> I
N --> T
Q -->|other failure or exhausted| X
O -. never enters generation .-> R
R -->|all pass; no skips| P[Promote exact workspace tree]
P --> C
R -->|failure or skip| X[Reject candidate]
C -->|ordinary commit| HThe generated suite is a current-state check derived during the same rebuild as the implementation. It must cite current non-acceptance specification documents, cover example, boundary, and invariant cases, and use arguments distinct from the visible acceptance interface. It is useful implementation evidence, but it is neither durable project source nor the verifier's acceptance oracle.
An eventually passing sample execution records its total attempt count and an ordered
list of versioned rejection records. Build and generated-test mismatch rejections carry
a bounded, redacted diagnostic_excerpt; no other rejection carries raw diagnostic
text. All four kinds bind the failed run and generation-stage output. A validation
rejection adds its allowlisted code plus candidate-tree, source-bundle, and
generated-suite identities and proves that no lifecycle step was admitted. A behavior
mismatch additionally
binds its source bundle, artifact, generated suite, case, and expected/observed result
identities. An application nonzero record binds the same built subject plus its case,
expected-result identity, application/backend role, host_execution.nonzero_exit,
nonzero return code, and stdout/stderr digests. A build rejection instead binds its
candidate-specific BuildError code, generated tree, source bundle, and generated suite
and proves that no build result existed. Today
that code is only builder.cpp_generated_source_rejected, backed by the successful
same-toolchain canary.
Exhaustion writes the compact
literate-ai/generated-candidate-attempts@1 envelope, including all three rejection
records and its own content identity, under the external attempt root before returning a
typed failure. Rejected candidates are never admitted to workspace or source cache. The
compact Git receipt retains the final report identity rather than rejected source or
diagnostic text.
The verifier-only oracle remains outside the generation closure. For a
portable-application, verification/acceptance/<component>.json keeps the existing
literate-ai/component-acceptance-oracle@1 exact JSON argument/result cases. A
persistent-service uses the distinct
literate-ai/persistent-service-acceptance@1 document at the same verifier-owned path:
{
"schema": "literate-ai/persistent-service-acceptance@1",
"specification_set_identity": "sha256:<locked-specification-set>",
"process": {
"arguments": ["--host", "127.0.0.1", "--port", "{port}"],
"environment": {"SERVICE_BASE_URL": "{base_url}"},
"startup_timeout_seconds": 30,
"timeout_seconds": 120,
"shutdown_timeout_seconds": 5,
"stdout_limit_bytes": 1048576,
"stderr_limit_bytes": 1048576
},
"readiness": {
"path": "/healthz",
"expected_status": 200,
"expected_text_contains": ["ready"],
"timeout_seconds": 2,
"response_limit_bytes": 4096
},
"requests": [
{"path": "/v1/status", "expected_json": {"state": "ready"}},
{
"path": "/v1/events",
"expected_headers": {"Content-Type": "text/event-stream"},
"expected_sse_events": [{"event": "state", "data": "connected"}]
}
]
}
A kind: library uses literate-ai/library-acceptance-oracle@1 at that path.
The document binds the exact specification-set, public-interface, and import-surface
identities plus a sibling verifier harness by SHA-256. Its canonical cases name a
provided capability, arguments, and the exact expected result. The harness runs outside
generated-source custody against the sealed directory package and must emit one
literate-ai/library-acceptance-results@1 observation per declared case. Python and
JavaScript load the exact packaged modules with ambient package paths removed; Rust
compiles the harness as a separate offline Cargo consumer using the sealed package as a
path dependency. A stale binding, undeclared capability, missing or extra case, changed
harness, escaped import, result mismatch, or package mutation fails closed.
The verifier substitutes only {port} and {base_url}, starts the packaged executable
with its locked execution command, retries readiness until the startup deadline, then
performs the requests in order. Requests support GET, POST, PUT, PATCH, DELETE,
and HEAD, optional string headers/body, exact status and JSON, exact response headers,
contained text, and an expected SSE event prefix (event, data, id, and retry).
Every request, response, process, startup, shutdown, stdout, and stderr bound is validated
against framework maxima. The child receives a loopback URL but this is process limiting,
not network sandboxing. The verifier sends graceful termination and forcibly terminates
the process tree after the shutdown deadline, then rechecks immutable package custody.
This supports one HTTP process that may internally coordinate workers; it does not yet
orchestrate multiple separately packaged processes, WebSockets, arbitrary streaming
protocols, TLS, or remote endpoints.
A project test runner produces a bounded provisional assertion whose raw receipt binds the complete
authority-review identity,
tested subject, compact versioned suite reference, positive all-passing test count,
normalized result, and an evidence-kind-to-identity map. The project policy independently
pins the admitted suite ID/version, exact runner identity, required evidence kinds, and
minimum count. A full rebuild policy also requires source-sbom, resolved-sbom, and
source-cache-lifecycle evidence. The last role deterministically joins every
derivation key to current build/test/acceptance/workspace/index/SBOM evidence. The outer
CLI exposes the distinct finalized envelope only after lifecycle and publication
validation. litai project test-receipt update accepts only that envelope and atomically
replaces the configured current raw receipt. The command does
not authenticate external evidence or commit Git: this remains a local Git assertion,
not remote attestation. The user or CI commits the replacement so ordinary Git history
carries prior passing states without an append-only log in the project.
The release-only project test-receipt require-current gate fails when policy is
unconfigured or the committed receipt is missing, stale, or mismatched; general project
validation still permits that onboarding state.
The phase-specific litai generate CLI stops at the source-generation boundary and
does not choose a project's build/test adapter or claim full lifecycle acceptance.
litai rebuild invokes the exact
content-pinned project driver instead. This repository's sample host driver
executes every generated case against the exact built artifact before preparing or
committing the tree, then runs the separate hidden-oracle and post-build cases as a
second pre-promotion gate. Only both passing results permit workspace preparation and
commit. A fully passing run can
emit the compact candidate with --test-receipt; generated expectations never become
the verifier's answer key.
Where skills fit
The five generation inputs have deliberately small, non-overlapping jobs:
| Input | It decides | It cannot decide |
|---|---|---|
| Base specification | Observable application behavior | Language technique or model |
| Selected Flavors | Target-specific requirements | Weakened base behavior or policy |
| Pinned skills | How to plan and implement those requirements | New behavior, target, model, or privilege |
| Workflow | Which stages run and in what dependency order | Their provider/model endpoint |
| Routing policy | Which eligible model handles each model stage | Behavior or lifecycle authorization |
Flavor and skill resolution is easiest to read as a merge of exact authorities:
flowchart LR
C[Component] --> B[Behavior specs]
C --> K[Base skill pins]
T[Target profile] --> F[Selected Flavors]
F --> FS[Flavor specs]
F --> LK[Language skill pins]
B --> R[Exact resolver]
K --> R
FS --> R
LK --> R
W[Workflow] --> R
M[Routing policy] --> R
R --> G[Generation recipe]The resolver verifies every content digest and skill dependency before producing the recipe. A target selects Flavor requirements; it does not grant privileges or rewrite the Component's behavior.
The project-level SKILL.md onboards agents but never enters a generation recipe. The
Component content-pins its general planning and implementation manifests in
authoring_inputs. A selected language Flavor can pin an additional language-specific
manifest. Resolution keeps Component skills first, then selected Flavor skills,
verifies exact dependency identities and order, and puts every skill hash into the
generation recipe.
Those same hashes appear in readiness evidence, the coding-CLI request, and the result
report. Skill content drift therefore fails before the coding CLI starts.
The framework does not discover ambient skills from the selected coding CLI. It sends only the exact resolved manifests and their instructions. A skill is guidance inside the recipe, not permission to override specifications, Flavors, workflow, routing, validation, security, or host-execution policy.
How to determine the flow from the implementation
Use state transitions, not the amount of frontmatter in component.md:
- The Component and selected Flavors resolve exact skill pins into the recipe; missing, changed, duplicated, or misordered skills fail before generation.
- The Component pins a workflow and routing policy. Their exact bytes compile into the model stages and guarded lifecycle order. The concrete route is selected only after generation chooses a coding CLI, then recorded in generation provenance.
literate.project.jsonpins the complete lifecycle driver. The driver must declare the minimum ordered phases from compose/cache/generate through independent acceptance and candidate-receipt production. Optional package, source-cache publication, artifact publication, and deployment phases are explicit extensions.- Concrete lifecycle adapters define the side effects at validation, authorization, build, workspace acceptance, and event-storage boundaries.
- The generation orchestrator interprets that plan and records each transition; it does not replace the pinned policies with hard-coded routing or stage definitions.
- The sample host runner adds executable acceptance: it validates the exact execution grant at its process boundary, starts the built result after explicit user acknowledgement, then compares its JSON output with verifier results independently derived from the specification. One invocation is created from fresh entropy only after the artifact exists, so checked-in examples cannot be the whole implementation.
- A project test adapter may construct only a passing provisional assertion. The outer CLI validates exact lifecycle membership and configured side effects, then crosses the supported API/TCB boundary by writing the finalized envelope. The receipt CLI accepts only that envelope, validates its raw project-authority/result bindings, and performs an atomic raw-receipt replacement, but creates no Git commit.
- Publication is a separate explicit operation; it is not an automatic side effect of a successful build.
The durable identities form a short provenance chain rather than an unstructured log:
flowchart LR
A[Specs + Flavors + exact skills] --> S[Source + tests + pre-build SBOM]
S --> C[(Reserved local index sidecar)]
S --> I[Source-tree identity]
C --> X[source-intelligence evidence]
C -. database bytes excluded .-> I
I --> V[Authorize + build]
X --> V
V --> R[Post-build SBOM]
R --> Q[Generated + independent tests]
Q --> T[Current passing test receipt]
T -->|binds source, index, and SBOM evidence| H[Git history]
T --> U[Optional publication receipt]Each arrow means the next record binds the relevant earlier identity. Operational paths and timestamps may also be recorded, but they do not replace the semantic content chain.
This distinction keeps the diagram stable even when implementations change. A product may add approval UI, remote caches, or package formats without changing the author's basic story.
After locking, each selected language and platform Flavor contributes one small,
machine-validated Standard command profile; a selected build-system Flavor may contribute
one more. These profiles describe entrypoints and artifact shape without embedding host
paths. The Standard projector resolves their declared tools on the current host and
creates exact shell-free build, generated-test, and smoke-execution commands. Generated
runnable artifacts expose --litai-test for current generated cases and --litai-smoke
for one real application invocation. Bazel projects additionally expose the portable
lifecycle target //:litai_artifact.
Read deeper only when you need to
- To author an app, continue with core concepts, the project layout, Flavors, and samples.
- To add conversion guidance, read skill architecture.
- To select coding agents and models, read model groups and generation.
- To integrate lifecycle ports, read the neutral domain model.
- To integrate environment preparation or dependency evidence, read the CycloneDX SBOM and dependency graph.
- To change trust or execution policy, read source trust and build security.
- To decide whether a rule is an invariant, a current default, or a future gate, read constraint classification.
Those documents explain mechanisms. This page remains the high-level product flow.