Repository / Agent Readiness
The original backend contract described here is unchanged. The 0.3 release line also provides an opt-in strict OCI subprocess-deny profile with a separate worker protocol; v1 static adapters retain their original guarantees.
Repository readiness means sufficient static evidence under this versioned policy. It is not a runtime guarantee, security certification, AI safety score, probability, LLM judgment, recommendation, or authorization to give an agent access.
The independent contracts are apizr.repository-readiness-policy/v1 and
apizr.repository-readiness/v1. They consume Catalog v1, Graph v1 and embedded
local Readiness v1 without changing any of those contracts. Local Readiness remains
authoritative for interface eligibility.
from apizr.repository_readiness import RepositoryReadinessPolicy, assess_repository
report = assess_repository(catalog, graph, policy=RepositoryReadinessPolicy())
This call performs no filesystem discovery, source parsing, AST analysis, import resolution, readiness rerun, source execution, or Docker availability check. It roundtrips both typed documents and the policy through validation, including nested unchecked model copies, and requires:
graph.catalog_digest == catalog_digest(catalog);graph.repository_digest == catalog.repository_digest;- graph capability metadata, module identities and catalog exit evidence agree with the Catalog.
The report binds the repository, catalog, graph and readiness-policy digests. It
introduces no separate source identity. Digests bind content; they do not authenticate
who supplied it or prove that declared evidence is true. validate_report(report,
catalog, graph) re-evaluates and compares every conclusion and snapshot against
its bound inputs. Parsing a standalone report validates its internal invariants;
use validate_report when the original artifacts are available.
Assessment universe and state
There is one assessment for every embedded per-source Readiness assessment,
including declarations rejected from IR. Its original capability_id is unchanged.
local_readiness retains source/module/symbol/span, in_ir, local state,
can_generate_interface, all dimensions, and the original APIZR-READY-* reasons.
in_catalog explicitly indicates trusted catalog membership. Rejected declarations
have unavailable graph evidence and unknown effect facts; no replacement IDs or
capabilities are invented. Sources without inspections have no declarations to
assess: their Catalog diagnostics remain in the report.
State precedence is ambiguous > unsupported > conditional > ready.
| State | Repository meaning |
|---|---|
ready |
Repository interface-eligible, including narrowly proven local imports; every supplied requirement is satisfied by static evidence and at least one declared mode supports all required controls. |
conditional |
Required evidence is incomplete, or an unresolved local blocker remains. Unknown information is not a hard failure. |
unsupported |
Local Readiness is unsupported, an effect required false is evidenced true, a hard interface requirement is unmet, or no declared mode supports all controls. |
ambiguous |
Upstream Readiness is ambiguous, or relevant Graph identity/import evidence cannot select a stable unique binding. This is never downgraded. |
ready does not mean every dependency executes, all behavior is known, side effects
are absent, or an agent should receive access. There is no numeric aggregate score
or blanket repository readiness state. Counts include all four states. Catalog and
Graph diagnostics/completeness remain separately visible, even for empty reports.
Policy and effect evidence
Default policy, shown as JSON (the CLI accepts JSON):
{
"schema_version": "apizr.repository-readiness-policy/v1",
"effects": {"require_known": [], "require_false": []},
"relationships": {"require_resolved": true},
"execution": {
"modes": ["local-process", "oci-container"],
"require_controls": []
},
"require_interface": false
}
Repository interface eligibility gates ready. require_interface: true
additionally makes remaining ineligibility a hard policy failure. A proven local
import can satisfy that requirement while its retained local report remains
conditional. The default is false to preserve the distinction between incomplete
evidence and proven lack of support. Unknown options, effect/control names and coercible boolean strings are
rejected; set-like policy lists are deduplicated and sorted.
Effects come only from Capability IR embedded in source Inspections. Every effect
retains its value and evidence: filesystem_read, filesystem_write, network,
environment, subprocess, state_mutation, secrets, external_service.
The current source analyzer generally leaves effects unknown. A declaration that
has no IR contributes unknown effects, never false by absence.
| Requirement | Unknown | True | False |
|---|---|---|---|
require_known |
conditional | satisfied as known | satisfied as known |
require_false |
conditional | unsupported | satisfied |
For example, {"require_known": ["network", "filesystem_write"],
"require_false": ["secrets"]} requires three explicit facts. A backend network
control does not turn unknown network effect evidence into false. When both effect
lists name one effect, both requirements apply and one unknown reason is retained.
Graph evidence and exact diagnostic mapping
Each in-Catalog declaration has a resolved, partial, or unavailable
relationship dimension. Graph v1 is the only source of relationships.
- Diagnostics match the declaration's source path. A diagnostic inside its inclusive local Readiness source span affects that declaration. A diagnostic inside another declaration's span does not affect it.
- Diagnostics outside every Readiness declaration span in that module, or without a line, affect all declarations in the module. This conservatively represents module binding/import uncertainty. Graph v1 has no diagnostic scope field; no new lexical analysis is performed.
- A global Graph resource-limit diagnostic (
path == ".") affects all declarations because Graph v1 discards every syntax relationship on aggregate exhaustion. - Missing/unanalysed module evidence, input failure, unavailable analysis, or resource
exhaustion yields
unavailable. Other relevant diagnostics yieldpartial. - Relevant import declarations with
unresolved,starorambiguousnames also make the dimension partial.APIZR-GRAPH-002(unstable/multiple repository import interpretations),APIZR-GRAPH-009(module collision), or an ambiguous import name additionally preserve identity ambiguity as repositoryambiguous. - Dynamic/star imports, rebound imports, unstable calls and unstable callable references therefore remain visible. Resolved external imports are ordinary evidence and do not independently make relationships partial. Their separate local Readiness dependency reasons remain authoritative.
relationships.require_resolved defaults to true. Setting it false removes the
relationship completeness requirement; it does not clear local Readiness or
identity ambiguity. Overall Graph incompleteness from an unrelated module does not
change a declaration's state, but remains visible on the report and CLI exit status.
relationships.direct preserves outgoing capability graph edges, including
calls_capability, references_capability, imports_capability, and any local or
external module imports. module_imports separately preserves module-scope imports
as context; these are not rewritten as capability edges. imports retains relevant
Graph import declarations. dependencies snapshots the IDs, local Readiness and IR
effects of the direct capability targets in those two groups.
A call from A to B does not cause A to inherit B's effects or overall readiness. For a local import refinement, the dependency snapshots also establish its binding and execution evidence; its private input/output eligibility is not propagated. A call from B to C does not add C to A's canonical direct relationships. Graph v1 edges describe possible direct static calls, not execution proofs. There is no transitive effect or state propagation in v1.
Resolved local import refinement
The 0.4.5 selected exposure proof consumes this complete audit; it does not filter or rewrite its assessments, diagnostics or aggregate completeness. It reuses the exact local-import predicate and shared module-initialization facts with validated execution support from the required closure. Source-local Readiness remains conservative. See selected evidence for the separate eligibility decision and unchanged full-repository identity.
Local Readiness remains source-only and retains APIZR-READY-015, its original
conditional state and can_generate_interface: false. Repository Readiness may
nevertheless become ready when every blocking local reason is discharged by
bound evidence. Only execution-dimension APIZR-READY-015 reasons can be discharged.
The shared repository_readiness.eligibility decision matches source path, import
line, source module/capability identity, unconditional declaration, each imported
name, target and exact relationship location. Every name on that import line must
have a unique local module/capability target and its matching import relationship.
Relevant Graph diagnostics or unresolved/star/ambiguous names prevent refinement.
A complete Graph alone is insufficient; external targets never satisfy this rule.
Required private capabilities must have stable IR bindings and ready execution
evidence. Their public input/output eligibility is irrelevant. Imported modules
and present package initializers must have sufficient retained initialization
facts: module-initialization, dynamic-import and dependency reasons remain blockers.
An empty initializer has exact size/digest-bound evidence. Nonempty modules without
callable assessments lack initialization evidence in Readiness v1 and keep the
relationship dimension partial; no source is reparsed to fill the gap. Imports
without a retained capability dependency likewise remain conditional.
The report shape and all v1 schemas are unchanged. Assessment state is derived
from the remaining local reasons plus repository policy reasons; the original
local document is neither copied with altered fields nor rewritten. validate_report
recomputes this conclusion against the bound Catalog/Graph. Affected canonical
reports and downstream digests can change, including for unselected declarations
in the same report. Unaffected reports and source-local evidence stay identical.
This does not resolve decorators, rebinding, namespace uncertainty, dynamic imports,
input types or unrelated execution blockers. No effects or transitive readiness
states are propagated, and no dependency closure is computed. Import is distinct
from call, static resolution from runtime availability, dependency from exposure,
and ready from safe execution.
Execution compatibility: additive v1 completion
Readiness defines its own transport-neutral Control vocabulary; it does not
extend the control enum or alter any execution policy, plan, backend, or generated
bundle contract. The static adapter lives in repository_readiness/execution.py.
It obtains local guarantees from BackendCapabilities without calling the host
availability function. Its explicit OCI additions map to the existing reviewed
network/filesystem controls and Resources.memory_bytes, cpu_millis, and pids.
No runtime behavior or #58 embedded-code hash changes are involved.
Only declared control support is assessed, independently of host OS, environment,
Docker, images or daemon access. Every mode says runtime_availability: not_assessed.
At least one selected mode must support all required controls; support cannot
be assembled from multiple modes. Compatibility is not a recommendation or ranking.
| Readiness control | direct | local-process | OCI-container |
|---|---|---|---|
wall_timeout |
no | yes | yes |
input_limit |
no | yes | yes |
output_limit |
no | yes | yes |
environment (clean/allowlisted) |
no | yes | yes |
working_directory (fresh) |
no | yes | yes |
network_deny |
no | no | yes |
filesystem_sandbox |
no | no | yes |
memory_limit (hard memory limit) |
no | no | yes |
cpu_limit (CPU quota) |
no | no | yes |
pid_limit |
no | no | yes |
subprocess_deny |
no | no | no |
direct represents existing ungoverned invocation, with an empty guarantee set
and backend_version: direct; it does not invent a governed runtime version.
It must be explicitly selected. With no requested controls it is compatible; with
any requested control it is incompatible. The unchanged default modes remain
local-process and oci-container.
Memory, CPU and PID requirements describe support for the existing OCI policy's
configured limits. Readiness does not choose numeric limits or promise a given
allocation. Memory hard limits are distinct from CPU quotas, which constrain CPU
use rather than guaranteeing latency. PID containment does not prohibit creating
subprocesses: subprocess_deny remains unsupported everywhere, in this frozen static adapter.
Byte compatibility with the original v1
Schemas only add enum values. Old policy defaults, accepted names, semantics and
canonical bytes remain unchanged. The original #59 policy/report goldens are
retained unchanged; additional snapshots capture the default policy and its report
at baseline ebe7af7. Tests cover all 768 combinations of the old control/mode
subsets, and revalidate saved reports against their original inputs.
To avoid changing old report bytes merely by expanding an advertised guarantee
list, supported_controls is a vocabulary projection:
- Policies using only original modes and controls retain the original v1 list.
- Explicit selection of
director any resource control enables the completed vocabulary in every selected mode's list.
This affects the breadth of the reported list, not the meaning of any old control. Compatibility always tests all requested controls against one mode's guarantees. New capabilities are visible only when the input explicitly opts into this additive completion; no default digest is silently changed. To inspect the full matrix in a report, explicitly select all three modes. Old documents remain valid, and new resource requirements are never silently ignored.
Container compatibility is conditional on actual deployment of the existing OCI execution policy, including clean environment, network deny, constrained filesystem and configured resource limits. Assessment does not create a plan, select an image, establish availability or promise invocation success. Docker, its daemon, a worker image, and the necessary Linux controls can all be absent while static compatibility is true.
Human output lists each selected mode's compatible/incompatible result, missing
controls and the number of repository-ready declarations whose control requirements
it satisfies. This is evidence context; it does not select a backend. --details
adds supported controls and expands all declarations.
Repository reason codes
Machine semantics use code and optional typed effect; messages are presentation.
Original local reason codes are retained unchanged in local_readiness.
| Code | Meaning |
|---|---|
| APIZR-REPOREADY-001 | Hard interface generation requirement unmet |
| APIZR-REPOREADY-002 | Required Graph evidence unavailable |
| APIZR-REPOREADY-003 | Required relationships partial |
| APIZR-REPOREADY-004 | Required effect unknown (effect names it) |
| APIZR-REPOREADY-005 | Required-false effect evidenced true (effect names it) |
| APIZR-REPOREADY-006 | No declared execution mode satisfies every required control |
| APIZR-REPOREADY-007 | Relevant identity/binding ambiguity |
| APIZR-REPOREADY-008 | Declaration absent from trusted Catalog |
Canonical UTF-8 JSON has sorted object keys, ordered assessments and a final newline.
policy_bytes, policy_digest, report_bytes, report_digest expose independent
content identities. Published schemas are
policy and
report.
Repository-first orchestration
apizr readiness ROOT calls graph_repository(...) exactly once, then passes that
result's Catalog and Graph to the same assess_repository used by the artifact-first
CLI. The existing discovery manifest feeds both layers: source bytes are not reopened
between Catalog, Graph and readiness. The pure assessment API above is unchanged.
--source-root, --exclude-dir and all Scan/Graph bounds share parsing and policy
construction with apizr scan and apizr graph. --policy FILE selects the readiness
policy; --report and --format json emit the same canonical v1 report, with no
wrapper or progress output on stdout. The root path never enters canonical identity.
--details expands human output beyond its default 20 declarations. The existing
apizr repository-readiness CATALOG GRAPH remains fully supported, including its
complete human output and --format json; it also accepts --report.
Instrumentation tests count exactly one discovery and one read per source, mutate source after Catalog assembly to detect reopening, compare independent Scan/Graph artifacts with repo-first bytes, and check ordering/location/hash-seed invariance. An isolated audit-hook test forbids source execution, source writes, subprocesses, network access, Git/package-install commands and Docker/transport imports; hostile top-level statements, decorators and defaults remain inert.
Explicit external import providers (0.4.5)
The ordinary scikit-learn journey in #267 exposed a missing boundary: a Run's
observed distribution version does not identify its import namespace. The
additive dependency_wheels policy evidence records exact distribution pins,
wheel filenames, SHA-256 identities and module names derived from admitted wheel
members. It does not infer scikit-learn → sklearn from names or import packages.
Empty evidence is omitted, preserving existing canonical policy/report bytes.
The two Readiness schemas include the additional optional evidence; experiment
Plan, Run, comparison and exposure schemas are unchanged.
Selected scope consumes only unconditional, location-matched external import
edges whose exact module is provided. Local missing, ambiguous, rebound, star or
dynamic dependencies retain their existing refusals. Provider/module collisions
are refused. A provider-backed selection remains CONDITIONAL, requiring explicit
--allow-conditional; the interface's JSON types must still be supported.
Before rendering, the ordinary repository builder recomputes each provider from its retained wheel bytes and checks the exact policy evidence and application pins. Missing bytes, a changed digest or fabricated module inventory cannot produce a bundle. Wheels are qualification/deployment inputs, not vendored SDKs inside Apizr or generated source bundles. Their identities remain in the bound Readiness report and bundle manifest.
This evidence proves wheel membership and correspondence to selected versions. It does not establish external initialization safety, symbol/API compatibility, native-library behavior or a successful future invocation. A Run's package version alone does not attest the bytes installed during that Run; the #267 qualification additionally installs and replays from the retained wheelhouses. No network lookup, environment import or framework allowlist grants eligibility.