diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index d70b9f2..5aa5a14 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -32,7 +32,7 @@ jobs:
python3 -m unittest discover -s scripts/tests -p 'test_*.py'
lean-proof:
- name: Lean assurance laws
+ name: Lean assurance and SDLC design laws
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
@@ -63,9 +63,18 @@ jobs:
echo "ELAN_HOME=$ELAN_HOME" >> "$GITHUB_ENV"
echo "$ELAN_HOME/bin" >> "$GITHUB_PATH"
- - name: Build assurance proof library
+ - name: Build assurance and SDLC proof libraries
working-directory: proof/lean
- run: lake build LambdaAitiaModuleAssuranceProof
+ run: lake build LambdaAitiaModuleAssuranceProof LambdaAitiaModuleSdlcProof
+
+ - name: Reject sorry axioms in exported laws
+ working-directory: proof/lean
+ shell: bash
+ run: |
+ set -euo pipefail
+ output="$(lake env lean AxiomAudit.lean)"
+ printf '%s\n' "$output"
+ ! grep -q 'sorryAx' <<< "$output"
- name: Save Lean cache
if: steps.lean-cache.outputs.cache-hit != 'true'
@@ -76,27 +85,59 @@ jobs:
proof/lean/.lake
key: lambda-aitia-lean-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('proof/lean/lean-toolchain', 'proof/lean/lakefile.lean', 'proof/lean/lake-manifest.json') }}
+ quint-model:
+ name: Quint lifecycle, retirement and ingress contracts
+ runs-on: ubuntu-latest
+ timeout-minutes: 20
+ steps:
+ - name: Checkout Lambda Aitia
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
+
+ - name: Set up Node for pinned Quint
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
+ with:
+ node-version: '22'
+
+ - name: Set up Java for Quint TLC backend
+ uses: actions/setup-java@d7793b545071e98d581d3bf084a51c3213318a07 # v4.9.0
+ with:
+ distribution: temurin
+ java-version: '21'
+
+ - name: Install locked Quint and check all 25 model contracts
+ env:
+ AITIA_QUINT_BIN: ${{ github.workspace }}/proof/quint/node_modules/.bin/quint
+ QUINT_HOME: ${{ runner.temp }}/lambda-aitia-quint
+ run: |
+ npm ci --prefix proof/quint
+ mkdir -p "$QUINT_HOME"
+ python3 proof/quint/check_contract.py
+
scheme-runtime:
name: Scheme, integration and Python runtime
runs-on: ubuntu-latest
timeout-minutes: 90
env:
GERBIL_BUILD_CORES: 12
- GERBIL_PATH: ${{ github.workspace }}/poo-flow/.gerbil
- GERBIL_LOADPATH: ${{ github.workspace }}/poo-flow/packages/lambda-aitia:${{ github.workspace }}/poo-flow:${{ github.workspace }}/poo-flow/.gerbil/lib
+ GERBIL_PATH: ${{ github.workspace }}/agentic-ai-lab/.gerbil
+ GERBIL_LOADPATH: ${{ github.workspace }}/agentic-ai-lab/packages/lambda-aitia:${{ github.workspace }}/agentic-ai-lab:${{ github.workspace }}/agentic-ai-lab/.gerbil/lib
steps:
- - name: Checkout pinned POO Flow mechanism library
+ - name: Checkout pinned Agentic AI Lab mechanism library
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
- repository: tao3k/poo-flow
- ref: da492eea00a7dab502cfb4c7586edefbba96bbec
- path: poo-flow
+ repository: tao3k/agentic-ai-lab
+ ref: f721d112f1d27569e404d979607007f4a6de6552
+ path: agentic-ai-lab
submodules: false
- name: Checkout Lambda Aitia under packages
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
- path: poo-flow/packages/lambda-aitia
+ path: agentic-ai-lab/packages/lambda-aitia
+
+ - name: Initialize pinned Core source directory
+ working-directory: agentic-ai-lab
+ run: git submodule update --init core
- name: Install Just
uses: extractions/setup-just@f8a3cce218d9f83db3a2ecd90e41ac3de6cdfd9b # v3
@@ -114,40 +155,73 @@ jobs:
repository-cache: true
- name: Resolve immutable Gerbil release and module graph
- working-directory: poo-flow
+ working-directory: agentic-ai-lab
run: bazelisk mod deps --lockfile_mode=error
- name: Restore pinned Gerbil package cache
id: gerbil-package-cache
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
- path: poo-flow/.gerbil
- key: lambda-aitia-gerbil-pkgs-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('poo-flow/gerbil.pkg', 'poo-flow/MODULE.bazel', 'poo-flow/MODULE.bazel.lock', 'poo-flow/gerbil-bazel.MODULE.bazel', 'poo-flow/gerbil-dependencies.MODULE.bazel') }}
+ path: agentic-ai-lab/.gerbil
+ key: lambda-aitia-gerbil-pkgs-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('agentic-ai-lab/gerbil.pkg', 'agentic-ai-lab/MODULE.bazel', 'agentic-ai-lab/MODULE.bazel.lock', 'agentic-ai-lab/gerbil-bazel.MODULE.bazel', 'agentic-ai-lab/gerbil-dependencies.MODULE.bazel') }}
+
+ - name: Materialize pinned native dependency commits
+ working-directory: agentic-ai-lab
+ run: python3 packages/automation/gerbil_dependency_pin.py prepare-native --package-root "$PWD/.gerbil/pkg"
- name: Install declared Gerbil package dependencies
if: steps.gerbil-package-cache.outputs.cache-hit != 'true'
- working-directory: poo-flow
+ working-directory: agentic-ai-lab
run: bazelisk run @local_gerbil//:install_dependencies
- name: Save pinned Gerbil package cache
if: steps.gerbil-package-cache.outputs.cache-hit != 'true' && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository)
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
- path: poo-flow/.gerbil
- key: lambda-aitia-gerbil-pkgs-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('poo-flow/gerbil.pkg', 'poo-flow/MODULE.bazel', 'poo-flow/MODULE.bazel.lock', 'poo-flow/gerbil-bazel.MODULE.bazel', 'poo-flow/gerbil-dependencies.MODULE.bazel') }}
+ path: agentic-ai-lab/.gerbil
+ key: lambda-aitia-gerbil-pkgs-v1-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('agentic-ai-lab/gerbil.pkg', 'agentic-ai-lab/MODULE.bazel', 'agentic-ai-lab/MODULE.bazel.lock', 'agentic-ai-lab/gerbil-bazel.MODULE.bazel', 'agentic-ai-lab/gerbil-dependencies.MODULE.bazel') }}
- - name: Build POO Flow mechanism library
- working-directory: poo-flow
+ - name: Build Agentic AI Lab mechanism library
+ working-directory: agentic-ai-lab
run: bazelisk run @local_gerbil//:native_scheme_env -- bash -lc 'cd "$BUILD_WORKSPACE_DIRECTORY" && just build'
- name: Run Scheme semantic closure
- working-directory: poo-flow
+ working-directory: agentic-ai-lab
run: bazelisk run @local_gerbil//:native_scheme_env -- bash -lc 'cd "$BUILD_WORKSPACE_DIRECTORY/packages/lambda-aitia" && just check-semantic'
+ - name: Bind Quint and Lean sources to the retirement POO contract
+ working-directory: agentic-ai-lab
+ run: bazelisk run @local_gerbil//:native_scheme_env -- bash -lc 'cd "$BUILD_WORKSPACE_DIRECTORY/packages/lambda-aitia" && just test-scheme-atomic formal retirement-binding-test.ss'
+
+ - name: Execute retirement ingress controls against Scheme Host
+ working-directory: agentic-ai-lab
+ run: bazelisk run @local_gerbil//:native_scheme_env -- bash -lc 'cd "$BUILD_WORKSPACE_DIRECTORY/packages/lambda-aitia" && just test-scheme-atomic formal retirement-execution-test.ss'
+
+ - name: Set up Node for pinned Quint correspondence traces
+ uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
+ with:
+ node-version: '22'
+
+ - name: Replay Quint states and unsafe-model controls through Scheme
+ working-directory: agentic-ai-lab
+ run: |
+ npm ci --prefix packages/lambda-aitia/proof/quint
+ bazelisk run @local_gerbil//:native_scheme_env -- bash -lc 'cd "$BUILD_WORKSPACE_DIRECTORY/packages/lambda-aitia" && just check-quint-scheme'
+
+ - name: Set up Java for complete lifecycle state graph
+ uses: actions/setup-java@d7793b545071e98d581d3bf084a51c3213318a07 # v4.9.0
+ with:
+ distribution: temurin
+ java-version: '21'
+
+ - name: Replay every reachable lifecycle state and authorization delivery fault
+ working-directory: agentic-ai-lab
+ run: bazelisk run @local_gerbil//:native_scheme_env -- bash -lc 'cd "$BUILD_WORKSPACE_DIRECTORY/packages/lambda-aitia" && just check-lifecycle-scheme'
+
- name: Run SDLC and GitOps integration
- working-directory: poo-flow
+ working-directory: agentic-ai-lab
run: bazelisk run @local_gerbil//:native_scheme_env -- bash -lc 'cd "$BUILD_WORKSPACE_DIRECTORY/packages/lambda-aitia" && just test-integration'
- name: Build and test native ABI and Python runtime
- working-directory: poo-flow
+ working-directory: agentic-ai-lab
run: bazelisk run @local_gerbil//:native_scheme_env -- bash -lc 'cd "$BUILD_WORKSPACE_DIRECTORY/packages/lambda-aitia" && just check-native'
diff --git a/.gitignore b/.gitignore
index aa2c3dd..524550e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,8 @@ version.ss
.cache/
.bin/
.lake/
+_apalache-out/
+proof/quint/node_modules/
__pycache__/
*.py[cod]
*.so
diff --git a/CONTRIBUTING.org b/CONTRIBUTING.org
index d148f1c..cd97baf 100644
--- a/CONTRIBUTING.org
+++ b/CONTRIBUTING.org
@@ -14,8 +14,8 @@ their format is covered by =REUSE.toml=.
- Lambda Aitia owns Software/SDLC, NASA, GitOps, assurance semantics and its
own C and Python bindings.
- Lambda Episteme owns non-SDLC vertical knowledge such as Healthcare.
-- POO Flow owns POO/functional composition, graph substrate and generic
- runtime handoff. POO Flow core must never import Lambda Aitia.
+- Agentic AI Lab owns POO/functional composition, graph substrate and generic
+ runtime handoff. Agentic AI Lab core must never import Lambda Aitia.
- Public extension APIs are ordinary POO-native objects and named pure
functions. Raw alist DSLs and anonymous compute hooks are not public APIs.
@@ -26,7 +26,7 @@ source owner, negative contracts, focused tests, affected public-consumer tests
and an attributable receipt. A plan, proof, authorization and executed effect
remain separate facts.
-Run the relevant repository gates from the POO Flow mount:
+Run the relevant repository gates from the Agentic AI Lab mount:
#+begin_src sh
just build-contribute lambda-aitia
diff --git a/LICENSE b/LICENSE
index bb1680e..debf4b3 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
SPDX-FileCopyrightText: 2026 tao3k team and Contributors
SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-The original work in the POO Flow repository is licensed under both of the
+The original work in the Agentic AI Lab repository is licensed under both of the
following licenses. The AND operator is intentional: recipients must comply
with the terms of both licenses.
diff --git a/README.org b/README.org
index b2db2b3..fa420bf 100644
--- a/README.org
+++ b/README.org
@@ -1,14 +1,18 @@
# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-#+title: Lambda Aitia — causal assurance as executable knowledge
+#+title: Lambda Aitia — causal assurance across the software lifecycle
#+startup: overview
* Purpose
-Lambda Aitia is the software and SDLC causal-assurance contribution for the POO
-Flow ecosystem. It also owns the software Architecture Decision Record (ADR)
-module migrated from Lambda Episteme. It answers five questions about an
+Lambda Aitia organizes software engineering around the complete SDLC:
+requirements, design, algorithms and implementation strategies, verification
+and testing, delivery, operation, maintenance and retirement. Causal Assurance
+connects the justification of engineering decisions across that lifecycle.
+Agentic AI Lab supplies the reusable composition, temporal/causal and runtime
+mechanisms. Aitia also owns the software Architecture Decision Record (ADR)
+module migrated from Lambda Episteme. It answers five questions about an
engineering conclusion:
1. What exactly is claimed?
@@ -18,54 +22,60 @@ engineering conclusion:
5. Which decisions and real effects must remain blocked until the resulting
obligations are discharged again?
-The project manages the justification and invalidation of conclusions. It is
-not a database of green verification results and it is not a generic knowledge
-graph.
+The project helps form, compare and revise design decisions, then retains the
+evidence explaining why their guarantees remain applicable. Requirements lead
+to explicit assumptions, design alternatives, responsibilities, state ownership
+and conditional guarantees. Algorithm choices and code implement those
+decisions; tests and runtime observations can challenge them and reopen design.
+
+System behavior trajectories and design/assurance evolution trajectories are
+linked through evidence. Observed executions, model traces, hypotheses and
+counterfactual alternatives preserve their distinct scope. Temporal order and
+graph reachability alone cannot establish a causal explanation.
+[[file:docs/rfcs/0004-sdlc-design-and-causal-trajectories.org][RFC 0004]] defines this lifecycle design and its pending acceptance gates.
* Place in the ecosystem
-#+begin_example
-lambda-aitia
- Software/SDLC, ADR, NASA and GitOps sources
- claims, assumptions, typed relations, obligations, evidence,
- invalidation and assurance planning
- ^
- |
-lambda-episteme
- optional non-SDLC vertical knowledge and decision-kind/ontology sources
- |
- v
-POO Flow
- POO-native composition, functional flow, graph substrate,
- verifier/runtime handoff and effect boundary
-#+end_example
+#+begin_export mermaid
+flowchart TD
+ App["Application
explicit composition"] --> A["Lambda Aitia
SDLC, design and Causal Assurance"]
+ App --> E["Lambda Episteme
optional vertical knowledge"]
+ E -->|source facts when composed| A
+ A -->|consumes public library| P["Agentic AI Lab
composition, graph, temporal / causal mechanisms and Runtime"]
+ E -->|consumes public library| P
+ A --> Py["Aitia Python Runtime
owned-byte C ABI, tools and observations"]
+ Py -->|uses owned runtime boundaries| P
+#+end_export
This is a conceptual flow, not permission to collapse repository ownership.
-POO Flow core never imports a concrete Lambda contribution. Lambda Aitia may
-consume the complete reviewed POO Flow public mechanism library needed by its
+Agentic AI Lab core never imports a concrete Lambda contribution. Lambda Aitia may
+consume the complete reviewed Agentic AI Lab public mechanism library needed by its
Software/SDLC implementation; dependency minimization is not an architectural
goal. Applications own the explicit composition of Episteme, Aitia and POO
Flow. Mounting this Git
submodule does not import a module, activate a Profile, run a verifier, grant a
capability, authorize a decision or execute an effect.
-The production Python SDLC Runtime is maintained entirely under
-=bindings/python= in this repository; it is not an example. POO Flow's
+The production Aitia Python Runtime is maintained entirely under
+=bindings/python= in this repository; it is not an example. Agentic AI Lab's
=packages/python-runtime= remains the generic graph execution and lifecycle
mechanism and does not own Aitia semantics. Aitia Scheme is compiled AOT
behind an owned-byte C ABI. The Python project validates typed lifecycle
receipts and exposes them to downstream systems without reimplementing Scheme
-decisions.
+decisions. The Python Runtime serves Aitia capabilities throughout the SDLC;
+the existing =SdlcRuntime.plan()= is one implemented assurance-flow projection.
+AnyIO is declared as its runtime-wide concurrency foundation; async execution
+and Host admission remain separate implementation gates. Generic Graph/DAG and
+FunFlow execution mechanisms remain owned by Agentic AI Lab. MRR relation-query and
+lineage integration is a later design direction, outside the current Python
+implementation stage.
* Core model
The initial semantic vocabulary is deliberately small:
-#+begin_example
-Artifact Claim Assumption Observation
-Event Action Obligation Evidence
-Counterexample Finding Decision Effect
-#+end_example
+=Artifact=, =Claim=, =Assumption=, =Observation=, =Event=, =Action=,
+=Obligation=, =Evidence=, =Counterexample=, =Finding=, =Decision= and =Effect=.
Relations are typed by plane. A generic =edge(from, to)= is not part of the
public model.
@@ -87,15 +97,14 @@ authority.
The first vertical slice is one fail-closed lifecycle:
-#+begin_example
-source revision changes
- -> structural impact is computed
- -> affected assumptions and claims are selected
- -> dependent evidence becomes stale
- -> new obligations are planned
- -> the old decision loses authority
- -> the associated effect remains blocked
-#+end_example
+#+begin_export mermaid
+flowchart TD
+ C["Source revision
changed"] --> I["Structural impact
affected assumptions and claims identified"]
+ I --> S["Dependent support
stale"]
+ S --> O["New obligations
pending"]
+ S --> D["Old decision
invalid for the changed closure"]
+ D --> E["Associated effect
blocked"]
+#+end_export
The slice succeeds only when receipts bind the subject, source revision,
assumption set, claim, obligation, producer identity, tool identity, artifact
@@ -114,28 +123,30 @@ evaluate that model.
** Thirty-second compression
-Spec-first Agent work asks an Agent to follow a better specification. Specula
-uses Agents to derive and validate TLA+ models from system code so that deep
-concurrency bugs can be found and reproduced. Lambda Aitia addresses the next
-system-level question: after RFCs, code, formal models, proofs, policies, tests
-and runtime observations all exist, which exact conclusion is still justified
-for the current revision, what change invalidated it, which obligations must be
-rerun, and why must an Agent effect remain blocked?
+Aitia uses existing verification methods to help choose and revise software
+designs throughout the SDLC. It connects requirements, assumptions, guarantees,
+RFC/ADR decisions, implementation strategies and observed behavior. A new
+finding can change the design, invalidate earlier support and create new
+obligations with an explanation path.
-Aitia therefore does not compete with Lean, TLA+, TLC, Cedar, Specula or POO
-Flow. It binds their distinct artifacts into a causal-assurance lifecycle
-without pretending that one tool's success proves the others' propositions.
+Specula already derives and validates TLA+ models, reproduces bugs and supports
+incremental verification. Aitia should reuse applicable tools, models, harnesses
+and checks while evaluating its own contribution: better-founded design choices,
+composition obligations and traceable changes in engineering justification.
+The full Specula application is optional; an upstream component or script can
+be reused without handing it ownership of Aitia's lifecycle.
** Related work and project-position matrix
| Work or project | Primary object | Main strength | Boundary relative to Aitia | Relationship |
|-----------------+----------------+---------------+----------------------------+--------------|
-| POO Flow Agentic Control Plane RFC suite | organization Bundle, Agent control plane, proof/evidence chain and effect token | establishes reusable mechanism, ownership and authority boundaries | intentionally does not own Aitia's Software/SDLC claims or assurance policy | POO Flow is the full public mechanism Library on which Aitia is built |
+| Agentic AI Lab Agentic Control Plane RFC suite | organization Bundle, Agent control plane, proof/evidence chain and effect token | establishes reusable mechanism, ownership and authority boundaries | intentionally does not own Aitia's Software/SDLC claims or assurance policy | Agentic AI Lab is the full public mechanism Library on which Aitia is built |
| Agent RFC / specification-first Agent development | human-reviewed intent, constraints and implementation plan | gives Agents an explicit architecture and acceptance target instead of an ad hoc prompt | a document does not establish current evidence, invalidation closure, authorization or execution | Aitia turns RFC clauses and revisions into typed claims, threats and obligations |
-| [[https://specula.info/][Specula]] ([[https://arxiv.org/abs/2607.25333][paper]]) | code-derived TLA+ specification, invariants, traces and reproduced bugs | autonomous specification generation, model checking, trace alignment and concrete bug reproduction | concentrates on discovering implementation/model violations; it is not a cross-tool evidence, policy and effect-authority ledger | a Specula run can satisfy Aitia TLA+/replay obligations when its artifacts are identity-bound and admitted |
+| [[https://github.com/specula-org/Specula][Specula]] ([[https://arxiv.org/abs/2607.25333][paper]]) | code-derived models, invariants, traces and reproduced bugs | specification generation, model checking, replay and incremental verification | Aitia must demonstrate additional value in design choices, composition obligations and changing justification | reuse qualified tools and assets under POO composition; the complete application is optional |
+| [[https://github.com/specula-org/specula-case-studies][Specula Case Studies]] | archived models, harnesses, traces and experiment records | concrete engineering assets and known-fault reproduction material | each selected record needs provenance, license and replay qualification | use selected assets as Recipe inputs; replay success is not a new discovery |
| [[https://arxiv.org/abs/2605.02454][Causal Software Engineering]] | lifecycle-wide causal models, assumptions and counterfactual diagnosis | provides the broader research vision for causal reasoning throughout software engineering | a vision and roadmap do not by themselves define Aitia's POO objects, revision receipts or Runtime gate | Aitia is an executable contribution pursuing this direction with typed relation planes and invalidation |
| Conventional CI/CD and test dashboards | jobs, statuses, logs and deployment stages | repeatable automation and immediate regression signals | a green result usually does not encode the complete subject, assumption, revision, causal support or downstream invalidation graph | Aitia consumes exact test/build receipts as evidence rather than treating green status as authority |
-| Lean, TLA+/TLC and Cedar used independently | theorem, checked state space or policy decision | strong, specialized reasoning inside a clearly defined formal boundary | none alone proves model-code alignment, evidence freshness, current authorization and effect completion | Aitia keeps the propositions separate and joins only digest-bound admitted receipts |
+| Lean, Quint/TLC and Cedar used independently | theorem, checked state space or policy decision | strong, specialized reasoning inside a clearly defined formal boundary | none alone proves model-code alignment, evidence freshness, current authorization and effect completion | Aitia keeps the propositions separate and joins only digest-bound admitted receipts |
The comparison is about responsibility rather than feature count. Aitia's
distinctive unit is the current, revision-bound justification of a conclusion
@@ -148,7 +159,7 @@ The threat model covers failures that ordinary pass/fail CI cannot distinguish:
- stale evidence is replayed after source, policy, assumption or tool changes;
- a cached Agent decision survives invalidation or revocation;
-- an RFC claim, Lean statement, TLA+ model and Cedar policy refer to different
+- an RFC claim, Lean statement, Quint model and Cedar policy refer to different
revisions of the supposed same subject;
- tool exit success is admitted without exact input, environment and artifact
bindings;
@@ -169,32 +180,45 @@ different propositions and trusted boundaries:
| Agent RFC and ADR | intent, vocabulary, trust boundary, decisions and required obligations | that an implementation, policy or runtime matches the documents |
| Aitia Assurance Graph | exact subject/revision bindings, typed support, invalidation, unresolved frontier and verification plan | temporal safety, authorization or effect execution |
| Lean | general laws such as freshness, monotone invalidation, modality preservation, no stale authority and composition obligations | that the current deployment supplied fresh facts or executed an effect |
-| TLA+/TLC | bounded lifecycle transitions and adverse interleavings across change, invalidate, plan, verify, admit, decide, authorize and effect | universal theorem proof or production authorization |
+| Quint/TLC | bounded lifecycle transitions and adverse interleavings across change, invalidate, plan, verify, admit, decide, authorize and effect | universal theorem proof or production authorization |
| Cedar | an allow/deny decision for one identity-bound principal, action, resource, context, policy and entity snapshot | evidence freshness, proof construction, runtime conformance or external success |
| Runtime Host | one bounded execution attempt and its typed execution receipt | that missing proof or authorization may be inferred |
-The intended evidence flow is:
-
-#+begin_example
-Agent RFC / ADR / source revisions
- -> Aitia snapshot and threat/impact graph
- -> invalidation and typed verification obligations
- -> Lean proof receipts + TLA+/TLC model-check receipts + test/replay evidence
- -> evidence admission against the same snapshot
- -> Cedar projection and identity-bound authorization decision
- -> one bounded POO Flow Runtime execution
- -> execution receipt and post-effect evidence
-#+end_example
-
-Every arrow is digest- and revision-bound. Lean cannot replace Cedar, Cedar
-cannot replace TLA+, a TLC completion cannot replace runtime evidence, and a
+The intended evidence workflow names semantic states, not implementation
+completion. RFC 0004 contains the full SDLC workflow and its design feedback.
+
+#+begin_export mermaid
+flowchart TD
+ D["RFC / ADR and sources
declared"] --> S["Snapshot / impact graph
bound"]
+ S --> O["Verification obligations
pending"]
+ O --> V["Proof, model check, test / replay
candidate results"]
+ V --> A{"Trusted admission valid?"}
+ A -->|yes| C["Scoped support
admitted and current"]
+ C --> G{"Effect gate allows?"}
+ G -->|yes| X["Bounded Runtime attempt
authorized"]
+ X --> R["Receipt and observations
outcome recorded"]
+ R --> F["Lifecycle reassessment
design review when challenged"]
+ F --> D
+ A -->|no / unknown| U["Unresolved / rejected
affected effect blocked"]
+ U --> O
+ G -->|no / unknown| B["Effect blocked
review / revalidation required"]
+ B --> O
+ C -->|changed / expired| B
+#+end_export
+
+Admission checks the subject, revision and cut. The effect gate requires a
+current decision, Cedar authorization and Runtime enforcement. Every arrow is
+digest- and revision-bound. Lean cannot replace Cedar, Cedar
+cannot replace Quint, a TLC completion cannot replace runtime evidence, and a
Runtime success cannot retroactively prove the RFC. Unknown, conflicted,
stale, mismatched or unavailable inputs fail closed and remain visible in the
receipt graph.
-The current repository has executable snapshot/invalidation and modular Lean
-evidence. The complete TLA+ lifecycle, Cedar admission and Runtime effect gate
-remain explicit roadmap phases; their absence is not represented as closure.
+The current repository has executable snapshot/invalidation, pure planning,
+modular Lean laws, bounded Quint lifecycle/retirement/ingress models and known-fault Python replay.
+The connected design/trajectory experiment, upstream Recipe qualification,
+Python-to-Host evidence admission and Runtime effect gate remain open. See
+[[file:ROADMAP.org][ROADMAP]] for phase-specific evidence and limits.
See [[file:docs/rfcs/0001-causal-assurance-core.org][RFC 0001]],
[[file:docs/rfcs/0002-snapshot-and-invalidation-kernel.org][RFC 0002]],
[[file:docs/rfcs/0003-composition-value-interface.org][RFC 0003]] and
@@ -202,16 +226,16 @@ See [[file:docs/rfcs/0001-causal-assurance-core.org][RFC 0001]],
* Project rules
-- Public extension APIs are POO-native. The ordinary =aitia.ss= surface selects
- the maintained =aitia= Composition and fills bounded Project slots; its macro
- lowers directly to those POO values. Prototype, C3 and slot-transform
- operators are exposed only when a user needs an advanced override. Neither
- layer uses raw alist DSLs or ad hoc patch languages.
+- Public extension APIs are POO-native. The maintained =aitia= Case now uses
+ Agentic AI Lab's =user-composition=, =compose profiles= and =use-module=.
+ The former no-import =aitia.ss= convenience is an open RFC 0003 UX gate,
+ not a supported loader in the current Profile algebra. Advanced overrides
+ use POO slots; neither path introduces an alist or patch-language DSL.
- Functional transformations are values first. Side effects live behind an
- explicit POO Flow verifier or runtime handoff.
+ explicit Agentic AI Lab verifier or runtime handoff.
- Native Scheme tests are never heap-unbounded: the Aitia Testing Interface
defaults to 512 MiB, while complete NASA catalog and prepared-source-graph
- tests declare a bounded 2 GiB POO memory profile. POO Flow's outer test
+ tests declare a bounded 2 GiB POO memory profile. Agentic AI Lab's outer test
launcher enforces the 512 MiB pre-import boundary before this profile loads.
- Relation planes remain disjoint and fail closed at their boundaries.
- =supported=, =violated=, =unknown=, =stale=, =conflicted=,
@@ -226,7 +250,7 @@ See [[file:docs/rfcs/0001-causal-assurance-core.org][RFC 0001]],
* License
-Lambda Aitia uses the same intentional dual-license contract as POO Flow:
+Lambda Aitia uses the same intentional dual-license contract as Agentic AI Lab:
=Apache-2.0 AND LGPL-2.1-or-later=. Recipients must comply with both licenses.
The machine-readable declaration and complete texts are maintained in
[[file:REUSE.toml][REUSE.toml]], [[file:LICENSE][LICENSE]] and [[file:LICENSES/][LICENSES/]].
@@ -238,15 +262,23 @@ The machine-readable declaration and complete texts are maintained in
- [[file:docs/rfcs/0003-composition-value-interface.org][RFC 0003 — Composition Value Interface]] defines the Jsonnet-style single-value
downstream file, the official =aitia= Composition and the advanced POO
override boundary.
+- [[file:docs/rfcs/0004-sdlc-design-and-causal-trajectories.org][RFC 0004 — SDLC Design, Causal Assurance and Trajectories]] defines the
+ complete lifecycle framework, design leverage, reuse contracts and future
+ MRR boundary, with implementation acceptance still pending.
+- [[file:docs/rfcs/0005-org-native-engineering-workspace.org][RFC 0005 — Org-native engineering workspace]] defines source-bound Agent
+ review, Agentic AI Lab dependency ownership and the unresolved package cycle.
+ The [[file:user-interface/workspaces/job-executor.org][maintained job-executor workspace]] is the first native authoring surface.
+ Qualification must use Scheme-owned declarations and the Rowan/AOT consumer;
+ earlier legacy CLI lint/query results do not establish this integration.
- [[file:docs/adrs/README.org][ADR contract and template]] defines standardized bounded decisions, lifecycle,
RFC links and the non-authorizing assurance projection.
-- [[file:docs/adrs/0007-consume-poo-flow-public-library.org][ADR 0007]] establishes POO Flow as Aitia's reusable public mechanism library.
+- [[file:docs/adrs/0007-consume-agentic-ai-lab-public-library.org][ADR 0007]] establishes Agentic AI Lab as Aitia's reusable public mechanism library.
- [[file:ROADMAP.org][ROADMAP]] defines phases, deliverables and completion gates.
- [[file:docs/plans/software-sdlc-integration-inventory.org][Software/SDLC integration inventory]] classifies the existing implementation as
keep, reference, generalize or later migrate.
-The repository has Phase 0 and Phase 1 evidence-partial work plus an active
-Phase 2 snapshot/invalidation slice. ABI revision 2 and =SdlcRuntime.plan()=
-form the first production Python runtime contract for the complete eight-stage
-SDLC DAG. That plan remains inert: executable stage receipts, release
-authority and completed effects are not claimed yet.
+Phase 2 snapshot/invalidation and Phase 3 pure planning have bounded completion
+receipts; later phases retain their explicit gaps. ABI revision 2 and
+=SdlcRuntime.plan()= expose the eight-stage assurance/execution DAG. That DAG
+is a protocol used within the full SDLC, and its plan remains inert: executable
+stage receipts, release authority and completed effects are not inferred.
diff --git a/ROADMAP.org b/ROADMAP.org
index df0eec8..6654e46 100644
--- a/ROADMAP.org
+++ b/ROADMAP.org
@@ -4,6 +4,62 @@
#+title: Lambda Aitia Roadmap
#+startup: overview
+* Lifecycle framework and current priority
+
+The complete SDLC is the product framework: requirements, software design,
+algorithm and implementation strategies, verification/testing, delivery,
+operation, maintenance and retirement. These activities exchange observations
+and reopen earlier decisions. The numbered phases below are implementation
+milestones for that framework, not the lifecycle experienced by a project.
+
+[[file:docs/rfcs/0004-sdlc-design-and-causal-trajectories.org][RFC 0004]] makes software design an early leverage point and Causal Assurance
+the connection across the lifecycle. The next product qualification must link
+requirements, at least two design alternatives, assumptions and guarantees to
+real execution trajectories, evidence, a revised ADR and renewed obligations.
+Recipe execution and tool integration contribute to that connected experiment.
+
+The agreed lifecycle Impact design in RFC 0004 covers capability introduction,
+change and retirement across historical assets/commitments, current code and
+operation, and future work. Agentic AI Lab owns generic analysis; Aitia adds SDLC
+meaning. A bounded job-executor retirement case is the next paired Impact
+qualification, not an instruction to remove a production capability. Its
+implementation and execution receipts remain pending.
+
+Reuse Agentic AI Lab Temporal Causality and existing upstream verification tools and
+assets. AnyIO serves the entire Aitia Python Runtime. MRR relation queries,
+derivation and lineage are deferred beyond the current Python implementation
+stage; this queue introduces no MRR integration.
+
+This view tracks implementation progress; it is separate from the engineering
+states in RFC 0004's lifecycle workflow.
+
+[[file:docs/rfcs/0005-org-native-engineering-workspace.org][RFC 0005]] adds the maintained [[file:user-interface/workspaces/job-executor.org][Org-native job-executor workspace]]. Its
+Scheme-owned contract and Rowan consumer qualification remain pending; the
+earlier legacy CLI checks do not close this gate. Agentic AI Lab owns the intended
+Orgize dependency; direct Scheme package
+installation is blocked by the Orgize → gerbil-parser → Agentic AI Lab dependency
+cycle and missing Orgize package entrypoint. Existing generated Cargo artifacts
+can be qualified independently of that source-package cycle. Rust/Rowan runtime
+delivery is the later durable path, not an interim workaround or a prerequisite
+for the current Python stage. The immediate implementation priority remains
+Aitia's production Python Runtime: preserve frozen source observations through
+AnyIO execution and reach the actual Scheme Host admission path. Python must
+not reimplement Org parsing or contract evaluation to bypass the pending
+Orgize boundary. Role projection, source-bound edits and the connected
+lifecycle remain separate gates.
+
+#+begin_export mermaid
+flowchart TD
+ B["Existing bounded foundations
invalidation, planning, formal laws and replay"]
+ B --> D["Pending
design alternatives and upstream qualification"]
+ B --> H["Pending
Python-to-Host admission and async transport"]
+ D --> T["Pending
connected behavior and design trajectories"]
+ H --> T
+ T --> R["Pending
revision, revalidation and comparative evidence"]
+ R --> O["Pending
contract-preserving optimization evidence"]
+ O -. later design .-> M["Deferred
MRR relation queries, derivation and lineage"]
+#+end_export
+
* Completion discipline
Each phase closes only when its source, negative contracts, executable checks
@@ -26,17 +82,17 @@ Status: =evidence-partial=
Deliverables:
1. Project charter and RFC 0001.
-2. [X] Repository license/SPDX expression synchronized with POO Flow as
+2. [X] Repository license/SPDX expression synchronized with Agentic AI Lab as
=Apache-2.0 AND LGPL-2.1-or-later=, including REUSE metadata and both full
license texts, plus a source-owned contribution policy.
3. Independent build, test and release lane; no implicit parent build.
4. [X] A versioned vocabulary manifest for node kinds, relation planes, states
and receipt schema identifiers.
5. [X] An Architecture Decision Record for the dependency direction:
- applications compose contributions; POO Flow core never imports Aitia.
+ applications compose contributions; Agentic AI Lab core never imports Aitia.
6. A checked integration inventory covering Lambda Episteme Software
- Engineering, SDLC, GitOps and decision knowledge plus POO Flow Graph, Lean,
- TLA+, Cedar and Runtime Host artifacts.
+ Engineering, SDLC, GitOps and decision knowledge plus Agentic AI Lab Graph, Lean,
+ Quint, Cedar and Runtime Host artifacts.
Exit gates:
@@ -48,13 +104,15 @@ Exit gates:
parent state;
- mounting the repository performs no activation or effect.
-Current evidence: the production dependency closure, Phase 2 Assurance fixture,
-modular Lean library, integration lane and native Scheme/C/Python package replay
+Current evidence: the independent PR CI, production dependency closure, Phase 2
+Assurance fixture, modular Lean library, integration lane and native
+Scheme/C/Python package replay
from an isolated checkout at exact revisions. The Homebrew Darwin toolchain
adaptation is child-process scoped and does not alter a Nix-selected toolchain
or the parent environment. See
=docs/receipts/2026-09-18-phase2-clean-replay.org=. The remaining Phase 0 work
-is the independent CI/release lane and checked integration inventory.
+is a release lane and executable integration-inventory acceptance. The PR CI
+does not by itself constitute a published release or complete Phase 0.
* Phase 1 — SDLC ownership migration and POO-native semantic kernel
@@ -65,7 +123,7 @@ Deliverables:
1. Complete the source-owned migration of SDLC implementation, tests, source
snapshots, tools and Profiles into Lambda Aitia.
2. Replace the old package namespace and owner identities with
- =:poo-flow/lambda-aitia/modules/sdlc= and =lambda-aitia=; do not publish a
+ =:agentic-ai-lab/lambda-aitia/modules/sdlc= and =lambda-aitia=; do not publish a
compatibility alias unless separately authorized.
3. [X] Establish the five-role SDLC module family: =types.ss=, =objects.ss=, =funs.ss=,
=config.ss= and =interface.ss=.
@@ -104,7 +162,7 @@ Deliverables:
1. [X] An =AssuranceSnapshot= that binds graph identity, source revisions, claim
revisions and an immutable fact cut.
-2. [X] Plane-specific projection and reachability queries over the POO Flow Graph
+2. [X] Plane-specific projection and reachability queries over the Agentic AI Lab Graph
substrate; Aitia does not create a second graph engine.
3. [X] Change admission and structural impact selection.
4. [X] Support-set invalidation from source/assumption changes to claims,
@@ -116,12 +174,20 @@ Deliverables:
Core law:
-#+begin_example
-changed(dependency)
-and reaches(dependency, claim)
-=> not authorized(claim)
-until current obligations are discharged by current evidence
-#+end_example
+#+begin_export mermaid
+stateDiagram-v2
+ state "Support: current" as Current
+ state "Support: stale; affected effect blocked" as Stale
+ state "Obligations: pending" as Pending
+ state "Support: renewed at a new cut" as Renewed
+ Current --> Stale: dependency changes and reaches claim
+ Stale --> Pending: derive current obligations
+ Pending --> Renewed: obligations discharged by current admitted evidence
+ Renewed --> Stale: another relevant change
+#+end_export
+
+Renewed support does not itself authorize an effect; current decision and
+authorization gates remain independently required.
Exit gates:
@@ -133,7 +199,56 @@ Exit gates:
* Phase 3 — Obligation derivation and verification planning
-Status: =planned=
+Status: =complete= for pure planning at the exact source cut in
+=docs/receipts/2026-09-23-phase3-planning-replay.org=. Verifier execution,
+evidence promotion and effect authority remain Phase 4/6 work.
+
+The first executable slice reuses the Phase 2 invalidation receipt to select
+snapshot-bound obligations. A POO-native verification policy declares
+available capabilities, and the resulting POO-native plan records selected
+obligations, capability requirements, separate unknown/conflicted blockers and
+the underlying invalidation witnesses. It is deterministic under inventory
+permutation and cannot claim verifier execution, release authority or runtime
+execution.
+Obligation evidence kinds are closed to proof, model checking, replay,
+unit/integration/native tests, static analysis, authorization differential and
+human review; an unknown kind is rejected at the model boundary.
+Within the affected obligation set, structural =depends-on= relations are
+projected into Agentic AI Lab Graph. Its topological order becomes the selected
+request order; a blocked prerequisite blocks dependents, an unplanned
+prerequisite is never assumed discharged, and a dependency cycle records its
+path while blocking only its strongly connected component and downstream
+dependents; an independent acyclic branch retains its own order. The plan
+records every cyclic component as well as one deterministic path witness; it
+still does not attest that any prerequisite has been verified.
+An obligation bound to an older snapshot is blocked rather than silently
+promoted to a replacement obligation. Selection compares snapshot identity,
+revision and a non-circular context digest. The context digest covers the
+canonical snapshot while excluding only obligation binding fields; the final
+snapshot digest still covers those fields. Binding an unbound candidate is an
+explicit pure step, and a previously bound obligation cannot be rebound.
+The pure replacement-requirements receipt traces affected old obligations to
+a changed target snapshot and records blockers for unresolved changes, stale
+source bindings, revised claims or policy, and incomplete targets. It derives
+the need for a new declaration without inventing a new obligation identity
+or copying an old evidence requirement across a changed claim. The explicit
+declaration step accepts a caller-authored, unbound candidate in a target draft
+with a revised claim and support edge; it checks the source derivation and
+canonical snapshots, binds only that fresh candidate through the existing
+snapshot binder, reconstructs the final snapshot, and returns an inert receipt.
+It does not copy evidence, invoke a verifier or grant release authority.
+The explicit verifier-candidate catalog is a set of POO-native inert declarations
+with evidence kinds, capability and priority. A pure explanation receipt
+records the chosen declaration, every rejected candidate and unassigned
+planned obligations; ties use candidate identity only after explicit priority.
+This is declared suitability, not adapter installation, execution or evidence
+admission.
+An explicit structural =composes= relation connects a composite claim to its
+component claims and projects through Agentic AI Lab Graph for invalidation. A pure
+composition-requirements receipt demands an independent, claim-declared,
+snapshot-bound obligation for the composite. Component status or evidence
+never supplies it, and even a present direct obligation does not attest that
+verification ran or evidence was admitted.
Deliverables:
@@ -157,27 +272,50 @@ Exit gates:
* Phase 4 — Verifier adapters and evidence admission
-Status: =planned=
+Status: =in-progress= (typed reported outcomes, pure structural eligibility and
+sealed-support checks reuse Agentic AI Lab's verification adapter. A configured
+Scheme Host capability now owns adapter, clock, lease, current snapshot source,
+revocation and a separate candidate admission ledger. An exact current
+assurance-edge witness can consume that ledger without promoting the snapshot
+evidence slot. A typed required-support receipt now checks all claim-declared
+obligations and both assurance links at the current Host cut, with explicit
+blockers and no release authority. Full Decision closure, trusted deployment,
+Cedar policy and the Runtime effect gate remain open. A Host-issued preflight
+can now bind an undecided Decision and its dependency edge to that support,
+but cannot produce =allow= or an effect token).
Deliverables:
-1. Adapter contracts for Lean, TLA+/TLC, native tests, static analyzers,
+1. Adapter contracts for Lean, Quint/TLC, native tests, static analyzers,
runtime replay and human review.
2. Evidence envelopes binding producer, tool/version, input artifact digests,
obligation, output digest, subject, revision, scope and validity interval.
-3. Admission rules for successful, failed, timed-out, unavailable and
- indeterminate verifier outcomes.
+3. [~] Admission rules for successful, failed, timed-out, unavailable and
+ indeterminate verifier outcomes. The pure eligibility receipt remains
+ inert. A configured Host may now issue a separate admission for candidate
+ evidence after its verifier succeeds over the exact current snapshot;
+ changing =admission-state= in a node is not the promotion operation.
+ Admission remains subject to Host clock, source invalidation and revocation
+ and cannot authorize release.
+ The normal Host support entrypoint requires an exact Agentic AI Lab adapter-issued
+ seal over the current semantic subject; no structural-only public support
+ predicate remains. The low-level under-adapter check is explicitly
+ conditional, not an authorization path. A forged adapter or Host
+ presentation is rejected; proving that application configuration installed
+ the intended Host and that its clock and snapshot source are trusted remains
+ open.
4. Provenance-preserving counterexample and finding ingestion.
5. Replay checks proving presentation mutation cannot forge admitted evidence.
-6. [X] An Aitia Scheme-native ABI contract following POO Flow's owned-byte,
+6. [X] An Aitia Scheme-native ABI contract following Agentic AI Lab's owned-byte,
caller-release pattern; public Scheme and Python namespaces remain
unversioned while ABI revision is explicit metadata.
-7. [X] An Aitia-owned, uv-managed =bindings/python= production SDLC Runtime
- with an out-of-line CFFI package. POO Flow's =packages/python-runtime=
+7. [X] An Aitia-owned, uv-managed =bindings/python= production Python Runtime
+ with an out-of-line CFFI package. Agentic AI Lab's =packages/python-runtime=
remains the generic runtime mechanism, and Python contains no duplicate
Aitia semantics.
-8. [X] ABI revision 2 publishes the canonical eight-stage POO Flow DAG as an
- inert typed =SdlcFlowPlan=; it does not claim authorization or execution.
+8. [X] ABI revision 2 publishes the eight-stage assurance/execution protocol as
+ an inert typed =SdlcFlowPlan=; this is one protocol within the full SDLC and
+ does not claim authorization or execution.
Exit gates:
@@ -190,7 +328,7 @@ Exit gates:
digests and typed failures;
- the installed Python wheel consumes the AOT/native artifact without Gerbil.
-* Phase 5 — Assurance laws in Lean and lifecycle model in TLA+
+* Phase 5 — Assurance laws in Lean and lifecycle models in Quint
Status: =evidence-partial=
@@ -201,14 +339,46 @@ Lean owns general laws, including:
- no stale authority;
- causal modality preservation;
- counterfactual isolation;
-- composition creates a new obligation;
+- [X] composition requires a current, independent direct obligation;
- unknown or conflicted support cannot grant authority.
-TLA+ owns the dynamic lifecycle:
-
-#+begin_example
-change -> invalidate -> plan -> verify -> admit -> decide -> authorize -> effect
-#+end_example
+Quint models the dynamic assurance/execution protocol within the SDLC:
+
+#+begin_export mermaid
+stateDiagram-v2
+ state "Change: admitted" as Changed
+ state "Support: invalidated" as Invalidated
+ state "Obligations: planned" as Planned
+ state "Verification: results produced" as Verified
+ state "Evidence: admitted" as Admitted
+ state "Decision: current" as Decided
+ state "Effect: authorized" as Authorized
+ state "Execution: receipt recorded" as Effect
+ Changed --> Invalidated
+ Invalidated --> Planned
+ Planned --> Verified: actual verifier execution
+ Verified --> Admitted: trusted evidence admission
+ Verified --> Planned: rejected or unresolved
+ Admitted --> Decided: decision obligations discharged
+ Decided --> Authorized: current authorization
+ Authorized --> Effect: Runtime gate and bounded attempt
+ Authorized --> Invalidated: revocation or expiry
+ Effect --> Changed: relevant new observation
+#+end_export
+
+A bounded Quint model in =proof/quint/AssuranceLifecycle.qnt= now checks current
+admission/decision/grant authority, expiry and revocation. Separate mutant
+configurations demonstrate unsafe report-only effect start, stale admission,
+grant before re-verification and effect start after revocation; a reachability
+configuration demonstrates a valid effect path. This is local model evidence,
+not proof that the Runtime Host enforces the contract. Clock/adapter trust,
+counterfactual transition authority, unconditional liveness and source-bound CI replay
+remain open.
+
+A separate stable-environment fairness configuration now checks eventual
+effect start; removing fairness produces a stuttering counterexample. This
+narrows the progress assumption but does not claim progress under source
+changes, clock expiry, revocation or an unavailable Host.
Required model-checking counterexamples include stale cached decisions,
evidence admitted after a source change, release before re-verification,
@@ -222,24 +392,35 @@ Exit gates:
- a Lean theorem is not treated as a runtime decision;
- formal artifacts have negative tests showing the intended boundary.
-* Phase 6 — POO Flow integration and effect gate
+* Phase 6 — Agentic AI Lab integration and effect gate
-Status: =planned=
+Status: =active= (the Host Decision preflight can now project a current,
+undecided candidate into Agentic AI Lab's POO-native Cedar request family. The
+request is inert and editable; Cedar evaluation, independent Host source
+admission and Runtime effect gating have not landed. The generic Runtime
+boundary rejects its preflight-only marker before Cedar evaluation. The
+Scheme Host can recheck an exact issued request against its current source
+cut, but Runtime does not yet invoke that predicate. Agentic AI Lab can now declare
+an action source-admission-required in the administrative Cedar capability;
+request editing cannot remove that requirement. No Aitia admitted =allow=
+Decision or trusted Runtime source-admission path exists yet).
Deliverables:
1. Application-owned composition of Lambda Episteme facts, Aitia assurance and
- POO Flow execution.
-2. POO Flow functional plans that consume Aitia obligations without importing
- Aitia into the POO Flow core bootstrap.
+ Agentic AI Lab execution.
+2. Agentic AI Lab functional plans that consume Aitia obligations without importing
+ Aitia into the Agentic AI Lab core bootstrap.
3. Aitia AOT Scheme exports through a dedicated C ABI using the established
- POO Flow Scheme-native result ownership convention.
-4. Aitia's own production Python SDLC Runtime consumes that ABI through CFFI
+ Agentic AI Lab Scheme-native result ownership convention.
+4. Aitia's own production Python Runtime consumes that ABI through CFFI
and returns typed
- projections. POO Flow's Python runtime remains a separate generic runtime
+ projections. Agentic AI Lab's Python runtime remains a separate generic runtime
and lifecycle transport.
-5. Cedar projection from a current admitted Decision, with snapshot and
- invalidation bindings.
+5. [~] Cedar request projection from a current Host preflight, with Decision,
+ claim, policy and snapshot bindings. This is not yet a projection from an
+ admitted =allow= Decision; the Runtime Host must independently validate
+ the source cut at use before any authority can be granted.
6. Runtime Host rejection of stale, unknown, conflicted, revoked or incomplete
assurance closures.
@@ -252,7 +433,46 @@ Exit gates:
* Phase 7 — Software/SDLC reference qualification
-Status: =planned=
+Status: =active= for inert design-contract replacement and snapshot-bound
+implementation-mapping slices; full reference qualification remains open.
+
+The target is the connected lifecycle experiment in RFC 0004: compare design
+alternatives, qualify reusable verification methods, link behavior and design
+evolution trajectories, and reopen obligations after a premise changes.
+Existing bounded results below are foundations for that experiment.
+
+The [[file:docs/receipts/2026-09-24-retirement-impact.org][retirement Impact analysis receipt]] adds seven Scheme qualification cases
+using the existing Agentic AI Lab Graph/Temporal Causality mechanisms. The synthetic
+automatic-retry case preserves old dependents and historical cuts, distinguishes
+explicit current activity from past occurrence, and retains unknown consumers
+and future/out-of-horizon work. Candidate graph edits are not migration receipts.
+Real persisted observations, derived migration duties and authorized execution
+remain pending; the lifecycle retirement gate is not closed.
+
+The first job-executor regression now records an ADR-bound POO-native design
+contract with assumptions, guarantees, state ownership, effects and variation
+points. A retry-policy revision reopens the unique-effect guarantee; the
+existing SDLC impact projection uses Agentic AI Lab Graph to select its verification
+trajectory. Stronger assumptions, weakened guarantees, new effects, changed
+decision and same-revision mutation have negative tests. This is a pure
+declaration comparison, not a behavioral implication proof, admitted verifier
+receipt or release decision. A follow-on mapping now binds each guarantee to
+exact source artifact and Assurance snapshot revisions/digests. It fails closed
+on source/snapshot changes and uncovered guarantees, but it does not establish
+semantic model-to-code conformance or independent acceptance. A Host support
+projection now requires the guarantee Claim, its declared source dependency,
+an exact source input in a current Host admission, and the Claim's full support
+set. This remains conditional on the configured Host and is not a proof of
+verifier independence or deployment trust.
+
+The Python project's first installed-wheel qualification now runs a real
+worker process twice against a persistent task ledger and loopback provider.
+An intentionally regenerated retry key reproduces two commits after a lost
+acknowledgement; a stable logical-operation key yields one commit and eventual
+task completion. [[file:docs/adrs/0008-stable-operation-key-after-lost-ack.org][ADR 0008]] proposes widening the guarantee from
+"per key" to "per logical operation" and the design-replacement test reopens
+the affected verification. This is known-fault behavioral evidence, not a
+Host-issued seal or proof of a production provider's idempotency.
The first reference case is a software change crossing requirement,
implementation, verification, release-decision and effect boundaries. It
@@ -297,20 +517,74 @@ domain branch and the public API remains POO-native.
* Immediate work queue
-These are the next bounded changes after Phase 0 review:
-
-1. [X] Add the repository contribution policy under the confirmed license contract.
-2. [X] Record the exact SDLC source/test/tool/profile inventory and current receipts.
-3. Move the SDLC and GitOps owners into Aitia and close the published Episteme
- deletion plus parent pin; Aitia-side source and parity are complete.
-4. [X] Add the five-role =modules/assurance/= skeleton with declarations only.
-5. [X] Define the versioned vocabulary manifest and schema identifiers.
-6. [X] Implement relation-plane validation and its negative test matrix.
-7. [X] Implement canonical identity/digest projection.
-8. [X] Define the Aitia Scheme-native C ABI and pure-C harness with an unversioned
- public namespace and explicit ABI revision metadata.
-9. [X] Complete Aitia's =bindings/python= CFFI consumer and wheel receipt.
-10. [X] Create the smallest change-to-invalidation fixture with no verifier calls.
-
-No Python semantic duplicate, Cedar policy, proof migration or effect execution
-belongs in this immediate queue.
+The earlier migration, nominal vocabulary, snapshot/invalidation and CFFI
+foundation work is recorded in the phases above. The current queue is:
+
+Immediate priority (2026-10-10): defer new persistence integration. First
+challenge the design with source-reviewed upstream failure reports and actual
+formal checks. [[file:proof/quint/README.org][Quint design checks]] separate work/cancellation, retirement review, ingress and
+the existing assurance lifecycle; [[file:docs/receipts/2026-09-24-retirement-formal-review.org][the formal review receipt]] records bounded
+exploration and Lean laws, not Runtime closure. Historical
+[[file:docs/receipts/2026-09-24-formal-source-qualification.org][TLA+ source qualification]] is retained as a receipt only. The maintained
+Quint lane checks source syntax through Quint and declared POO Contract/source-cut
+invalidation. The local retirement Host and its execution test now check a
+bounded Scheme behavior cut, including a real callback and negative cases;
+the source binding covers Lean, Quint and Scheme. Independent replay, broader
+semantic correspondence and a refinement argument remain open.
+The [[file:docs/receipts/2026-09-24-retirement-ingress-review.org][bounded ingress composition]] now admits post-retirement requests and
+checks epoch fencing, with two unsafe mutants; deployed authority/Runtime
+correspondence, new grant issuance and eventual progress remain unqualified.
+Extract admission,
+revocation and grant contracts from the existing lifecycle model with atomic
+counterexamples; retain the whole-protocol regression. Do not resume storage
+work merely because these design-level tests pass.
+
+1. [ ] Extend the job-executor design case with a common requirement set and
+ comparable alternatives, keeping completion and unique-effect obligations.
+ Historical-source applicability and the owner/coverage audit are documented
+ in [[file:docs/plans/engineering-case-source-inventory.org][the case-source inventory]] and ADR 0008 r2. Parameter mismatch, retention,
+ independent commit/crash and concurrent-attempt checks remain unqualified.
+ Reuse existing Cedar/Runtime mechanisms for authorization; keep provider
+ effect uniqueness separate. Add an executable source-correction/review case
+ before claiming historical-judgment invalidation is complete.
+2. [ ] Qualify one asset-complete upstream bug case. Record files, exact
+ revisions, licenses, dependencies, resource bounds and required upstream
+ checks in the integration inventory. Do not add a TLA+/TLAPS execution lane.
+3. [ ] Project experimental behavior and design/assurance evolution through
+ Agentic AI Lab temporal/causal mechanisms. Check modality, causal cuts, late
+ observations and missing parents without turning structural paths into
+ causal proof.
+ Pair the repair case with one capability-retirement experiment: bind old
+ persisted results, current/in-flight consumers and queued work to pre/post
+ snapshots. Preserve historical identity, distinguish old-but-active state
+ from past occurrence, and derive migration/drain obligations with witnesses.
+ Include an unrelated negative control and unknown external consumers;
+ disappearance from the new graph must not imply safe deletion. Close only
+ with the scoped qualification and effect receipts required by RFC 0004.
+ The [[file:docs/receipts/2026-09-24-retirement-impact.org][first bounded analysis slice]] passes; actual persistent-state and effect
+ qualification remains open and is deferred behind the formal design gates.
+4. [ ] Connect real tool observations from the Aitia Python Runtime to the
+ configured Scheme Host, preserving source bytes and native-session ownership
+ through the AnyIO execution boundary. This is required before claiming
+ admitted support or progressing to the remaining Phase 6 effect gates.
+ The bounded frozen-pytest AnyIO worker now waits for process-group cleanup
+ under cancellation and never carries a thread-affine native session; it
+ remains an observation-only slice, not Host admission. The installed-wheel
+ qualification also exercises a real native session before and after that
+ worker, with the lost-ACK failure/fix and stale-source rejection. The next
+ gate is an owner-preserving Host operation and opaque capability transport,
+ followed by source-change, expiry, revocation and forged-receipt negatives.
+5. [ ] Compose the qualified methods through existing POO Profiles and slots;
+ an override must preserve required checks or reopen corresponding obligations.
+6. [ ] Replay failure, design revision, re-verification and a later assumption
+ change as one lifecycle case. Compare with the same upstream tools/assets
+ alone, and record explanation quality, missed obligations, unnecessary
+ reruns and execution costs.
+7. [ ] Qualify one contract-preserving implementation optimization with both
+ conformance and performance evidence.
+
+Euclid/GCD is a candidate tool qualification, not evidence for an unrelated
+job-executor claim. Known-fault replay is not novel bug discovery. Full Specula
+CLI lifecycle mapping, new checker implementations and MRR integration are not
+required deliverables in this queue. Phase 4/6/7 closure still requires actual
+Host and Runtime receipts rather than a documentation or Recipe-only milestone.
diff --git a/bindings/c/aitia-contract.ss b/bindings/c/aitia-contract.ss
index 50f186a..71469ba 100644
--- a/bindings/c/aitia-contract.ss
+++ b/bindings/c/aitia-contract.ss
@@ -8,11 +8,11 @@
JSONReadOptions json->string string->json)
(only-in :clan/poo/object .ref)
(only-in :gerbil/core call-with-output-string display-exception)
- (only-in :poo-flow/lambda-aitia/user-interface/config
+ (only-in :agentic-ai-lab/lambda-aitia/user-interface/config
github-gitops-sdlc)
- (only-in :poo-flow/lambda-aitia/modules/sdlc/funs
+ (only-in :agentic-ai-lab/lambda-aitia/modules/sdlc/funs
sdlc-flow-plan)
- (only-in :poo-flow/lambda-aitia/user-interface/scenarios/github-gitops
+ (only-in :agentic-ai-lab/lambda-aitia/user-interface/scenarios/github-gitops
github-change github-check github-run-gitops))
(export aitia-abi-revision
@@ -67,7 +67,9 @@
(def (json-check object repository revision)
(github-check
(json-symbol object "name") repository revision
- (json-symbol object "conclusion")))
+ (json-symbol object "conclusion")
+ standard-edition: (hash-get object "standardEdition")
+ source-lock-digest: (hash-get object "sourceLockDigest")))
(def (symbols->json values)
(list->vector (map symbol->string values)))
@@ -110,7 +112,7 @@
(staleChecks (symbols->json (.ref decision 'stale-checks)))
(reasons (symbols->json (.ref decision 'reasons)))
(semanticOwner "lambda-aitia")
- (runtimeOwner "poo-flow")
+ (runtimeOwner "agentic-ai-lab")
(authorityStatus "not-evaluated")
(releaseAuthorized #f)
(runtimeExecuted #f))))
diff --git a/bindings/c/aitia-native.ss b/bindings/c/aitia-native.ss
index 0062f96..69bd216 100644
--- a/bindings/c/aitia-native.ss
+++ b/bindings/c/aitia-native.ss
@@ -7,7 +7,10 @@
(import (only-in :std/ffi
C-declare C-ffi-macrology
def-C-lambda def-C-type)
- :poo-flow/lambda-aitia/bindings/c/aitia-contract)
+ ;; Orgize owns the Scheme implementation and public C symbols. Keep
+ ;; this module in Aitia's native link closure without copying its ABI.
+ :orgize/bindings/c/orgize
+ :agentic-ai-lab/lambda-aitia/bindings/c/aitia-contract)
(export aitia-c-round-trip)
@@ -23,16 +26,16 @@ typedef struct {
int32_t status;
uint8_t *payload;
size_t length;
-} poo_flow_aitia_result;
+} agentic_ai_lab_aitia_result;
-void poo_flow_aitia_result_init(poo_flow_aitia_result *result) {
+void agentic_ai_lab_aitia_result_init(agentic_ai_lab_aitia_result *result) {
if (result == NULL) return;
result->status = 0;
result->payload = NULL;
result->length = 0;
}
-void poo_flow_aitia_result_release(poo_flow_aitia_result *result) {
+void agentic_ai_lab_aitia_result_release(agentic_ai_lab_aitia_result *result) {
if (result == NULL) return;
free(result->payload);
result->status = 0;
@@ -40,77 +43,77 @@ void poo_flow_aitia_result_release(poo_flow_aitia_result *result) {
result->length = 0;
}
-uint32_t poo_flow_aitia_abi_revision(void);
-int32_t poo_flow_aitia_descriptor(poo_flow_aitia_result *result);
-int32_t poo_flow_aitia_sdlc_flow_plan(char *payload,
- poo_flow_aitia_result *result);
-int32_t poo_flow_aitia_gitops_evaluate(char *payload,
- poo_flow_aitia_result *result);
+uint32_t agentic_ai_lab_aitia_abi_revision(void);
+int32_t agentic_ai_lab_aitia_descriptor(agentic_ai_lab_aitia_result *result);
+int32_t agentic_ai_lab_aitia_sdlc_flow_plan(char *payload,
+ agentic_ai_lab_aitia_result *result);
+int32_t agentic_ai_lab_aitia_gitops_evaluate(char *payload,
+ agentic_ai_lab_aitia_result *result);
-static void poo_flow_aitia_native_phase(int32_t phase) {
+static void agentic_ai_lab_aitia_native_phase(int32_t phase) {
fprintf(stderr, "[lambda-aitia-native] scheme-phase=%d\n", phase);
fflush(stderr);
}
-static int poo_flow_aitia_c_round_trip(void) {
+static int agentic_ai_lab_aitia_c_round_trip(void) {
static const char input[] =
- "{\"event\":\"pull-request\",\"repository\":\"tao3k/poo-flow\","
+ "{\"event\":\"pull-request\",\"repository\":\"tao3k/agentic-ai-lab\","
"\"revision\":\"0123456789abcdef\",\"source-ref\":\"feature/aitia\","
"\"target-ref\":\"develop\",\"pull-request\":42,\"checks\":["
"{\"name\":\"commit-policy\",\"conclusion\":\"success\"},"
"{\"name\":\"build\",\"conclusion\":\"success\"},"
"{\"name\":\"unit-test\",\"conclusion\":\"success\"},"
"{\"name\":\"nasa-7150-2d\",\"conclusion\":\"success\"}]}";
- poo_flow_aitia_result result;
+ agentic_ai_lab_aitia_result result;
static const char plan_input[] = "{\"lifecycle-id\":\"release/42\"}";
- if (poo_flow_aitia_abi_revision() != 2u) return 1;
- poo_flow_aitia_result_init(&result);
- if (poo_flow_aitia_descriptor(&result) != 0 || result.payload == NULL ||
+ if (agentic_ai_lab_aitia_abi_revision() != 2u) return 1;
+ agentic_ai_lab_aitia_result_init(&result);
+ if (agentic_ai_lab_aitia_descriptor(&result) != 0 || result.payload == NULL ||
strstr((const char *)result.payload,
"lambda-aitia.native-descriptor") == NULL)
return 2;
- poo_flow_aitia_result_release(&result);
- if (poo_flow_aitia_sdlc_flow_plan((char *)plan_input, &result) != 0 ||
+ agentic_ai_lab_aitia_result_release(&result);
+ if (agentic_ai_lab_aitia_sdlc_flow_plan((char *)plan_input, &result) != 0 ||
result.payload == NULL ||
strstr((const char *)result.payload,
"lambda-aitia.sdlc-flow-plan") == NULL ||
strstr((const char *)result.payload,
"release/42/effect") == NULL) {
- poo_flow_aitia_result_release(&result);
+ agentic_ai_lab_aitia_result_release(&result);
return 3;
}
- poo_flow_aitia_result_release(&result);
- if (poo_flow_aitia_gitops_evaluate((char *)input, &result) != 0 ||
+ agentic_ai_lab_aitia_result_release(&result);
+ if (agentic_ai_lab_aitia_gitops_evaluate((char *)input, &result) != 0 ||
result.payload == NULL ||
strstr((const char *)result.payload, "\"accepted\":true") == NULL) {
- poo_flow_aitia_result_release(&result);
+ agentic_ai_lab_aitia_result_release(&result);
return 4;
}
- poo_flow_aitia_result_release(&result);
+ agentic_ai_lab_aitia_result_release(&result);
return 0;
}
END-C
)
-(def-C-type poo_flow_aitia_result "poo_flow_aitia_result")
-(def-C-type poo_flow_aitia_result-borrowed-ptr*
- (pointer poo_flow_aitia_result
- (poo_flow_aitia_result-borrowed-ptr*)))
+(def-C-type agentic_ai_lab_aitia_result "agentic_ai_lab_aitia_result")
+(def-C-type agentic_ai_lab_aitia_result-borrowed-ptr*
+ (pointer agentic_ai_lab_aitia_result
+ (agentic_ai_lab_aitia_result-borrowed-ptr*)))
-(def-C-lambda poo_flow_aitia_result-status
- (poo_flow_aitia_result-borrowed-ptr*) int32
+(def-C-lambda agentic_ai_lab_aitia_result-status
+ (agentic_ai_lab_aitia_result-borrowed-ptr*) int32
"___return (___arg1->status);")
-(def-C-lambda poo_flow_aitia_result-status-set!
- (poo_flow_aitia_result-borrowed-ptr* int32) void
+(def-C-lambda agentic_ai_lab_aitia_result-status-set!
+ (agentic_ai_lab_aitia_result-borrowed-ptr* int32) void
"___arg1->status = ___arg2; ___return;")
-(def-C-lambda poo-flow-aitia-native-phase
+(def-C-lambda agentic-ai-lab-aitia-native-phase
(int32) void
- "poo_flow_aitia_native_phase(___arg1); ___return;")
+ "agentic_ai_lab_aitia_native_phase(___arg1); ___return;")
-(def-C-lambda poo-flow-aitia-result-set-bytes!
- (poo_flow_aitia_result-borrowed-ptr* scheme-object) void
+(def-C-lambda agentic-ai-lab-aitia-result-set-bytes!
+ (agentic_ai_lab_aitia_result-borrowed-ptr* scheme-object) void
#<payload);
___arg1->payload = NULL;
@@ -130,73 +133,73 @@ END-C
)
(def-C-lambda aitia-c-round-trip () int
- "poo_flow_aitia_c_round_trip")
+ "agentic_ai_lab_aitia_c_round_trip")
(begin-foreign
- (c-define (poo-flow-aitia-abi-revision)
- () unsigned-int32 "poo_flow_aitia_abi_revision" "extern"
- (poo-flow/lambda-aitia/bindings/c/aitia-contract#aitia-abi-revision))
+ (c-define (agentic-ai-lab-aitia-abi-revision)
+ () unsigned-int32 "agentic_ai_lab_aitia_abi_revision" "extern"
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-contract#aitia-abi-revision))
- (c-define (poo-flow-aitia-descriptor result)
- (poo_flow_aitia_result-borrowed-ptr*) int32
- "poo_flow_aitia_descriptor" "extern"
+ (c-define (agentic-ai-lab-aitia-descriptor result)
+ (agentic_ai_lab_aitia_result-borrowed-ptr*) int32
+ "agentic_ai_lab_aitia_descriptor" "extern"
(with-exception-catcher
(lambda (exception)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo_flow_aitia_result-status-set! result -1)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-result-set-bytes!
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic_ai_lab_aitia_result-status-set! result -1)
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-result-set-bytes!
result (string->utf8
- (poo-flow/lambda-aitia/bindings/c/aitia-contract#aitia-error-payload
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-contract#aitia-error-payload
exception)))
-1)
(lambda ()
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-native-phase 101)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo_flow_aitia_result-status-set! result 0)
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-native-phase 101)
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic_ai_lab_aitia_result-status-set! result 0)
(let* ((payload
- (poo-flow/lambda-aitia/bindings/c/aitia-contract#aitia-descriptor-payload))
- (_ (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-native-phase 102))
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-contract#aitia-descriptor-payload))
+ (_ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-native-phase 102))
(bytes (string->utf8 payload)))
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-native-phase 103)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-result-set-bytes!
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-native-phase 103)
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-result-set-bytes!
result bytes)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-native-phase 104))
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo_flow_aitia_result-status result))))
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-native-phase 104))
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic_ai_lab_aitia_result-status result))))
- (c-define (poo-flow-aitia-gitops-evaluate payload result)
- (UTF-8-string poo_flow_aitia_result-borrowed-ptr*) int32
- "poo_flow_aitia_gitops_evaluate" "extern"
+ (c-define (agentic-ai-lab-aitia-gitops-evaluate payload result)
+ (UTF-8-string agentic_ai_lab_aitia_result-borrowed-ptr*) int32
+ "agentic_ai_lab_aitia_gitops_evaluate" "extern"
(with-exception-catcher
(lambda (exception)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo_flow_aitia_result-status-set! result -1)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-result-set-bytes!
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic_ai_lab_aitia_result-status-set! result -1)
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-result-set-bytes!
result (string->utf8
- (poo-flow/lambda-aitia/bindings/c/aitia-contract#aitia-error-payload
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-contract#aitia-error-payload
exception)))
-1)
(lambda ()
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo_flow_aitia_result-status-set! result 0)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-result-set-bytes!
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic_ai_lab_aitia_result-status-set! result 0)
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-result-set-bytes!
result
(string->utf8
- (poo-flow/lambda-aitia/bindings/c/aitia-contract#aitia-gitops-evaluate-payload
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-contract#aitia-gitops-evaluate-payload
payload)))
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo_flow_aitia_result-status result))))
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic_ai_lab_aitia_result-status result))))
- (c-define (poo-flow-aitia-sdlc-flow-plan payload result)
- (UTF-8-string poo_flow_aitia_result-borrowed-ptr*) int32
- "poo_flow_aitia_sdlc_flow_plan" "extern"
+ (c-define (agentic-ai-lab-aitia-sdlc-flow-plan payload result)
+ (UTF-8-string agentic_ai_lab_aitia_result-borrowed-ptr*) int32
+ "agentic_ai_lab_aitia_sdlc_flow_plan" "extern"
(with-exception-catcher
(lambda (exception)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo_flow_aitia_result-status-set! result -1)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-result-set-bytes!
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic_ai_lab_aitia_result-status-set! result -1)
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-result-set-bytes!
result (string->utf8
- (poo-flow/lambda-aitia/bindings/c/aitia-contract#aitia-error-payload
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-contract#aitia-error-payload
exception)))
-1)
(lambda ()
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo_flow_aitia_result-status-set! result 0)
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo-flow-aitia-result-set-bytes!
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic_ai_lab_aitia_result-status-set! result 0)
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic-ai-lab-aitia-result-set-bytes!
result
(string->utf8
- (poo-flow/lambda-aitia/bindings/c/aitia-contract#aitia-sdlc-flow-plan-payload
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-contract#aitia-sdlc-flow-plan-payload
payload)))
- (poo-flow/lambda-aitia/bindings/c/aitia-native#poo_flow_aitia_result-status result)))))
+ (agentic-ai-lab/lambda-aitia/bindings/c/aitia-native#agentic_ai_lab_aitia_result-status result)))))
diff --git a/bindings/c/aitia-runtime.c b/bindings/c/aitia-runtime.c
index b51f114..2817ba5 100644
--- a/bindings/c/aitia-runtime.c
+++ b/bindings/c/aitia-runtime.c
@@ -2,39 +2,44 @@
//
// SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-/* ___VERSION and POO_FLOW_AITIA_LINKER come from the generated link unit. */
+/* ___VERSION and AGENTIC_AI_LAB_AITIA_LINKER come from the generated link unit. */
#include "gambit.h"
#include
+#include
-#ifndef POO_FLOW_AITIA_LINKER
-#error "POO_FLOW_AITIA_LINKER must name the generated Gambit link-unit linker"
+#ifndef AGENTIC_AI_LAB_AITIA_LINKER
+#error "AGENTIC_AI_LAB_AITIA_LINKER must name the generated Gambit link-unit linker"
#endif
___BEGIN_NEW_LNK
-___DEF_NEW_LNK(POO_FLOW_AITIA_LINKER)
+___DEF_NEW_LNK(AGENTIC_AI_LAB_AITIA_LINKER)
___END_NEW_LNK
-static int poo_flow_aitia_runtime_initialized = 0;
+static int agentic_ai_lab_aitia_runtime_initialized = 0;
-int32_t poo_flow_aitia_runtime_init(void) {
+int32_t agentic_ai_lab_aitia_runtime_init(void) {
___setup_params_struct setup_params;
___SCMOBJ status;
- if (poo_flow_aitia_runtime_initialized) return 0;
+ if (agentic_ai_lab_aitia_runtime_initialized) return 0;
___setup_params_reset(&setup_params);
setup_params.version = ___VERSION;
- setup_params.linker = POO_FLOW_AITIA_LINKER;
+ setup_params.linker = AGENTIC_AI_LAB_AITIA_LINKER;
/* Embedded callers must report uncaught Scheme errors without a REPL. */
setup_params.debug_settings = ___DEBUG_SETTINGS_INITIAL;
status = ___setup(&setup_params);
- if (status != ___FIX(___NO_ERR)) return -1;
- poo_flow_aitia_runtime_initialized = 1;
+ if (status != ___FIX(___NO_ERR)) {
+ (void)fprintf(stderr, "[lambda-aitia-native] setup-error=%ld\n",
+ (long)___INT(status));
+ return -1;
+ }
+ agentic_ai_lab_aitia_runtime_initialized = 1;
return 0;
}
-void poo_flow_aitia_runtime_shutdown(void) {
- if (!poo_flow_aitia_runtime_initialized) return;
+void agentic_ai_lab_aitia_runtime_shutdown(void) {
+ if (!agentic_ai_lab_aitia_runtime_initialized) return;
___cleanup();
- poo_flow_aitia_runtime_initialized = 0;
+ agentic_ai_lab_aitia_runtime_initialized = 0;
}
diff --git a/bindings/c/include/lambda_aitia/aitia.h b/bindings/c/include/lambda_aitia/aitia.h
index 5732e0f..17ae911 100644
--- a/bindings/c/include/lambda_aitia/aitia.h
+++ b/bindings/c/include/lambda_aitia/aitia.h
@@ -13,25 +13,25 @@ extern "C" {
#endif
/* Public names stay stable; negotiate this metadata before calling. */
-#define POO_FLOW_AITIA_ABI_REVISION 2u
+#define AGENTIC_AI_LAB_AITIA_ABI_REVISION 2u
typedef struct {
int32_t status;
/* Owned UTF-8 bytes, NUL-terminated; length excludes the NUL byte. */
uint8_t *payload;
size_t length;
-} poo_flow_aitia_result;
-
-int32_t poo_flow_aitia_runtime_init(void);
-void poo_flow_aitia_runtime_shutdown(void);
-void poo_flow_aitia_result_init(poo_flow_aitia_result *result);
-void poo_flow_aitia_result_release(poo_flow_aitia_result *result);
-uint32_t poo_flow_aitia_abi_revision(void);
-int32_t poo_flow_aitia_descriptor(poo_flow_aitia_result *result);
-int32_t poo_flow_aitia_sdlc_flow_plan(char *payload,
- poo_flow_aitia_result *result);
-int32_t poo_flow_aitia_gitops_evaluate(char *payload,
- poo_flow_aitia_result *result);
+} agentic_ai_lab_aitia_result;
+
+int32_t agentic_ai_lab_aitia_runtime_init(void);
+void agentic_ai_lab_aitia_runtime_shutdown(void);
+void agentic_ai_lab_aitia_result_init(agentic_ai_lab_aitia_result *result);
+void agentic_ai_lab_aitia_result_release(agentic_ai_lab_aitia_result *result);
+uint32_t agentic_ai_lab_aitia_abi_revision(void);
+int32_t agentic_ai_lab_aitia_descriptor(agentic_ai_lab_aitia_result *result);
+int32_t agentic_ai_lab_aitia_sdlc_flow_plan(char *payload,
+ agentic_ai_lab_aitia_result *result);
+int32_t agentic_ai_lab_aitia_gitops_evaluate(char *payload,
+ agentic_ai_lab_aitia_result *result);
#ifdef __cplusplus
}
diff --git a/bindings/c/tests/aitia-dynamic-harness.c b/bindings/c/tests/aitia-dynamic-harness.c
index ed080fc..c85de99 100644
--- a/bindings/c/tests/aitia-dynamic-harness.c
+++ b/bindings/c/tests/aitia-dynamic-harness.c
@@ -27,10 +27,10 @@ typedef void *library_symbol;
typedef uint32_t (*abi_revision_fn)(void);
typedef int32_t (*runtime_init_fn)(void);
typedef void (*runtime_shutdown_fn)(void);
-typedef int32_t (*descriptor_fn)(poo_flow_aitia_result *);
-typedef int32_t (*payload_operation_fn)(char *, poo_flow_aitia_result *);
-typedef void (*result_init_fn)(poo_flow_aitia_result *);
-typedef void (*result_release_fn)(poo_flow_aitia_result *);
+typedef int32_t (*descriptor_fn)(agentic_ai_lab_aitia_result *);
+typedef int32_t (*payload_operation_fn)(char *, agentic_ai_lab_aitia_result *);
+typedef void (*result_init_fn)(agentic_ai_lab_aitia_result *);
+typedef void (*result_release_fn)(agentic_ai_lab_aitia_result *);
static int load_symbol(library_handle library, const char *name,
void *destination, size_t destination_size) {
@@ -54,7 +54,7 @@ int main(int argc, char **argv) {
payload_operation_fn sdlc_flow_plan;
result_init_fn result_init;
result_release_fn result_release;
- poo_flow_aitia_result result;
+ agentic_ai_lab_aitia_result result;
char plan_input[] = "{\"lifecycle-id\":\"release/42\"}";
if (argc != 2) return 64;
@@ -69,19 +69,19 @@ int main(int argc, char **argv) {
return 1;
}
native_phase("library-open-complete");
- if (!load_symbol(library, "poo_flow_aitia_runtime_init", &runtime_init,
+ if (!load_symbol(library, "agentic_ai_lab_aitia_runtime_init", &runtime_init,
sizeof(runtime_init)) ||
- !load_symbol(library, "poo_flow_aitia_runtime_shutdown",
+ !load_symbol(library, "agentic_ai_lab_aitia_runtime_shutdown",
&runtime_shutdown, sizeof(runtime_shutdown)) ||
- !load_symbol(library, "poo_flow_aitia_abi_revision", &abi_revision,
+ !load_symbol(library, "agentic_ai_lab_aitia_abi_revision", &abi_revision,
sizeof(abi_revision)) ||
- !load_symbol(library, "poo_flow_aitia_descriptor", &descriptor,
+ !load_symbol(library, "agentic_ai_lab_aitia_descriptor", &descriptor,
sizeof(descriptor)) ||
- !load_symbol(library, "poo_flow_aitia_sdlc_flow_plan", &sdlc_flow_plan,
+ !load_symbol(library, "agentic_ai_lab_aitia_sdlc_flow_plan", &sdlc_flow_plan,
sizeof(sdlc_flow_plan)) ||
- !load_symbol(library, "poo_flow_aitia_result_init", &result_init,
+ !load_symbol(library, "agentic_ai_lab_aitia_result_init", &result_init,
sizeof(result_init)) ||
- !load_symbol(library, "poo_flow_aitia_result_release", &result_release,
+ !load_symbol(library, "agentic_ai_lab_aitia_result_release", &result_release,
sizeof(result_release))) {
LIBRARY_CLOSE(library);
return 2;
@@ -92,7 +92,7 @@ int main(int argc, char **argv) {
return 3;
}
native_phase("runtime-init-complete");
- if (abi_revision() != POO_FLOW_AITIA_ABI_REVISION) {
+ if (abi_revision() != AGENTIC_AI_LAB_AITIA_ABI_REVISION) {
runtime_shutdown();
LIBRARY_CLOSE(library);
return 4;
diff --git a/bindings/c/tests/aitia-header-harness.c b/bindings/c/tests/aitia-header-harness.c
index 4fad6fc..e8f8976 100644
--- a/bindings/c/tests/aitia-header-harness.c
+++ b/bindings/c/tests/aitia-header-harness.c
@@ -6,13 +6,13 @@
#include
-_Static_assert(offsetof(poo_flow_aitia_result, status) == 0u,
+_Static_assert(offsetof(agentic_ai_lab_aitia_result, status) == 0u,
"status must be the first field");
-_Static_assert(offsetof(poo_flow_aitia_result, payload) >
- offsetof(poo_flow_aitia_result, status),
+_Static_assert(offsetof(agentic_ai_lab_aitia_result, payload) >
+ offsetof(agentic_ai_lab_aitia_result, status),
"payload must follow status");
-_Static_assert(offsetof(poo_flow_aitia_result, length) >
- offsetof(poo_flow_aitia_result, payload),
+_Static_assert(offsetof(agentic_ai_lab_aitia_result, length) >
+ offsetof(agentic_ai_lab_aitia_result, payload),
"length must follow payload");
-int main(void) { return POO_FLOW_AITIA_ABI_REVISION == 2u ? 0 : 1; }
+int main(void) { return AGENTIC_AI_LAB_AITIA_ABI_REVISION == 2u ? 0 : 1; }
diff --git a/bindings/python/LICENSE b/bindings/python/LICENSE
index bb1680e..debf4b3 100644
--- a/bindings/python/LICENSE
+++ b/bindings/python/LICENSE
@@ -1,7 +1,7 @@
SPDX-FileCopyrightText: 2026 tao3k team and Contributors
SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-The original work in the POO Flow repository is licensed under both of the
+The original work in the Agentic AI Lab repository is licensed under both of the
following licenses. The AND operator is intentional: recipients must comply
with the terms of both licenses.
diff --git a/bindings/python/README.md b/bindings/python/README.md
index 2aff181..23e3f9a 100644
--- a/bindings/python/README.md
+++ b/bindings/python/README.md
@@ -3,26 +3,119 @@ SPDX-FileCopyrightText: 2026 tao3k team and Contributors
SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-->
-# Lambda Aitia Python SDLC Runtime
+# Lambda Aitia Python Runtime
This is Lambda Aitia's production Python project, not an example package. It
-is the Python runtime surface for the complete SDLC lifecycle:
+is the Python runtime surface for Aitia across the complete SDLC: requirements,
+design, algorithms and implementation strategies, testing, delivery, operation
+and evolution. The first planning API exposes the assurance/execution protocol
+used within that lifecycle:
-```text
-change -> invalidate -> plan -> verify -> admit -> decide -> authorize -> effect
+```mermaid
+flowchart TD
+ C["change
identified"] --> I["invalidate
dependent support stale"]
+ I --> P["plan
obligations pending"]
+ P --> V["verify
candidate results produced"]
+ V --> A["admit
evidence accepted within scope"]
+ A --> D["decide
decision current"]
+ D --> U["authorize
bounded effect permitted"]
+ U --> E["effect
execution receipt recorded"]
+ V -->|failed or unresolved| P
+ A -->|relevant premise changes| I
+ U -->|revoked or expired| I
```
+These are semantic workflow states, not implementation-progress labels.
+Feedback edges describe lifecycle reassessment, not edges returned by the
+current API. The API projects only an inert, ordered eight-stage DAG, not
+executed transitions. Admission, decision, authorization and execution each
+require their own checked receipt.
+
Lambda Aitia Scheme owns the lifecycle vocabulary, assurance semantics,
-decisions and receipts. POO Flow owns the reusable Graph/DAG and runtime
+decisions and receipts. Agentic AI Lab owns the reusable Graph/DAG and runtime
mechanisms. The Python package consumes those contracts through the stable C
ABI and does not reimplement either owner's semantics.
-The current production surface publishes and validates the canonical lifecycle
+AnyIO is a production dependency for the runtime-wide asynchronous execution
+boundary: structured task lifetimes, cancellation and bounded concurrency will
+apply across all Aitia capabilities. The current native session is
+thread-affine, so it must not be passed into `anyio.to_thread.run_sync`; an async
+*native-session* entry point requires a qualified owner-preserving transport
+before it can claim execution.
+
+`lambda_aitia.verification.run_pytest_frozen_async` now runs the bounded pytest
+observer in an AnyIO worker, with an optional capacity limiter. Cancellation
+waits for its timeout-bound process-group cleanup; it never abandons pytest or
+passes an `AitiaNativeSession` to that worker. This returns a source-bound
+observation only, not a Scheme Host admission or authorization.
+
+The current production surface publishes and validates the assurance-flow
DAG through `SdlcRuntime.plan()`. The returned receipt is deliberately inert:
it cannot claim release authorization or runtime execution. Stage execution is
added only as each real Scheme operation and attributable receipt becomes
available; the package will never simulate completion with Python callbacks.
+[RFC 0004](../../docs/rfcs/0004-sdlc-design-and-causal-trajectories.org) defines
+the connected design and trajectory qualification. Agentic AI Lab owns generic
+temporal/causal mechanisms; this project integrates actual tool execution and
+scoped observations through its native boundary. Reusable upstream checker,
+model and harness qualification is pending. MRR integration is deferred beyond
+the current Python stage.
+
+`lambda_aitia.verification.run_pytest` is a production subprocess observation
+surface, not a Host-issued admission. It preserves exit status, selected test
+count, JUnit digest and source-tree digest; zero collected tests, skipped-only
+runs, timeouts, missing reports and source drift do not pass its obligation.
+It captures a bounded, canonical source-byte payload and executes pytest only
+from a separately materialized copy; selectors cannot escape that copy.
+`capture_source_tree` and `run_pytest_frozen` expose the same payload boundary
+for a future Host-owned source reader. This still does not prove repository
+provenance, interpreter independence, or trusted external services. The
+Assurance Host owns admission, revocation and execution authority.
+
+`prepare_org_edit_review` is the Aitia-owned preflight for an Org-native
+engineering workspace. It accepts a node ID, byte span and expected old bytes
+from an upstream Orgize projection, checks them against the exact projected
+source digest, rejects stale, moved, duplicate or overlapping edits, and
+returns an inert owner-review proposal. It does not parse Org, apply edits or
+grant authorization. The existing Orgize PR #15 now supplies a Scheme-AOT
+graph-backed source transformation that rechecks node ownership and produces
+candidate text. Aitia-to-Orgize transport and owner-approved persistence are
+still pending; this Python API does not claim those steps.
+
+```python
+from lambda_aitia import OrgNodeEdit, prepare_org_edit_review
+
+review = prepare_org_edit_review(
+ source_path,
+ source_id="design/decision.org",
+ projected_source_digest=orgize_projection.source_digest,
+ edits=(OrgNodeEdit(node_id, start_byte, end_byte, expected_old, replacement),),
+)
+assert review.source_current(source_path) # freshness only; not approval
+```
+
+The POSIX verifier runs pytest in its own process group and stops that group
+on timeout or output overflow. `max_output_bytes` defaults to 8 MiB; only the
+last 8 KiB is retained in the observation. Cleanup uncertainty is reported as
+`control-error`, never as a passing result.
+
+`AitiaNativeSession` keeps one Gambit transport runtime alive across calls to
+`SdlcRuntime(session=...)`, `evaluate_gitops(..., session=...)`, and
+`evaluate_org_contract(..., session=...)`. It is
+process-exclusive and thread-affine; use it as a context manager. It does not
+issue Host verification seals or admission capabilities. A separate Scheme
+Host operation and opaque ABI handles are still required before Python
+observations can be admitted.
+
+`evaluate_org_contract` calls Orgize's versioned C ABI from the same initialized
+native link unit. The input is a sequence of `OrgElementFact` values already
+projected by the source owner, not raw Org text. Orgize owns Element graph
+queries and Contract evaluation; Aitia does not parse Org or treat a matching
+contract as authenticated provenance, review, admission, or effect authority.
+The binary row/result layout and revision are defined in Orgize's
+`bindings/c/include/orgize.h`. Aitia checks the revision before each call.
+
```python
from lambda_aitia import SdlcRuntime
@@ -36,22 +129,35 @@ Builds require `LAMBDA_AITIA_NATIVE_LIBRARY` to identify the qualified native
library that will be bundled into the wheel.
The binding is an independent uv project owned entirely by Lambda Aitia. From
-this directory, synchronize and test the locked environment with:
+the repository root, refresh the generated CFFI extension and check its current
+Orgize row type with:
```sh
-env -u SDKROOT uv sync --locked --extra test
-env -u SDKROOT uv run --locked --extra test pytest
+just dev-python
```
-Build the distributable wheel after producing the Scheme-native library:
+To remove only stale generated CFFI modules and their temporary C objects:
```sh
-LAMBDA_AITIA_NATIVE_LIBRARY=/absolute/path/to/libpoo_flow_aitia.dylib \
- env -u SDKROOT uv sync --locked --extra test
-LAMBDA_AITIA_NATIVE_LIBRARY=/absolute/path/to/libpoo_flow_aitia.dylib \
- env -u SDKROOT uv build --wheel --offline --no-build-isolation
+just clean-python-cffi
```
+`dev-python` requires the declared Agentic AI Lab/Gerbil dependencies, including
+Orgize's C header, in the selected `GERBIL_PATH`. It cleans and rebuilds only
+the in-place CFFI extension, without compiling Agentic AI Lab or replacing the native
+library. Run `just check-native` against the qualified Agentic AI Lab version for
+the complete Scheme/native/Python and wheel qualification.
+The `justfile` removes `SDKROOT` only on Darwin; it does not alter that
+environment variable on Linux.
+
+`just check-native` also installs that wheel in a fresh uv environment outside
+the repository, runs the native plan, reproduces a lost-acknowledgement bug in
+two real worker processes and a loopback HTTP service, checks the corrected
+worker through the AnyIO frozen-source verifier while the main thread retains
+one native session, then rejects the old observation after a source edit. This
+is a known fault-injection qualification case, not a newly discovered
+production defect or an Assurance Host seal.
+
On Darwin, the repository `justfile` selects `/usr/bin/cc`, unsets `SDKROOT`
for Gerbil invocations, and keeps the deployment metadata consistent with the
installed Gerbil/Gambit native objects. The large Gambit closure uses DWARF
diff --git a/bindings/python/pyproject.toml b/bindings/python/pyproject.toml
index 897797b..e44a773 100644
--- a/bindings/python/pyproject.toml
+++ b/bindings/python/pyproject.toml
@@ -9,12 +9,12 @@ build-backend = "setuptools.build_meta"
[project]
name = "lambda-aitia"
version = "0.1.0"
-description = "Production Python runtime for Lambda Aitia's Scheme-owned SDLC"
+description = "Production Python runtime for Lambda Aitia"
readme = "README.md"
requires-python = ">=3.11"
license = "Apache-2.0 AND LGPL-2.1-or-later"
license-files = ["LICENSE"]
-dependencies = ["cffi>=2.0"]
+dependencies = ["anyio>=4.14.1", "cffi>=2.0"]
[project.optional-dependencies]
test = ["pytest>=8.0", "setuptools>=77"]
diff --git a/bindings/python/qualification/job_executor/README.org b/bindings/python/qualification/job_executor/README.org
new file mode 100644
index 0000000..e1c7195
--- /dev/null
+++ b/bindings/python/qualification/job_executor/README.org
@@ -0,0 +1,59 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Python job-executor qualification case
+
+This case belongs to the production =bindings/python= uv project. Its worker
+is a real child process, its task ledger and provider effect log are SQLite
+files, and the effect provider is a loopback HTTP server. The service commits
+once, withholds the first acknowledgement, and lets a restarted worker retry.
+
+The =buggy= strategy generates a new provider idempotency key after restart:
+the test must fail with two commits. The =fixed= strategy retains a key derived
+from the logical operation: the same test must pass with one commit and a
+completed task. This is a deliberate known-fault replay, not a novel bug.
+
+The installed-wheel project test copies the scenario outside the checkout,
+installs the built wheel and locked dependencies in a new uv environment, and
+runs both strategies through =lambda_aitia.verification.run_pytest=. It also
+changes one source file after the passing observation and requires that
+=source_current= reject the old observation. The observation is not a Scheme
+Host admission. Pytest runs from captured source bytes in a fresh directory,
+but repository provenance, Scheme Host admission, independent provider trust,
+and a Runtime effect gate remain open.
+
+The case challenges the original guarantee's *per key* scope: a provider can
+honor that scope while a logical operation is duplicated with two keys.
+[[file:../../../../docs/adrs/0008-stable-operation-key-after-lost-ack.org][ADR 0008]]
+proposes a revised logical-operation guarantee and keeps its acceptance and
+re-verification separate from this test result.
+
+* Coverage boundary
+
+The worker has one fixed job and constant payload; the provider's single SQLite
+row represents both the deduplication key and the effect. This is not a model
+of multi-tenant identity, changed intent, retention expiry, concurrent attempts
+or atomicity across a ledger and an independent external service. Fixed mode
+repairs the injected identity fault, not every idempotency failure mode.
+
+ADR 0008's r2 coverage matrix assigns those remaining qualifications to their
+owners. Existing Agentic AI Lab Cedar authorization and Runtime effect mechanisms
+must be reused, not reimplemented in this fixture. A Cedar permit answers an
+authorization question; it does not establish provider commit uniqueness or
+resolve an unknown outcome after a lost acknowledgement.
+
+* Focused replay receipt — 2026-09-24
+
+The unchanged worker/test sources at Aitia commit
+=f3438241780e863db6c0b518d86628b540f96cd1= were rerun during the ADR r2 audit.
+From =bindings/python=, =uv run --locked --no-sync= ran
+=pytest qualification/job_executor/test_unique_effect.py= with a process-scoped
+=AITIA_QUALIFICATION_MODE=:
+
+- =fixed=: one test passed; one commit and task completion were asserted.
+- =buggy=: the expected negative test failed specifically at =committed == 1=,
+ observing two commits, rather than failing to start the worker/provider.
+
+This was a focused source-fixture replay in the existing uv environment, not a
+new installed-wheel qualification or Cedar/Runtime execution receipt. The new
+owner matrix does not promote untested boundaries to passing evidence.
diff --git a/bindings/python/qualification/job_executor/test_unique_effect.py b/bindings/python/qualification/job_executor/test_unique_effect.py
new file mode 100644
index 0000000..77fedc6
--- /dev/null
+++ b/bindings/python/qualification/job_executor/test_unique_effect.py
@@ -0,0 +1,72 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+#
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Project qualification of acknowledgement loss in real worker processes."""
+
+from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
+import os
+from pathlib import Path
+import sqlite3
+import subprocess
+import sys
+import tempfile
+from threading import Thread
+
+
+def test_unique_effect_after_lost_ack_and_restart() -> None:
+ mode = os.environ["AITIA_QUALIFICATION_MODE"]
+ with tempfile.TemporaryDirectory(prefix="aitia-worker-state-") as directory:
+ state = Path(directory)
+ effects = state / "effects.sqlite"
+ ledger = state / "tasks.sqlite"
+
+ class EffectHandler(BaseHTTPRequestHandler):
+ def do_POST(self) -> None:
+ key = self.headers.get("Idempotency-Key")
+ assert key
+ with sqlite3.connect(effects) as database:
+ database.execute(
+ "create table if not exists effects "
+ "(key text primary key, payload blob not null)"
+ )
+ previous = database.execute(
+ "select count(*) from effects"
+ ).fetchone()[0]
+ database.execute(
+ "insert or ignore into effects values (?, ?)",
+ (key, self.rfile.read(int(self.headers["Content-Length"]))),
+ )
+ if previous == 0:
+ # The service committed; the worker never receives its ACK.
+ self.close_connection = True
+ return
+ self.send_response(200)
+ self.end_headers()
+
+ def log_message(self, format: str, *args: object) -> None:
+ pass
+
+ server = ThreadingHTTPServer(("127.0.0.1", 0), EffectHandler)
+ thread = Thread(target=server.serve_forever, daemon=True)
+ thread.start()
+ try:
+ endpoint = f"http://127.0.0.1:{server.server_port}/effect"
+ command = (sys.executable, str(Path(__file__).with_name("worker.py")),
+ str(ledger), endpoint, mode)
+ first = subprocess.run(command, check=False, timeout=10)
+ second = subprocess.run(command, check=False, timeout=10)
+ assert first.returncode == 2
+ assert second.returncode == 0
+ with sqlite3.connect(effects) as database:
+ committed = database.execute("select count(*) from effects").fetchone()[0]
+ with sqlite3.connect(ledger) as database:
+ final_state = database.execute(
+ "select state from tasks where job = 'job-42'"
+ ).fetchone()[0]
+ assert committed == 1
+ assert final_state == "complete"
+ finally:
+ server.shutdown()
+ server.server_close()
+ thread.join(timeout=5)
diff --git a/bindings/python/qualification/job_executor/worker.py b/bindings/python/qualification/job_executor/worker.py
new file mode 100644
index 0000000..dc8ab9d
--- /dev/null
+++ b/bindings/python/qualification/job_executor/worker.py
@@ -0,0 +1,41 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+#
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Qualification worker with a persistent task ledger and HTTP side effect."""
+
+import sqlite3
+import sys
+from urllib.request import ProxyHandler, Request, build_opener
+from uuid import uuid4
+
+
+def execute(ledger_path: str, endpoint: str, mode: str) -> int:
+ if mode not in ("buggy", "fixed"):
+ raise ValueError("unknown worker mode")
+ with sqlite3.connect(ledger_path) as ledger:
+ ledger.execute(
+ "create table if not exists tasks (job text primary key, state text not null)"
+ )
+ ledger.execute("insert or ignore into tasks values ('job-42', 'pending')")
+ state = ledger.execute(
+ "select state from tasks where job = 'job-42'"
+ ).fetchone()[0]
+ if state == "complete":
+ return 0
+ # Bug: regenerating the provider key after restart creates a second effect.
+ key = "job-42" if mode == "fixed" else uuid4().hex
+ request = Request(endpoint, data=b"commit", headers={"Idempotency-Key": key})
+ try:
+ with build_opener(ProxyHandler({})).open(request, timeout=3) as response:
+ if response.status != 200:
+ return 2
+ except Exception:
+ return 2
+ with sqlite3.connect(ledger_path) as ledger:
+ ledger.execute("update tasks set state = 'complete' where job = 'job-42'")
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(execute(sys.argv[1], sys.argv[2], sys.argv[3]))
diff --git a/bindings/python/setup.py b/bindings/python/setup.py
index 96b5fdd..79509a0 100644
--- a/bindings/python/setup.py
+++ b/bindings/python/setup.py
@@ -44,9 +44,9 @@ class BuildPyWithAitiaLibrary(build_py):
def run(self) -> None:
super().run()
library_name = {
- "Darwin": "libpoo_flow_aitia.dylib",
- "Windows": "poo_flow_aitia.dll",
- }.get(platform.system(), "libpoo_flow_aitia.so")
+ "Darwin": "libagentic_ai_lab_aitia.dylib",
+ "Windows": "agentic_ai_lab_aitia.dll",
+ }.get(platform.system(), "libagentic_ai_lab_aitia.so")
target = Path(self.build_lib) / "lambda_aitia" / "_native" / "lib"
target.mkdir(parents=True, exist_ok=True)
shutil.copy2(_native_library(), target / library_name)
diff --git a/bindings/python/src/lambda_aitia/__init__.py b/bindings/python/src/lambda_aitia/__init__.py
index 93da0ed..05c02b0 100644
--- a/bindings/python/src/lambda_aitia/__init__.py
+++ b/bindings/python/src/lambda_aitia/__init__.py
@@ -2,17 +2,26 @@
#
# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-"""Production Python runtime for Lambda Aitia's Scheme-owned SDLC."""
+"""Production Python runtime for Lambda Aitia."""
from .gitops import GitOpsDecision, evaluate_gitops
-from .native import AitiaNativeError, descriptor
+from .native import AitiaNativeError, AitiaNativeSession, descriptor
+from .org_contract import OrgContractResult, OrgElementFact, evaluate_org_contract
+from .org_workspace import OrgEditReview, OrgNodeEdit, prepare_org_edit_review
from .runtime import SdlcFlowPlan, SdlcRuntime
__all__ = [
"AitiaNativeError",
+ "AitiaNativeSession",
"GitOpsDecision",
+ "OrgContractResult",
+ "OrgElementFact",
+ "OrgEditReview",
+ "OrgNodeEdit",
"SdlcFlowPlan",
"SdlcRuntime",
"descriptor",
"evaluate_gitops",
+ "evaluate_org_contract",
+ "prepare_org_edit_review",
]
diff --git a/bindings/python/src/lambda_aitia/_native/_build.py b/bindings/python/src/lambda_aitia/_native/_build.py
index 96aed4a..284c58f 100644
--- a/bindings/python/src/lambda_aitia/_native/_build.py
+++ b/bindings/python/src/lambda_aitia/_native/_build.py
@@ -5,12 +5,26 @@
from __future__ import annotations
from pathlib import Path
+import os
from cffi import FFI
ffibuilder = FFI()
ffibuilder.cdef(
"""
+ typedef struct lambda_aitia_python_session lambda_aitia_python_session;
+ lambda_aitia_python_session *lambda_aitia_python_open(
+ const char *library_path, char *error, size_t error_capacity);
+ void lambda_aitia_python_close(lambda_aitia_python_session *session);
+ int lambda_aitia_python_session_call(
+ lambda_aitia_python_session *session,
+ const char *operation,
+ const uint8_t *payload,
+ size_t payload_length,
+ uint8_t **output,
+ size_t *output_length,
+ char *error,
+ size_t error_capacity);
int lambda_aitia_python_call(
const char *library_path,
const char *operation,
@@ -21,19 +35,47 @@
char *error,
size_t error_capacity);
void lambda_aitia_python_release(uint8_t *output);
+ typedef struct {
+ int64_t id;
+ int64_t parent_id;
+ const char *kind;
+ const char *field_name;
+ const char *field_value;
+ } orgize_element_row;
+ typedef struct {
+ int32_t status;
+ uint32_t matched_count;
+ int32_t passed;
+ } orgize_contract_result;
+ int lambda_aitia_python_session_org_contract(
+ lambda_aitia_python_session *session, const orgize_element_row *rows,
+ uint32_t row_count, int64_t scope_id, const char *query_kind,
+ const char *field_name, const char *field_value,
+ uint32_t expectation, uint32_t expected_count,
+ orgize_contract_result *result, char *error, size_t error_capacity);
"""
)
native_dir = Path(__file__).resolve().parent
c_binding_dir = native_dir.parents[3] / "c"
+gerbil_path = os.environ.get("GERBIL_PATH")
+if gerbil_path is None:
+ raise RuntimeError("GERBIL_PATH must identify the installed Orgize dependency")
+orgize_c_dir = (
+ Path(gerbil_path).resolve()
+ / "pkg/github.com/tao3k/orgize/bindings/c/include"
+)
+if not (orgize_c_dir / "orgize.h").is_file():
+ raise RuntimeError("Orgize's public C header is absent; install Agentic AI Lab dependencies")
ffibuilder.set_source(
"lambda_aitia._native._aitia_cffi",
'#include "aitia_shim.c"',
- include_dirs=[str(native_dir), str(c_binding_dir / "include")],
+ include_dirs=[str(native_dir), str(c_binding_dir / "include"), str(orgize_c_dir)],
)
if __name__ == "__main__":
import sys
+ import sysconfig
python_project = Path(__file__).resolve().parents[3]
if str(python_project) not in sys.path:
@@ -43,6 +85,8 @@
sanitize_python_linker_config()
ffibuilder.compile(
tmpdir=str(native_dir / "_build_temp"),
- target=str(native_dir / "_aitia_cffi.*"),
+ target=str(
+ native_dir / ("_aitia_cffi" + sysconfig.get_config_var("EXT_SUFFIX"))
+ ),
verbose=True,
)
diff --git a/bindings/python/src/lambda_aitia/_native/aitia_shim.c b/bindings/python/src/lambda_aitia/_native/aitia_shim.c
index e0b80b3..a94b001 100644
--- a/bindings/python/src/lambda_aitia/_native/aitia_shim.c
+++ b/bindings/python/src/lambda_aitia/_native/aitia_shim.c
@@ -3,7 +3,9 @@
// SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
#include "lambda_aitia/aitia.h"
+#include "orgize.h"
+#include
#include
#include
#include
@@ -27,10 +29,28 @@ typedef void *lambda_aitia_symbol;
typedef uint32_t (*lambda_aitia_revision_fn)(void);
typedef int32_t (*lambda_aitia_runtime_init_fn)(void);
typedef void (*lambda_aitia_runtime_shutdown_fn)(void);
-typedef void (*lambda_aitia_result_init_fn)(poo_flow_aitia_result *);
-typedef void (*lambda_aitia_result_release_fn)(poo_flow_aitia_result *);
-typedef int32_t (*lambda_aitia_descriptor_fn)(poo_flow_aitia_result *);
-typedef int32_t (*lambda_aitia_evaluate_fn)(char *, poo_flow_aitia_result *);
+typedef void (*lambda_aitia_result_init_fn)(agentic_ai_lab_aitia_result *);
+typedef void (*lambda_aitia_result_release_fn)(agentic_ai_lab_aitia_result *);
+typedef int32_t (*lambda_aitia_descriptor_fn)(agentic_ai_lab_aitia_result *);
+typedef int32_t (*lambda_aitia_evaluate_fn)(char *, agentic_ai_lab_aitia_result *);
+typedef uint32_t (*orgize_revision_fn)(void);
+typedef int32_t (*orgize_evaluate_fn)(const orgize_element_row *, uint32_t,
+ int64_t, const char *, const char *,
+ const char *, uint32_t, uint32_t,
+ orgize_contract_result *);
+
+typedef struct lambda_aitia_python_session {
+ lambda_aitia_library library;
+ lambda_aitia_runtime_shutdown_fn runtime_shutdown;
+ lambda_aitia_result_init_fn result_init;
+ lambda_aitia_result_release_fn result_release;
+ lambda_aitia_descriptor_fn descriptor;
+ lambda_aitia_evaluate_fn sdlc_flow_plan;
+ lambda_aitia_evaluate_fn evaluate;
+} lambda_aitia_python_session;
+
+/* Gambit has one process runtime. A live session excludes transient calls. */
+static atomic_flag lambda_aitia_runtime_lease = ATOMIC_FLAG_INIT;
static int lambda_aitia_load_symbol(lambda_aitia_library library,
const char *name, void *destination,
@@ -57,121 +77,187 @@ static const char *lambda_aitia_loader_error(void) {
#endif
}
-void lambda_aitia_python_release(uint8_t *output) { free(output); }
-
-int lambda_aitia_python_call(const char *library_path, const char *operation,
- const uint8_t *payload, size_t payload_length,
- uint8_t **output, size_t *output_length,
- char *error, size_t error_capacity) {
- lambda_aitia_library library;
+lambda_aitia_python_session *lambda_aitia_python_open(
+ const char *library_path, char *error, size_t error_capacity) {
+ lambda_aitia_python_session *session;
lambda_aitia_revision_fn revision;
lambda_aitia_runtime_init_fn runtime_init;
- lambda_aitia_runtime_shutdown_fn runtime_shutdown;
- lambda_aitia_result_init_fn result_init;
- lambda_aitia_result_release_fn result_release;
- lambda_aitia_descriptor_fn descriptor;
- lambda_aitia_evaluate_fn sdlc_flow_plan;
- lambda_aitia_evaluate_fn evaluate;
- poo_flow_aitia_result result;
- char *input = NULL;
- int32_t status;
- if (output == NULL || output_length == NULL || library_path == NULL ||
- operation == NULL) {
- lambda_aitia_write_error(error, error_capacity, "invalid Aitia call");
- return -100;
+ if (library_path == NULL || library_path[0] == '\0') {
+ lambda_aitia_write_error(error, error_capacity, "invalid Aitia library path");
+ return NULL;
}
- *output = NULL;
- *output_length = 0;
- library = LAMBDA_AITIA_OPEN(library_path);
- if (library == NULL) {
+ if (atomic_flag_test_and_set(&lambda_aitia_runtime_lease)) {
+ lambda_aitia_write_error(error, error_capacity,
+ "Lambda Aitia runtime already has an active session");
+ return NULL;
+ }
+ session = (lambda_aitia_python_session *)calloc(1, sizeof(*session));
+ if (session == NULL) {
+ lambda_aitia_write_error(error, error_capacity, "session allocation failed");
+ goto fail_lease;
+ }
+ session->library = LAMBDA_AITIA_OPEN(library_path);
+ if (session->library == NULL) {
lambda_aitia_write_error(error, error_capacity, lambda_aitia_loader_error());
- return -101;
+ goto fail_session;
}
- if (!lambda_aitia_load_symbol(library, "poo_flow_aitia_abi_revision",
+ if (!lambda_aitia_load_symbol(session->library, "agentic_ai_lab_aitia_abi_revision",
&revision, sizeof(revision)) ||
- !lambda_aitia_load_symbol(library, "poo_flow_aitia_runtime_init",
+ !lambda_aitia_load_symbol(session->library, "agentic_ai_lab_aitia_runtime_init",
&runtime_init, sizeof(runtime_init)) ||
- !lambda_aitia_load_symbol(library, "poo_flow_aitia_runtime_shutdown",
- &runtime_shutdown,
- sizeof(runtime_shutdown)) ||
- !lambda_aitia_load_symbol(library, "poo_flow_aitia_result_init",
- &result_init, sizeof(result_init)) ||
- !lambda_aitia_load_symbol(library, "poo_flow_aitia_result_release",
- &result_release, sizeof(result_release)) ||
- !lambda_aitia_load_symbol(library, "poo_flow_aitia_descriptor",
- &descriptor, sizeof(descriptor)) ||
- !lambda_aitia_load_symbol(library, "poo_flow_aitia_sdlc_flow_plan",
- &sdlc_flow_plan, sizeof(sdlc_flow_plan)) ||
- !lambda_aitia_load_symbol(library, "poo_flow_aitia_gitops_evaluate",
- &evaluate, sizeof(evaluate))) {
+ !lambda_aitia_load_symbol(session->library, "agentic_ai_lab_aitia_runtime_shutdown",
+ &session->runtime_shutdown,
+ sizeof(session->runtime_shutdown)) ||
+ !lambda_aitia_load_symbol(session->library, "agentic_ai_lab_aitia_result_init",
+ &session->result_init, sizeof(session->result_init)) ||
+ !lambda_aitia_load_symbol(session->library, "agentic_ai_lab_aitia_result_release",
+ &session->result_release,
+ sizeof(session->result_release)) ||
+ !lambda_aitia_load_symbol(session->library, "agentic_ai_lab_aitia_descriptor",
+ &session->descriptor, sizeof(session->descriptor)) ||
+ !lambda_aitia_load_symbol(session->library, "agentic_ai_lab_aitia_sdlc_flow_plan",
+ &session->sdlc_flow_plan,
+ sizeof(session->sdlc_flow_plan)) ||
+ !lambda_aitia_load_symbol(session->library, "agentic_ai_lab_aitia_gitops_evaluate",
+ &session->evaluate, sizeof(session->evaluate))) {
lambda_aitia_write_error(error, error_capacity,
"Lambda Aitia ABI symbol is absent");
- LAMBDA_AITIA_CLOSE(library);
- return -102;
+ goto fail_library;
}
if (runtime_init() != 0) {
lambda_aitia_write_error(error, error_capacity,
"Lambda Aitia runtime initialization failed");
- LAMBDA_AITIA_CLOSE(library);
- return -103;
+ goto fail_library;
}
- if (revision() != POO_FLOW_AITIA_ABI_REVISION) {
+ if (revision() != AGENTIC_AI_LAB_AITIA_ABI_REVISION) {
lambda_aitia_write_error(error, error_capacity,
"Lambda Aitia ABI revision mismatch");
- runtime_shutdown();
- LAMBDA_AITIA_CLOSE(library);
- return -104;
+ session->runtime_shutdown();
+ goto fail_library;
+ }
+ return session;
+
+fail_library:
+ LAMBDA_AITIA_CLOSE(session->library);
+fail_session:
+ free(session);
+fail_lease:
+ atomic_flag_clear(&lambda_aitia_runtime_lease);
+ return NULL;
+}
+
+void lambda_aitia_python_close(lambda_aitia_python_session *session) {
+ if (session == NULL) return;
+ session->runtime_shutdown();
+ LAMBDA_AITIA_CLOSE(session->library);
+ free(session);
+ atomic_flag_clear(&lambda_aitia_runtime_lease);
+}
+
+void lambda_aitia_python_release(uint8_t *output) { free(output); }
+
+int lambda_aitia_python_session_call(
+ lambda_aitia_python_session *session, const char *operation,
+ const uint8_t *payload, size_t payload_length, uint8_t **output,
+ size_t *output_length, char *error, size_t error_capacity) {
+ agentic_ai_lab_aitia_result result;
+ char *input = NULL;
+ int32_t status;
+
+ if (session == NULL || output == NULL || output_length == NULL ||
+ operation == NULL) {
+ lambda_aitia_write_error(error, error_capacity, "invalid Aitia call");
+ return -100;
}
- result_init(&result);
+ *output = NULL;
+ *output_length = 0;
+ session->result_init(&result);
if (strcmp(operation, "descriptor") == 0) {
- status = descriptor(&result);
+ status = session->descriptor(&result);
} else if (strcmp(operation, "sdlc-flow-plan") == 0 ||
strcmp(operation, "gitops-evaluate") == 0) {
if (payload == NULL || payload_length == 0 || payload_length == SIZE_MAX) {
lambda_aitia_write_error(error, error_capacity,
"Aitia operation requires JSON input");
- result_release(&result);
- runtime_shutdown();
- LAMBDA_AITIA_CLOSE(library);
- return -105;
+ status = -105;
+ goto done;
}
input = (char *)malloc(payload_length + 1u);
if (input == NULL) {
lambda_aitia_write_error(error, error_capacity, "input allocation failed");
- result_release(&result);
- runtime_shutdown();
- LAMBDA_AITIA_CLOSE(library);
- return -106;
+ status = -106;
+ goto done;
}
memcpy(input, payload, payload_length);
input[payload_length] = '\0';
status = strcmp(operation, "sdlc-flow-plan") == 0
- ? sdlc_flow_plan(input, &result)
- : evaluate(input, &result);
- free(input);
+ ? session->sdlc_flow_plan(input, &result)
+ : session->evaluate(input, &result);
} else {
lambda_aitia_write_error(error, error_capacity, "unknown Aitia operation");
- result_release(&result);
- runtime_shutdown();
- LAMBDA_AITIA_CLOSE(library);
- return -107;
+ status = -107;
+ goto done;
}
if (result.payload != NULL && result.length > 0) {
*output = (uint8_t *)malloc(result.length);
if (*output == NULL) {
- result_release(&result);
lambda_aitia_write_error(error, error_capacity,
"output allocation failed");
- runtime_shutdown();
- LAMBDA_AITIA_CLOSE(library);
- return -108;
+ status = -108;
+ goto done;
}
memcpy(*output, result.payload, result.length);
*output_length = result.length;
}
- result_release(&result);
- runtime_shutdown();
- LAMBDA_AITIA_CLOSE(library);
+
+done:
+ free(input);
+ session->result_release(&result);
+ return status;
+}
+
+int lambda_aitia_python_session_org_contract(
+ lambda_aitia_python_session *session, const orgize_element_row *rows,
+ uint32_t row_count, int64_t scope_id, const char *query_kind,
+ const char *field_name, const char *field_value, uint32_t expectation,
+ uint32_t expected_count, orgize_contract_result *result,
+ char *error, size_t error_capacity) {
+ orgize_revision_fn revision;
+ orgize_evaluate_fn evaluate;
+
+ if (session == NULL || result == NULL) {
+ lambda_aitia_write_error(error, error_capacity, "invalid Orgize call");
+ return -100;
+ }
+ if (!lambda_aitia_load_symbol(session->library, "orgize_abi_revision",
+ &revision, sizeof(revision)) ||
+ !lambda_aitia_load_symbol(session->library, "orgize_contract_evaluate",
+ &evaluate, sizeof(evaluate))) {
+ lambda_aitia_write_error(error, error_capacity,
+ "Orgize ABI symbols are absent");
+ return -101;
+ }
+ if (revision() != 1u) {
+ lambda_aitia_write_error(error, error_capacity,
+ "Orgize ABI revision mismatch");
+ return -102;
+ }
+ return evaluate(rows, row_count, scope_id, query_kind, field_name,
+ field_value, expectation, expected_count, result);
+}
+
+int lambda_aitia_python_call(const char *library_path, const char *operation,
+ const uint8_t *payload, size_t payload_length,
+ uint8_t **output, size_t *output_length,
+ char *error, size_t error_capacity) {
+ lambda_aitia_python_session *session =
+ lambda_aitia_python_open(library_path, error, error_capacity);
+ int status;
+ if (session == NULL) return -101;
+ status = lambda_aitia_python_session_call(
+ session, operation, payload, payload_length, output, output_length,
+ error, error_capacity);
+ lambda_aitia_python_close(session);
return status;
}
diff --git a/bindings/python/src/lambda_aitia/gitops.py b/bindings/python/src/lambda_aitia/gitops.py
index 6114711..7aae518 100644
--- a/bindings/python/src/lambda_aitia/gitops.py
+++ b/bindings/python/src/lambda_aitia/gitops.py
@@ -9,7 +9,7 @@
from dataclasses import dataclass
from typing import Any, Mapping
-from .native import AitiaNativeError, _evaluate_gitops_payload
+from .native import AitiaNativeError, AitiaNativeSession, _evaluate_gitops_payload
from .runtime import _boolean, _string, _strings
@@ -60,16 +60,20 @@ def from_payload(cls, payload: Mapping[str, Any]) -> GitOpsDecision:
),
runtime_executed=_boolean(payload.get("runtimeExecuted"), "runtimeExecuted"),
)
- if decision.semantic_owner != "lambda-aitia" or decision.runtime_owner != "poo-flow":
+ if decision.semantic_owner != "lambda-aitia" or decision.runtime_owner != "agentic-ai-lab":
raise AitiaNativeError("unexpected GitOps decision owner")
if decision.authority_status != "not-evaluated":
raise AitiaNativeError("unexpected GitOps authority status")
return decision
-def evaluate_gitops(change: Mapping[str, Any]) -> GitOpsDecision:
+def evaluate_gitops(
+ change: Mapping[str, Any], *, session: AitiaNativeSession | None = None
+) -> GitOpsDecision:
"""Evaluate check evidence without implying release authorization or execution."""
if not isinstance(change, Mapping):
raise TypeError("change must be a mapping")
- return GitOpsDecision.from_payload(_evaluate_gitops_payload(change))
+ return GitOpsDecision.from_payload(
+ _evaluate_gitops_payload(change, session=session)
+ )
diff --git a/bindings/python/src/lambda_aitia/native.py b/bindings/python/src/lambda_aitia/native.py
index 5ba9b88..4d9ae52 100644
--- a/bindings/python/src/lambda_aitia/native.py
+++ b/bindings/python/src/lambda_aitia/native.py
@@ -10,6 +10,8 @@
import os
from pathlib import Path
import platform
+from threading import get_ident
+from types import TracebackType
from typing import Any, Mapping
from ._native._aitia_cffi import ffi, lib
@@ -27,30 +29,18 @@ def _library_path() -> Path:
candidate = Path(configured).expanduser().resolve()
else:
library_name = {
- "Darwin": "libpoo_flow_aitia.dylib",
- "Windows": "poo_flow_aitia.dll",
- }.get(platform.system(), "libpoo_flow_aitia.so")
+ "Darwin": "libagentic_ai_lab_aitia.dylib",
+ "Windows": "agentic_ai_lab_aitia.dll",
+ }.get(platform.system(), "libagentic_ai_lab_aitia.so")
candidate = Path(__file__).parent / "_native" / "lib" / library_name
if not candidate.is_file():
raise AitiaNativeError(f"Lambda Aitia native library is absent: {candidate}")
return candidate
-def _call(operation: str, payload: bytes = b"") -> dict[str, Any]:
- output = ffi.new("uint8_t **")
- output_length = ffi.new("size_t *")
- error = ffi.new("char[512]")
- payload_pointer = ffi.from_buffer(payload) if payload else ffi.NULL
- status = lib.lambda_aitia_python_call(
- os.fsencode(_library_path()),
- operation.encode("ascii"),
- payload_pointer,
- len(payload),
- output,
- output_length,
- error,
- 512,
- )
+def _decode_call(
+ status: int, output: Any, output_length: Any, error: Any
+) -> dict[str, Any]:
try:
response_bytes = (
bytes(ffi.buffer(output[0], output_length[0]))
@@ -73,23 +63,119 @@ def _call(operation: str, payload: bytes = b"") -> dict[str, Any]:
return value
+def _call(operation: str, payload: bytes = b"") -> dict[str, Any]:
+ output = ffi.new("uint8_t **")
+ output_length = ffi.new("size_t *")
+ error = ffi.new("char[512]")
+ payload_pointer = ffi.from_buffer(payload) if payload else ffi.NULL
+ status = lib.lambda_aitia_python_call(
+ os.fsencode(_library_path()),
+ operation.encode("ascii"),
+ payload_pointer,
+ len(payload),
+ output,
+ output_length,
+ error,
+ 512,
+ )
+ return _decode_call(status, output, output_length, error)
+
+
+class AitiaNativeSession:
+ """Own one process-exclusive Gambit transport session, not Host authority.
+
+ Calls and close must run on the thread that opened the session. Its lifetime
+ keeps Scheme state alive, but only Scheme-issued opaque capabilities can
+ establish verification/admission authority in a later ABI revision.
+ """
+
+ def __init__(self) -> None:
+ error = ffi.new("char[512]")
+ handle = lib.lambda_aitia_python_open(
+ os.fsencode(_library_path()), error, 512
+ )
+ if handle == ffi.NULL:
+ raise AitiaNativeError(ffi.string(error).decode("utf-8", errors="replace"))
+ self._handle = handle
+ self._owner_thread = get_ident()
+
+ @property
+ def closed(self) -> bool:
+ return self._handle == ffi.NULL
+
+ def _require_owner(self) -> None:
+ if get_ident() != self._owner_thread:
+ raise AitiaNativeError("Aitia native session belongs to another thread")
+
+ def close(self) -> None:
+ self._require_owner()
+ if not self.closed:
+ handle = self._handle
+ self._handle = ffi.NULL
+ lib.lambda_aitia_python_close(handle)
+
+ def _call(self, operation: str, payload: bytes = b"") -> dict[str, Any]:
+ self._require_owner()
+ if self.closed:
+ raise AitiaNativeError("Aitia native session is closed")
+ output = ffi.new("uint8_t **")
+ output_length = ffi.new("size_t *")
+ error = ffi.new("char[512]")
+ payload_pointer = ffi.from_buffer(payload) if payload else ffi.NULL
+ status = lib.lambda_aitia_python_session_call(
+ self._handle,
+ operation.encode("ascii"),
+ payload_pointer,
+ len(payload),
+ output,
+ output_length,
+ error,
+ 512,
+ )
+ return _decode_call(status, output, output_length, error)
+
+ def __enter__(self) -> AitiaNativeSession:
+ self._require_owner()
+ if self.closed:
+ raise AitiaNativeError("Aitia native session is closed")
+ return self
+
+ def __exit__(
+ self,
+ exc_type: type[BaseException] | None,
+ exc: BaseException | None,
+ traceback: TracebackType | None,
+ ) -> None:
+ self.close()
+
+ def __del__(self) -> None:
+ if getattr(self, "_handle", ffi.NULL) != ffi.NULL:
+ # Gambit cleanup is thread-affine. Refuse silent cross-thread cleanup.
+ if get_ident() == self._owner_thread:
+ self.close()
+
+
def descriptor() -> dict[str, Any]:
"""Return the native ABI descriptor published by Scheme."""
return _call("descriptor")
-def sdlc_flow_plan(lifecycle_id: str) -> dict[str, Any]:
- """Ask Scheme to project an SDLC lifecycle onto the POO Flow DAG."""
+def sdlc_flow_plan(
+ lifecycle_id: str, *, session: AitiaNativeSession | None = None
+) -> dict[str, Any]:
+ """Ask Scheme to project an SDLC lifecycle onto the Agentic AI Lab DAG."""
payload = json.dumps(
{"lifecycle-id": lifecycle_id}, separators=(",", ":"), ensure_ascii=False
).encode()
- return _call("sdlc-flow-plan", payload)
+ return (session._call if session is not None else _call)("sdlc-flow-plan", payload)
-def _evaluate_gitops_payload(change: Mapping[str, Any]) -> dict[str, Any]:
+def _evaluate_gitops_payload(
+ change: Mapping[str, Any], *, session: AitiaNativeSession | None = None
+) -> dict[str, Any]:
"""Ask Scheme to evaluate one GitOps change and its check evidence."""
payload = json.dumps(change, separators=(",", ":"), ensure_ascii=False).encode()
- return _call("gitops-evaluate", payload)
+ return (session._call if session is not None else _call)("gitops-evaluate", payload)
diff --git a/bindings/python/src/lambda_aitia/org_contract.py b/bindings/python/src/lambda_aitia/org_contract.py
new file mode 100644
index 0000000..bd9227c
--- /dev/null
+++ b/bindings/python/src/lambda_aitia/org_contract.py
@@ -0,0 +1,145 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+#
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Call Orgize's Scheme-owned Element/Contract C ABI from Aitia's runtime.
+
+Rows are already-admitted Org graph facts. Org parsing and contract semantics
+remain in Orgize; this module only owns Python transport and lifetime checks.
+"""
+
+from __future__ import annotations
+
+from dataclasses import dataclass
+from typing import Literal, Sequence
+
+from ._native._aitia_cffi import ffi, lib
+from .native import AitiaNativeError, AitiaNativeSession
+
+
+Expectation = Literal["exactly", "at-least", "at-most"]
+_EXPECTATION_CODE = {"exactly": 0, "at-least": 1, "at-most": 2}
+_INT64_MAX = (1 << 63) - 1
+
+
+@dataclass(frozen=True, slots=True)
+class OrgElementFact:
+ """One Orgize-projected graph node with at most one projected field."""
+
+ id: int
+ parent_id: int
+ kind: str
+ field_name: str = ""
+ field_value: str = ""
+
+
+@dataclass(frozen=True, slots=True)
+class OrgContractResult:
+ matched_count: int
+ passed: bool
+
+
+def _integer(value: int, *, name: str, minimum: int, maximum: int) -> int:
+ if type(value) is not int or not minimum <= value <= maximum:
+ raise ValueError(f"{name} must be an integer between {minimum} and {maximum}")
+ return value
+
+
+def _utf8(value: str, *, name: str, required: bool = False) -> bytes:
+ if not isinstance(value, str) or (required and not value):
+ raise ValueError(f"{name} must be {'nonempty ' if required else ''}text")
+ if "\0" in value:
+ raise ValueError(f"{name} cannot contain NUL")
+ return value.encode("utf-8")
+
+
+def _evaluate(
+ rows: Sequence[OrgElementFact],
+ scope_id: int,
+ query_kind: str,
+ field_name: str,
+ field_value: str,
+ expectation: Expectation,
+ expected_count: int,
+ session: AitiaNativeSession,
+) -> OrgContractResult:
+ session._require_owner()
+ if session.closed:
+ raise AitiaNativeError("Aitia native session is closed")
+
+ # Keep the same library handle and process-exclusive Gambit session used
+ # by Aitia. Opening a second dynamic handle can break cleanup/reinit.
+ buffers = []
+
+ def pointer(value: str, name: str, required: bool = False):
+ buffer = ffi.new("char[]", _utf8(value, name=name, required=required))
+ buffers.append(buffer)
+ return buffer
+
+ native_rows = ffi.new("orgize_element_row[]", len(rows))
+ for index, row in enumerate(rows):
+ native_rows[index].id = _integer(
+ row.id, name="row id", minimum=0, maximum=_INT64_MAX
+ )
+ native_rows[index].parent_id = _integer(
+ row.parent_id, name="parent id", minimum=-1, maximum=_INT64_MAX
+ )
+ native_rows[index].kind = pointer(row.kind, "row kind", required=True)
+ native_rows[index].field_name = pointer(row.field_name, "field name")
+ native_rows[index].field_value = pointer(row.field_value, "field value")
+ result = ffi.new("orgize_contract_result *")
+ error = ffi.new("char[512]")
+ status = lib.lambda_aitia_python_session_org_contract(
+ session._handle,
+ native_rows if rows else ffi.NULL,
+ len(rows),
+ scope_id,
+ pointer(query_kind, "query kind", required=True),
+ pointer(field_name, "field name"),
+ pointer(field_value, "field value"),
+ _EXPECTATION_CODE[expectation],
+ expected_count,
+ result,
+ error,
+ 512,
+ )
+ if status != 0 or result.status != 0:
+ detail = ffi.string(error).decode("utf-8", errors="replace")
+ raise AitiaNativeError(detail or "Orgize rejected graph contract evaluation")
+ return OrgContractResult(result.matched_count, result.passed == 1)
+
+
+def evaluate_org_contract(
+ rows: Sequence[OrgElementFact],
+ *,
+ scope_id: int,
+ query_kind: str,
+ field_name: str = "",
+ field_value: str = "",
+ expectation: Expectation = "exactly",
+ expected_count: int = 1,
+ session: AitiaNativeSession | None = None,
+) -> OrgContractResult:
+ """Evaluate an Orgize Contract on source-owner-projected graph facts.
+
+ This result is an observation, not source authenticity, Host admission,
+ review approval, or runtime-effect authority.
+ """
+ if not isinstance(rows, Sequence) or isinstance(rows, (str, bytes)):
+ raise TypeError("rows must be a sequence of OrgElementFact values")
+ if len(rows) > 10000 or any(not isinstance(row, OrgElementFact) for row in rows):
+ raise ValueError("rows must contain at most 10000 OrgElementFact values")
+ _integer(scope_id, name="scope id", minimum=0, maximum=_INT64_MAX)
+ _integer(expected_count, name="expected count", minimum=0, maximum=10000)
+ if expectation not in _EXPECTATION_CODE:
+ raise ValueError("expectation must be exactly, at-least, or at-most")
+ if session is None:
+ with AitiaNativeSession() as owned:
+ return _evaluate(
+ rows, scope_id, query_kind, field_name, field_value,
+ expectation, expected_count, owned,
+ )
+ return _evaluate(
+ rows, scope_id, query_kind, field_name, field_value,
+ expectation, expected_count, session,
+ )
diff --git a/bindings/python/src/lambda_aitia/org_workspace.py b/bindings/python/src/lambda_aitia/org_workspace.py
new file mode 100644
index 0000000..7da207e
--- /dev/null
+++ b/bindings/python/src/lambda_aitia/org_workspace.py
@@ -0,0 +1,169 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+#
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Source-bound Org edit proposals; Orgize owns parsing and application.
+
+The caller supplies node identities and byte ranges from an Orgize projection.
+This module checks that those ranges still refer to the projected source. It
+does not authenticate the projection, interpret Org syntax, or write a file.
+"""
+
+from dataclasses import dataclass
+import hashlib
+import os
+from pathlib import Path
+import re
+import stat
+from typing import Sequence
+
+
+MAX_ORG_SOURCE_BYTES = 16 * 1024 * 1024
+MAX_ORG_EDITS = 128
+_DIGEST_PATTERN = re.compile(r"sha256:[0-9a-f]{64}\Z")
+
+
+def _read_source(source: Path) -> bytes:
+ if not hasattr(os, "O_NOFOLLOW"):
+ raise OSError("Org source preflight requires O_NOFOLLOW")
+ flags = os.O_RDONLY | os.O_NOFOLLOW
+ if hasattr(os, "O_CLOEXEC"):
+ flags |= os.O_CLOEXEC
+ descriptor = os.open(source, flags)
+ try:
+ with os.fdopen(descriptor, "rb") as stream:
+ descriptor = -1
+ info = os.fstat(stream.fileno())
+ if not stat.S_ISREG(info.st_mode):
+ raise ValueError("Org source must be a regular file")
+ if info.st_size > MAX_ORG_SOURCE_BYTES:
+ raise ValueError("Org source exceeds byte limit")
+ payload = stream.read(MAX_ORG_SOURCE_BYTES + 1)
+ if len(payload) > MAX_ORG_SOURCE_BYTES:
+ raise ValueError("Org source exceeds byte limit")
+ return payload
+ finally:
+ if descriptor >= 0:
+ os.close(descriptor)
+
+
+def org_source_digest(payload: bytes) -> str:
+ """Digest exact Org source bytes, not a parsed or canonicalized tree."""
+ return "sha256:" + hashlib.sha256(payload).hexdigest()
+
+
+@dataclass(frozen=True, slots=True)
+class OrgNodeEdit:
+ """An Orgize-projected node's original byte span and proposed replacement."""
+
+ node_id: str
+ start_byte: int
+ end_byte: int
+ expected_old: bytes
+ replacement: bytes
+
+
+@dataclass(frozen=True, slots=True)
+class OrgEditReview:
+ """Inert proposal for owner review and source-owned application."""
+
+ source_id: str
+ source_digest: str
+ source_size_bytes: int
+ edits: tuple[OrgNodeEdit, ...]
+
+ def source_current(self, source: Path) -> bool:
+ """Recheck bytes before review; application must check again itself."""
+ try:
+ payload = _read_source(Path(source))
+ except (OSError, ValueError):
+ return False
+ return (
+ len(payload) == self.source_size_bytes
+ and org_source_digest(payload) == self.source_digest
+ and all(
+ payload[edit.start_byte : edit.end_byte] == edit.expected_old
+ for edit in self.edits
+ )
+ )
+
+
+def prepare_org_edit_review(
+ source: Path,
+ *,
+ source_id: str,
+ projected_source_digest: str,
+ edits: Sequence[OrgNodeEdit],
+) -> OrgEditReview:
+ """Reject stale/ambiguous Orgize anchors without modifying the source.
+
+ ``projected_source_digest`` must describe the exact bytes used to produce
+ the upstream node IDs and byte ranges. A matching digest is a freshness
+ check, not proof that the caller's projection is trusted or authorized.
+ """
+ if not isinstance(source_id, str) or not source_id.strip():
+ raise ValueError("source_id must be nonempty")
+ if not isinstance(projected_source_digest, str) or not _DIGEST_PATTERN.fullmatch(
+ projected_source_digest
+ ):
+ raise ValueError("projected_source_digest must be a SHA-256 digest")
+ payload = _read_source(Path(source))
+ try:
+ payload.decode("utf-8")
+ except UnicodeDecodeError as error:
+ raise ValueError("Org source must be UTF-8") from error
+ digest = org_source_digest(payload)
+ if digest != projected_source_digest:
+ raise ValueError("Org source changed since projection")
+ if not 1 <= len(edits) <= MAX_ORG_EDITS:
+ raise ValueError("Org edit count must be between 1 and 128")
+ if any(not isinstance(edit, OrgNodeEdit) for edit in edits):
+ raise TypeError("edits must be OrgNodeEdit values")
+ if any(
+ type(edit.start_byte) is not int or type(edit.end_byte) is not int
+ for edit in edits
+ ):
+ raise ValueError("Org node edit has an invalid byte span")
+
+ ordered = sorted(edits, key=lambda edit: (edit.start_byte, edit.end_byte))
+ seen_ids: set[str] = set()
+ prior_end = 0
+ replacement_bytes = 0
+ for edit in ordered:
+ if not isinstance(edit.node_id, str) or not edit.node_id.strip():
+ raise ValueError("node_id must be nonempty")
+ if edit.node_id in seen_ids:
+ raise ValueError("duplicate Org node ID in edit proposal")
+ seen_ids.add(edit.node_id)
+ if (
+ not 0 <= edit.start_byte < edit.end_byte <= len(payload)
+ ):
+ raise ValueError("Org node edit has an invalid byte span")
+ if (
+ edit.start_byte < len(payload)
+ and payload[edit.start_byte] & 0xC0 == 0x80
+ ) or (
+ edit.end_byte < len(payload)
+ and payload[edit.end_byte] & 0xC0 == 0x80
+ ):
+ raise ValueError("Org node edit splits a UTF-8 codepoint")
+ if edit.start_byte < prior_end:
+ raise ValueError("Org node edits overlap")
+ if not isinstance(edit.expected_old, bytes) or not isinstance(
+ edit.replacement, bytes
+ ):
+ raise TypeError("Org node edits require exact source bytes")
+ try:
+ edit.node_id.encode("utf-8")
+ edit.expected_old.decode("utf-8")
+ edit.replacement.decode("utf-8")
+ except UnicodeError as error:
+ raise ValueError("Org node edit must use UTF-8") from error
+ replacement_bytes += len(edit.replacement)
+ if replacement_bytes > MAX_ORG_SOURCE_BYTES:
+ raise ValueError("Org replacements exceed byte limit")
+ if payload[edit.start_byte : edit.end_byte] != edit.expected_old:
+ raise ValueError("Org node moved or its expected content changed")
+ prior_end = edit.end_byte
+
+ return OrgEditReview(source_id, digest, len(payload), tuple(ordered))
diff --git a/bindings/python/src/lambda_aitia/runtime.py b/bindings/python/src/lambda_aitia/runtime.py
index d7d007b..bf025e4 100644
--- a/bindings/python/src/lambda_aitia/runtime.py
+++ b/bindings/python/src/lambda_aitia/runtime.py
@@ -9,7 +9,7 @@
from dataclasses import dataclass
from typing import Any, Mapping
-from .native import AitiaNativeError, sdlc_flow_plan
+from .native import AitiaNativeError, AitiaNativeSession, sdlc_flow_plan
def _string(value: Any, field: str) -> str:
@@ -71,7 +71,7 @@ def from_payload(cls, payload: Mapping[str, Any]) -> SdlcFlowPlan:
),
runtime_executed=_boolean(payload.get("runtimeExecuted"), "runtimeExecuted"),
)
- if plan.semantic_owner != "lambda-aitia" or plan.runtime_owner != "poo-flow":
+ if plan.semantic_owner != "lambda-aitia" or plan.runtime_owner != "agentic-ai-lab":
raise AitiaNativeError("unexpected SDLC flow-plan owner")
if plan.release_authorized or plan.runtime_executed:
raise AitiaNativeError(
@@ -87,9 +87,14 @@ class SdlcRuntime:
complete until every Scheme-owned stage publishes an attributable receipt.
"""
+ def __init__(self, *, session: AitiaNativeSession | None = None) -> None:
+ self._session = session
+
def plan(self, lifecycle_id: str) -> SdlcFlowPlan:
- """Build and validate the canonical POO Flow DAG for a lifecycle."""
+ """Build and validate the canonical Agentic AI Lab DAG for a lifecycle."""
if not isinstance(lifecycle_id, str) or not lifecycle_id:
raise ValueError("lifecycle_id must be a non-empty string")
- return SdlcFlowPlan.from_payload(sdlc_flow_plan(lifecycle_id))
+ return SdlcFlowPlan.from_payload(
+ sdlc_flow_plan(lifecycle_id, session=self._session)
+ )
diff --git a/bindings/python/src/lambda_aitia/verification.py b/bindings/python/src/lambda_aitia/verification.py
new file mode 100644
index 0000000..13e94fe
--- /dev/null
+++ b/bindings/python/src/lambda_aitia/verification.py
@@ -0,0 +1,422 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+#
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Observable pytest execution, not an Assurance Host admission."""
+
+from __future__ import annotations
+
+from dataclasses import dataclass, replace
+import hashlib
+import os
+from pathlib import Path, PurePosixPath, PureWindowsPath
+import selectors
+import signal
+import subprocess
+import tempfile
+import time
+from uuid import uuid4
+import xml.etree.ElementTree as ET
+
+import anyio
+
+
+_SOURCE_MAGIC = b"lambda-aitia.source-tree.v1\0"
+_MAX_SOURCE_BYTES = 64 * 1024 * 1024
+_MAX_SOURCE_FILES = 10_000
+
+
+def _source_payload_digest(payload: bytes) -> str:
+ return "sha256:" + hashlib.sha256(payload).hexdigest()
+
+
+def capture_source_tree(root: Path) -> bytes:
+ """Freeze a regular-file tree into canonical, source-lock-compatible bytes.
+
+ Source paths and contents are length-framed, ordered, and bounded. The
+ returned bytes can be independently rehashed by the Scheme Host's source
+ reader; their digest is not a verification seal.
+ """
+
+ root = root.resolve(strict=True)
+ if not root.is_dir():
+ raise ValueError("source root must be a directory")
+ entries: list[tuple[bytes, bytes]] = []
+ size = len(_SOURCE_MAGIC) + 8
+ for path in root.rglob("*"):
+ if path.is_symlink():
+ raise ValueError(f"source tree contains a symlink: {path}")
+ if path.is_dir():
+ continue
+ if not path.is_file():
+ raise ValueError(f"source tree contains a non-file: {path}")
+ relative = path.relative_to(root).as_posix().encode("utf-8")
+ remaining = _MAX_SOURCE_BYTES - size - 4 - len(relative) - 8
+ if remaining < 0:
+ raise ValueError("source tree exceeds verifier capture limit")
+ with path.open("rb") as source:
+ contents = source.read(remaining + 1)
+ size += 4 + len(relative) + 8 + len(contents)
+ if size > _MAX_SOURCE_BYTES or len(entries) >= _MAX_SOURCE_FILES:
+ raise ValueError("source tree exceeds verifier capture limit")
+ entries.append((relative, contents))
+ entries.sort(key=lambda entry: entry[0])
+ framed = bytearray(_SOURCE_MAGIC)
+ framed.extend(len(entries).to_bytes(8, "big"))
+ for relative, contents in entries:
+ framed.extend(len(relative).to_bytes(4, "big"))
+ framed.extend(relative)
+ framed.extend(len(contents).to_bytes(8, "big"))
+ framed.extend(contents)
+ return bytes(framed)
+
+
+def _source_entries(payload: bytes) -> tuple[tuple[Path, bytes], ...]:
+ if len(payload) > _MAX_SOURCE_BYTES or not payload.startswith(_SOURCE_MAGIC):
+ raise ValueError("invalid frozen source payload")
+ position = len(_SOURCE_MAGIC)
+
+ def take(length: int) -> bytes:
+ nonlocal position
+ if length < 0 or position + length > len(payload):
+ raise ValueError("truncated frozen source payload")
+ result = payload[position : position + length]
+ position += length
+ return result
+
+ count = int.from_bytes(take(8), "big")
+ if count > _MAX_SOURCE_FILES:
+ raise ValueError("frozen source file count exceeds limit")
+ entries: list[tuple[Path, bytes]] = []
+ previous = b""
+ for _ in range(count):
+ relative = take(int.from_bytes(take(4), "big"))
+ if not relative or relative <= previous or b"\\" in relative or b"\0" in relative:
+ raise ValueError("invalid frozen source path ordering")
+ previous = relative
+ try:
+ decoded = relative.decode("utf-8")
+ except UnicodeDecodeError as error:
+ raise ValueError("invalid frozen source path encoding") from error
+ path = PurePosixPath(decoded)
+ if (
+ path.is_absolute()
+ or PureWindowsPath(decoded).drive
+ or any(part in ("", ".", "..") for part in decoded.split("/"))
+ ):
+ raise ValueError("frozen source path escapes root")
+ contents = take(int.from_bytes(take(8), "big"))
+ entries.append((Path(*path.parts), contents))
+ if position != len(payload):
+ raise ValueError("trailing frozen source payload bytes")
+ return tuple(entries)
+
+
+def source_digest(root: Path) -> str:
+ """Hash the canonical frozen bytes of a regular-file tree."""
+
+ return _source_payload_digest(capture_source_tree(root))
+
+
+@dataclass(frozen=True, slots=True)
+class PytestObservation:
+ """One subprocess observation; this value carries no issuing authority."""
+
+ run_id: str
+ source_digest: str
+ argv: tuple[str, ...]
+ exit_code: int | None
+ status: str
+ collected: int
+ passed: int
+ skipped: int
+ report_digest: str | None
+ output: str
+
+ @property
+ def passed_obligation(self) -> bool:
+ return self.status == "passed"
+
+ def source_current(self, root: Path) -> bool:
+ try:
+ return source_digest(root) == self.source_digest
+ except (OSError, ValueError):
+ return False
+
+
+def _validated_selectors(
+ selectors: tuple[str, ...], entries: tuple[tuple[Path, bytes], ...]
+) -> None:
+ selected_files = {path.as_posix() for path, _ in entries}
+ if not selectors:
+ raise ValueError("at least one explicit pytest selector is required")
+ for selector in selectors:
+ filename = selector.split("::", 1)[0]
+ if (
+ not filename
+ or selector.startswith("-")
+ or "\\" in filename
+ or "\0" in filename
+ or any(part in ("", ".", "..") for part in filename.split("/"))
+ or filename not in selected_files
+ ):
+ raise ValueError("pytest selector must name a file in frozen source")
+
+
+def _stop_process_group(process: subprocess.Popen[bytes]) -> bool:
+ """Stop pytest's group; return false if descendant cleanup is uncertain."""
+
+ controlled = True
+ try:
+ os.killpg(process.pid, signal.SIGTERM)
+ except ProcessLookupError:
+ pass
+ except PermissionError:
+ controlled = False
+ try:
+ process.wait(timeout=0.2)
+ except subprocess.TimeoutExpired:
+ pass
+ try:
+ os.killpg(process.pid, signal.SIGKILL)
+ except ProcessLookupError:
+ pass
+ except PermissionError:
+ controlled = False
+ try:
+ process.wait(timeout=1)
+ except subprocess.TimeoutExpired:
+ controlled = False
+ process.kill()
+ process.wait()
+ return controlled
+
+
+def _run_bounded_verifier(
+ argv: tuple[str, ...],
+ root: Path,
+ environment: dict[str, str],
+ timeout_seconds: int,
+ max_output_bytes: int,
+) -> tuple[int | None, str, str | None]:
+ """Drain bounded output and terminate the whole verifier group on failure.
+
+ Non-POSIX process trees are rejected until an equivalent descendant-kill
+ contract is qualified; silently killing only pytest would leave effects.
+ """
+
+ if os.name != "posix":
+ raise OSError("controlled pytest verification requires POSIX process groups")
+ tail = bytearray()
+ observed_bytes = 0
+ deadline = time.monotonic() + timeout_seconds
+ stop_reason = None
+ process = subprocess.Popen(
+ argv,
+ cwd=root,
+ env=environment,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ start_new_session=True,
+ )
+ try:
+ assert process.stdout is not None
+ with selectors.DefaultSelector() as selector:
+ selector.register(process.stdout, selectors.EVENT_READ)
+ output_complete = False
+ while not (output_complete and process.poll() is not None):
+ remaining = deadline - time.monotonic()
+ if remaining <= 0:
+ stop_reason = "timeout"
+ break
+ for key, _ in selector.select(timeout=min(remaining, 0.1)):
+ chunk = os.read(key.fileobj.fileno(), 65536)
+ if not chunk:
+ selector.unregister(key.fileobj)
+ output_complete = True
+ continue
+ observed_bytes += len(chunk)
+ tail.extend(chunk)
+ del tail[:-8192]
+ if observed_bytes > max_output_bytes:
+ stop_reason = "output-exceeded"
+ break
+ if stop_reason:
+ break
+ if stop_reason:
+ if not _stop_process_group(process):
+ stop_reason = "control-error"
+ exit_code = None
+ else:
+ exit_code = process.wait()
+ return exit_code, tail.decode("utf-8", "replace"), stop_reason
+ finally:
+ if process.poll() is None:
+ _stop_process_group(process)
+ if process.stdout is not None:
+ process.stdout.close()
+
+
+def run_pytest_frozen(
+ python: Path,
+ source_payload: bytes,
+ selectors: tuple[str, ...],
+ *,
+ timeout_seconds: int = 30,
+ max_output_bytes: int = 8 * 1024 * 1024,
+ environment: dict[str, str] | None = None,
+) -> PytestObservation:
+ """Run selected tests only from a validated frozen source payload.
+
+ The caller owns the interpreter, dependencies and external services. The
+ payload is observable process input, not a Host-issued verification seal.
+ """
+
+ entries = _source_entries(source_payload)
+ _validated_selectors(selectors, entries)
+ if timeout_seconds <= 0:
+ raise ValueError("timeout_seconds must be positive")
+ if max_output_bytes <= 0:
+ raise ValueError("max_output_bytes must be positive")
+ before = _source_payload_digest(source_payload)
+ run_id = uuid4().hex
+ interpreter = python.absolute()
+ if not interpreter.is_file():
+ raise ValueError("Python interpreter is absent")
+ safe_environment = os.environ.copy()
+ for name in ("PYTHONPATH", "PYTEST_ADDOPTS", "PYTEST_PLUGINS"):
+ safe_environment.pop(name, None)
+ safe_environment["PYTEST_DISABLE_PLUGIN_AUTOLOAD"] = "1"
+ safe_environment["PYTHONDONTWRITEBYTECODE"] = "1"
+ if environment:
+ if any(not key.startswith("AITIA_QUALIFICATION_") for key in environment):
+ raise ValueError("only AITIA_QUALIFICATION_ environment values are allowed")
+ safe_environment.update(environment)
+ with tempfile.TemporaryDirectory(prefix="aitia-pytest-") as workspace:
+ root = Path(workspace) / "source"
+ root.mkdir()
+ for relative, contents in entries:
+ target = root / relative
+ target.parent.mkdir(parents=True, exist_ok=True)
+ target.write_bytes(contents)
+ report = Path(workspace) / f"{run_id}.xml"
+ argv = (
+ str(interpreter), "-m", "pytest", "-q", "-s",
+ "-p", "no:cacheprovider", f"--junitxml={report}", *selectors,
+ )
+ exit_code, output, stop_reason = _run_bounded_verifier(
+ argv, root, safe_environment, timeout_seconds, max_output_bytes
+ )
+ try:
+ after = source_digest(root)
+ except (OSError, ValueError):
+ after = None
+ collected = passed = skipped = 0
+ report_digest = None
+ report_valid = False
+ if report.is_file():
+ report_bytes = report.read_bytes()
+ report_digest = "sha256:" + hashlib.sha256(report_bytes).hexdigest()
+ try:
+ suites = ET.fromstring(report_bytes)
+ cases = suites.findall(".//testcase")
+ collected = len(cases)
+ skipped = sum(case.find("skipped") is not None for case in cases)
+ failed = sum(
+ case.find("failure") is not None or case.find("error") is not None
+ for case in cases
+ )
+ passed = collected - skipped - failed
+ report_valid = suites.tag in ("testsuite", "testsuites")
+ except ET.ParseError:
+ pass
+ if before != after:
+ status = "source-changed"
+ elif stop_reason:
+ status = stop_reason
+ elif exit_code == 2:
+ status = "interrupted"
+ elif exit_code == 3:
+ status = "internal-error"
+ elif exit_code == 4:
+ status = "usage-error"
+ elif exit_code == 6:
+ status = "warnings-exceeded"
+ elif not report_valid:
+ status = "report-invalid"
+ elif collected == 0:
+ status = "no-tests"
+ elif exit_code != 0 or passed + skipped != collected:
+ status = "failed"
+ elif passed == 0:
+ status = "no-passing-tests"
+ elif skipped:
+ status = "skipped"
+ else:
+ status = "passed"
+ return PytestObservation(
+ run_id, before, argv, exit_code, status, collected, passed,
+ skipped, report_digest, output[-8192:],
+ )
+
+
+async def run_pytest_frozen_async(
+ python: Path,
+ source_payload: bytes,
+ selectors: tuple[str, ...],
+ *,
+ timeout_seconds: int = 30,
+ max_output_bytes: int = 8 * 1024 * 1024,
+ environment: dict[str, str] | None = None,
+ limiter: anyio.CapacityLimiter | None = None,
+) -> PytestObservation:
+ """Run a frozen verifier through AnyIO without abandoning its process.
+
+ Cancellation waits for the bounded worker to terminate and clean up the
+ pytest process group. No thread-affine native session enters this worker;
+ the result remains an observation, not a Host admission.
+ """
+
+ frozen_payload = bytes(source_payload)
+ frozen_selectors = tuple(selectors)
+ frozen_environment = dict(environment) if environment is not None else None
+
+ def execute() -> PytestObservation:
+ return run_pytest_frozen(
+ python,
+ frozen_payload,
+ frozen_selectors,
+ timeout_seconds=timeout_seconds,
+ max_output_bytes=max_output_bytes,
+ environment=frozen_environment,
+ )
+
+ return await anyio.to_thread.run_sync(
+ execute, abandon_on_cancel=False, limiter=limiter
+ )
+
+
+def run_pytest(
+ python: Path,
+ source_root: Path,
+ selectors: tuple[str, ...],
+ *,
+ timeout_seconds: int = 30,
+ max_output_bytes: int = 8 * 1024 * 1024,
+ environment: dict[str, str] | None = None,
+) -> PytestObservation:
+ """Capture source, execute its frozen copy, and detect caller-tree drift.
+
+ A changing caller tree invalidates the observation, but even a passing
+ observation is not a Scheme Assurance Host admission.
+ """
+
+ payload = capture_source_tree(source_root)
+ observation = run_pytest_frozen(
+ python, payload, selectors,
+ timeout_seconds=timeout_seconds, max_output_bytes=max_output_bytes,
+ environment=environment,
+ )
+ if not observation.source_current(source_root):
+ return replace(observation, status="source-changed")
+ return observation
diff --git a/bindings/python/tests/installed_wheel_qualification.py b/bindings/python/tests/installed_wheel_qualification.py
new file mode 100644
index 0000000..205344b
--- /dev/null
+++ b/bindings/python/tests/installed_wheel_qualification.py
@@ -0,0 +1,107 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+#
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Project qualification of an installed wheel outside the checkout."""
+
+from __future__ import annotations
+
+import os
+from pathlib import Path
+import shutil
+import subprocess
+import tempfile
+
+
+PROJECT = Path(__file__).resolve().parents[3]
+PYTHON = PROJECT / "bindings/python/.venv/bin/python"
+WHEELS = PROJECT / "bindings/python/dist"
+SCENARIO = PROJECT / "bindings/python/qualification/job_executor"
+
+
+def run(
+ *argv: str,
+ cwd: Path,
+ environment: dict[str, str] | None = None,
+ quiet: bool = False,
+) -> None:
+ subprocess.run(
+ argv, cwd=cwd, env=environment, check=True, timeout=90,
+ stdout=subprocess.DEVNULL if quiet else None,
+ )
+
+
+def test_installed_wheel_qualification() -> None:
+ wheels = list(WHEELS.glob("lambda_aitia-*.whl"))
+ if not wheels:
+ raise RuntimeError("build the Aitia wheel before qualification")
+ wheel = max(wheels, key=lambda path: path.stat().st_mtime_ns)
+ with tempfile.TemporaryDirectory(prefix="aitia-installed-wheel-") as directory:
+ root = Path(directory)
+ venv = root / "venv"
+ scenario = root / "scenario"
+ requirements = root / "requirements.txt"
+ shutil.copytree(SCENARIO, scenario)
+ run("uv", "export", "--offline", "--locked", "--extra", "test",
+ "--no-emit-project", "--output-file", str(requirements),
+ cwd=PROJECT / "bindings/python", quiet=True)
+ run("uv", "venv", "--python", str(PYTHON), str(venv), cwd=root)
+ interpreter = venv / "bin/python"
+ # A fresh CI cache can lack a locked wheel even when the source-tree
+ # environment already has it. Resolve only hashes from uv.lock;
+ # reuse cached wheels and fetch missing ones when needed.
+ run("uv", "pip", "install", "--python", str(interpreter),
+ "-r", str(requirements), cwd=root)
+ run("uv", "pip", "install", "--offline", "--no-deps", "--python",
+ str(interpreter), str(wheel), cwd=root)
+ environment = os.environ.copy()
+ for name in ("PYTHONPATH", "LAMBDA_AITIA_NATIVE_LIBRARY", "VIRTUAL_ENV"):
+ environment.pop(name, None)
+ # Import, native invocation, verifier and stale-source test all occur
+ # with cwd outside the checkout and no development path override.
+ code = """
+import anyio
+from pathlib import Path
+from lambda_aitia import (AitiaNativeSession, OrgElementFact, SdlcRuntime,
+ evaluate_org_contract)
+from lambda_aitia.verification import capture_source_tree, run_pytest, run_pytest_frozen_async
+root = Path('scenario').resolve()
+assert SdlcRuntime().plan('qualification/job-42').lifecycle_id == 'qualification/job-42'
+with AitiaNativeSession() as session:
+ runtime = SdlcRuntime(session=session)
+ assert runtime.plan('qualification/job-42/first').lifecycle_id == 'qualification/job-42/first'
+ assert runtime.plan('qualification/job-42/second').lifecycle_id == 'qualification/job-42/second'
+ graph = (OrgElementFact(0, -1, 'org-data'),
+ OrgElementFact(1, 0, 'headline', 'title', 'Evidence'))
+ org_result = evaluate_org_contract(graph, scope_id=0, query_kind='headline',
+ field_name='title', field_value='Evidence',
+ session=session)
+ assert org_result.passed and org_result.matched_count == 1
+assert session.closed
+selector = ('test_unique_effect.py::test_unique_effect_after_lost_ack_and_restart',)
+buggy = run_pytest(Path(__import__('sys').executable), root, selector,
+ environment={'AITIA_QUALIFICATION_MODE': 'buggy'})
+assert buggy.status == 'failed', buggy
+assert 'assert 2 == 1' in buggy.output, buggy.output
+source_payload = capture_source_tree(root)
+
+async def verify_fixed():
+ return await run_pytest_frozen_async(Path(__import__('sys').executable),
+ source_payload, selector,
+ environment={'AITIA_QUALIFICATION_MODE': 'fixed'},
+ limiter=anyio.CapacityLimiter(1))
+
+with AitiaNativeSession() as session:
+ runtime = SdlcRuntime(session=session)
+ assert runtime.plan('qualification/job-42/first').lifecycle_id == 'qualification/job-42/first'
+ fixed = anyio.run(verify_fixed)
+ assert fixed.passed_obligation and fixed.collected == 1, fixed
+ assert runtime.plan('qualification/job-42/second').lifecycle_id == 'qualification/job-42/second'
+assert session.closed
+assert fixed.source_current(root)
+worker = root / 'worker.py'
+worker.write_bytes(worker.read_bytes() + b'\\n# changed after verification\\n')
+assert not fixed.source_current(root)
+print('installed-wheel-qualification: buggy=reproduced fixed=passed stale=rejected')
+"""
+ run(str(interpreter), "-c", code, cwd=root, environment=environment)
diff --git a/bindings/python/tests/test_native.py b/bindings/python/tests/test_native.py
index d9fd888..45a5715 100644
--- a/bindings/python/tests/test_native.py
+++ b/bindings/python/tests/test_native.py
@@ -4,7 +4,13 @@
import pytest
-from lambda_aitia import GitOpsDecision, SdlcRuntime, descriptor, evaluate_gitops
+from lambda_aitia import (
+ AitiaNativeSession,
+ GitOpsDecision,
+ SdlcRuntime,
+ descriptor,
+ evaluate_gitops,
+)
from lambda_aitia.native import AitiaNativeError
from lambda_aitia.runtime import SdlcFlowPlan
@@ -32,7 +38,7 @@ def test_production_runtime_materializes_scheme_owned_sdlc_plan() -> None:
)
assert plan.topological_order[-1] == "release/42/effect"
assert plan.semantic_owner == "lambda-aitia"
- assert plan.runtime_owner == "poo-flow"
+ assert plan.runtime_owner == "agentic-ai-lab"
assert plan.release_authorized is False
assert plan.runtime_executed is False
@@ -42,6 +48,33 @@ def test_runtime_rejects_invalid_lifecycle_before_native_dispatch() -> None:
SdlcRuntime().plan("")
+def test_session_keeps_one_scheme_runtime_for_distinct_calls() -> None:
+ with AitiaNativeSession() as session:
+ runtime = SdlcRuntime(session=session)
+ assert runtime.plan("session/first").lifecycle_id == "session/first"
+ assert runtime.plan("session/second").lifecycle_id == "session/second"
+ assert evaluate_gitops(_gitops_change(), session=session).accepted is True
+ with pytest.raises(AitiaNativeError, match="active session"):
+ AitiaNativeSession()
+ with pytest.raises(AitiaNativeError, match="active session"):
+ descriptor()
+ assert session.closed
+ session.close()
+ with pytest.raises(AitiaNativeError, match="closed"):
+ runtime.plan("session/after-close")
+ assert descriptor()["semanticOwner"] == "lambda-aitia"
+
+
+def test_session_rejects_cross_thread_calls() -> None:
+ from concurrent.futures import ThreadPoolExecutor
+
+ with AitiaNativeSession() as session:
+ with ThreadPoolExecutor(max_workers=1) as pool:
+ failure = pool.submit(SdlcRuntime(session=session).plan, "other/thread")
+ with pytest.raises(AitiaNativeError, match="another thread"):
+ failure.result()
+
+
@pytest.mark.parametrize("field", ["releaseAuthorized", "runtimeExecuted"])
def test_runtime_rejects_inert_plan_claiming_effect(field: str) -> None:
payload = {
@@ -52,7 +85,7 @@ def test_runtime_rejects_inert_plan_claiming_effect(field: str) -> None:
"cyclePath": None,
"accepted": True,
"semanticOwner": "lambda-aitia",
- "runtimeOwner": "poo-flow",
+ "runtimeOwner": "agentic-ai-lab",
"releaseAuthorized": False,
"runtimeExecuted": False,
}
@@ -62,23 +95,30 @@ def test_runtime_rejects_inert_plan_claiming_effect(field: str) -> None:
SdlcFlowPlan.from_payload(payload)
+def _gitops_change() -> dict[str, object]:
+ return {
+ "event": "pull-request",
+ "repository": "tao3k/agentic-ai-lab",
+ "revision": "0123456789abcdef",
+ "source-ref": "feature/aitia",
+ "target-ref": "develop",
+ "pull-request": 42,
+ "checks": [
+ {"name": "commit-policy", "conclusion": "success"},
+ {"name": "build", "conclusion": "success"},
+ {"name": "unit-test", "conclusion": "success"},
+ {
+ "name": "nasa/sdlc/npr-7150.2",
+ "conclusion": "success",
+ "standardEdition": "D",
+ "sourceLockDigest": "sha256:cfb963b8cd81fd8e22e9b47251c1dc7927b85fcdf9ec9366057cd38cb94f338c",
+ },
+ ],
+ }
+
+
def test_python_delegates_gitops_decision_to_scheme() -> None:
- decision = evaluate_gitops(
- {
- "event": "pull-request",
- "repository": "tao3k/poo-flow",
- "revision": "0123456789abcdef",
- "source-ref": "feature/aitia",
- "target-ref": "develop",
- "pull-request": 42,
- "checks": [
- {"name": "commit-policy", "conclusion": "success"},
- {"name": "build", "conclusion": "success"},
- {"name": "unit-test", "conclusion": "success"},
- {"name": "nasa-7150-2d", "conclusion": "success"},
- ],
- }
- )
+ decision = evaluate_gitops(_gitops_change())
assert isinstance(decision, GitOpsDecision)
assert decision.accepted is True
assert decision.profile == "dev"
@@ -86,3 +126,28 @@ def test_python_delegates_gitops_decision_to_scheme() -> None:
assert decision.authority_status == "not-evaluated"
assert decision.release_authorized is False
assert decision.runtime_executed is False
+
+
+@pytest.mark.parametrize(
+ ("field", "value"),
+ [
+ ("standardEdition", "C"),
+ ("sourceLockDigest", "sha256:wrong-lock"),
+ ("sourceLockDigest", None),
+ ],
+)
+def test_python_rejects_stale_standard_assessment(field: str, value: str | None) -> None:
+ change = _gitops_change()
+ checks = change["checks"]
+ assert isinstance(checks, list)
+ standard_check = checks[-1]
+ assert isinstance(standard_check, dict)
+ if value is None:
+ standard_check.pop(field)
+ else:
+ standard_check[field] = value
+
+ decision = evaluate_gitops(change)
+ assert decision.accepted is False
+ assert decision.stale_checks == ("nasa/sdlc/npr-7150.2",)
+ assert decision.reasons == ("standard-assessment-mismatch",)
diff --git a/bindings/python/tests/test_org_contract.py b/bindings/python/tests/test_org_contract.py
new file mode 100644
index 0000000..413131b
--- /dev/null
+++ b/bindings/python/tests/test_org_contract.py
@@ -0,0 +1,58 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+#
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""The delivered Aitia library calls Orgize's Scheme-owned C ABI."""
+
+import pytest
+
+from lambda_aitia import (
+ AitiaNativeSession,
+ OrgElementFact,
+ evaluate_org_contract,
+)
+from lambda_aitia.native import AitiaNativeError
+
+
+ROWS = (
+ OrgElementFact(0, -1, "org-data"),
+ OrgElementFact(1, 0, "headline", "title", "Evidence"),
+)
+
+
+def test_orgize_contract_through_bundled_native_library() -> None:
+ result = evaluate_org_contract(
+ ROWS, scope_id=0, query_kind="headline", field_name="title",
+ field_value="Evidence",
+ )
+ assert result.matched_count == 1
+ assert result.passed is True
+ assert evaluate_org_contract(
+ ROWS, scope_id=0, query_kind="headline", field_name="title",
+ field_value="Missing",
+ ).passed is False
+
+
+def test_orgize_contract_uses_existing_native_session() -> None:
+ with AitiaNativeSession() as session:
+ result = evaluate_org_contract(
+ ROWS, scope_id=0, query_kind="headline", session=session,
+ )
+ assert result.matched_count == 1
+ with pytest.raises(AitiaNativeError, match="closed"):
+ evaluate_org_contract(
+ ROWS, scope_id=0, query_kind="headline", session=session,
+ )
+
+
+@pytest.mark.parametrize(
+ ("rows", "kind", "error"),
+ [
+ ((OrgElementFact(0, -1, "head\x00line"),), "headline", "NUL"),
+ ((OrgElementFact(-1, -1, "headline"),), "headline", "row id"),
+ (ROWS, "head\x00line", "NUL"),
+ ],
+)
+def test_orgize_transport_rejects_unsafe_inputs(rows, kind, error) -> None:
+ with pytest.raises(ValueError, match=error):
+ evaluate_org_contract(rows, scope_id=0, query_kind=kind)
diff --git a/bindings/python/tests/test_org_workspace.py b/bindings/python/tests/test_org_workspace.py
new file mode 100644
index 0000000..19ec0e5
--- /dev/null
+++ b/bindings/python/tests/test_org_workspace.py
@@ -0,0 +1,178 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+#
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Aitia preflight uses Orgize anchors; it never parses or mutates Org."""
+
+import hashlib
+from pathlib import Path
+
+import pytest
+
+from lambda_aitia import OrgNodeEdit, prepare_org_edit_review
+
+
+SOURCE = b"* Design\n:PROPERTIES:\n:ID: design-1\n:END:\nOld guarantee\n* Notes\nKeep me\n"
+
+
+def _digest(payload: bytes) -> str:
+ return "sha256:" + hashlib.sha256(payload).hexdigest()
+
+
+def _edit(payload: bytes = SOURCE, target: bytes = b"Old guarantee") -> OrgNodeEdit:
+ start = payload.index(target)
+ return OrgNodeEdit("design-1", start, start + len(target), target, b"New guarantee")
+
+
+def test_prepares_source_bound_review_without_writing(tmp_path: Path) -> None:
+ source = tmp_path / "design.org"
+ source.write_bytes(SOURCE)
+ review = prepare_org_edit_review(
+ source,
+ source_id="design.org",
+ projected_source_digest=_digest(SOURCE),
+ edits=(_edit(),),
+ )
+ assert review.source_id == "design.org"
+ assert review.source_digest == _digest(SOURCE)
+ assert review.edits == (_edit(),)
+ assert review.source_current(source)
+ assert source.read_bytes() == SOURCE
+
+
+def test_preflights_aitia_maintained_workspace_without_mutating_it() -> None:
+ source = Path(__file__).resolve().parents[3] / "user-interface/workspaces/job-executor.org"
+ payload = source.read_bytes()
+ expected = b"This subtree is the review context for ADR 0008."
+ start = payload.index(expected)
+ review = prepare_org_edit_review(
+ source,
+ source_id="job-executor",
+ projected_source_digest=_digest(payload),
+ edits=(
+ OrgNodeEdit(
+ "aitia-job-executor-design-decision",
+ start,
+ start + len(expected),
+ expected,
+ b"This subtree requires renewed review for ADR 0008.",
+ ),
+ ),
+ )
+ assert review.source_current(source)
+ assert source.read_bytes() == payload
+
+
+def test_rejects_stale_projection_even_when_old_text_remains(tmp_path: Path) -> None:
+ source = tmp_path / "design.org"
+ source.write_bytes(SOURCE + b"* Later\n")
+ with pytest.raises(ValueError, match="changed since projection"):
+ prepare_org_edit_review(
+ source,
+ source_id="design.org",
+ projected_source_digest=_digest(SOURCE),
+ edits=(_edit(),),
+ )
+
+
+def test_rejects_moved_span_with_fresh_digest(tmp_path: Path) -> None:
+ source = tmp_path / "design.org"
+ moved = SOURCE.replace(b"Old guarantee", b"prefix Old guarantee")
+ source.write_bytes(moved)
+ with pytest.raises(ValueError, match="moved or its expected content changed"):
+ prepare_org_edit_review(
+ source,
+ source_id="design.org",
+ projected_source_digest=_digest(moved),
+ edits=(_edit(),),
+ )
+
+
+def test_rejects_overlapping_edits_and_duplicate_node(tmp_path: Path) -> None:
+ source = tmp_path / "design.org"
+ source.write_bytes(SOURCE)
+ first = _edit()
+ second = OrgNodeEdit(
+ "design-2",
+ first.start_byte + 1,
+ first.end_byte,
+ SOURCE[first.start_byte + 1 : first.end_byte],
+ b"changed",
+ )
+ with pytest.raises(ValueError, match="overlap"):
+ prepare_org_edit_review(
+ source, source_id="design.org", projected_source_digest=_digest(SOURCE),
+ edits=(first, second),
+ )
+ with pytest.raises(ValueError, match="duplicate Org node ID"):
+ prepare_org_edit_review(
+ source, source_id="design.org", projected_source_digest=_digest(SOURCE),
+ edits=(first, first),
+ )
+
+
+def test_review_goes_stale_after_preflight(tmp_path: Path) -> None:
+ source = tmp_path / "design.org"
+ source.write_bytes(SOURCE)
+ review = prepare_org_edit_review(
+ source, source_id="design.org", projected_source_digest=_digest(SOURCE),
+ edits=(_edit(),),
+ )
+ source.write_bytes(SOURCE.replace(b"Keep me", b"Changed"))
+ assert not review.source_current(source)
+
+
+def test_refuses_symlink_and_invalid_byte_span(tmp_path: Path) -> None:
+ source = tmp_path / "design.org"
+ source.write_bytes(SOURCE)
+ alias = tmp_path / "alias.org"
+ alias.symlink_to(source)
+ with pytest.raises(OSError):
+ prepare_org_edit_review(
+ alias, source_id="design.org", projected_source_digest=_digest(SOURCE),
+ edits=(_edit(),),
+ )
+ bad = OrgNodeEdit("design-1", True, 3, b"* D", b"new")
+ with pytest.raises(ValueError, match="invalid byte span"):
+ prepare_org_edit_review(
+ source, source_id="design.org", projected_source_digest=_digest(SOURCE),
+ edits=(bad,),
+ )
+
+
+def test_refuses_non_utf8_source_and_split_codepoint(tmp_path: Path) -> None:
+ source = tmp_path / "design.org"
+ source.write_bytes(SOURCE + b"\xff")
+ with pytest.raises(ValueError, match="source must be UTF-8"):
+ prepare_org_edit_review(
+ source, source_id="design.org",
+ projected_source_digest=_digest(source.read_bytes()), edits=(_edit(),),
+ )
+ unicode_source = SOURCE + "说明\n".encode()
+ source.write_bytes(unicode_source)
+ start = unicode_source.index("说明".encode()) + 1
+ split = OrgNodeEdit("design-1", start, start + 1, b"\x01", b"x")
+ with pytest.raises(ValueError, match="splits a UTF-8 codepoint"):
+ prepare_org_edit_review(
+ source, source_id="design.org",
+ projected_source_digest=_digest(unicode_source), edits=(split,),
+ )
+
+
+def test_refuses_non_utf8_replacement_and_excess_edit_count(tmp_path: Path) -> None:
+ source = tmp_path / "design.org"
+ source.write_bytes(SOURCE)
+ edit = _edit()
+ invalid = OrgNodeEdit(
+ edit.node_id, edit.start_byte, edit.end_byte, edit.expected_old, b"\xff",
+ )
+ with pytest.raises(ValueError, match="edit must use UTF-8"):
+ prepare_org_edit_review(
+ source, source_id="design.org", projected_source_digest=_digest(SOURCE),
+ edits=(invalid,),
+ )
+ with pytest.raises(ValueError, match="edit count"):
+ prepare_org_edit_review(
+ source, source_id="design.org", projected_source_digest=_digest(SOURCE),
+ edits=(edit,) * 129,
+ )
diff --git a/bindings/python/tests/test_verification.py b/bindings/python/tests/test_verification.py
new file mode 100644
index 0000000..817ee82
--- /dev/null
+++ b/bindings/python/tests/test_verification.py
@@ -0,0 +1,221 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+#
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+from pathlib import Path
+import hashlib
+import os
+import sys
+import time
+
+import anyio
+import pytest
+
+from lambda_aitia.verification import (
+ capture_source_tree,
+ run_pytest,
+ run_pytest_frozen,
+ run_pytest_frozen_async,
+ source_digest,
+)
+
+
+@pytest.mark.parametrize(
+ ("body", "status"),
+ [
+ ("def test_ok():\n assert True\n", "passed"),
+ ("def test_no():\n assert False\n", "failed"),
+ ("import pytest\n@pytest.mark.skip\ndef test_skip():\n pass\n", "no-passing-tests"),
+ ],
+)
+def test_pytest_observation_classifies_execution(
+ tmp_path: Path, body: str, status: str
+) -> None:
+ (tmp_path / "test_case.py").write_text(body)
+ observed = run_pytest(Path(sys.executable), tmp_path, ("test_case.py",))
+ assert observed.status == status
+ assert observed.passed_obligation is (status == "passed")
+ assert observed.collected == 1
+ assert observed.report_digest is not None
+ assert observed.source_current(tmp_path)
+
+
+def test_pytest_observation_rejects_no_collection(tmp_path: Path) -> None:
+ (tmp_path / "test_case.py").write_text("x = 1\n")
+ observed = run_pytest(Path(sys.executable), tmp_path, ("test_case.py",))
+ assert observed.status == "no-tests"
+ assert observed.exit_code == 5
+
+
+def test_pytest_observation_detects_source_drift(tmp_path: Path) -> None:
+ source = tmp_path / "test_case.py"
+ source.write_text(
+ "from pathlib import Path\n"
+ "def test_change():\n"
+ " Path(__file__).write_text('changed')\n"
+ )
+ observed = run_pytest(Path(sys.executable), tmp_path, ("test_case.py",))
+ assert observed.status == "source-changed"
+ assert not observed.passed_obligation
+ # The verifier mutated only the frozen execution tree, not caller source.
+ assert observed.source_current(tmp_path)
+ assert source.read_text().startswith("from pathlib import Path")
+
+
+def test_frozen_execution_uses_captured_bytes_not_later_source(tmp_path: Path) -> None:
+ source = tmp_path / "test_case.py"
+ source.write_text("def test_ok():\n assert True\n")
+ payload = capture_source_tree(tmp_path)
+ assert source_digest(tmp_path) == "sha256:" + hashlib.sha256(payload).hexdigest()
+ source.write_text("def test_no():\n assert False\n")
+ observed = run_pytest_frozen(Path(sys.executable), payload, ("test_case.py",))
+ assert observed.status == "passed"
+ assert not observed.source_current(tmp_path)
+ assert observed.source_digest != source_digest(tmp_path)
+
+
+def test_anyio_frozen_execution_keeps_source_and_authority_separate(
+ tmp_path: Path,
+) -> None:
+ source = tmp_path / "test_case.py"
+ source.write_text("def test_ok():\n assert True\n")
+ payload = capture_source_tree(tmp_path)
+
+ async def execute():
+ return await run_pytest_frozen_async(
+ Path(sys.executable), payload, ("test_case.py",),
+ limiter=anyio.CapacityLimiter(1),
+ )
+
+ observed = anyio.run(execute)
+ assert observed.status == "passed"
+ assert observed.source_digest == "sha256:" + hashlib.sha256(payload).hexdigest()
+ assert observed.source_current(tmp_path)
+
+
+def test_anyio_cancellation_waits_for_bounded_verifier_cleanup(
+ tmp_path: Path,
+) -> None:
+ if os.name != "posix":
+ pytest.skip("process-group termination is qualified on POSIX")
+ marker = tmp_path.parent / "cancelled-verifier-marker"
+ started = tmp_path.parent / "cancelled-verifier-started"
+ (tmp_path / "test_case.py").write_text(
+ "import subprocess, sys, time\n"
+ "from pathlib import Path\n"
+ "def test_child():\n"
+ " subprocess.Popen([sys.executable, '-c', "
+ f"\"import time; from pathlib import Path; time.sleep(2); "
+ f"Path({str(marker)!r}).write_text('orphan')\"])\n"
+ f" Path({str(started)!r}).write_text('started')\n"
+ " time.sleep(5)\n"
+ )
+ payload = capture_source_tree(tmp_path)
+
+ async def observe() -> None:
+ await run_pytest_frozen_async(
+ Path(sys.executable), payload, ("test_case.py",),
+ timeout_seconds=1,
+ )
+
+ async def execute() -> None:
+ async with anyio.create_task_group() as tasks:
+ tasks.start_soon(observe)
+ with anyio.fail_after(3):
+ while not started.exists():
+ await anyio.sleep(0.01)
+ tasks.cancel_scope.cancel()
+
+ anyio.run(execute)
+ time.sleep(2.2)
+ assert not marker.exists()
+
+
+def test_frozen_source_rejects_escaping_selectors_and_malformed_bytes(
+ tmp_path: Path,
+) -> None:
+ (tmp_path / "test_case.py").write_text("def test_ok():\n assert True\n")
+ payload = capture_source_tree(tmp_path)
+ with pytest.raises(ValueError, match="selector"):
+ run_pytest_frozen(Path(sys.executable), payload, ("../test_case.py",))
+ with pytest.raises(ValueError, match="trailing"):
+ run_pytest_frozen(Path(sys.executable), payload + b"forged", ("test_case.py",))
+
+
+def test_frozen_source_orders_paths_by_canonical_bytes(tmp_path: Path) -> None:
+ nested = tmp_path / "a"
+ nested.mkdir()
+ (nested / "test_case.py").write_text("def test_ok():\n assert True\n")
+ (tmp_path / "a.txt").write_text("sibling")
+ payload = capture_source_tree(tmp_path)
+ observed = run_pytest_frozen(Path(sys.executable), payload, ("a/test_case.py",))
+ assert observed.status == "passed"
+
+
+def test_caller_tree_change_during_frozen_run_invalidates_observation(
+ tmp_path: Path,
+) -> None:
+ source = tmp_path / "test_case.py"
+ source.write_text(
+ "from pathlib import Path\n"
+ "def test_mutate_caller():\n"
+ f" Path({str(source)!r}).write_text('changed')\n"
+ )
+ observed = run_pytest(Path(sys.executable), tmp_path, ("test_case.py",))
+ assert observed.status == "source-changed"
+ assert not observed.source_current(tmp_path)
+
+
+def test_source_capture_refuses_symlink(tmp_path: Path) -> None:
+ (tmp_path / "real.py").write_text("x = 1\n")
+ (tmp_path / "alias.py").symlink_to(tmp_path / "real.py")
+ with pytest.raises(ValueError, match="symlink"):
+ capture_source_tree(tmp_path)
+
+
+def test_pytest_observation_rejects_timeout(tmp_path: Path) -> None:
+ (tmp_path / "test_case.py").write_text(
+ "from time import sleep\n"
+ "def test_slow():\n"
+ " sleep(5)\n"
+ )
+ observed = run_pytest(
+ Path(sys.executable), tmp_path, ("test_case.py",), timeout_seconds=1
+ )
+ assert observed.status == "timeout"
+ assert observed.exit_code is None
+ assert not observed.passed_obligation
+
+
+def test_pytest_observation_stops_child_process_on_timeout(tmp_path: Path) -> None:
+ if os.name != "posix":
+ pytest.skip("process-group termination is qualified on POSIX")
+ marker = tmp_path.parent / "orphan-marker"
+ (tmp_path / "test_case.py").write_text(
+ "import subprocess, sys, time\n"
+ "def test_child():\n"
+ " subprocess.Popen([sys.executable, '-c', "
+ f"\"import time; from pathlib import Path; time.sleep(2); "
+ f"Path({str(marker)!r}).write_text('orphan')\"])\n"
+ " time.sleep(5)\n"
+ )
+ observed = run_pytest(
+ Path(sys.executable), tmp_path, ("test_case.py",), timeout_seconds=1
+ )
+ assert observed.status == "timeout"
+ time.sleep(2.2)
+ assert not marker.exists()
+
+
+def test_pytest_observation_caps_output(tmp_path: Path) -> None:
+ (tmp_path / "test_case.py").write_text(
+ "def test_loud():\n print('x' * 500_000)\n"
+ )
+ observed = run_pytest(
+ Path(sys.executable), tmp_path, ("test_case.py",),
+ max_output_bytes=4096,
+ )
+ assert observed.status == "output-exceeded"
+ assert observed.exit_code is None
+ assert len(observed.output) <= 8192
+ assert not observed.passed_obligation
diff --git a/bindings/python/uv.lock b/bindings/python/uv.lock
index dac486f..e655752 100644
--- a/bindings/python/uv.lock
+++ b/bindings/python/uv.lock
@@ -2,6 +2,19 @@ version = 1
revision = 3
requires-python = ">=3.11"
+[[package]]
+name = "anyio"
+version = "4.15.1"
+source = { registry = "https://pypi.org/simple" }
+dependencies = [
+ { name = "idna" },
+ { name = "typing-extensions", marker = "python_full_version < '3.15'" },
+]
+sdist = { url = "https://files.pythonhosted.org/packages/a9/d2/f4d173e22df740bc37b1db102b386ba719b66e95b0f0d751f556b387e6d2/anyio-4.15.1.tar.gz", hash = "sha256:9f28306018cbd6d329e64a36d58256edff76dd996fe423bc957326e578b82a94", size = 276966, upload-time = "2026-09-05T10:42:39.44Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/12/b8/4bd346e22b28902df4d651910f5242c28d84e4a5c2435ca5c3f797ed7e2e/anyio-4.15.1-py3-none-any.whl", hash = "sha256:6152fdbbf9a77fdec97731721bebf7c4c44f7c29b424b0065826173efc7ed101", size = 132079, upload-time = "2026-09-05T10:42:37.923Z" },
+]
+
[[package]]
name = "cffi"
version = "2.1.1"
@@ -109,6 +122,15 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
]
+[[package]]
+name = "idna"
+version = "3.20"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f5/08/8eea9d4b8302028f3abb2c0813953f7aec26d33b7a8960ed760e65ff29fa/idna-3.20.tar.gz", hash = "sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44", size = 216463, upload-time = "2026-09-17T14:11:04.752Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/58/a2/bb081bab032533a855d44de1d56f8e8426114ff1ba5d1f07a438a0a654f8/idna-3.20-py3-none-any.whl", hash = "sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c", size = 69583, upload-time = "2026-09-17T14:11:03.168Z" },
+]
+
[[package]]
name = "iniconfig"
version = "2.3.0"
@@ -123,6 +145,7 @@ name = "lambda-aitia"
version = "0.1.0"
source = { editable = "." }
dependencies = [
+ { name = "anyio" },
{ name = "cffi" },
]
@@ -134,6 +157,7 @@ test = [
[package.metadata]
requires-dist = [
+ { name = "anyio", specifier = ">=4.14.1" },
{ name = "cffi", specifier = ">=2.0" },
{ name = "pytest", marker = "extra == 'test'", specifier = ">=8.0" },
{ name = "setuptools", marker = "extra == 'test'", specifier = ">=77" },
@@ -200,3 +224,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/6d/44/f5da03a8ef95d3691
wheels = [
{ url = "https://files.pythonhosted.org/packages/95/9c/c510029fc6ef33a6275cd2c5d3cecd6613dfd6aa401d57c54f1c18852ccf/setuptools-84.0.0-py3-none-any.whl", hash = "sha256:51a52592b3b99e102b609654876bd65f19f999935166d1352678931132b0c670", size = 818216, upload-time = "2026-08-08T18:27:56.719Z" },
]
+
+[[package]]
+name = "typing-extensions"
+version = "4.16.0"
+source = { registry = "https://pypi.org/simple" }
+sdist = { url = "https://files.pythonhosted.org/packages/f6/cc/6253133b5bb138fc3306cebfbda2c520f545d36b5be2c7255cc528bb45d6/typing_extensions-4.16.0.tar.gz", hash = "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5", size = 113555, upload-time = "2026-07-02T08:40:05.92Z" }
+wheels = [
+ { url = "https://files.pythonhosted.org/packages/49/d3/b8441a820a491ddfc024b0b0cf0393375b75ea13866d9c66727e54c2fc80/typing_extensions-4.16.0-py3-none-any.whl", hash = "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", size = 45571, upload-time = "2026-07-02T08:40:04.659Z" },
+]
diff --git a/build.ss b/build.ss
index fb9f466..fbbeffd 100755
--- a/build.ss
+++ b/build.ss
@@ -20,6 +20,7 @@
"modules/formal-methods/interface.ss"
"modules/gitops/interface.ss"
"modules/sdlc/interface.ss"
+ "modules/sdlc/retirement-host.ss"
"modules/sdlc/standards/interface.ss"
"user-interface/compositions/aitia.ss"
"user-interface/profiles/software-engineering/project.ss"
@@ -27,7 +28,7 @@
"user-interface/profiles/gitops/dev.ss"
"user-interface/profiles/gitops/staging.ss"
"user-interface/profiles/gitops/production.ss"
- "user-interface/profiles/sdlc/nasa-7150-2d.ss"))
+ "user-interface/profiles/nasa/sdlc.ss"))
(asp-gerbil-scheme-package-spec!
(lambda-aitia-package @ asp-gerbil-scheme-library-package-prototype)
@@ -37,4 +38,10 @@
'((gxc: "testing-interface")
(gxc: "testing-observer"))))
-(defbuild-script (lambda-aitia-native-spec))
+(cond-expand
+ (darwin
+ ;; Gerbil v0.19's cross-module keyword specialization on Darwin can
+ ;; reference private __% procedures from POO CLOS .ssxi metadata.
+ (defbuild-script (lambda-aitia-native-spec) optimize: #f))
+ (else
+ (defbuild-script (lambda-aitia-native-spec))))
diff --git a/docs/adrs/0001-dependency-direction.org b/docs/adrs/0001-dependency-direction.org
index 1dc1eee..ff4900f 100644
--- a/docs/adrs/0001-dependency-direction.org
+++ b/docs/adrs/0001-dependency-direction.org
@@ -10,13 +10,13 @@
:REVISION: r1
:RFC_ID: lambda-aitia-rfc-0001
:DECISION_MAKERS: tao3k-maintainers
-:CONSULTED: poo-flow-maintainers
+:CONSULTED: agentic-ai-lab-maintainers
:INFORMED: lambda-aitia-consumers
:END:
* Context and Problem Statement
-Lambda Aitia needs POO Flow composition and graph contracts, while POO Flow
+Lambda Aitia needs Agentic AI Lab composition and graph contracts, while Agentic AI Lab
must remain independently usable. The ownership of Software/SDLC, native
bindings and runtime transport also needs one explicit direction.
@@ -30,15 +30,15 @@ bindings and runtime transport also needs one explicit direction.
* Considered Options
-1. POO Flow core imports Aitia.
-2. Bidirectional imports between POO Flow and Aitia.
-3. Aitia imports reviewed POO Flow public contracts; applications compose them.
+1. Agentic AI Lab core imports Aitia.
+2. Bidirectional imports between Agentic AI Lab and Aitia.
+3. Aitia imports reviewed Agentic AI Lab public contracts; applications compose them.
* Decision Outcome
-Lambda Aitia may import reviewed public POO Flow contracts. POO Flow core must
+Lambda Aitia may import reviewed public Agentic AI Lab contracts. Agentic AI Lab core must
remain usable without Lambda Aitia and must never import Aitia source modules.
-Applications explicitly compose POO Flow, Aitia and any other contribution.
+Applications explicitly compose Agentic AI Lab, Aitia and any other contribution.
Mounting the Aitia Git submodule performs no activation, verification or
effect.
@@ -49,9 +49,9 @@ it is not an Aitia semantic owner.
* Consequences
-- Good: Aitia modules use precise POO Flow import owners rather than aggregate
+- Good: Aitia modules use precise Agentic AI Lab import owners rather than aggregate
facades when a precise owner exists.
-- Good: integration adapters live in Aitia or an application, not POO Flow core.
+- Good: integration adapters live in Aitia or an application, not Agentic AI Lab core.
- Good: Python calls the Aitia C ABI and does not reproduce Scheme decisions.
- Neutral: parent registration identifies and locates the contribution but grants no
runtime authority.
@@ -62,7 +62,7 @@ it is not an Aitia semantic owner.
- Parent registry and import-policy tests retain the one-way dependency.
- Aitia native and Python smoke tests cross only the owned C ABI.
-- Source scans reject Aitia imports from POO Flow core.
+- Source scans reject Aitia imports from Agentic AI Lab core.
* More Information
diff --git a/docs/adrs/0002-standardize-ADR-and-connect-RFC.org b/docs/adrs/0002-standardize-ADR-and-connect-RFC.org
index 7551678..35a3689 100644
--- a/docs/adrs/0002-standardize-ADR-and-connect-RFC.org
+++ b/docs/adrs/0002-standardize-ADR-and-connect-RFC.org
@@ -10,7 +10,7 @@
:REVISION: r1
:RFC_ID: lambda-aitia-rfc-0001
:DECISION_MAKERS: tao3k-maintainers
-:CONSULTED: poo-flow-maintainers
+:CONSULTED: agentic-ai-lab-maintainers
:INFORMED: lambda-aitia-consumers
:END:
diff --git a/docs/adrs/0003-review-poo-flow-contract-allowlist.org b/docs/adrs/0003-review-agentic-ai-lab-contract-allowlist.org
similarity index 80%
rename from docs/adrs/0003-review-poo-flow-contract-allowlist.org
rename to docs/adrs/0003-review-agentic-ai-lab-contract-allowlist.org
index 52bc23c..9476c82 100644
--- a/docs/adrs/0003-review-poo-flow-contract-allowlist.org
+++ b/docs/adrs/0003-review-agentic-ai-lab-contract-allowlist.org
@@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-#+title: ADR 0003 — Review the POO Flow contract allowlist
+#+title: ADR 0003 — Review the Agentic AI Lab contract allowlist
:PROPERTIES:
:ID: lambda-aitia-adr-0003
@@ -11,25 +11,25 @@
:SUPERSEDED_BY: lambda-aitia-adr-0007
:RFC_ID: lambda-aitia-rfc-0001
:DECISION_MAKERS: tao3k-maintainers
-:CONSULTED: poo-flow-maintainers
+:CONSULTED: agentic-ai-lab-maintainers
:INFORMED: lambda-aitia-consumers
:END:
* Context and Problem Statement
-Lambda Aitia depends on POO Flow mechanisms but must not track arbitrary parent
+Lambda Aitia depends on Agentic AI Lab mechanisms but must not track arbitrary parent
internals. RFC 0001 requires a reviewed stable dependency boundary.
* Decision Drivers
-- Keep POO Flow independently usable without Aitia.
+- Keep Agentic AI Lab independently usable without Aitia.
- Make every imported mechanism owner auditable.
- Prevent convenience imports from silently expanding the dependency surface.
* Considered Options
-1. Permit any =:poo-flow/src/= import.
-2. Copy POO Flow mechanisms into Aitia.
+1. Permit any =:agentic-ai-lab/src/= import.
+2. Copy Agentic AI Lab mechanisms into Aitia.
3. Maintain an exact reviewed owner allowlist and require an ADR revision for
additions.
@@ -49,7 +49,7 @@ required by the migrated implementation:
Aggregate parent facades, runtime lifecycle owners, Cedar authority and effect
execution are not implicitly allowed. A new owner path requires review and a
new ADR revision. Moving an allowlisted contract is a coordinated breaking
-change until POO Flow publishes a stable facade for it.
+change until Agentic AI Lab publishes a stable facade for it.
* Consequences
@@ -62,14 +62,14 @@ change until POO Flow publishes a stable facade for it.
- Review compares Scheme imports against the owner set; an executable
repository gate remains required before this check can be called automatic.
-- POO Flow core import-policy tests continue to reject Aitia imports.
+- Agentic AI Lab core import-policy tests continue to reject Aitia imports.
- RFC acceptance remains blocked if the allowlist and actual imports diverge.
* More Information
- [[file:../rfcs/0001-causal-assurance-core.org][RFC 0001 — Causal Assurance Core]]
- [[file:0001-dependency-direction.org][ADR 0001 — Contribution Dependency Direction]]
-- [[file:0007-consume-poo-flow-public-library.org][ADR 0007 — Consume POO Flow as the mechanism library]]
+- [[file:0007-consume-agentic-ai-lab-public-library.org][ADR 0007 — Consume Agentic AI Lab as the mechanism library]]
This decision was superseded because an exact owner allowlist incorrectly
treated dependency count as an architectural objective. The retained
diff --git a/docs/adrs/0004-own-assurance-proofs-in-aitia.org b/docs/adrs/0004-own-assurance-proofs-in-aitia.org
index 7c6c188..decca48 100644
--- a/docs/adrs/0004-own-assurance-proofs-in-aitia.org
+++ b/docs/adrs/0004-own-assurance-proofs-in-aitia.org
@@ -7,41 +7,45 @@
:ID: lambda-aitia-adr-0004
:STATUS: accepted
:DATE: 2026-09-17
-:REVISION: r1
+:REVISION: r2
:RFC_ID: lambda-aitia-rfc-0001
:DECISION_MAKERS: tao3k-maintainers
-:CONSULTED: poo-flow-proof-maintainers
+:CONSULTED: agentic-ai-lab-proof-maintainers
:INFORMED: lambda-aitia-consumers
:END:
* Context and Problem Statement
-The assurance laws and lifecycle model need one source owner. POO Flow already
+The assurance laws and lifecycle model need one source owner. Agentic AI Lab already
contains generic composition and runtime proofs, but those artifacts must not
become owners of Aitia claim, evidence or invalidation semantics.
* Decision Outcome
-Lambda Aitia owns Lean statements and TLA+ models whose vocabulary is defined by
+Lambda Aitia owns Lean statements and Quint models whose vocabulary is defined by
Aitia, including evidence freshness, no stale authority, invalidation,
counterfactual isolation and the assurance lifecycle. It may consume a pinned,
-independently versioned POO Flow proof package for generic composition laws.
-POO Flow proof sources are referenced, not copied or silently moved.
+independently versioned Agentic AI Lab proof package for generic composition laws.
+Agentic AI Lab proof sources are referenced, not copied or silently moved.
-Theorems and TLC receipts remain evidence inputs. Neither grants a current
+Theorems and Quint/TLC receipts remain evidence inputs. Neither grants a current
Decision or Effect authority.
+The 2026-10-10 r2 amendment replaces the maintained TLA+ source and TLAPS
+roadmap lane with Quint. TLC remains the bounded checker behind Quint; generated
+TLA+ for fairness is a temporary checker artifact, not a maintained model.
+
* Consequences
- Good: proof statements evolve with their semantic owner.
-- Good: generic POO Flow laws remain reusable and independently released.
+- Good: generic Agentic AI Lab laws remain reusable and independently released.
- Bad: cross-repository theorem dependencies require explicit version receipts.
* Confirmation
- [X] Aitia proof builds run from Aitia-owned source paths through
=just check-proof=.
-- [X] The initial proof package imports no POO Flow theorem; therefore no
+- [X] The initial proof package imports no Agentic AI Lab theorem; therefore no
cross-repository proof revision is currently admitted.
- [X] The inert-receipt theorem keeps proof success separate from release
authority and runtime execution.
diff --git a/docs/adrs/0005-canonical-snapshot-persistence.org b/docs/adrs/0005-canonical-snapshot-persistence.org
index 2a5ec65..0405c03 100644
--- a/docs/adrs/0005-canonical-snapshot-persistence.org
+++ b/docs/adrs/0005-canonical-snapshot-persistence.org
@@ -10,7 +10,7 @@
:REVISION: r1
:RFC_ID: lambda-aitia-rfc-0001
:DECISION_MAKERS: tao3k-maintainers
-:CONSULTED: poo-flow-maintainers
+:CONSULTED: agentic-ai-lab-maintainers
:INFORMED: lambda-aitia-consumers
:END:
diff --git a/docs/adrs/0006-production-python-sdlc-runtime.org b/docs/adrs/0006-production-python-sdlc-runtime.org
index cfd2131..6d53eec 100644
--- a/docs/adrs/0006-production-python-sdlc-runtime.org
+++ b/docs/adrs/0006-production-python-sdlc-runtime.org
@@ -1,16 +1,17 @@
# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-#+title: ADR 0006 — Maintain Python as the production SDLC runtime
+#+title: ADR 0006 — Maintain Aitia Python Runtime as a production project
:PROPERTIES:
:ID: lambda-aitia-adr-0006
:STATUS: accepted
:DATE: 2026-09-18
-:REVISION: r1
+:REVISION: r3
+:UPDATED: 2026-09-24
:RFC_ID: lambda-aitia-rfc-0001
:DECISION_MAKERS: tao3k-maintainers
-:CONSULTED: poo-flow-maintainers
+:CONSULTED: agentic-ai-lab-maintainers
:INFORMED: lambda-aitia-consumers
:END:
@@ -23,24 +24,45 @@ implementations to drift.
* Decision
-=bindings/python= is Lambda Aitia's production Python project. Its public
-runtime covers the complete lifecycle vocabulary:
+=bindings/python= is Lambda Aitia's production Python Runtime serving all its
+capabilities within the complete SDLC: requirements, design, algorithms and
+implementation strategies, testing, delivery, operation and evolution. Its
+first lifecycle-planning API projects this assurance/execution protocol:
-#+begin_example
-change -> invalidate -> plan -> verify -> admit -> decide -> authorize -> effect
-#+end_example
+#+begin_export mermaid
+flowchart TD
+ C["change
identified"] --> I["invalidate
dependent support stale"]
+ I --> P["plan
obligations pending"]
+ P --> V["verify
candidate results produced"]
+ V --> A["admit
evidence accepted within scope"]
+ A --> D["decide
decision current"]
+ D --> U["authorize
bounded effect permitted"]
+ U --> E["effect
execution receipt recorded"]
+ V -->|failed or unresolved| P
+ A -->|relevant premise changes| I
+ U -->|revoked or expired| I
+#+end_export
+
+Node labels describe the states a completed stage would establish. Feedback
+edges describe lifecycle reassessment, not edges returned by the current API.
+The API projects only an inert, ordered eight-stage DAG, not executed
+transitions. Admission, decision, authorization and execution each require
+their own checked receipt.
The responsibilities remain layered:
- Lambda Aitia Scheme owns SDLC stages, assurance semantics, decisions and
attributable receipts.
-- POO Flow owns reusable Graph/DAG algorithms and generic runtime mechanisms.
+- Agentic AI Lab owns reusable Graph/DAG algorithms and generic runtime mechanisms.
- The stable C ABI transfers owned JSON request and receipt bytes.
- Python validates and materializes those receipts for production consumers;
it does not reproduce the semantic algorithms.
+- AnyIO is the runtime-wide asynchronous foundation for structured task
+ lifetimes, cancellation and bounded concurrency across Aitia capabilities.
+ It does not grant Host authority or make an inert plan executable.
-The first admitted runtime operation is =SdlcRuntime.plan()=. It obtains the
-canonical eight-stage DAG from Scheme through ABI revision 2. The plan is
+The first exposed planning operation is =SdlcRuntime.plan()=. It obtains the
+eight-stage assurance DAG from Scheme through ABI revision 2. The plan is
inert and explicitly reports that it neither authorizes release nor proves
runtime execution.
@@ -49,9 +71,13 @@ runtime execution.
- Downstream users depend on =lambda-aitia= as a real uv-managed project.
- Python API stability is a release concern, not example-code maintenance.
- No stage may be presented as executed until its Scheme operation publishes a
- source-bound receipt and the POO Flow runtime actually executes it.
-- The complete lifecycle remains the product boundary even while individual
- executable stages are delivered incrementally.
+ source-bound receipt and the Agentic AI Lab runtime actually executes it.
+- The full SDLC organizes the Python project; the planning API is one capability
+ within it. Executable capabilities are delivered only with owned operations
+ and attributable receipts.
+- Generic temporal/causal trajectories and execution mechanisms are reused
+ from Agentic AI Lab. Upstream tools, checkers and assets are qualified at their
+ usable boundaries; MRR integration is deferred beyond this Python stage.
* Confirmation
@@ -60,3 +86,11 @@ runtime execution.
- Python tests construct the typed plan through the bundled native library.
- Wheel verification imports and calls the installed production package
without a Gerbil runtime in the Python process.
+
+* Scope clarification
+
+Revision r3 clarifies that the complete SDLC is the framework and the existing
+eight-stage plan is its assurance/execution protocol. It preserves the Python
+project and dependency ownership decision. Async execution, connected causal
+trajectories and real tool-to-Host admission remain pending gates under
+[[file:../rfcs/0004-sdlc-design-and-causal-trajectories.org][RFC 0004]].
diff --git a/docs/adrs/0007-consume-poo-flow-public-library.org b/docs/adrs/0007-consume-agentic-ai-lab-public-library.org
similarity index 61%
rename from docs/adrs/0007-consume-poo-flow-public-library.org
rename to docs/adrs/0007-consume-agentic-ai-lab-public-library.org
index 6dc8a41..030f70c 100644
--- a/docs/adrs/0007-consume-poo-flow-public-library.org
+++ b/docs/adrs/0007-consume-agentic-ai-lab-public-library.org
@@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-#+title: ADR 0007 — Consume POO Flow as the mechanism library
+#+title: ADR 0007 — Consume Agentic AI Lab as the mechanism library
:PROPERTIES:
:ID: lambda-aitia-adr-0007
@@ -11,46 +11,46 @@
:RFC_ID: lambda-aitia-rfc-0001
:SUPERSEDES: lambda-aitia-adr-0003
:DECISION_MAKERS: tao3k-maintainers
-:CONSULTED: poo-flow-maintainers
+:CONSULTED: agentic-ai-lab-maintainers
:INFORMED: lambda-aitia-consumers
:END:
* Context and Problem Statement
-Lambda Aitia is a Software/SDLC contribution built on POO Flow. POO Flow is
+Lambda Aitia is a Software/SDLC contribution built on Agentic AI Lab. Agentic AI Lab is
not an optional adapter from which Aitia should minimize imports; it is the
project's public mechanism and library dependency. Graph traversal, impact
trajectories, POO composition, functional flow, source locks, Standards,
module loading, verification handoff and generic Runtime mechanisms belong in
-POO Flow so every contribution can reuse them.
+Agentic AI Lab so every contribution can reuse them.
The former exact-owner allowlist confused auditable ownership with minimizing
the dependency surface. It also encouraged Aitia to reason about individual
-POO Flow source paths instead of the public library contract POO Flow releases.
+Agentic AI Lab source paths instead of the public library contract Agentic AI Lab releases.
* Decision Drivers
-- Reuse POO Flow's complete public mechanism library where Aitia needs it.
-- Keep generic mechanisms and high-quality algorithms in POO Flow rather than
+- Reuse Agentic AI Lab's complete public mechanism library where Aitia needs it.
+- Keep generic mechanisms and high-quality algorithms in Agentic AI Lab rather than
duplicating them in Aitia.
- Keep Software/SDLC semantics, assurance policy and the production Python SDLC
Runtime in Aitia.
-- Preserve the one-way dependency: POO Flow never imports Aitia.
+- Preserve the one-way dependency: Agentic AI Lab never imports Aitia.
- Make public-library compatibility and clean installation executable release
gates.
* Considered Options
-1. Keep an exact and intentionally small POO Flow owner allowlist.
+1. Keep an exact and intentionally small Agentic AI Lab owner allowlist.
2. Copy required mechanisms into Aitia to reduce parent dependencies.
-3. Treat POO Flow as Aitia's public mechanism library and govern the ownership
+3. Treat Agentic AI Lab as Aitia's public mechanism library and govern the ownership
direction plus public API stability.
* Decision Outcome
-Choose option 3. Lambda Aitia may consume any reviewed public POO Flow library
+Choose option 3. Lambda Aitia may consume any reviewed public Agentic AI Lab library
needed by its implementation. There is no architectural target to minimize
-that dependency. POO Flow owns and publishes reusable mechanisms, including
+that dependency. Agentic AI Lab owns and publishes reusable mechanisms, including
Graph/Impact Graph algorithms and trajectories, POO CLOS, functional flow,
Sources Lock, Standards, User Interface discovery, verification adapters and
generic Runtime/lifecycle infrastructure.
@@ -60,32 +60,32 @@ ADR/RFC integration, assurance semantics, Aitia ABI projection and its
production Python SDLC Runtime. It does not fork or locally reproduce a POO
Flow mechanism merely to avoid a dependency.
-Direct internal =:poo-flow/src/= paths remain migration debt. POO Flow should
+Direct internal =:agentic-ai-lab/src/= paths remain migration debt. Agentic AI Lab should
publish cohesive Library facades; Aitia should consume those facades as they
become available. This is API stabilization, not dependency minimization.
* Consequences
-- Good: shared mechanisms and optimized algorithms retain one POO Flow owner.
-- Good: Aitia can use the complete POO Flow feature set needed by production
+- Good: shared mechanisms and optimized algorithms retain one Agentic AI Lab owner.
+- Good: Aitia can use the complete Agentic AI Lab feature set needed by production
Software/SDLC flows.
- Good: review focuses on semantic ownership and public API stability.
-- Neutral: a POO Flow release becomes an explicit Aitia build dependency.
-- Bad: incompatible POO Flow public-library changes block Aitia until the two
+- Neutral: a Agentic AI Lab release becomes an explicit Aitia build dependency.
+- Bad: incompatible Agentic AI Lab public-library changes block Aitia until the two
repositories are advanced together.
* Confirmation
-- A clean POO Flow installation exposes every public library imported by the
+- A clean Agentic AI Lab installation exposes every public library imported by the
pinned Aitia revision.
- Aitia production build, Scheme tests, native ABI and Python tests run against
that installation without dirty parent sources.
-- POO Flow source and import-policy checks continue to reject Aitia imports.
+- Agentic AI Lab source and import-policy checks continue to reject Aitia imports.
- Graph, Sources Lock, Standards and Runtime mechanisms have no duplicate Aitia
implementation.
* More Information
- [[file:0001-dependency-direction.org][ADR 0001 — Contribution Dependency Direction]]
-- [[file:0003-review-poo-flow-contract-allowlist.org][ADR 0003 — Superseded owner allowlist]]
+- [[file:0003-review-agentic-ai-lab-contract-allowlist.org][ADR 0003 — Superseded owner allowlist]]
- [[file:../rfcs/0001-causal-assurance-core.org][RFC 0001 — Causal Assurance Core]]
diff --git a/docs/adrs/0008-stable-operation-key-after-lost-ack.org b/docs/adrs/0008-stable-operation-key-after-lost-ack.org
new file mode 100644
index 0000000..b676932
--- /dev/null
+++ b/docs/adrs/0008-stable-operation-key-after-lost-ack.org
@@ -0,0 +1,125 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: ADR 0008 — Bind retry identity to the logical operation
+
+:PROPERTIES:
+:ID: lambda-aitia-adr-0008
+:STATUS: proposed
+:DATE: 2026-09-24
+:REVISION: r2
+:UPDATED: 2026-09-24
+:RFC_ID: lambda-aitia-rfc-0001
+:DECISION_MAKERS: tao3k-maintainers
+:CONSULTED: agentic-ai-lab-maintainers
+:INFORMED: lambda-aitia-consumers
+:END:
+
+* Context and Problem Statement
+
+The original job-executor declaration says that the provider deduplicates
+=tenant/job/operation= keys and guarantees at most one commit *per key*. A
+real-process qualification case exposes the gap: after a provider commits but
+its acknowledgement is lost, a restarted worker can generate a new key. The
+provider correctly deduplicates each key while committing the same logical
+job operation twice. This is a known fault-injection case, not a newly found
+defect in a deployed application.
+
+* Decision Drivers
+
+- Keep a single logical identity across retries and process restarts.
+- Preserve completion after a transient acknowledgement loss.
+- Do not claim exactly-once effects without provider idempotency and durable
+ task-state assumptions.
+- Keep a revised guarantee and its evidence separate from the old declaration.
+
+* Considered Options
+
+1. Keep the per-key guarantee and accept duplicate logical operations.
+2. Turn off retries, avoiding duplicates by sacrificing completion.
+3. Persist or deterministically derive a stable provider key from the logical
+ operation identity and revise the guarantee scope.
+
+* Decision Outcome
+
+Propose option 3. The job ledger owns the logical operation identity and retry
+state. The same tenant/job/operation key reaches an idempotent provider after
+restart. The revised =unique-effect= guarantee is at most one external commit
+per logical job operation across retries and restarts, conditional on the
+provider retaining its deduplication record. A changed guarantee, retry
+variation and ADR identity reopen verification; old evidence is not admitted
+by declaration-level compatibility.
+
+* Consequences
+
+- Good: acknowledgement loss does not create a second effect in the bounded
+ qualification case, and the worker can still complete after restart.
+- Bad: key retention, scoping and provider deduplication are new operational
+ dependencies to qualify before any production assurance claim.
+- Neutral: this proposed ADR neither issues a Host seal nor authorizes an
+ effect. Acceptance requires independent review of the actual provider and
+ persistence mechanism.
+
+* Confirmation
+
+- The Python project's installed-wheel qualification runs two worker processes
+ against a persistent SQLite ledger and a loopback HTTP provider. The buggy
+ key strategy fails with two commits; the stable strategy passes with one.
+- The Scheme design-replacement test treats the changed guarantee and decision
+ as requiring fresh review, with no evidence admission or release authority.
+- Full source-bound Host admission and production provider qualification remain
+ open.
+
+* Historical input and current coverage
+
+Revision r2 retains the proposed decision and adds an applicability and owner
+audit. It does not accept the ADR or certify a production provider.
+[[file:../plans/engineering-case-source-inventory.org][The case-source inventory]] records the AWS article used as design inspiration,
+alongside candidate history/observability and composition cases. Its treatment
+of late retries and changed intent motivates questions about retention and
+payload binding; it is not verification evidence for this project.
+
+Source inspection on 2026-09-24 found that the fixture worker uses one literal
+=job-42= key in fixed mode and always sends =commit=. The provider stores the
+effect and key as one SQLite row, uses =insert or ignore= and withholds the
+first ACK. This covers a bounded lost-ACK/restart scenario; it has no separate
+external effect, expiry, parameter-conflict check or tenant namespace. The
+=fixed= mode name denotes the repair to that specific injected fault only.
+The inspected sources are the [[file:../../bindings/python/qualification/job_executor/worker.py][worker]],
+[[file:../../bindings/python/qualification/job_executor/test_unique_effect.py][provider/test fixture]] and [[file:../../modules/assurance/host.ss][Host preflight projection]]. The reused Agentic AI Lab boundary is
+=src/modules/authorization/providers/cedar/interface.ss= and its existing
+decision/effect-token projection, not a new Aitia-owned authorization module.
+
+| Contract question | Existing mechanism / evidence boundary | Remaining obligation and owner |
+|-------------------+----------------------------------------+--------------------------------|
+| Is this attempt currently permitted? | Agentic AI Lab Cedar Provider and effect-token machinery exist; Aitia projects preflight requests and rechecks their currentness | Host supplies trusted facts; existing Cedar evaluates policy; Runtime enforces at use. The Aitia-to-Runtime path remains unqualified; no new local authorization engine |
+| Does retry preserve logical identity? | fixed mode uses one job identity across two sequential worker processes | Aitia task-state contract and actual provider must qualify tenant/job/operation scope, persistence and concurrent attempts |
+| Can the same identity change its intent? | payload is constant; provider does not compare an incoming payload with the stored payload | provider rejects inconsistent reuse; Host/Runtime bind authorized intent to dispatched bytes. Test mismatch rejection without an additional effect |
+| What if the deduplication record expires? | no expiry or cleanup is modeled | provider owns retention guarantee; Aitia records retry horizon and review conditions. Test boundary/late requests and explicit reconciliation or rejection outside the guarantee |
+| Is effect commit atomic with deduplication? | one SQLite row stands for both key and effect; no failure between independent commits is modeled | actual provider owns atomicity or its recovery protocol. Qualify crashes before/after commit and lost response; policy permission alone is insufficient |
+| What if two attempts are allowed concurrently? | existing scenario restarts workers sequentially | Runtime/provider qualify atomic reservation or deduplication and outcome reconciliation; two Cedar permits must not be mistaken for unique execution |
+
+Do not copy these checks into a second Python policy layer. Trusted
+identity/intent, current authority and applicable retry-window conditions may
+be inputs to the existing Cedar policy boundary. Their truth must come from
+the responsible Host/provider, not caller-supplied booleans. Policy evaluation
+does not persist a deduplication record, make a network request atomic, or
+prove whether an unacknowledged attempt committed.
+
+Retry identity and authorization identity are distinct: a logical operation
+keeps its identity after restart, but an old permit need not remain valid.
+An unknown result must retain that uncertainty until the provider's qualified
+retry/reconciliation contract resolves it. Generic Agentic AI Lab reconciliation
+cannot be assumed to establish uniqueness of an external provider effect.
+
+The desired design remains stable logical identity with current authorization
+and a qualified provider contract. The added obligations refine its conditions;
+they do not silently turn the guarantee into unconditional exactly-once delivery.
+
+* More Information
+
+- [[file:../../bindings/python/qualification/job_executor/README.org][Job-executor qualification case]]
+- [[file:../rfcs/0001-causal-assurance-core.org][RFC 0001 — Causal Assurance Core]]
+- [[file:../rfcs/0004-sdlc-design-and-causal-trajectories.org][RFC 0004 — Historical cases and lifecycle design]]
+- [[https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/][AWS Builders' Library — Idempotent API design]]
+- [[https://docs.cedarpolicy.com/auth/authorization.html][Cedar authorization semantics]]
diff --git a/docs/adrs/README.org b/docs/adrs/README.org
index ed73d1a..18db1f1 100644
--- a/docs/adrs/README.org
+++ b/docs/adrs/README.org
@@ -62,11 +62,12 @@ assurance closure and authority receipt is required before any effect.
- [[file:0001-dependency-direction.org][ADR 0001 — Dependency direction]]
- [[file:0002-standardize-ADR-and-connect-RFC.org][ADR 0002 — Standardize ADR and connect RFC]]
-- [[file:0003-review-poo-flow-contract-allowlist.org][ADR 0003 — Superseded POO Flow contract allowlist]]
+- [[file:0003-review-agentic-ai-lab-contract-allowlist.org][ADR 0003 — Superseded Agentic AI Lab contract allowlist]]
- [[file:0004-own-assurance-proofs-in-aitia.org][ADR 0004 — Own assurance proofs in Aitia]]
- [[file:0005-canonical-snapshot-persistence.org][ADR 0005 — Canonical snapshot persistence]]
-- [[file:0006-production-python-sdlc-runtime.org][ADR 0006 — Maintain Python as the production SDLC runtime]]
-- [[file:0007-consume-poo-flow-public-library.org][ADR 0007 — Consume POO Flow as the mechanism library]]
+- [[file:0006-production-python-sdlc-runtime.org][ADR 0006 — Maintain Aitia Python Runtime as a production project]]
+- [[file:0007-consume-agentic-ai-lab-public-library.org][ADR 0007 — Consume Agentic AI Lab as the mechanism library]]
+- [[file:0008-stable-operation-key-after-lost-ack.org][ADR 0008 — Bind retry identity to the logical operation (proposed)]]
* Standardization Sources
diff --git a/docs/migrations/episteme-sdlc-gitops-qualification-history.org b/docs/migrations/episteme-sdlc-gitops-qualification-history.org
index 22e6d1e..f624c6a 100644
--- a/docs/migrations/episteme-sdlc-gitops-qualification-history.org
+++ b/docs/migrations/episteme-sdlc-gitops-qualification-history.org
@@ -8,13 +8,13 @@
* Source and architecture
The contribution has no =gerbil.pkg= and owns no executable build script.
-POO Flow's default =build.ss= contains only its six maintained public roots:
+Agentic AI Lab's default =build.ss= contains only its six maintained public roots:
core API, Module System API, Feature System interface, Agent loop, kernel
profiles, and the hygienic User Interface init declaration owner.
-The POO Flow-owned =build-contribute.ss= adapter constructs the contribution
+The Agentic AI Lab-owned =build-contribute.ss= adapter constructs the contribution
source internally, consumes Lambda's source-neutral module bundle, and submits each selected module
tree to the ASP Build API as an independent source stage. The source files are
-derived by POO Flow's shared deterministic tree walk. Shared governance
+derived by Agentic AI Lab's shared deterministic tree walk. Shared governance
and the User Interface scenario are explicit non-module stages. There is no
=modules= override, =all-gerbil-modules= call, implementation-file enumeration,
second compiler, scheduler, or artifact cache.
@@ -43,7 +43,7 @@ not present on its load path. No SDLC result grants release authority.
** Superseded eager contribution closure (2026-09-14)
-After adding the contribution roots to POO Flow's PackageSpec, six unchanged
+After adding the contribution roots to Agentic AI Lab's PackageSpec, six unchanged
invocations completed in 101.89, 103.49, 90.77, 67.03, 84.89 and 100.46
seconds. Every invocation still emitted native compile jobs. A subsequent
production build after the focused core =gxtest= run rebuilt the broad closure
@@ -57,13 +57,13 @@ the full =src/module-system/api.ss= facade.
The linked ASP source is exactly the =gerbil.pkg= revision
=2a69a080976a0c0b80a78f5b6d05204fc7b4c653= and contains the linear import
closure projection. The failure therefore is not caused by a child-owned API,
-an old ASP checkout, or a second PackageSpec. POO Flow does not patch the
+an old ASP checkout, or a second PackageSpec. Agentic AI Lab does not patch the
upstream executor. The successful source build and 580 test checks establish
structural and behavioral evidence only; they do not establish build-performance
closure.
The table below is a historical observation of the superseded child-package
-layout. It must not be cited as evidence for the current POO Flow-owned
+layout. It must not be cited as evidence for the current Agentic AI Lab-owned
=build.ss= path.
The same isolated child output was built repeatedly without source changes.
@@ -92,7 +92,7 @@ ordered 39-module closure.
| content-bound hit | 1.501, 0.534, 0.454 | 0.534 |
The isolated projection reduced p50 by 94.4 percent, but it measured only the
-PackageSpec projection. Complete POO Flow warm-build comparison later measured
+PackageSpec projection. Complete Agentic AI Lab warm-build comparison later measured
a 38.24-second native-projection p50 and a 39.80-second receipt-hit p50. A hit
returned only paths and forced =std/make= to reconstruct contexts that a fresh
projection had already loaded. The receipt therefore moved work across the
@@ -114,7 +114,7 @@ recompile waves from the new shared tree function settled, the stable warm
Lambda's top-level interface now exports only its contribution identity. POO
Flow's core loader constructs contributor and user source objects from
-repository-root inputs; =poo-flow-load-modules= discovers the five direct module
+repository-root inputs; =agentic-ai-lab-load-modules= discovers the five direct module
directories without a contributor =modules/init.ss=. Lambda contains no =modules/source.ss= and no
=user-interface/modules/interface.ss=. The root-owned contribution adapter
derives five public =interface.ss= entrypoints from the source collection and adds fixed stages for
@@ -135,17 +135,17 @@ and init were separately visible at 6ms, 217ms, 281ms and 2ms.
Every stage emits its source, full package prefix, executor, elapsed time, and
receipt count before advancing. The core and contributor build gates are now
-separate, while both install under the existing =poo-flow= package namespace.
+separate, while both install under the existing =agentic-ai-lab= package namespace.
The User Interface layout gate accepts only top-level =init.ss= and =config.ss=
before ASP/std-make begins. A temporary =unclassified.ss= negative
-fixture failed in 1.19 seconds with =POO-FLOW-UI-E002= and named the offending
-file. The corrected top-level =init.ss= owns only =poo-flow!= module selection.
+fixture failed in 1.19 seconds with =AGENTIC-AI-LAB-UI-E002= and named the offending
+file. The corrected top-level =init.ss= owns only =agentic-ai-lab!= module selection.
The core-owned configuration =use-composition= discovers =profiles/= and
=scenarios/= once per expansion context, imports them into =config.ss=, and
establishes each named composition directly. A temporary incomplete
=modules/incomplete/config.ss= fixture failed in 1.21 seconds with
-=POO-FLOW-UI-E005= and named the four missing roles. Local module directories
+=AGENTIC-AI-LAB-UI-E005= and named the four missing roles. Local module directories
are ignored by Git until explicitly promoted to the contribution's top-level
=modules/= tree.
@@ -177,36 +177,36 @@ reported 1.08 seconds inside ASP and 2.71 seconds for the process. The complete
undefined-symbol warning or process crash.
During the rejected experiment, reversing the qualification load path exposed
-stale copied =poo-flow= artifacts inside the ASP build directory and failed
+stale copied =agentic-ai-lab= artifacts inside the ASP build directory and failed
before timing; that result was not counted as a performance sample.
* Limits
The verification uses isolated output plus linked dependency libraries, not a
-clean release installation or the whole POO Flow suite. NASA source and local
+clean release installation or the whole Agentic AI Lab suite. NASA source and local
structured gates are implemented; authenticated institutional approval,
external parser execution, runtime execution, and automatic content identity
for an in-place dirty linked dependency remain separate authority boundaries.
The measurements do not establish a fully clean release installation or the
-whole POO Flow suite. The prior 13--19 second floor and the later minute-scale
+whole Agentic AI Lab suite. The prior 13--19 second floor and the later minute-scale
warm rebuilds do not apply to the corrected separated path; no upstream code
was modified and no replacement scheduler or cache was introduced.
* Unified module-source and atomic phase receipts (2026-09-14)
Lambda has no =modules/init.ss=. Its =user-interface/init.ss= contains module
-identities and flags. POO Flow constructs contribution and User Interface source objects through
-=make-poo-flow-contribution-module-*= and
-=make-poo-flow-user-interface-module-*=. Core and contributor lookup use the
-same =poo-flow-module-selection-source-refs= function; an explicit private
+identities and flags. Agentic AI Lab constructs contribution and User Interface source objects through
+=make-agentic-ai-lab-contribution-module-*= and
+=make-agentic-ai-lab-user-interface-module-*=. Core and contributor lookup use the
+same =agentic-ai-lab-module-selection-source-refs= function; an explicit private
=@ modules-path= uses the loader's internal config-role projection, while
-=poo-flow-load-modules= remains fixed to public =interface.ss=. The core-owned official
+=agentic-ai-lab-load-modules= remains fixed to public =interface.ss=. The core-owned official
registry maps both =lambda-episteme= and its module names to the immutable
submodule revision; an absent checkout produces a registry materialization
source instead of performing network I/O during =init.ss= expansion.
The contributor-owned =t/modules/unit/source-collection-test.ss= proves that
-the default order is =(poo-flow-maintained lambda-episteme)=, that core and
+the default order is =(agentic-ai-lab-maintained lambda-episteme)=, that core and
Lambda selections resolve through their respective source objects, that source
metadata retains collection ownership, and that a missing module raises the
typed =missing-module-source= control-plane failure. Its immediate warm exact
@@ -230,7 +230,7 @@ implementation receipts, not NASA institutional certification.
* Atomic observability and import-closure qualification (2026-09-14)
-The POO Flow-owned =test-contribute-atomic= target now performs a reader-only
+The Agentic AI Lab-owned =test-contribute-atomic= target now performs a reader-only
POO authoring preflight before loading the exact =t//...= test.
For the certification file it scanned 17 files and 389 slot observations; for
the lifecycle file it scanned 17 files and 411 observations. Both reported zero
@@ -246,7 +246,7 @@ or type-predicate diagnostic, so the same class of failure no longer appears as
an opaque =invalid POO model= error.
The exact contribution load path now places the isolated contribution test
-library before POO Flow's production library. This prevents stale production
+library before Agentic AI Lab's production library. This prevents stale production
copies of contribution modules from shadowing the test closure. Static CLOS
indexes use Gerbil's =list->hash-table-eq/string= constructors; the NASA rule
mode lookup returns the constructor's stored value directly instead of applying
@@ -278,7 +278,7 @@ failed its 60-second warm bound; its own selected test body receipt was 254ms.
The upstream downstream-framework scenario passed the relevant incremental
selection assertions but required 33.31 seconds as a complete gxtest process.
Its fixture's 1ms policy/collection measurement therefore does not establish
-startup wall-clock performance. POO Flow does not add a cache, scheduler or
+startup wall-clock performance. Agentic AI Lab does not add a cache, scheduler or
replacement build API to hide this remaining failure.
The atomic build path now passes its exact test file to the same ASP PackageSpec
@@ -297,7 +297,7 @@ and asking =std/make= to reconstruct it again was redundant. Certification now
projects exactly one target in 0ms. Its isolated cold build completed in 21.17
seconds; the immediate zero-compile warm build completed in 13.38 seconds. The
atomic image contains only selected test artifacts and consumes the production
-POO Flow library after it, preventing test-built production copies from
+Agentic AI Lab library after it, preventing test-built production copies from
shadowing the production image.
A same-target, same-image warm A/B invoked native Gerbil =defbuild-script=
@@ -349,7 +349,7 @@ qualification identified as the remaining dominant error.
The Lambda entry then exposed a second, independent over-import:
=user-interface/init.ss= imported the complete UI syntax facade, including
doctor, presentation, sandbox, durable-memory and loop policy owners, although
-its only operation was =poo-flow!= declaration lowering. The canonical macro
+its only operation was =agentic-ai-lab!= declaration lowering. The canonical macro
now lives in =src/user-interface/init-declaration-syntax.ss= and the complete
facade reexports it. Lambda and root init files import that owner directly.
Lambda init compilation changed from exceeding a 25-second bound to 7.50
@@ -388,10 +388,10 @@ compiled-library dependency loading from recursive source-context expansion.
** Retired root-scoped test BuildSpec
Gerbil 0.18.2 =defbuild-script= derives =srcdir= from the directory containing
-the script. Because =build-contribute-tests.ss= is POO Flow-owned at the
+the script. Because =build-contribute-tests.ss= is Agentic AI Lab-owned at the
repository root, its old invocation added the complete checkout to the source
load path. The selected test was one BuildSpec target, but its imports could be
-resolved from POO Flow and Lambda sources instead of the already-built
+resolved from Agentic AI Lab and Lambda sources instead of the already-built
=.gerbil/lib= image. This violated the intended contribution-test boundary and
made the one-target currentness check reconstruct a large source context.
@@ -402,7 +402,7 @@ probe took about 5.02 seconds. The difference is the source-root boundary, not
the =use-composition= macro body and not a fixed native initialization charge.
That intermediate repair was later removed with =build-contribute-tests.ss=.
-The current POO Flow entry builds contribution production owners once and
+The current Agentic AI Lab entry builds contribution production owners once and
passes module trees or exact files directly to native =gxtest=. The retained
=build-root.ss= fixtures express shared test imports; they no longer define or
seed a separate BuildSpec.
@@ -425,7 +425,7 @@ The production projection is now closed over nine native public entrypoints:
the contribution identity, governance, five discovered module =interface.ss=
files, and the User Interface =init.ss=/=config.ss= pair. An immediate warm run
reported nine receipts, no compile row, 318ms inside the ASP Build API and
-1.54 seconds wall time. =poo-flow-load-modules= accepts only the source
+1.54 seconds wall time. =agentic-ai-lab-load-modules= accepts only the source
collection and always projects =modules//interface.ss=. Role-level
projection remains an internal function excluded from the public loader facade;
normal selection, loading and build declarations cannot substitute =config.ss=
@@ -440,8 +440,8 @@ atomic tests now exit normally from an attached terminal.
* Repository-wide public interface closure (2026-09-14)
-The root =build.ss= now invokes =poo-flow-load-modules= over
-=poo-flow-maintained-module-source= and uses the resulting source-ref values as
+The root =build.ss= now invokes =agentic-ai-lab-load-modules= over
+=agentic-ai-lab-maintained-module-source= and uses the resulting source-ref values as
the complete ASP PackageSpec public-root set. It does not list the 17 maintained
module names a second time and does not add a compiler, scheduler, cache or
=all-gerbil-modules= scan. The first build compiled all 17
@@ -483,7 +483,7 @@ cases normally.
The root PackageSpec no longer passes =all-gerbil-modules= as its =modules=
slot. Maintained module roots are derived once through
-=poo-flow-load-modules= and each value is the conventional
+=agentic-ai-lab-load-modules= and each value is the conventional
=src/modules//interface.ss=. The resulting 27-root BuildSpec is
handed directly to ASP Build API and upstream =std/make=; user-owned
=user-interface/custom= sources and contribution test scripts do not enter the
@@ -516,10 +516,10 @@ final architecture. Treating every discovered module interface as a native
build target makes package planning proportional to the available catalog and
does not support a Doom-like contribution ecosystem.
-At this stage the parent POO Flow PackageSpec became a clean-image bootstrap
+At this stage the parent Agentic AI Lab PackageSpec became a clean-image bootstrap
containing seven
stable framework targets and zero catalog targets. It imports only ASP's Build
-API: importing a =:poo-flow= loader before the package exists failed in the
+API: importing a =:agentic-ai-lab= loader before the package exists failed in the
hermetic Bazel image and exposed the stale local =.ssi= dependency. Module
selection begins after this bootstrap through the ordinary POO module load
path. Adding 100 or 1,000 available-but-unselected module source refs therefore
@@ -586,10 +586,10 @@ unrelated facade with a much wider closure.
* Module owner admission and Observability correction (2026-09-15)
Every maintained module role is now inspected by the reader-native owner-import
-policy before =poo-flow-load-modules= admits its =interface.ss=. Importing an
+policy before =agentic-ai-lab-load-modules= admits its =interface.ss=. Importing an
aggregate framework surface from an implementation role produces a native
-=poo-flow.module-owner-import-observation.v1= receipt and fails with
-=POO-FLOW-MODULE-E008=. The receipt retains the source scope, aggregate owner,
+=agentic-ai-lab.module-owner-import-observation.v1= receipt and fails with
+=AGENTIC-AI-LAB-MODULE-E008=. The receipt retains the source scope, aggregate owner,
=module-admission= phase, =aggregate-owner-import= status, stable code, and
=import-precise-owner= recommendation without expanding or evaluating source.
diff --git a/docs/migrations/legacy-user-interface-history.org b/docs/migrations/legacy-user-interface-history.org
index a25a629..08ba977 100644
--- a/docs/migrations/legacy-user-interface-history.org
+++ b/docs/migrations/legacy-user-interface-history.org
@@ -9,16 +9,16 @@ The direct children have fixed responsibilities:
| Path | Responsibility |
|------+----------------|
-| =init.ss= | Module enablement only; one =poo-flow!= declaration selects Modules and flags. |
+| =init.ss= | Module enablement only; one =agentic-ai-lab!= declaration selects Modules and flags. |
| =config.ss= | Final User Composition declarations using direct =use-composition= forms. |
| =modules/= | User-owned modules that are private or not ready for contribution. |
| =profiles/= | Reusable, inheritable POO Profile objects. |
| =scenarios/= | Reusable scenario cases and review exercises referenced by compositions. |
-No other top-level Scheme file is accepted by the POO Flow contributor builder.
+No other top-level Scheme file is accepted by the Agentic AI Lab contributor builder.
This keeps a repository readable from its directory shape and prevents a
scenario from silently becoming a second module registry or Profile library.
-There is no =package.ss=: POO Flow owns construction and module loading.
+There is no =package.ss=: Agentic AI Lab owns construction and module loading.
=modules//= is the only admitted local-module shape. Each module
contains =types.ss=, =objects.ss=, =funs.ss=, =config.ss= and =interface.ss=;
the directory itself contains no loader or registry. Local module directories
@@ -26,7 +26,7 @@ are ignored by Git so unfinished work is not pushed accidentally. A ready
module moves to the repository's top-level =modules/= tree and passes the
contribution gate.
-=init.ss= enables Funflow and SDLC only. POO Flow's internal User Interface
+=init.ss= enables Funflow and SDLC only. Agentic AI Lab's internal User Interface
loader discovers every Scheme module under =profiles/= and =scenarios/= once,
imports those bindings into =config.ss=, and then expands its direct
=use-composition= declarations. The user writes no discovery list, aggregate
@@ -59,11 +59,11 @@ reserved for the Git Change, Check and Decision boundary contracts.
=scenarios/sdlc-cases.ss= demonstrates NASA plus a local standard, native POO
derivation, explicit facts, and pure review preparation. The files import the
-installed POO Flow interface and this contribution only; they do not import the
+installed Agentic AI Lab interface and this contribution only; they do not import the
parent repository's downstream configuration.
Run =just build-scheme= followed by =just test-scheme=. Both commands delegate
-to the POO Flow root environment. The contribution's =gerbil.pkg= declares
+to the Agentic AI Lab root environment. The contribution's =gerbil.pkg= declares
native package identity only; it owns no build script or PackageSpec.
* Team release policy
@@ -99,7 +99,7 @@ provider integration declarations without claiming those external effects.
scenario suite passed 39 checks across twelve scenarios and malformed inputs;
the existing SDLC and init configuration suites passed 17 and 7 checks.
These 63 checks exercise explicit source facts, not live authority or runtime
-integration. Tests used isolated child output and POO Flow library dependencies.
+integration. Tests used isolated child output and Agentic AI Lab library dependencies.
* NASA release review case
=scenarios/nasa-release.ss= assembles all 130 applicability records and class-specific
diff --git a/docs/plans/engineering-case-source-inventory.org b/docs/plans/engineering-case-source-inventory.org
new file mode 100644
index 0000000..01a1d3b
--- /dev/null
+++ b/docs/plans/engineering-case-source-inventory.org
@@ -0,0 +1,77 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Engineering case sources and transfer judgments
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-engineering-case-source-inventory
+:STATUS: draft
+:DATE: 2026-09-24
+:END:
+
+* Scope
+
+This is a reviewed reading inventory, not an imported dataset or a qualified
+Recipe catalog. The links below were inspected on 2026-09-24. No upstream
+source bytes, executable revision or license grant are pinned by this document.
+No article or Issue is reproduced here. Asset reuse requires a separate version,
+attribution/license and execution audit under
+[[file:../rfcs/0004-sdlc-design-and-causal-trajectories.org][RFC 0004]].
+
+* Source claims and our proposed transfer
+
+| Source | Source scope | Aitia design question / proposed transfer | Status and limit |
+|--------+--------------+------------------------------------------+------------------|
+| [[https://aws.amazon.com/builders-library/making-retries-safe-with-idempotent-APIs/][Malcolm Featonby: Making retries safe with idempotent APIs]]; sections on late requests and changed intent | design account of request identity, retention and parameter mismatch | which component owns identity, trusted retry context and durable effect uniqueness? | inspiration for ADR 0008; no qualification of AWS services or our provider |
+| [[https://github.com/etcd-io/etcd/issues/19179][etcd #19179]]; original report by serathius, 2025-01-13 | reports a resumable-watch violation involving deletion, compaction, crash and resumed watch; original author had no local reproduction | does our assessment distinguish an absent event from incomplete history, and an author's interpretation from a checked cause? | external report only; linked CI artifacts, later resolution and affected-version range not qualified here |
+| [[https://github.blog/news-insights/company-news/oct21-post-incident-analysis/][GitHub: October 21 post-incident analysis]]; Jason Warner, incident in 2018 | describes failover into a database topology incompatible with application expectations | do composition obligations cover recovery topology and latency assumptions across owners? | historical account for applicability review, not a replayed Aitia case or claim about present GitHub architecture |
+
+The last two rows are candidate questions, not findings about Aitia. They are
+not additional implementation workstreams in this slice. Search results,
+Issue closure or repeated citations cannot promote their status.
+
+* Retirement design challenges (2026-09-24)
+
+| Primary source | Observation status | Design transfer and executable check | Remaining limit |
+|----------------+--------------------+--------------------------------------+-----------------|
+| [[https://github.com/temporalio/sdk-python#asyncio-cancellation][Temporal Python SDK cancellation documentation]] | documented behavior, not a reported bug: cancellation can be caught or shielded; cancelling a child-start task is not equivalent to cancelling an already started child | =WorkLifecycle= keeps request separate from completion; =RetirementReviewCancellation= must produce a counterexample | no Temporal integration or reproduction claimed |
+| [[https://github.com/etcd-io/etcd/issues/19179][etcd #19179]] | original report links CI evidence; local reproduction and affected versions are not qualified here | discovered history/inventory gaps reopen completeness; =RetirementReviewUnknown= must fail | the Boolean inventory abstraction is not a model or reproduction of etcd compaction |
+| [[https://github.com/langchain-ai/langgraph/issues/8039][LangGraph #8039]] | author reports checkpoint/write ordering and repeated side effects on recovery, with a reproducer; not independently reproduced here | challenge the assumption that a checkpoint proves all effects are recorded; retain operation identity and replay-epoch obligations | no persistence implementation added; crash/replay model and upstream qualification remain pending |
+
+The stale-review mutant adds a separate Aitia design challenge: work observed
+after review must be rechecked at the final cut. It is not presented as the
+root cause of any of these upstream reports. Source reports motivate tests;
+their conclusions are not admitted as local evidence. See the
+[[file:../receipts/2026-09-24-retirement-formal-review.org][formal review receipt]] for what was actually executed.
+
+* First bounded transfer judgment
+
+The current job-executor shares the first source's response-loss uncertainty
+and logical retry identity question. It differs in workload and provider: one
+fixed job, constant payload, local SQLite and a loopback HTTP endpoint. It has
+no multi-tenant identity, retention policy or independently committed remote
+side effect. Those differences prevent a claim that it implements the source's
+complete service contract.
+
+The source motivates questions; source inspection answers what the fixture
+currently models. [[file:../adrs/0008-stable-operation-key-after-lost-ack.org][ADR 0008]] assigns pending checks to their actual owners,
+including existing Cedar authorization and Runtime handoff mechanisms. The
+judgment is provisional: provider changes, conflicting observations or source
+corrections reopen it. A future executable assessment must bind the consulted
+source revision and affected ADR/claim identities before testing invalidation.
+
+* Acceptance evidence still required
+
+- [ ] Bind the selected source snapshot/claims and accountable applicability
+ review without conflating external reports with local observations.
+- [ ] Record which previously omitted assumption or design option changed,
+ compared with the same design review without the historical source.
+- [ ] Qualify the pending ADR 0008 contracts with actual positive/negative
+ receipts; preserve Cedar, Runtime and provider ownership.
+- [ ] Introduce a corrected source claim and show a new review cut and reopened
+ obligations while preserving the earlier judgment and its evidence.
+
+This inventory adds neither a new public object family nor an inference engine.
+Successful designs and rejected alternatives should be included when selecting
+further cases, so the corpus does not reduce to incident-driven prescriptions.
diff --git a/docs/plans/software-sdlc-integration-inventory.org b/docs/plans/software-sdlc-integration-inventory.org
index fedddda..89b09e4 100644
--- a/docs/plans/software-sdlc-integration-inventory.org
+++ b/docs/plans/software-sdlc-integration-inventory.org
@@ -2,10 +2,15 @@
# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
#+title: Software/SDLC-to-Aitia Integration Inventory
-#+status: draft
-#+date: 2026-09-17
#+startup: overview
+:PROPERTIES:
+:ID: lambda-aitia-software-sdlc-integration-inventory
+:STATUS: draft
+:DATE: 2026-09-17
+:UPDATED: 2026-09-24
+:END:
+
* Purpose
Lambda Aitia owns causal assurance for software engineering and the SDLC,
@@ -17,12 +22,12 @@ ontology surfaces.
The software Architecture Decision Record module is also Aitia-owned and is
published as =ADR=. No lowercase compatibility module is retained.
-The Aitia-side source migration and parity inventory are complete. Publication
-cutover remains evidence-partial until Lambda Episteme publishes the deletion
-of ADR, GitOps and SDLC and POO Flow pins that clean child commit. This
-inventory governs the intended post-migration boundary and prevents either
-repository from reintroducing compatibility aliases or duplicate semantic
-owners.
+The Aitia-side source migration and parity inventory are complete. The
+Episteme deletion is published, and the Agentic AI Lab main gitlink already pins a
+clean Episteme cut. The Aitia PR head is newer than the Agentic AI Lab main gitlink
+and requires a separate pin update after acceptance. This inventory governs
+the post-migration boundary and prevents either repository from reintroducing
+compatibility aliases or duplicate semantic owners.
Classification:
@@ -34,24 +39,25 @@ Classification:
* Normative layering
-#+begin_example
-Lambda Aitia
- Software Engineering and SDLC modules
- NASA standards and GitOps Profiles
- claim and assumption support
- typed provenance/dependency/causal/assurance/authority relations
- change impact, evidence invalidation and obligation planning
- |
- | inert plans, decisions and receipts
- v
-POO Flow
- POO composition, functional execution, graph substrate,
- verifier/runtime adapters and effect handoff
-#+end_example
+#+begin_export mermaid
+flowchart TD
+ A["Lambda Aitia
Software Engineering, SDLC, NASA standards and GitOps"]
+ A --> S["Aitia assurance semantics
claims, assumptions and typed relations"]
+ S --> I["Impact, invalidation and obligation planning
inert plans and receipts"]
+ I -->|consumes public mechanisms| P["Agentic AI Lab
composition, graph, temporal / causal algorithms and Runtime"]
+ A --> Py["Aitia Python Runtime
tools and observations"]
+ Py -->|owned runtime boundaries| P
+ Py -->|candidate evidence, not authority| S
+#+end_export
Lambda Episteme composes beside Aitia when an application needs non-SDLC
vertical knowledge; it is not an upstream owner for Aitia's SDLC semantics.
-POO Flow execution does not redefine Aitia reasoning.
+Agentic AI Lab execution does not redefine Aitia reasoning.
+
+The complete SDLC organizes requirements, design, algorithm/implementation
+strategies, testing, delivery, operation and evolution. RFC 0004 specifies how
+behavior and design/assurance trajectories connect these activities. The
+eight-step assurance/execution protocol is one mechanism within this framework.
* Inventory
@@ -65,14 +71,37 @@ POO Flow execution does not redefine Aitia reasoning.
| =t/sdlc/=, NASA source snapshots, import/report tools and SDLC Profiles | Lambda Aitia | migrated with SDLC | qualification evidence and reproducible sources | production, tests, tools and Profiles share one owner |
| =modules/gitops/=, GitOps/GitHub Profiles and scenario adapter | Lambda Aitia | migrated | repository revision, check and delivery-decision facts | stable public namespace has no version suffix; revision is evidence metadata |
| =modules/decision-kind/= | Lambda Episteme | keep, reference | accountable software decision kinds and conflicts | Aitia links decisions but does not redefine their domain meaning |
-| =src/graph/= | POO Flow | reference | graph substrate and typed traversal | Aitia creates no second graph engine |
-| POO Flow verification contribution contracts | POO Flow | reference | verifier capability and receipt handoff | a plan never invokes a verifier directly |
-| =bindings/runtime-c/include/poo_flow/scheme_native_v1.h= pattern | POO Flow | reference | owned-byte AOT Scheme ABI convention | Aitia uses stable unversioned language namespaces; ABI revision is descriptor metadata |
-| =bindings/python= | Lambda Aitia | new | Aitia-owned CFFI consumer and wheel for the Scheme-native ABI | Python transports JSON and never duplicates Scheme decisions |
-| =packages/python-runtime= | POO Flow | keep, separate | generic runtime and lifecycle binding | never owns Aitia or SDLC semantics |
-| =packages/proof/lean/PooFlowProof/Enterprise/EvidenceFreshness.lean= | POO Flow proof package | reference | seed for general freshness/no-stale-authority laws | theorem ownership decision must close before any move |
-| SDLC/change lifecycle TLA+ model to be added | Aitia | new | invalidate, plan, reverify, decide and gate lifecycle | must be generic, with NASA supplied only as external facts |
-| Cedar adapter and Runtime Host | POO Flow | reference | current release/effect authority and final execution gate | no fallback or locally manufactured authority |
+| =src/graph/= | Agentic AI Lab | reference | graph substrate and typed traversal | Aitia creates no second graph engine |
+| =src/modules/temporal-causality/= | Agentic AI Lab | reference | event graphs, cuts, trajectory contracts and temporal classification | Aitia supplies software meaning; complete behavior/design trajectory integration remains pending |
+| Agentic AI Lab verification contribution contracts | Agentic AI Lab | reference | verifier capability and receipt handoff | a plan never invokes a verifier directly |
+| =bindings/runtime-c/include/agentic_ai_lab/scheme_native_v1.h= pattern | Agentic AI Lab | reference | owned-byte AOT Scheme ABI convention | Aitia uses stable unversioned language namespaces; ABI revision is descriptor metadata |
+| =bindings/python= | Lambda Aitia | maintained | production Runtime across Aitia's SDLC capabilities, CFFI, tool observations and AnyIO dependency | async execution and tool-to-Host admission remain pending; Scheme retains semantic ownership |
+| =packages/python-runtime= | Agentic AI Lab | keep, separate | generic runtime and lifecycle binding | never owns Aitia or SDLC semantics |
+| =packages/proof/lean/AgenticAILabProof/Enterprise/EvidenceFreshness.lean= | Agentic AI Lab proof package | reference | seed for general freshness/no-stale-authority laws | theorem ownership decision must close before any move |
+| =proof/quint/AssuranceLifecycle.qnt= | Aitia | bounded candidate | invalidate, plan, reverify, admit, decide, authorize and effect lifecycle | generic model; stable-environment progress is conditional, and Host enforcement remains open |
+| Cedar adapter and Runtime Host | Agentic AI Lab | reference | current release/effect authority and final execution gate | no fallback or locally manufactured authority |
+
+* Candidate reuse qualification
+
+Historical design sources have a separate
+[[file:engineering-case-source-inventory.org][source and applicability inventory]]. Inspiration and judgment do not require
+an executable asset, and do not qualify a Recipe or establish local evidence.
+ADR 0008 records the first source-inspected coverage and mechanism-owner audit.
+
+The following are candidates, not installed or qualified dependencies. Before
+selection, bind exact files and revision/digests, original attribution/license,
+dependencies, applicability assumptions, mandatory checks and replay receipt.
+
+| Candidate | Reuse target | Qualification required | Current status |
+|-----------+--------------+------------------------+----------------|
+| Specula tools and Case Studies | models, harnesses, traces, reproduction programs and applicable checker code | select an asset-complete record; audit attribution, version and replay conditions | unqualified; no archive-wide import or complete-app backend requirement |
+| MRR | future relation queries, derivation and lineage | a later ownership and snapshot-admission contract against its then-current capabilities | deferred; no current Python integration |
+
+The production code follows upstream reuse only after qualification. No new
+proof scorer, Agent kernel or Specula workflow state machine is authorized by
+this inventory. Use existing POO composition and Agentic AI Lab runtime mechanisms
+to organize the selected operations. See
+[[file:../rfcs/0004-sdlc-design-and-causal-trajectories.org][RFC 0004]] and the [[file:../../ROADMAP.org][current work queue]].
* Existing semantics to preserve
@@ -92,7 +121,7 @@ weaken:
* Target abstraction map
-| Source/POO Flow concept | Aitia abstraction |
+| Source/Agentic AI Lab concept | Aitia abstraction |
|---------------------------+--------------------|
| software requirement or standard clause | source-owned Artifact plus Claim/Assumption input |
| implementation artifact/revision | changed Artifact and structural dependency seed |
@@ -109,19 +138,19 @@ weaken:
The first fixture is purely software engineering:
-#+begin_example
-Requirement R@1 constrains Implementation I@1
-Verification V@1 checks I@1 against R@1
-Evidence E@1 discharges Obligation O@1 for ReleaseClaim C@1
-Decision D@1 permits deployment Effect X under Snapshot G@1
-
-Change R@1 -> R@2 or I@1 -> I@2
- => dependent assumptions and C@1 impacted
- => E@1 stale for the changed closure
- => O@2 derived for the exact impacted verification set
- => D@1 invalid
- => X blocked
-#+end_example
+#+begin_export mermaid
+flowchart TD
+ R["Requirement R@1
scoped"] -->|constrains| I["Implementation I@1
candidate"]
+ I --> V["Verification V@1
checks I@1 against R@1"]
+ V -->|bound admission| E["Evidence E@1
current"]
+ E --> O["Obligation O@1
discharged for ReleaseClaim C@1"]
+ O --> D["Decision D@1
current under Snapshot G@1"]
+ D --> X["Deployment Effect X
requires separate authorization / Runtime gate"]
+ C["R@2 or I@2
changed"] --> A["Dependent assumptions and C@1
impacted"]
+ A --> S["E@1
stale for changed closure"]
+ S --> N["O@2
pending for impacted verification set"]
+ S --> B["D@1 invalid
X blocked"]
+#+end_export
Required negative cases:
@@ -139,7 +168,7 @@ Required negative cases:
1. Freeze the software fixture and negative contracts in Aitia.
2. Implement relation-plane and status vocabulary without importing a concrete
standard, provider or vertical domain.
-3. Implement snapshot and invalidation semantics with the POO Flow Graph
+3. Implement snapshot and invalidation semantics with the Agentic AI Lab Graph
library and reuse its impact, trajectory and SCC algorithms.
4. Preserve the completed SDLC/GitOps ownership cutover with source-collection
and negative namespace tests.
@@ -156,10 +185,10 @@ Required negative cases:
- deterministic canonical-output comparison;
- negative-contract parity;
- standard/proof/model dependency audit;
-- POO Flow core bootstrap proving it does not import Lambda Aitia;
+- Agentic AI Lab core bootstrap proving it does not import Lambda Aitia;
- application integration test showing stale software evidence blocks release
and deployment effects;
- rollback plan retaining the original source owner until acceptance.
No item in this document authorizes moving SDLC, GitOps or Aitia Python
-semantics back into Lambda Episteme or POO Flow's generic Python runtime.
+semantics back into Lambda Episteme or Agentic AI Lab's generic Python runtime.
diff --git a/docs/receipts/2026-09-18-phase2-clean-candidate-replay.org b/docs/receipts/2026-09-18-phase2-clean-candidate-replay.org
index 67bcb08..e9ed6e5 100644
--- a/docs/receipts/2026-09-18-phase2-clean-candidate-replay.org
+++ b/docs/receipts/2026-09-18-phase2-clean-candidate-replay.org
@@ -19,13 +19,13 @@ toolchain contract and current evidence are recorded in
* Exact source cut
-- POO Flow: =f4575d4abed2cf6ed605a57f193ddd522eeb3488=
+- Agentic AI Lab: =f4575d4abed2cf6ed605a57f193ddd522eeb3488=
- Lambda Aitia: =46b6393185a8cde0251f5ee5820a0fc2531e6213=
- Host: Darwin arm64
- Build concurrency: =GERBIL_BUILD_CORES=12=
- Darwin environment: =env -u SDKROOT=
-The replay used detached worktrees. The POO Flow worktree contained only the
+The replay used detached worktrees. The Agentic AI Lab worktree contained only the
expected Lambda Aitia gitlink difference plus temporary build products and one
candidate build-spec addition making the already tracked
=src/user-interface/config-discovery-syntax.ss= an installed public entry.
@@ -43,7 +43,7 @@ and removed the deprecated =-ld_classic= option. After that correction:
- =just build= completed with no linker warning;
- no deployment-target downgrade or macOS-version compatibility path was used.
-This adapter is replay infrastructure, not yet a published POO Flow build
+This adapter is replay infrastructure, not yet a published Agentic AI Lab build
contract. The owning parent build must publish an equivalent Darwin arm64
toolchain boundary before the clean-clone gate can close.
@@ -51,7 +51,7 @@ toolchain boundary before the clean-clone gate can close.
The Phase 2 Assurance test was run with an isolated atomic-test =GERBIL_PATH=
and an explicit source/load closure containing only the two detached worktrees
-and the freshly built POO Flow library. It completed with all test cases and
+and the freshly built Agentic AI Lab library. It completed with all test cases and
checks passing, including:
- canonical snapshot stability under input permutation;
@@ -75,7 +75,7 @@ Build completed successfully (4 jobs).
The complete =just build-contribute lambda-aitia= replay is not green. It
first demonstrated that the tracked User Interface discovery module was absent
-from the published POO Flow build closure. After the isolated candidate entry
+from the published Agentic AI Lab build closure. After the isolated candidate entry
was added, the build advanced and then stopped at additional parent-owned
dependencies that are present only in the dirty parent workspace:
@@ -86,12 +86,12 @@ dependencies that are present only in the dirty parent workspace:
- the generic =modules/standards= library is not committed at the replayed
parent revision.
-These are POO Flow mechanism/library owners. They must be reviewed, tested and
-published in POO Flow; copying them into Aitia would violate the established
+These are Agentic AI Lab mechanism/library owners. They must be reviewed, tested and
+published in Agentic AI Lab; copying them into Aitia would violate the established
dependency direction. Healthcare qualification material is unrelated to this
Software/SDLC replay and is not part of the required Aitia closure.
-POO Flow is Aitia's public mechanism library. This blocker does not justify
+Agentic AI Lab is Aitia's public mechanism library. This blocker does not justify
minimizing Aitia's dependency or removing required mechanisms; it requires POO
Flow to publish its complete reviewed public Library closure for the pinned
Aitia revision.
@@ -100,5 +100,5 @@ Aitia revision.
The bounded Phase 2 Scheme kernel and modular Lean proof are admitted for this
exact source cut. RFC 0002 remains =active= because the repository-wide clean
-checkout gate additionally requires a published POO Flow dependency revision
+checkout gate additionally requires a published Agentic AI Lab dependency revision
whose installed library closes every direct Aitia production import.
diff --git a/docs/receipts/2026-09-18-phase2-clean-replay.org b/docs/receipts/2026-09-18-phase2-clean-replay.org
index ff341d5..5167e2e 100644
--- a/docs/receipts/2026-09-18-phase2-clean-replay.org
+++ b/docs/receipts/2026-09-18-phase2-clean-replay.org
@@ -14,18 +14,18 @@
* Exact source cut
-- POO Flow: =43bf47869c48b0944984b64aefec80846129c949=
+- Agentic AI Lab: =43bf47869c48b0944984b64aefec80846129c949=
- Lambda Aitia: =d5d3c2cba1251069cca98d387034c833515505aa=
- Host: Darwin arm64
- Build concurrency: =GERBIL_BUILD_CORES=12=
The replay started from an empty project-local =.gerbil= tree in an isolated
-clone. It did not depend on the dirty shared POO Flow checkout or on a
+clone. It did not depend on the dirty shared Agentic AI Lab checkout or on a
user-global Gerbil installation.
* Toolchain boundary
-POO Flow now detects whether the active =gsc= is the Homebrew Gambit runtime.
+Agentic AI Lab now detects whether the active =gsc= is the Homebrew Gambit runtime.
Only for that runtime, and only for each =just= child process, the build:
- removes =SDKROOT=;
@@ -42,9 +42,9 @@ is changed. If the active Gerbil runtime is not the Homebrew Cellar runtime,
including a Nix-provided Gerbil/Gambit toolchain, the boundary evaluates to
plain =env= and preserves the toolchain selected by Nix.
-* Published POO Flow library closure
+* Published Agentic AI Lab library closure
-The replayed POO Flow revision publishes the mechanism owners consumed by
+The replayed Agentic AI Lab revision publishes the mechanism owners consumed by
Aitia rather than copying them into Aitia:
- Graph types, algorithms and structural-impact trajectories;
diff --git a/docs/receipts/2026-09-23-phase3-planning-replay.org b/docs/receipts/2026-09-23-phase3-planning-replay.org
new file mode 100644
index 0000000..e355af3
--- /dev/null
+++ b/docs/receipts/2026-09-23-phase3-planning-replay.org
@@ -0,0 +1,53 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Phase 3 pure planning replay receipt
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-phase3-planning-replay-2026-09-23
+:STATUS: admitted
+:DATE: 2026-09-23
+:RFC: lambda-aitia-rfc-0001
+:END:
+
+* Exact source cut
+
+- Agentic AI Lab mechanism library: =8aa14eafe87ed63d32295f3eac5e5a4eda6658f5=
+- Lambda Aitia: =6b1476b38888080c03e514bc36a6d5789056ac64=
+- Aitia PR CI: =35847725375= (license, Lean, Scheme/integration/Python passed)
+- Local host: Darwin arm64, Gerbil v0.19, =GERBIL_BUILD_CORES=12=,
+ child-process =env -u SDKROOT=.
+
+The source cut is an open-PR candidate, not a merged release. The local replay
+used isolated checkouts rather than the dirty shared parent worktree. Its
+=just check= completed, including the native C ABI harness and Python wheel.
+
+* Source and negative-contract map
+
+The public planner in =modules/assurance/funs.ss= consumes a typed snapshot,
+changed identities and a matching POO-native verification policy. It uses the
+Agentic AI Lab Graph dependency order and loop analysis; the plan and verifier-choice
+receipts cannot claim verifier execution, release authority or Runtime work.
+
+=t/assurance/unit/assurance-kernel-test.ss= directly checks:
+
+- deterministic plan and choice digests under inventory permutation;
+- affected prerequisite order, unplanned dependencies, blocked propagation,
+ SCC cycle witnesses and retention of an independent acyclic branch;
+- missing capability, unresolved input and conflicted snapshot blockers;
+- same-identity revision/content changes rejecting old obligation bindings;
+- independent composition obligations and explicit replacement declaration;
+- chosen and rejected verifier candidates, including unavailable capability.
+
+The verification policy has no suppression or authorization operation. It can
+declare capabilities but cannot convert a current failed or blocked request into
+an authority decision; =release-authorized?= and =runtime-executed?= are fixed
+false in the plan model. Authority remains a separate relation and Host gate.
+
+* Admission decision
+
+Phase 3's pure planning and explanation contract is closed for this exact
+source cut. This receipt does not attest that any candidate adapter is installed
+or trusted, that a verifier ran, that evidence was admitted, or that an effect
+was authorized or executed. Those remain Phase 4 and Phase 6 exit gates.
diff --git a/docs/receipts/2026-09-23-phase4-admission-ledger.org b/docs/receipts/2026-09-23-phase4-admission-ledger.org
new file mode 100644
index 0000000..4686d0e
--- /dev/null
+++ b/docs/receipts/2026-09-23-phase4-admission-ledger.org
@@ -0,0 +1,52 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Phase 4 Host admission ledger candidate
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-phase4-admission-ledger-2026-09-23
+:STATUS: evidence-partial
+:DATE: 2026-09-23
+:RFC: lambda-aitia-rfc-0001
+:END:
+
+* Source cut
+
+- Aitia base: =9ea6385de909bcde784132532e1e3db7a99a53e4=.
+- Agentic AI Lab verification owner: =90d1c79f474f89a4f975b282611de55662301b74=.
+- Isolated Darwin arm64 checkouts; the Aitia load path selected that exact
+ Agentic AI Lab source before the older installed library. Child tests retained
+ the runner's =-:max-heap=512M= limit; no global environment was modified.
+
+* Evidence and negative contracts
+
+=assurance-host-admit= reads the Host-configured current snapshot and clock,
+checks candidate evidence and an exactly bound successful outcome, executes
+the configured Agentic AI Lab verifier, then issues a private-indexed POO admission.
+It does not alter =AssuranceEvidence.admission-state= or the source snapshot.
+Currentness rechecks the full semantic snapshot, Host epoch, verifier seal,
+candidate evidence, outcome binding and lease. The Host also reconstructs each
+snapshot through =assurance-snapshot= before use, rejecting a POO presentation
+whose displayed digest, context, state or conflict fields disagree with the
+canonical inventory.
+
+=t/assurance/unit/evidence-admission-test.ss= checks that copied or fabricated
+admissions fail; changed source, same displayed digest with changed semantic
+content, invalid snapshot source, expiry, clock rollback, explicit revocation
+and verifier refusal cannot provide current admission. A source cut returning
+to an older value does not revive its earlier admission or Host seal.
+
+Local =just build-scheme= and =just check-semantic= passed, including the
+assurance, ADR, SDLC, GitOps and composition test groups. Agentic AI Lab's focused
+verification test passed with its weak-key issued-receipt registry and a GC
+case proving a live indexed admission retains its receipt.
+
+* Limits
+
+This is Host-local issuance and validity, not proof that a deployment installed
+a trusted verifier, clock or snapshot source. It is not yet consumed by an
+assurance Decision, Cedar projection or Runtime effect gate. The older
+snapshot-node =admission-state= remains metadata; no release authority follows
+from a Host admission object alone. CI for this candidate cut is separate
+from the local replay and must be reported independently.
diff --git a/docs/receipts/2026-09-23-phase4-host-capability.org b/docs/receipts/2026-09-23-phase4-host-capability.org
new file mode 100644
index 0000000..5cbe6ce
--- /dev/null
+++ b/docs/receipts/2026-09-23-phase4-host-capability.org
@@ -0,0 +1,45 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Phase 4 configured verification Host candidate
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-phase4-host-capability-2026-09-23
+:STATUS: evidence-partial
+:DATE: 2026-09-23
+:RFC: lambda-aitia-rfc-0001
+:END:
+
+* Source cut and boundary
+
+- Aitia base: =742291f3c0bbef5df8a7e6c3fcaba93c0c8afe8c=.
+- Agentic AI Lab verification mechanism: =8aa14eafe87ed63d32295f3eac5e5a4eda6658f5=.
+- The application-configured =assurance-verification-host= keeps the exact
+ Agentic AI Lab adapter, clock and lease in private weak-key storage. Its POO
+ presentation cannot be copied or edited into a capability.
+- Verification refuses an ineligible outcome or evidence not bound to the
+ current snapshot/outcome before invoking the configured operation. The
+ operation must still return true to receive a seal.
+- Support checks read the Host clock internally; expiry, receipt revocation
+ and clock rollback fail closed. The low-level under-adapter function is
+ explicitly conditional, not a Host admission decision.
+
+* Replay
+
+The isolated local checkout used the current Agentic AI Lab source before the older
+installed library in =GERBIL_LOADPATH=. The first attempted test with only the
+older installed Agentic AI Lab failed an existing fake-adapter rejection assertion;
+that run is not accepted as evidence for this source cut. With the pinned
+source in the load path, the atomic evidence-admission and assurance-kernel
+tests passed, as did =just build-scheme=, the complete assurance test group,
+and =just check-semantic= across assurance, ADR, SDLC, GitOps and modules.
+The test runner capped each child at =-:max-heap=512M=.
+
+* Limits
+
+The Host constructor is a configuration capability, not proof that a trusted
+deployment installed it or that its clock is secure. =AssuranceEvidence='s
+caller-supplied =admission-state= is still metadata; there is no Host-owned
+promotion transition, Cedar projection, or Runtime effect gate in this slice.
+No seal or green test outcome is release authority.
diff --git a/docs/receipts/2026-09-23-phase5-lifecycle-model.org b/docs/receipts/2026-09-23-phase5-lifecycle-model.org
new file mode 100644
index 0000000..aed302c
--- /dev/null
+++ b/docs/receipts/2026-09-23-phase5-lifecycle-model.org
@@ -0,0 +1,60 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Phase 5 bounded lifecycle model replay receipt
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-phase5-lifecycle-model-2026-09-23
+:STATUS: evidence-partial
+:DATE: 2026-09-23
+:RFC: lambda-aitia-rfc-0001
+:END:
+
+This is a historical TLA+ receipt. Its =proof/tla/= paths refer to the source
+at commit =49cbc5d5fd4ec983c98dca8070a0b99bc3fc68b4=; the maintained model
+and checks are now in [[file:../../proof/quint/README.org][Quint]].
+
+* Exact model cut
+
+- Aitia base commit: =608525c84e853ed5f5b156693c8f72fe58cfcf97=;
+ the progress extension and this updated
+ receipt are the candidate change on top of that commit.
+- =AssuranceLifecycle.tla= SHA-256:
+ =a2a12f2fe4723fe76a248a1eaeebdfd8130590e150bda82116f854f179dde9ab=.
+- Safe TLC configuration SHA-256:
+ =984c59bc517d3ae0a4477e7cb578f4a5a553bd966aed577d202e513679df21e9=.
+- Progress and no-fairness configuration SHA-256:
+ =4940784d1a627de1642cef9f4df7714780345a66aa70b1421923e360558db21f= and
+ =67ed10ce6eb65ef8eb2998f8f3bfce0cb0984fea1747fd9cd867b15fb31de439=.
+- TLC2 2.19, single worker, =JAVA_TOOL_OPTIONS=-Xmx512m=, Darwin arm64.
+- Replay commands and the expected invariant for every configuration are in
+ =proof/tla/README.org=. Each run used a separate =-metadir= under
+ =/private/tmp=; no global Gerbil/Nix environment was changed.
+
+* Result
+
+| Configuration | Expected | Observed |
+|---------------+----------+----------|
+| Safe | exit 0 | 7,468 generated; 2,202 distinct; queue empty |
+| Stable progress with weak fairness | exit 0 | 38 generated; 18 distinct; temporal property passed |
+| Stable progress without fairness | =EventuallyEffect= counterexample | exit 12; stuttering after authorization |
+| Reachable | =NoEffectStarted= counterexample | exit 12; valid effect trace |
+| Unsafe report-only effect | =NoUnsafeEffectStart= counterexample | exit 12 |
+| Late admission after change | =AdmissionIsCurrent= counterexample | exit 12 |
+| Grant before re-verification | =GrantRequiresCurrentDecision= counterexample | exit 12 |
+| Effect after revocation | =NoUnsafeEffectStart= counterexample | exit 12 |
+
+These are local bounded-model results, not CI results. A deliberate mutant's
+exit 12 is a successful *negative contract* only when TLC names the expected
+invariant. The safe run's queue was empty, so the finite state space for the
+declared bounds was exhausted.
+
+* Admission boundary
+
+This receipt supports a candidate dynamic lifecycle contract. It does not
+promote a reported result to admitted evidence, establish a trusted Host
+adapter/clock, cryptographically bind a Runtime grant, or close Phase 5.
+Unconditional progress, counterfactual transition authority, source-bound CI
+replay, and the executable Host handoff remain open. The existing Agentic AI Lab Cedar
+=governance_admitted= field is not an Aitia evidence-admission decision.
diff --git a/docs/receipts/2026-09-24-formal-source-qualification.org b/docs/receipts/2026-09-24-formal-source-qualification.org
new file mode 100644
index 0000000..55e126d
--- /dev/null
+++ b/docs/receipts/2026-09-24-formal-source-qualification.org
@@ -0,0 +1,124 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Formal source qualification — local joint gate
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-formal-source-qualification-2026-09-24
+:STATUS: locally-qualified-source-boundary
+:DATE: 2026-09-24
+:RFC_ID: lambda-aitia-rfc-0004
+:END:
+
+This is a historical TLA+ receipt. Its =proof/tla/= paths refer to the source
+at commit =49cbc5d5fd4ec983c98dca8070a0b99bc3fc68b4=; the maintained model
+and checks are now in [[file:../../proof/quint/README.org][Quint]].
+
+* What closes here
+
+This follows the [[file:2026-09-24-retirement-ingress-review.org][ingress review]]. The previously rejected multiline and modular
+TLA+ forms now parse in the parser owner without changing the Aitia models.
+All five maintained models pass syntax success, artifact validity and exact
+source-byte roundtrip. TLC and Lean remain independent gates.
+
+The native repair lives in the existing linked gerbil-parser checkout, not a
+new Aitia parser. Its grammar now treats newlines as lossless whitespace rather
+than declaration terminators. Named instances, qualified names and flat leading
+junction expressions have explicit CST nodes. The scope does not include
+nested indentation-sensitive junction lists, full TLA+ syntax, configuration
+parsing or rebuilt Rust/Rowan AOT products. TLC still performs its own parsing
+and semantic checks for the exact models/configurations.
+
+An initial optional-newline production introduced a shift ambiguity at the
+next definition and exceeded a 60-second probe. It was replaced, not accepted
+as qualified. The stale diagnostic process was interrupted. Gerbil probes
+kept a 512 MiB heap; one cold generation diagnostic used a 180-second wall limit.
+The final native regression processes completed within the 60-second gate.
+
+* Maintained POO declaration and source binding
+
+[[file:../../user-interface/scenarios/job-retirement-contract.ss][The retirement contract]] declares identity =job-executor/retirement=,
+revision =r1=, guarantee =retirement-safety/g1= and four explicit assumptions:
+atomic epoch fencing, known inventory, no new grant after closure, and the
+single-client bound. It grants no allowed runtime effects.
+
+[[file:../../t/formal/retirement-binding-test.ss][Binding qualification]] uses existing =sdlc-design-implementation-link=,
+=sdlc-design-implementation-review=, Assurance snapshots and source digests.
+The TLA source group contains four model/helper files and fourteen configs;
+the Lean group contains both retirement proof modules. Every member's content
+digest participates in its source-group identity. The links bind both groups
+to the same contract identity, revision, contract digest and snapshot cut.
+
+Checks confirm that either source-group mutation changes the snapshot context
+and invalidates both old links, even if nominal revisions are unchanged. A
+changed design assumption also rejects both links as =contract-changed=.
+An initial test incorrectly expected =source-changed=; the existing owner
+correctly diagnoses =snapshot-changed= first. The test was corrected without
+weakening that owner or changing invalidation semantics.
+
+These are declared source bindings. They do not prove that the formal formulas
+are faithful projections of the natural-language contract, that a Scheme
+implementation refines the models, or that the Host admitted verifier evidence.
+Review values continue to report =implementation-conforms?=,
+=evidence-admitted?= and =release-authorized?= as false. A source-group manifest
+is not a complete verifier/toolchain attestation. The explicit joint gate runs
+every verifier; source mapping alone is not evidence-coverage admission.
+
+* Executed gates and replay
+
+| Gate | Result |
+|------+--------|
+| parser-owned native suite | 12 test cases, including new CST/roundtrip and incomplete-form rejection tests; =MODULE-OK= / =HARNESS-OK= |
+| Aitia native syntax suite | 2 cases; five actual model files plus a lossless rejected-source control |
+| Aitia POO binding suite | 4 cases; current binding and source/premise invalidation |
+| TLC | 22 configurations match positive/expected-counterexample outcomes |
+| Lean | both libraries build; all 20 audited laws have no axioms and no =sorryAx= |
+| repository hygiene | license contract and its 7 tests pass; both changed repositories pass whitespace checks |
+
+=just check-formal= runs the two native suites, TLC and Lean in order. It is an
+explicit qualification lane while the parser change remains uncommitted;
+default CI is not silently changed to require an unpublished dependency.
+With the current package layout, from the Aitia root:
+
+#+begin_src sh
+GERBIL_PATH="$PWD/../../.gerbil" \
+GERBIL_LOADPATH="$PWD/../../.gerbil/pkg/github.com/tao3k/gerbil-parser:$PWD:$PWD/../..:$PWD/../../.gerbil/lib" \
+TLA_TOOLS_JAR=/path/to/verified/tla2tools.jar just check-formal
+#+end_src
+
+No new root variable, global tool installation or source flattening is needed.
+The existing atomic test recipe bounds its observer at 1 GiB and its native
+test child at 512 MiB; direct parser probes used 512 MiB for the observer too.
+TLC uses its checksum-pinned jar, one worker and 512 MiB Java heap. Its local
+RMI listener required sandbox execution permission. No remote CI run is claimed.
+
+* Source cut
+
+Aitia remains at =de65fa2033ce62569147ee5411c05c50051206dd= with local changes.
+The linked parser branch advanced independently during the work from
+=f42393559de4aa78620a836777bbfd91ee6751ca= to
+=f0df5a11d8014bdfe8be30be5a1f3ad9203ce0bf=. Its unrelated artifact-filename
+change is preserved. Our parser edits remain confined to the two files below.
+The qualified parser source resolves through the parent's existing package
+link to =/private/tmp/gerbil-parser-rowan-scanned-tokens=.
+
+| Source | SHA-256 |
+|--------+---------|
+| parser =languages/tla-plus/v1/grammar.ss= | =a419e55d490afbdd7c8e31cf36fa17b2e598aac0b470dd6d8e2a5a12089299e6= |
+| parser =languages/tla-plus/v1/parser-test.ss= | =44fcd73fd6e9f736ec8b736db0f92fc83f635a0ef04f1bfca16a0874ee5a56da= |
+| Aitia =user-interface/scenarios/job-retirement-contract.ss= | =e333a91bf0964fb2762ddcf54e7bd5fa7c5e8071e721a45b50479617c27b5965= |
+| Aitia =t/formal/tla-syntax-test.ss= | =2f95897254ac97067eba5f728fd01be2b3b7f49ac1f2be2aef8fe1c25a8ff982= |
+| Aitia =t/formal/retirement-binding-test.ss= | =93438d52f8e71242615b6ef8feeb5f600d83da7a0344de6ad33916f1c3679f79= |
+
+* Remaining exit gates
+
+- Publish the parser-owned repair, update the actual dependency authority and
+ independently replay without relying on this dirty linked checkout. Neither
+ commits, pushes nor dependency-pin changes were performed in this slice.
+- Establish semantic correspondence or generation of the formal projections
+ from the owning POO contract; source identity tests cannot substitute for it.
+- Refine atomic fencing to actual authority/Runtime behavior, then evaluate
+ repeated clients and fairness under explicit assumptions.
+- Keep persistence and actual effect execution deferred. This is local closure
+ of the source/verification plumbing, not production or SDLC-wide closure.
diff --git a/docs/receipts/2026-09-24-retirement-formal-review.org b/docs/receipts/2026-09-24-retirement-formal-review.org
new file mode 100644
index 0000000..8b811da
--- /dev/null
+++ b/docs/receipts/2026-09-24-retirement-formal-review.org
@@ -0,0 +1,162 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Retirement design — modular formal review
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-retirement-formal-review-2026-09-24
+:STATUS: evidence-partial
+:DATE: 2026-09-24
+:RFC_ID: lambda-aitia-rfc-0004
+:END:
+
+This is a historical TLA+ receipt. Its =proof/tla/= paths refer to the source
+at commit =49cbc5d5fd4ec983c98dca8070a0b99bc3fc68b4=; the maintained model
+and checks are now in [[file:../../proof/quint/README.org][Quint]].
+
+* Decision and evidence boundary
+
+New persistence integration is deferred. The prior
+[[file:2026-09-24-retirement-impact.org][Scheme Impact checks]] exercise structural/temporal analysis, not a proof of
+retirement safety. Existing Lean laws covered fixed-snapshot impact and design
+substitution; the existing TLA+ model covered assurance admission/authorization.
+Neither covered the new retirement review. This slice adds design experiments,
+not deployed deletion, a new public DSL, or a second generic Impact engine.
+
+[[file:../plans/engineering-case-source-inventory.org][The source inventory]] distinguishes Temporal's documented cancellation
+semantics, the etcd watch report and a LangGraph recovery report from our own
+proposed transfers. None was replayed locally in this slice. Known upstream
+reports are not new bug discoveries, and these models do not reproduce their
+implementations.
+
+* Executed checks
+
+Run from the Aitia root with the existing pinned =TLA_TOOLS_JAR=:
+
+#+begin_src sh
+just check-tla work
+just check-tla retirement
+just check-tla
+just check-proof
+just check-license-contract
+#+end_src
+
+| Lane / configuration | Generated / distinct states | Observed result |
+|----------------------+-----------------------------+-----------------|
+| =WorkLifecycle= | 14 / 8 | exit 0; queue empty |
+| =WorkCancellation= | 3 / 2 | exit 0; work remains after request |
+| =WorkCancellationReachable= | 2 / 2 | exit 12; =NeverCancelled= violated |
+| =WorkQuiescenceReachable= | 8 / 7 | exit 12; =NeverQuiescent= violated |
+| =RetirementReview= | 84 / 42 | exit 0; queue empty; deadlock checks enabled |
+| =RetirementReviewCancellation= | 24 / 15 | exit 12; =NoOutstandingWork= violated |
+| =RetirementReviewStale= | 46 / 27 | exit 12; =NoOutstandingWork= violated |
+| =RetirementReviewUnknown= | 49 / 28 | exit 12; =InventoryKnown= violated |
+| =RetirementReviewReachable= | 39 / 21 | exit 12; =NeverRetired= violated |
+
+All nine new configurations and the eight unchanged assurance configurations
+passed their expected-outcome contracts. This means 17 configurations within
+three unittest methods, not 17 successful safety theorems. The harness checks
+the exact counterexample property, exit code, nonempty exploration and trace.
+Negative checks stop at a counterexample and need not exhaust their queues.
+
+One local work-only run took 2.595 s; retirement-only took 3.321 s; the final
+all-module run took 11.390 s. These are single-run unittest wall times including
+JVM startup, not a repeated benchmark or a general speedup claim. Atomic
+selection avoids unrelated models; changing the shared work module still
+requires its retirement consumer check.
+
+Lean 4.31.0 built both assurance/SDLC libraries. Six new exported laws prove
+initial safety, one-step preservation, reachable-state safety and three unsafe
+state witnesses. All 16 audited laws reported no axioms; no =sorryAx= was used.
+The observation relation overapproximates all nonterminal observations, while
+the finalize action checks current work/inventory. This is an abstract-model
+proof, not an established refinement from TLA+ or Scheme.
+
+The invalid module selector =not-a-module= was also checked with the project's
+existing Python interpreter: argparse exited 2 rather than running zero tests.
+The same unittest suite remains discoverable through the existing CI command.
+No remote CI run or clean-checkout validation is claimed.
+
+* Unclosed native syntax gate
+
+The parent dependency resolves to gerbil-parser commit
+=562dcd428f00b05ca87407fd54b1e04dcf076ae9= at
+=/private/tmp/gerbil-parser-rowan-scanned-tokens=, with a clean source worktree
+at inspection. Importing its public =parse-tla-plus-v1= and runtime artifact
+checks under a 512 MiB Gerbil heap / 60-second timeout rejected both sources:
+
+| Source | First diagnostic |
+|--------+------------------|
+| =WorkLifecycle.tla= | =GERBIL-PARSER-TLA-PLUS-V1=, =lr-no-action=, state 209, byte 472: newline after the =RequestCancellation= definition header |
+| =RetirementReview.tla= | same code/kind, state 205, byte 541: newline within the =VARIABLES= declaration |
+
+The inspected grammar requires these expressions/declarations on one line;
+TLC's parser accepts the native multiline forms. These are first-failure
+locations, not an exhaustive parser capability audit: named =INSTANCE= and
+qualified operators also require qualification after the newline gap is fixed.
+No alternate parser, flattened-source workaround or false roundtrip receipt
+was introduced. Native parser acceptance/byte-roundtrip remains failed.
+
+The executable reproduction uses the parent =GERBIL_PATH= and its existing
+=GERBIL_LOADPATH= dependency source/library paths, then for each model:
+
+#+begin_src scheme
+(import (only-in :std/misc/ports read-all-as-string)
+ (only-in :gerbil-parser/languages/tla-plus/v1/parser parse-tla-plus-v1)
+ (only-in :gerbil-parser/src/runtime/artifact
+ parse-artifact-success? parse-artifact-valid?
+ parse-artifact-roundtrip parse-artifact-ref))
+(let* ((source (call-with-input-file "proof/tla/WorkLifecycle.tla" read-all-as-string))
+ (artifact (parse-tla-plus-v1 source)))
+ (displayln (parse-artifact-ref artifact 'diagnostics))
+ (exit (if (and (parse-artifact-success? artifact)
+ (parse-artifact-valid? artifact)
+ (equal? source (parse-artifact-roundtrip artifact))) 0 1)))
+#+end_src
+
+* Reproducibility and source cut
+
+Aitia HEAD is =de65fa2033ce62569147ee5411c05c50051206dd= with uncommitted
+changes; this is a shared-worktree receipt. TLC release v1.7.2 reports TLC2
+2.17 (2022-02-02, revision 3c7caa5); its SHA-256 is
+=fa18543e44ed5974a85bd2c60c0dc16620ae117680ea8e693d2691999ed90b22=.
+Each execution used one worker, =-Xmx512m=, a fresh temporary state directory
+and a 60-second process timeout. The sandbox first blocked Java's local RMI
+listener; the same bounded checks passed with local execution permission.
+
+| Source (relative to Aitia) | SHA-256 |
+|---------------------------+---------|
+| =proof/tla/WorkLifecycle.tla= | =079452f967fc2f1d21a1e962dd0d38a5e62fa6b36a4055d2c42358fb006fbb23= |
+| =proof/tla/RetirementReview.tla= | =4edbe49d59f663a007ad986108d1e374e3408c4593fb4c4c53a34c02232ed01a= |
+| =proof/lean/LambdaAitiaProof/Modules/Sdlc/Retirement.lean= | =86f899c87cfd51ed2daa23dbc0c4b3bb88914851b42afeed28dc51e067eb45d3= |
+| =bindings/python/tests/tla_contract.py= | =788e97254d0923104357654b59e6ad2902a9ec483eb72f35c75d8e18657c13a3= |
+| =proof/tla/WorkCancellation.cfg= | =503131d547fa46de7555b245156dc072ebb04c4a32f3fc6f4672ff600f751198= |
+| =proof/tla/WorkCancellationReachable.cfg= | =a79ba63517e17e4fd7ca1eb7d2964455f8c40e58a2b5a87aef6f29d565d8f5b1= |
+| =proof/tla/WorkLifecycle.cfg= | =1084116ad37aeb2bbb511ce9fd7bded6381c946f0ba39f927116ff722a8910bf= |
+| =proof/tla/WorkQuiescenceReachable.cfg= | =a4467507d11ce289101a29644dd84d45c57fb72c534d25d096b2276d46d31ed7= |
+| =proof/tla/RetirementReview.cfg= | =9a433fe46ec346fe6d180ca0483b415cdf0f6f4fc9650cb739c6ce4e72dfd2df= |
+| =proof/tla/RetirementReviewCancellation.cfg= | =641e05f7356e568494e2dc7fbc340635031706593a07971c612c6891ada31969= |
+| =proof/tla/RetirementReviewReachable.cfg= | =1ec1a31f4e3d25c0d7dba39abdc1f79300a4ef7a80e683565cdf8a2d96231093= |
+| =proof/tla/RetirementReviewStale.cfg= | =28e8245f7bb71691d7d0b274a06b6458d6a81f932520b74bc5d228f6d9e8442f= |
+| =proof/tla/RetirementReviewUnknown.cfg= | =e935c67af6280fb68fddb1819ed0364ddbb5cd21aae6fb4f428df48d9027d61a= |
+
+* Next gates, not claimed complete
+
+Follow-up: [[file:2026-09-24-retirement-ingress-review.org][the ingress review]] adds a bounded challenge to item 3 and extracts the
+existing grant predicate. The source hashes and 17-case results above remain
+the earlier cut; the follow-up records its changed runner/model hashes and
+22-case run. Items 1, 2 and live authority correspondence remain open.
+
+1. Qualify the native parser for modular/multiline TLA+ without weakening the
+ source-byte identity or introducing a downstream parsing authority.
+2. Bind admitted Scheme Contract identity/revision and projection digests to
+ the TLA+ and Lean views, with an executable correspondence check.
+3. Challenge the terminal assumption by composing retirement with ingress and
+ revocation: a late request after finalization must not be hidden by a
+ frozen state. Reuse the current authority owners; do not add a policy engine.
+4. State fairness assumptions before proving eventual drain/retirement.
+ Unknown inventory, replay, multiple consumers and repeated late arrivals
+ remain outside this finite model's complete guarantees.
+5. Keep persistence and real effect execution deferred. Neither abstract proof
+ nor the synthetic Scheme case constitutes production readiness.
diff --git a/docs/receipts/2026-09-24-retirement-impact.org b/docs/receipts/2026-09-24-retirement-impact.org
new file mode 100644
index 0000000..ed6adf0
--- /dev/null
+++ b/docs/receipts/2026-09-24-retirement-impact.org
@@ -0,0 +1,102 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Job-executor retirement Impact — bounded analysis receipt
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-retirement-impact-2026-09-24
+:STATUS: evidence-partial
+:DATE: 2026-09-24
+:RFC_ID: lambda-aitia-rfc-0004
+:END:
+
+* Subject and source boundary
+
+The selected capability is automatic retry in a synthetic job-executor case.
+The candidate successor is reviewed recovery. These are fixture identities,
+not deployed features or evidence that a migration occurred. The case reuses
+Agentic AI Lab Graph and its public Temporal Causality interface; no new traversal,
+time classifier, policy evaluator or Runtime is implemented.
+
+The [[file:../../user-interface/scenarios/job-executor-retirement.ss][maintained scenario]] contains pre-removal and candidate post-removal graphs,
+plus an explicitly identified synthetic event history. The [[file:../../t/sdlc/unit/job-retirement-impact-test.ss][Scheme qualification]]
+checks inert analysis receipts. It does not read the Python fixture's SQLite
+ledger; historical results and current activity here are modeled facts.
+
+The shared worktrees were dirty. The parent checkout reported
+=a9a2b331d42fda409ea142fb67137f395721397e= and Aitia reported
+=de65fa2033ce62569147ee5411c05c50051206dd=; the new files below were uncommitted.
+This is not an isolated clean-build or release receipt.
+
+| Source | SHA-256 |
+|--------+---------|
+| Aitia =user-interface/scenarios/job-executor-retirement.ss= | =1977be963e74ef6aabd48ff7b1649f423b1cb2a9b047d273bbfbf98e42c43044= |
+| Aitia =t/sdlc/unit/job-retirement-impact-test.ss= | =8bc2fab67c2249a1433038f7c957e94189a8d65f1b47067ffc849eefc94887a6= |
+| Agentic AI Lab =src/modules/temporal-causality/funs.ss= | =4ffc3517b48bba51abafb28f91c3e0a2e0994a1904911509b222e2780c0df00b= |
+| Agentic AI Lab =src/modules/temporal-causality/objects.ss= | =19ada4187ad1f380c7dc95f58be97c24681f01b9d8d0ac21afaa582583893454= |
+| Agentic AI Lab =src/modules/temporal-causality/types.ss= | =78499931958750bbfb458c14ba92beb3d44a4d1e6f0298f8c87adf1a85fd6a53= |
+
+These are inspected source hashes, not an attestation of all transitive binary
+dependencies. Tests use the existing compiled dependency library and source
+load paths below. No claim of fresh whole-package compilation is made.
+
+* Seven retirement checks
+
+1. The old graph retains the historical result, active job, queued job and its
+ verification dependency; an unrelated export is excluded. The verification
+ witness is =automatic-retry → queued-job → verify-queued-retry=.
+2. Selecting the removed identity in the candidate graph raises an error
+ instead of reporting no impact; the before graph remains available.
+3. An incomplete external-consumer inventory yields =partial-impact=.
+4. The cut at logical position 4 separates past completion/start, explicit
+ current activity, declared future retry, counterfactual retirement and an
+ out-of-horizon retry. No activity is inferred merely from an old start.
+5. Creating the later cut retains the earlier historical cut and its original
+ observed result/payload.
+6. A missing causal parent remains =unknown-consumer-origin= in the unknown
+ frontier and yields partial temporal classification.
+7. The retirement proposal cannot be selected as an observed trigger in the
+ current cut. Neither structural nor temporal analysis grants execution.
+
+* Local replay
+
+From the Aitia root, against the existing parent dependency installation:
+
+#+begin_src sh
+GERBIL_LOADPATH="$PWD:$PWD/../..:$PWD/../../.gerbil/lib" \
+ just test-scheme-atomic sdlc unit/job-retirement-impact-test.ss
+GERBIL_LOADPATH="$PWD:$PWD/../..:$PWD/../../.gerbil/lib" \
+ just test-scheme-atomic sdlc unit/design-contract-test.ss
+env -u SDKROOT GERBIL_PATH="$PWD/.gerbil" \
+ GERBIL_LOADPATH="$PWD:$PWD/../..:$PWD/../../.gerbil/lib" \
+ timeout --foreground --signal=TERM --kill-after=3s 60s \
+ gxi -:max-heap=512M ./run-test.ss ../../t/temporal-causality-core-test.ss
+#+end_src
+
+All three focused modules returned =MODULE-OK= and =HARNESS-OK= with exit 0.
+They contain seven retirement, eight design-replacement and eight core cases.
+Gerbil reported =2591dcd on Gambit dcd677c=. The existing Testing Interface
+selects a 512 MiB isolated test process; the existing Justfile's observer
+process has a separate 1 GiB bound. The direct core observer used 512 MiB.
+
+The initial run with only the child default load path failed to resolve
+=asp-gerbil-scheme/testing-api=. Supplying the parent dependency library via
+=GERBIL_LOADPATH= fixed module discovery; no new root variable, global package
+installation or user-environment mutation was introduced.
+
+* Remaining closure
+
+- [ ] Derive current activity and historical results from actual persisted
+ task/provider observations, rather than this synthetic inventory.
+- [ ] Bind a source-level change and both graph revisions to admitted SDLC
+ facts, then derive reviewed migration/drain obligations with accountable owners.
+- [ ] Exercise actual cancellation/migration through existing authorization and
+ Runtime boundaries, including races and failure/recovery receipts.
+- [ ] Demonstrate replay/interpretation of an old persisted result and prevent
+ a successor from inheriting incompatible historical support.
+- [ ] Qualify the Scheme-owned Org Contract / Rowan presentation separately;
+ these tests do not exercise Org parsing or the old CLI.
+
+The lifecycle retirement gate in RFC 0004 remains open. This receipt qualifies
+one bounded analysis scenario, not safe production deletion or completed SDLC.
diff --git a/docs/receipts/2026-09-24-retirement-ingress-review.org b/docs/receipts/2026-09-24-retirement-ingress-review.org
new file mode 100644
index 0000000..9b00403
--- /dev/null
+++ b/docs/receipts/2026-09-24-retirement-ingress-review.org
@@ -0,0 +1,147 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Retirement ingress — terminal assumptions challenged
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-retirement-ingress-review-2026-09-24
+:STATUS: evidence-partial
+:DATE: 2026-09-24
+:RFC_ID: lambda-aitia-rfc-0004
+:END:
+
+This is a historical TLA+ receipt. Its =proof/tla/= paths refer to the source
+at commit =49cbc5d5fd4ec983c98dca8070a0b99bc3fc68b4=; the maintained model
+and checks are now in [[file:../../proof/quint/README.org][Quint]].
+
+* Design finding
+
+The [[file:2026-09-24-retirement-formal-review.org][isolated review model]] prevents observations after its terminal state.
+That does not prove that external callers stop sending requests. The new
+[[file:../../proof/tla/RetirementIngress.tla][ingress composition]] permits a request before or after retirement, including
+a client retaining a cached grant. Merely removing a capability from a graph,
+or marking review complete, does not fence these callers.
+
+The modeled correction is ordered: close grant issuance and advance the
+authority epoch, drain known work, then finalize. At effect start, recheck the
+grant epoch. =EffectAdmission.CurrentGrant= is extracted without changing the
+existing =AssuranceLifecycle.StartEffect= predicate; both consumers use that
+same operator. This is reuse of a formal authorization contract, not a new
+policy evaluator or a claim that Cedar/Runtime already implements the mapping.
+
+* Executed model checks
+
+#+begin_src sh
+just check-tla ingress
+just check-tla
+just check-proof
+#+end_src
+
+The same pinned TLC jar and 512 MiB / one-worker / 60-second-per-run limits as
+the earlier receipt were used. Local RMI required sandbox execution permission.
+
+| Configuration | Generated / distinct | Expected and observed outcome |
+|---------------+----------------------+-------------------------------|
+| =RetirementIngress= | 741 / 248 | exit 0, queue empty; no post-retirement start; retired work drained, inventory known, epoch fenced |
+| =RetirementIngressUnfenced= | 413 / 150 | exit 12, =NoPostRetirementStart= violated when finalization omits the fence |
+| =RetirementIngressCachedGrant= | 524 / 179 | exit 12, same invariant violated when effect start skips grant validation |
+| =RetirementIngressRejected= | 499 / 178 | exit 12, =NeverRejectAfterRetirement= violated: a later request really reaches rejection |
+| =RetirementIngressStarted= | 38 / 23 | exit 12, =NeverStarted= violated: the model also allows an ordinary pre-retirement start |
+
+The last two are non-vacuity controls, not defects. The safe model includes
+explicit terminal self-loops and keeps deadlock checking enabled. Negative
+configurations require an actual trace and the named invariant violation, not
+an arbitrary nonzero process result.
+
+All 22 configurations across four unittest methods matched their contracts.
+The eight existing assurance checks retained exactly their preceding generated
+and distinct state counts after extraction of =CurrentGrant=. This is a
+regression observation, not a formal equivalence proof of the extraction.
+The ingress-only run took 3.407 s and the complete run 14.813 s; these are
+single-run wall times including JVM startup, not general performance claims.
+
+Four additional Lean laws prove initial safety, incompatibility of a current
+cached epoch with safe retirement, preservation across abstract boundary steps,
+and reachable-state safety. They reuse =Retirement.stepPreservesSafety=.
+Requests/rejections can stutter after retirement; a current-grant start is not
+excluded by a hard-coded retired guard but by the proved fence invariant.
+All 20 exported audited laws reported no axioms and no =sorryAx=.
+
+* Explicit abstraction limits
+
+- One pending request and one attempt are modeled, with epochs 0 and 1 and a
+ cached epoch 0. Revision, admission, decision and time are fixed to isolate
+ revocation. New grant issuance, grant expiry and repeated retries are not
+ explored by this composition; the existing lifecycle regression is separate.
+- Closing issuance and advancing the epoch is one atomic action. Actual
+ distributed ordering, concurrent authorities and restart behavior remain
+ obligations, not facts inferred from TLC.
+- =known= is an assumption about inventory, not proof of actual completeness.
+ Post-retirement discovery of previously unknown work is not covered.
+- No fairness or eventual retirement is claimed. Lean's abstract relation is
+ not yet a proved refinement of the TLA+ actions or a Scheme implementation.
+- Persistence, runtime effects, package publication and remote CI were not
+ performed. The worktree remains uncommitted.
+
+* Native parser: four independent capability gaps
+
+At parser commit =562dcd428f00b05ca87407fd54b1e04dcf076ae9=, the public native
+=parse-tla-plus-v1= API was probed with this wrapper:
+
+#+begin_example
+---- MODULE Probe ----
+
+====
+#+end_example
+
+| Body | Parse success | First native diagnostic |
+|------+---------------+-------------------------|
+| =Value == TRUE= | true | none; valid artifact and exact byte roundtrip |
+| =Work == INSTANCE WorkLifecycle= | false | =lr-no-action=, state 137, byte 40, =WorkLifecycle= |
+| =Value == Work!Quiescent= | false | =lr-no-action=, state 137, byte 36, =!= |
+| =VARIABLES active,= then newline and = queued= | false | =lr-no-action=, state 205, byte 40, newline |
+| =Value= definition header, then newline and =TRUE= | false | =lr-no-action=, state 209, byte 31, newline |
+
+These are syntax probes, not standalone resolved modules or TLC checks.
+Grammar inspection agrees: only unnamed instance declarations exist, qualified
+operator selection has no production, and newlines terminate declarations.
+This expands the previous first-failure diagnosis; it does not repair the
+parser. No parser-owner source was modified and no downstream fallback added.
+
+Notably the four rejected probes still reported a valid artifact and lossless
+roundtrip. Those properties describe a well-formed diagnostic/lossless token
+artifact; they do NOT mean successful syntax admission. Qualification must
+continue requiring =success AND valid AND exact roundtrip=.
+
+The probe used a bounded =gxi -:max-heap=512M= process with 60-second timeout
+and parent source/dependency paths in =GERBIL_LOADPATH=. An initial attempt
+omitting the parent source path failed at an unbound observability import;
+the corrected path resolved that import without changing dependencies.
+
+* Source cut and next obligations
+
+This continues the uncommitted Aitia source cut at
+=de65fa2033ce62569147ee5411c05c50051206dd=.
+
+| Source | SHA-256 |
+|--------+---------|
+| =proof/tla/EffectAdmission.tla= | =94ab242a5b2610dff134511dd9e4431e9e831d863938bfa30dadea7718a2deb5= |
+| =proof/tla/AssuranceLifecycle.tla= | =8b63b1b334cf31d490630c594aec7de0c30b0a5d4dcc4728d4f9d9c5fbc5bcfc= |
+| =proof/tla/RetirementIngress.tla= | =7227aa8deea008de87e3204c659254d72e2bb153889f5baf2d2993b979067af5= |
+| =proof/tla/RetirementIngress.cfg= | =df8d25edb57d96fc1756167e07b93f95eac717ab6741cbc5a8b0e5149a2c217a= |
+| =proof/tla/RetirementIngressCachedGrant.cfg= | =9c9330666e2bed4cddb2fad63020b9c8432ad573722ca8d18a751e7da253acd0= |
+| =proof/tla/RetirementIngressRejected.cfg= | =7c5725cf1ab1269da358a2366bba7609da0f704787df710dc8cff0a7299d1a51= |
+| =proof/tla/RetirementIngressStarted.cfg= | =b2645bd555d48a306e6a232ce0ecd2a534d3a5ae27b6f8a1d36f15855dcc5b8e= |
+| =proof/tla/RetirementIngressUnfenced.cfg= | =ec3c2181c8714a0408ce4da1430bdb79cc23d30623f6963e99d84673ea5064b0= |
+| =proof/lean/LambdaAitiaProof/Modules/Sdlc/RetirementIngress.lean= | =cc1b7609613461a61ef6825edd39ae055860d99c1691895b437af099c3e27dd0= |
+| =bindings/python/tests/tla_contract.py= | =2dfb943c0dabfe3e97ed4225926f3ce88e60e4f3ce6ddfba5e749ddbd3d1a548= |
+
+1. Repair modular/multiline syntax in the parser owner and require exact
+ source-byte roundtrip. Do not flatten source to disguise missing grammar.
+2. Bind the formal projections to admitted Scheme Contract identity/revision
+ and prove or test the claimed correspondence; hashes alone do not do that.
+3. Challenge atomic fencing/new issuance and repeated/concurrent requests,
+ then state fairness premises for progress. Keep using the existing authority
+ owner rather than adding another authorization implementation.
+4. Keep persistence deferred while these design/verification gates are open.
diff --git a/docs/rfcs/0001-causal-assurance-core.org b/docs/rfcs/0001-causal-assurance-core.org
index 3b49a47..c51155f 100644
--- a/docs/rfcs/0001-causal-assurance-core.org
+++ b/docs/rfcs/0001-causal-assurance-core.org
@@ -8,23 +8,31 @@
:ID: lambda-aitia-rfc-0001
:STATUS: draft
:DATE: 2026-09-17
+:UPDATED: 2026-09-24
:END:
* Decision summary
-Lambda Aitia owns a domain-neutral, POO-native model of why an engineering
-claim is justified, what defeats or invalidates that justification, which
-verification obligations follow, and which decisions/effects must remain
-blocked. It does not own domain knowledge, a second graph engine, verifier
-implementations, runtime execution or effect authority.
+Lambda Aitia organizes its software-engineering capabilities around the
+complete SDLC, including requirements, design, algorithms and implementation
+strategies, verification/testing, delivery, operation, maintenance and
+retirement. Its POO-native assurance kernel models why an engineering claim is
+justified, what defeats or invalidates that justification, which obligations
+follow, and which decisions/effects must remain blocked. Software semantics
+belong to Aitia's modules; generic graph, temporal/causal and runtime mechanisms
+remain Agentic AI Lab-owned, and existing verifiers retain their checking semantics.
The core abstraction is an executable causal assurance case, not a collection
of verification result flags:
-#+begin_example
-claims + assumptions + typed relations + obligations + evidence
-+ invalidation + decisions + effect guards
-#+end_example
+claims, assumptions, typed relations, obligations and evidence, together with
+invalidation, decisions and effect guards.
+
+[[file:0004-sdlc-design-and-causal-trajectories.org][RFC 0004]] refines this architecture with design alternatives, conditional
+guarantees, behavior and design-evolution trajectories, reusable Recipes and
+the deferred MRR direction. Software design is an early leverage point within
+the full lifecycle. The eight-stage assurance/execution flow is a protocol
+used throughout that lifecycle, not a complete SDLC phase list.
* Problem
@@ -49,32 +57,34 @@ through named, checked functions that emit receipts.
|-------+------+--------------|
| Lambda Episteme | vertical knowledge, Profiles, Cases and non-SDLC domain sources | Software/SDLC causal assurance or runtime authority |
| Lambda Aitia | Software/SDLC, ADR and standards modules; claims, assumptions, relation semantics, obligations, evidence admission, invalidation and planning | non-software vertical truth, graph runtime, verifier semantics or effect execution |
-| POO Flow | POO composition, functional flow, graph substrate, adapter/runtime handoff | concrete contribution semantics or silent assurance promotion |
-| POO Flow Python runtime | generic runtime and lifecycle transport | Aitia bindings, Aitia Scheme semantics or a second SDLC implementation |
-| Aitia Python SDLC Runtime | production SDLC API, Aitia-owned CFFI transport, ABI negotiation and typed receipt projection | reimplementing Scheme decisions or POO Flow's generic Runtime mechanisms |
+| Agentic AI Lab | POO composition, functional flow, graph substrate, adapter/runtime handoff | concrete contribution semantics or silent assurance promotion |
+| Agentic AI Lab Python runtime | generic runtime and lifecycle transport | Aitia bindings, Aitia Scheme semantics or a second SDLC implementation |
+| Aitia Python Runtime | production APIs across Aitia's SDLC capabilities, CFFI transport, tool execution integration and typed observations/receipts | reimplementing Scheme decisions or Agentic AI Lab's generic Runtime mechanisms |
| Lean | general proof terms and assurance laws | current runtime state or action authority |
-| TLA+/TLC | bounded temporal lifecycle behavior and counterexamples | theorem proving or production execution |
+| Quint/TLC | bounded temporal lifecycle behavior and counterexamples | theorem proving or production execution |
| Cedar | authorization evaluation over admitted input | evidence freshness, proof construction or effect completion |
| Runtime Host | final typed boundary for authorized execution | manufacturing missing evidence or guessing transport/runtime state |
| Application | explicit selection, composition and policy | redefining source-owned semantics |
-Dependency rule: POO Flow core must remain usable without Lambda Aitia.
-Lambda Aitia consumes POO Flow as its public mechanism library and may use the
+Dependency rule: Agentic AI Lab core must remain usable without Lambda Aitia.
+Lambda Aitia consumes Agentic AI Lab as its public mechanism library and may use the
complete reviewed public surface needed by Software/SDLC. The constraint is
one-way semantic ownership and public API stability, not a minimal dependency.
Integration belongs to an application or an isolated contribution adapter;
-POO Flow core never imports Lambda Aitia, and the parent Git submodule causes no
+Agentic AI Lab core never imports Lambda Aitia, and the parent Git submodule causes no
implicit activation.
Lambda Aitia owns its Python project under =bindings/python=. Its Scheme
semantic surface is compiled AOT and exposed through a dedicated C ABI using
-the owned result/release convention established by POO Flow's Scheme-native
+the owned result/release convention established by Agentic AI Lab's Scheme-native
ABI. Public Scheme and Python namespaces remain unversioned; ABI revision is
explicit descriptor metadata rather than part of those names. The production
Python package validates and materializes lifecycle requests and receipts;
-Scheme remains the decision owner. POO Flow's =packages/python-runtime=
+Scheme remains the decision owner. Agentic AI Lab's =packages/python-runtime=
remains the separate generic execution/lifecycle mechanism consumed by the
-Aitia SDLC runtime rather than becoming a second SDLC semantic API.
+Aitia Python Runtime rather than becoming a second SDLC semantic API. AnyIO
+provides the runtime-wide concurrency foundation; thread-affine native sessions
+and Host-issued authority must retain their owner at asynchronous boundaries.
* Semantic objects
@@ -106,7 +116,23 @@ commitment state and declared causal parents.
A question that must be discharged for a claim or decision at an exact
snapshot. The obligation states the required evidence kind and capability;
-it does not select or invoke a tool by itself.
+it does not select or invoke a tool by itself. A candidate obligation is
+explicitly bound to the snapshot identity, revision and canonical context
+digest before selection. That context digest excludes only the obligations'
+own binding fields to avoid a self-referential hash; the final snapshot digest
+includes the complete bound obligations. Rebinding an old obligation is not
+replacement-obligation derivation and is rejected.
+The first derivation step emits an inert replacement-requirements receipt
+from an old snapshot, a target snapshot and a change set. It names affected
+old obligations and their structural witnesses, and blocks automatic carryover
+when the source binding, target frontier, claim or policy is not current.
+It does not assign a new obligation identity or claim a replacement exists.
+An explicit second step may bind a caller-authored fresh obligation already
+declared in a target draft with the revised claim and =supports= edge. It
+replays the derivation, rejects non-canonical or unresolved snapshots, and
+returns a final snapshot plus an inert declaration receipt. A changed claim
+blocks automatic carryover but not this explicit declaration; a policy change
+still blocks it. Neither step admits evidence or authorizes an effect.
** Evidence
@@ -147,6 +173,13 @@ that an assurance obligation is discharged, or that an effect is authorized.
=unknown=, and deprecated/superseded records to =stale=. Only a separately
admitted assurance closure and authority receipt can cross the effect boundary.
+Requirements, assumptions, alternatives and conditional guarantees form the
+design context for these choices. A finding can reopen that context before
+implementation changes. Algorithm optimization is evaluated against the chosen
+contract; changing its assumptions or guarantees reopens the design decision.
+The existing design-contract review checks declarations, not arbitrary logical
+implication. RFC 0004 specifies the corresponding qualification work.
+
* Relation planes
** Provenance plane
@@ -157,7 +190,9 @@ itself manufacture a derivation or causal claim.
** Structural dependency plane
-Representative relations: =depends-on=, =implements=, =tests= and =refines=.
+Representative relations: =depends-on=, =composes=, =implements=, =tests= and
+=refines=. =composes= points from a composite claim to a component claim;
+its reverse impact projection uses the shared Agentic AI Lab Graph.
This plane supports reverse impact and obligation selection. Its output is
explicitly structural and has no release or runtime authority.
@@ -168,6 +203,13 @@ Representative relations: =precedes=, =causal-parent=, =enables= and
counterfactual. Missing parents and temporal contradictions create an unknown
frontier. Earlier-than never automatically promotes to caused-by.
+Agentic AI Lab's Temporal Causality owns generic event graphs, causal cuts, trajectory
+assessment and witness paths. Aitia connects scoped system behavior to the
+evolution of design decisions and their assurance using checked projections.
+Late observations create new assessment cuts; observed failures, model traces
+and counterfactual branches retain their modality and environment. Full Aitia
+trajectory integration is a pending RFC 0004 gate, beyond structural impact.
+
** Assurance plane
Representative relations: =supports=, =discharges=, =defeats= and
@@ -211,15 +253,15 @@ An assurance snapshot binds:
Change processing is pure:
-#+begin_example
-admit change
- -> compute structural witnesses
- -> select affected claims and assumptions
- -> invalidate dependent support
- -> derive obligations
- -> invalidate decisions
- -> emit effect guards
-#+end_example
+#+begin_export mermaid
+flowchart TD
+ C["Change
admitted"] --> W["Structural witnesses
computed"]
+ W --> A["Claims and assumptions
affected set selected"]
+ A --> S["Dependent support
invalidated"]
+ S --> O["New obligations
pending"]
+ S --> D["Dependent decisions
invalidated"]
+ D --> E["Effect guards
blocked"]
+#+end_export
An invalidation receipt reports affected and unresolved identities. Its slots
for temporal assessment, assurance closure, release authorization and runtime
@@ -228,21 +270,101 @@ receipt. Presentation values cannot mutate the admitted snapshot.
* Functional verification planning
-The planner consumes values and returns a value:
-
-#+begin_example
-Plan : Change -> Snapshot -> Policy -> PlanningResult
-#+end_example
+The planner consumes =Change=, =Snapshot= and =Policy= values and returns a
+=PlanningResult= value.
PlanningResult contains ordered obligations, capability requirements,
dependency constraints, rejected alternatives and blockers. Tool invocation
is outside this function. An adapter later consumes one obligation and returns
a typed execution outcome; evidence admission is another separate function.
-
-The first verifier kinds are Lean proof, TLA+/TLC model check, runtime replay,
+The first reported-outcome contract records exact input identity, revision and
+digest bindings and emits an inert structural eligibility receipt. A reported
+success, even when structurally eligible, is not a trusted execution
+attestation. Host-owned adapter identity and effectful admission are required
+before an =AssuranceEvidence= may become authoritative. Its caller-supplied
+=admission-state= is metadata, not proof of that transition. Changing that
+slot after verification would alter the snapshot context and invalidate the
+outcome's original binding. A configured Host therefore issues a separate
+admission object over candidate evidence without editing the snapshot. Its
+private issuance record binds the verifier seal, obligation, evidence, outcome,
+full semantic snapshot, validity interval and source-invalidation epoch.
+Currentness is checked against the Host's configured snapshot source and clock;
+the Host reconstructs the source snapshot to reject stale displayed digests,
+and source changes invalidate earlier seals, including if the old cut reappears.
+This is a Host-local admission candidate, not a decision or effect grant.
+=assurance-host-admitted-support?= consumes that exact current admission with
+one current =supports=/=discharges= assurance relation to its bound obligation.
+It requires the relation to be present in the same Host snapshot and rejects
+copied admissions, speculative modalities, expiration and source invalidation.
+This is one edge witness; it does not close all claim requirements or produce
+an =allow= Decision. Full closure, Cedar policy and Runtime effect gating remain
+separate steps.
+=assurance-host-required-support= now evaluates the claim-declared obligation
+inventory against the Host's current cut. Its typed POO receipt reports one
+blocker per required obligation, rejects missing obligation-to-claim and
+evidence-to-obligation links, and leaves empty/duplicate requirements,
+assumptions, defeaters, unresolved frontiers and challenges visibly blocked.
+Even =complete?= means only that the declared support inventory is witnessed;
+=release-authorized?= remains false. Validity intervals, policy evaluation and
+the actual Decision authority boundary are still separate work.
+The Host may now issue a weak-key-indexed Decision preflight for an exact
+*undecided* Decision node already present in that cut. It checks the
+=depends-on= edge to the supported claim, policy/snapshot/subject bindings and
+current required support; currentness rechecks the Host source epoch and the
+admissions. Copies, revocation, source changes and rollback cannot reuse it.
+This preflight carries =release-authorized? #f= and is not a Cedar result,
+an =allow= Decision or an effect token. The Agentic AI Lab Cedar Provider constructs
+inert inputs; the independent Runtime Host still owns policy evaluation and
+effect admission.
+=assurance-host-cedar-request= now rechecks that exact preflight and projects
+its Decision authority, claim subject, policy identity/revision and full
+semantic snapshot digest into Agentic AI Lab's POO-native Cedar request family.
+The application supplies the action, intent and Agentic AI Lab runtime handoff.
+The resulting request and its context are editable input, not a second Host
+seal; copying or changing them cannot establish Aitia admission. The Runtime
+Host rejects the projected =agentic_ai_lab_preflight_only= marker before policy
+evaluation, regardless of its value. This fail-closed check blocks accidental
+promotion of the official preflight path; it does not attest an edited request
+with the marker removed. A future Runtime-owned admission must independently
+bind the source cut at use, evaluate Cedar through both engines and gate the
+effect. The Scheme Host now keeps a weak identity ledger for projected Cedar
+requests. =assurance-host-cedar-request-current?= rechecks the exact issued
+request and the current source cut, rejecting copied or edited presentations,
+revocation, source change and rollback. This is a source-owned predicate, not
+Runtime admission: no Runtime path calls it yet, and its truth cannot authorize
+an effect. The Scheme projection does not evaluate Cedar or gate an effect.
+The Agentic AI Lab Cedar capability may require Runtime-owned source admission for
+an action independently of caller context. Aitia's eventual release action
+must use that administrative requirement, and the unmarked request path must
+remain closed until an admitted =allow= Decision and exact current source are
+checked at issue and effect consumption. The present preflight is undecided
+and cannot satisfy that requirement.
+=assurance-host-sealed-support?= is the configured Host seal predicate, not a
+promotion transition.
+The lower-level =assurance-support-sealed-under-adapter?= is conditional on a
+caller-supplied adapter and time; it is not an authority or effect gate.
+It checks structural relationships, the current snapshot, exact
+evidence/outcome bindings and a Agentic AI Lab verification seal over the complete
+semantic subject. Agentic AI Lab rejects copied or forged adapter presentations as
+well as copied, modified, expired or revoked receipts. This proves issuance by
+the exact adapter instance, not that a caller-supplied adapter was installed
+by a trusted Host. Adapter selection and the evaluation clock must both be
+controlled at the execution boundary; caller-provided values cannot authorize
+an effect. Cedar and Runtime Host remain separate.
+Verifier choice explanation consumes the inert plan and an explicit catalog of
+POO-native candidate declarations. Evidence-kind/capability compatibility and
+declared numeric priority determine a deterministic choice; every rejected
+candidate and unassigned planned obligation remains visible. A chosen
+declaration is not proof that an adapter is installed, executable or trusted.
+
+Verifier integrations include Lean proof, Quint/TLC model check, runtime replay,
unit test, integration test, Cedar differential, static analysis and human
review. This list is extensible through named POO-native helpers, not raw
compute hooks.
+Tool-specific producers qualify against the existing evidence-kind vocabulary;
+the maintained lane does not include TLAPS.
+Reuse the necessary upstream checker and trusted execution boundary before
+adding a new implementation, as specified by RFC 0004.
* Assurance laws
@@ -258,13 +380,24 @@ The architecture requires executable formal statements of at least these laws:
history without an explicit authorized transition.
5. Composition obligation: independently supported A and B do not imply that
compose(A,B) is supported.
+ An explicit =composes= relation identifies the component claims, while a
+ separate obligation must be declared on the composite claim, named in that
+ claim's support requirements, linked by =supports= and bound to the exact
+ snapshot. The composition-requirements receipt only checks this structural
+ declaration; it never admits evidence or grants authority.
6. Unknown blocks closure: an unresolved required frontier cannot grant
authority.
7. Effect separation: authorization neither proves effect start nor effect
completion.
-Lean proves general laws. TLA+/TLC checks lifecycle interleavings such as a
+Lean proves general laws. Quint/TLC checks lifecycle interleavings such as a
source change racing a cached decision or an effect beginning after revocation.
+The bounded lifecycle model additionally separates safety from progress:
+eventual effect start is required only when the source and clock remain stable,
+no revocation intervenes, and the Host weakly fairly schedules every enabled
+stage. Without that scheduling assumption, a stuttering behavior after a grant
+is a valid counterexample. Neither result substitutes for a trusted Host clock,
+adapter identity, or Runtime effect gate.
* Public API direction
@@ -308,7 +441,7 @@ standards compliance, release certification or unrestricted causal inference.
3. Copying Software/SDLC standards into the assurance kernel: rejected because
standards already have an Aitia-owned SDLC module and hard-coding them into
the kernel would collapse the domain/module boundary.
-4. A second Graph implementation: rejected because POO Flow owns the graph
+4. A second Graph implementation: rejected because Agentic AI Lab owns the graph
substrate and algorithms.
5. Green-check aggregation: rejected because it loses revisions, assumptions,
provenance, invalidation and effect boundaries.
@@ -318,11 +451,11 @@ standards compliance, release certification or unrestricted causal inference.
* Closed architecture decisions and remaining acceptance work
The repository license is closed as =Apache-2.0 AND
-LGPL-2.1-or-later=, matching POO Flow. The former open decisions are closed by:
+LGPL-2.1-or-later=, matching Agentic AI Lab. The former open decisions are closed by:
-1. ADR 0004: Aitia owns assurance-specific Lean/TLA+ sources and may consume a
- pinned POO Flow proof package for generic laws.
-2. ADR 0007 supersedes ADR 0003: POO Flow is Aitia's public mechanism library;
+1. ADR 0004 r2: Aitia owns assurance-specific Lean/Quint sources and may consume a
+ pinned Agentic AI Lab proof package for generic laws.
+2. ADR 0007 supersedes ADR 0003: Agentic AI Lab is Aitia's public mechanism library;
additions require a stable public owner, not an artificially small
allowlist.
3. ADR 0005: canonical JSON snapshots are persistence projections, never
diff --git a/docs/rfcs/0002-snapshot-and-invalidation-kernel.org b/docs/rfcs/0002-snapshot-and-invalidation-kernel.org
index 61a288a..d0340b1 100644
--- a/docs/rfcs/0002-snapshot-and-invalidation-kernel.org
+++ b/docs/rfcs/0002-snapshot-and-invalidation-kernel.org
@@ -19,6 +19,10 @@ source, claim, policy and evidence revisions. A change produces an inert
=InvalidationReceipt= through pure traversal of typed relations. The receipt
selects affected current obligations, evidence, decisions and effects; it does
not run a verifier, derive replacement obligations or authorize an effect.
+The snapshot also exposes a non-circular context digest used by Phase 3
+obligation binding. Unlike the final snapshot digest, it omits only each
+obligation's own snapshot-binding slots; it retains all other node, relation,
+revision, policy and frontier content.
* Input contracts
@@ -42,8 +46,8 @@ to the effect target. Temporal precedence is never promoted into causality and
does not participate in structural invalidation.
The current implementation projects the Aitia-owned relation directions into
-POO Flow Graph values and delegates reachability, relation trajectories and SCC
-analysis to the POO Flow structural-impact algorithms. Aitia does not retain a
+Agentic AI Lab Graph values and delegates reachability, relation trajectories and SCC
+analysis to the Agentic AI Lab structural-impact algorithms. Aitia does not retain a
second traversal engine. Dangling relations remain in the snapshot frontier
but are excluded from the executable Graph projection, so an incomplete
snapshot produces an inert receipt rather than an invalid Graph.
@@ -73,7 +77,7 @@ outcomes and evidence admission. The Runtime Host owns effect execution.
* Acceptance gates
-- [X] Replace the local traversal with the POO Flow Graph library projection.
+- [X] Replace the local traversal with the Agentic AI Lab Graph library projection.
- [X] Add deterministic SCC and complete witness-path behavior.
- [X] Exercise monotone invalidation for the bounded fixed snapshot.
- [X] Reject stale or revision-mismatched evidence before obligation discharge.
@@ -86,14 +90,14 @@ The bounded executable fixture validates the implementation, while
general fixed-snapshot monotonicity law and the unresolved-frontier boundary.
The isolated replay recorded by
-=docs/receipts/2026-09-18-phase2-clean-replay.org= admits the complete POO Flow
+=docs/receipts/2026-09-18-phase2-clean-replay.org= admits the complete Agentic AI Lab
library closure, Assurance fixture, modular Lean gate, integration lane and
-native Scheme/C/Python package at exact commits. POO Flow remains Aitia's
+native Scheme/C/Python package at exact commits. Agentic AI Lab remains Aitia's
public mechanism library; the closure was achieved by publishing its mechanism
owners, not by duplicating or minimizing them in Aitia.
* Relationship to ADRs
-- ADR 0007 establishes POO Flow as Aitia's public mechanism library.
+- ADR 0007 establishes Agentic AI Lab as Aitia's public mechanism library.
- ADR 0004 assigns the general laws and lifecycle models to Aitia.
- ADR 0005 defines persistence as a canonical non-authoritative projection.
diff --git a/docs/rfcs/0003-composition-value-interface.org b/docs/rfcs/0003-composition-value-interface.org
index 92664db..a65a8c5 100644
--- a/docs/rfcs/0003-composition-value-interface.org
+++ b/docs/rfcs/0003-composition-value-interface.org
@@ -6,215 +6,135 @@
:PROPERTIES:
:ID: lambda-aitia-rfc-0003
-:STATUS: active
+:STATUS: draft
:DATE: 2026-09-18
+:UPDATED: 2026-09-24
:PARENT_RFC: lambda-aitia-rfc-0001
:IMPLEMENTS: lambda-aitia-rfc-0001
:END:
-* Decision summary
+* Decision and present boundary
-Lambda Aitia configuration has Jsonnet-style file-value semantics. A downstream
-=aitia.ss= contains one root =use-composition= expression. Evaluating the file
-returns one closed POO-native Case; the file is not a conventional Gerbil library
-module and the user does not write =import=, =export= or a result binding.
+Lambda Aitia owns Software Engineering Profile values and the maintained
+=aitia= Case. Agentic AI Lab owns semantic Module identities, Profile exports,
+=use-module=, =compose profiles=, =user-composition=, Case lowering, admission
+and Session behavior. The ordinary value is POO-native; Aitia does not own a
+parallel selector, catalog, graph or runtime.
-The official root Composition is named =aitia=:
+Agentic AI Lab's current public expression surface is:
#+begin_src scheme
-(use-composition aitia)
+(user-composition project
+ (compose profiles
+ (use-module AitiaModule default)))
#+end_src
-The official Composition carries a default Software Engineering Project Profile.
-That Profile composes the Aitia-owned SDLC, NASA NPR 7150.2D knowledge, GitOps,
-ADR/RFC, assurance and formal-method obligations, including TLA+ model checking.
-These Modules and Profiles are implicit in the ordinary user surface. Selecting
-=aitia= does not require the downstream project to restate or import them.
+The maintained Aitia owner provides =AitiaModule= and its already composed
+=aitia= value in =user-interface/compositions/aitia.ss=. The default Project
+declares GitOps, SDLC, NASA, ADR/RFC, assurance and formal-method selections.
+Declaration alone neither executes a verifier nor establishes compliance or
+release authority.
-* User experience
+The former =(use-composition aitia)=, implicit catalog and single-expression
+file loader were removed from Agentic AI Lab's public surface by its native Profile
+algebra migration. Their earlier tests no longer qualify the current API.
+The no-import, one-expression downstream convenience requested for ordinary
+users remains open. Aitia will not recreate the removed loader locally or
+present an untested downstream snippet as supported.
-The common path exposes Project facts and named Composition slots rather than the
-POO meta-object protocol:
+* Namespace and edition
-#+begin_src scheme
-(use-composition aitia
- (project
- repository: "tao3k/example"
- languages: '(rust python))
- (delivery
- provider: github))
-#+end_src
-
-The clauses are hygienic syntax projected onto ordinary POO-native objects and
-slot operations. They are not an alist, JSON or directory-shaped runtime DSL.
-The resulting value remains a normal POO Flow Scenario Case.
+The canonical NASA standard-family identity is =nasa/sdlc/npr-7150.2=:
+organization =nasa=, domain Module =sdlc=, Profile =npr-7150.2=. The selected
+standard object explicitly carries =edition: D=, effective date and source
+URLs. Its versioned Source Lock uses exact edition, source digests and byte
+counts. A future edition changes the bound source and assessment evidence,
+not the public family namespace or Scheme/Python import path.
-The default UI does not require knowledge of prototypes, C3 linearization,
-=.mix=, =super=, ExecutionPlan or Session. A user who needs a non-default model
-may explicitly extend the default Project Profile with the reviewed POO-native
-override surface:
+The maintained GitOps Scenario selects this typed Module Profile with:
#+begin_src scheme
-(use-composition aitia
- (.def (project @ default-software-engineering-project)
- (reviewers =>.+ '(security release))))
+(use-module NasaSdlcModule npr-7150.2)
#+end_src
-This is progressive disclosure: POO remains the implementation and extension
-model, but it is not prerequisite knowledge for selecting the maintained
-Composition and supplying ordinary Project facts.
-
-* File-value contract
-
-An =aitia.ss= input MUST contain exactly one root value expression. The POO
-Flow Composition value loader expands that expression in a bounded prelude
-which supplies only the public Composition syntax, an explicitly provided
-official Composition catalog and the reviewed POO override operators. Aitia
-contributes the =aitia= catalog entry; it does not own or wrap the loader.
-Loading MUST NOT depend on a user-written import or export and MUST NOT discover
-semantics by recursively importing a directory.
-
-The POO Flow loader MUST:
-
-1. read and expand the single root expression with source locations preserved;
-2. resolve its Composition identity from the Composition catalog;
-3. apply ordinary slot clauses and then explicit advanced POO overrides;
-4. recompute derived slots and reject unresolved conflicts;
-5. validate the closed object graph; and
-6. return exactly one Case without starting a Runtime Session or executing an
- effect.
-
-=aitia doctor= consumes the same value path. It may present effective values,
-linearization and per-slot provenance, but it does not create a second
-configuration representation.
-
-* Composition and Module namespaces
-
-Composition identities and Module identities are distinct typed namespaces.
-The public official Composition identity =aitia= is reserved to the Lambda Aitia
-project. A user-authored Composition MUST declare a user-owned namespace and
-MUST NOT:
-
-- use =aitia= as its namespace;
-- equal any registered Module identity;
-- shadow an official Composition identity; or
-- rely on import order to select between a Composition and a Module.
-
-The expander rejects these conflicts before Case construction. Catalog lookup
-never falls back from the Composition namespace to the Module namespace.
-
-The exact textual spelling of user-owned qualified identities is owned by the
-implementation slice, but the semantic identity MUST contain a namespace and a
-local name. An unqualified identity is permitted only for an official reserved
-Composition such as =aitia=.
-
-* Official =aitia= Composition
-
-The official Composition is a maintained object graph, not an empty template.
-Its default Project Profile owns at least these slots:
-
-| Slot | Default owner | Meaning |
-|------+---------------+---------|
-| =project= | Lambda Aitia | Software Engineering Project facts and lifecycle |
-| =sdlc= | Lambda Aitia | SDLC structure and review obligations |
-| =standards= | Lambda Aitia | NASA NPR 7150.2D applicability knowledge |
-| =delivery= | Lambda Aitia | GitOps development, staging and production flow |
-| =decisions= | Lambda Aitia | ADR and RFC relationships |
-| =assurance= | Lambda Aitia | Claims, obligations, evidence and invalidation |
-| =formal-methods= | Lambda Aitia | TLA+ and Lean obligation projections |
-| =graph-policy= | POO Flow | Execution, impact and temporal graph projection |
-| =runtime-policy= | POO Flow | Case admission and fresh Session construction |
-
-The default does not claim universal NASA compliance, successful model checking,
-proof completion or release authority. It installs the corresponding knowledge,
-obligations and gates. Receipts establish what was actually evaluated.
-
-* Ownership boundaries
-
-Lambda Aitia owns the Software Engineering domain model, the official =aitia=
-Composition catalog entry, its default Project Profile and its qualification
-Scenarios.
-
-POO Flow owns =use-composition=, the single-expression value loader, typed
-Composition identities and catalog resolution, generic POO composition
-mechanisms, C3 behavior, Graph and ExecutionPlan projection, impact and temporal
-algorithms, Case admission, Session state and runtime receipts. Aitia MUST
-reuse those public mechanisms and MUST NOT implement a second selector, loader,
-graph, planner or runtime engine.
-
-The Python project under =bindings/python= is a production SDLC Runtime consumer.
-It consumes the closed Case projections and C ABI receipts; it does not parse a
-parallel Python configuration model or redefine Composition semantics.
-
-* Scenario boundary
-
-=user-interface/scenarios/= contains Aitia-owned reference, qualification and
-regression assets. Each Scenario invokes the same public Composition value path
-as downstream users and adds fixed inputs plus expected projections and receipts.
-It is not a directory contract copied into downstream projects.
-
-Downstream projects normally contain only =aitia.ss=. Advanced users may split
-ordinary Scheme implementation files for their own maintenance, but the root
-configuration still evaluates to one value and directory shape does not acquire
-configuration semantics.
-
-* Slot resolution
-
-C3 determines deterministic prototype precedence. Each public slot also owns a
-declared resolution policy; linearization alone does not imply merge behavior.
-The initial policies are:
-
-- scalar facts replace the inherited value;
-- ordered collections append with identity-based de-duplication;
-- keyed objects merge only through their owning POO protocol;
-- assurance obligations are monotone unless an explicit authority-governed
- waiver object is admitted;
-- derived slots are recomputed after overrides and are not directly writable;
-- incompatible Profile selections fail closed.
-
-The resolved Case retains origin metadata sufficient for =aitia doctor= to show
-which official Profile or downstream override contributed an effective slot.
-
-* Implementation sequence
-
-1. POO Flow supplies a source-located single-expression value loader and changes
- the downstream =use-composition= surface from declaration/export semantics to
- expression semantics. Existing internal Case builders remain the lowering
- target.
-2. Lambda Aitia publishes the official =aitia= Composition and default Software
- Engineering Project Profile with the implicit Module closure described above.
-3. Aitia qualification Scenarios exercise zero-override, ordinary-slot and
- advanced-POO paths through the same loader.
-4. =aitia doctor= projects value, provenance, obligations and Plan summaries from
- the closed Case.
-5. Python Runtime and C ABI consume the same canonical Case projections without
- introducing another configuration source.
-
-There is no compatibility layer preserving directory discovery or explicit
-downstream export syntax. Migration is direct because the former surface had
-not established the desired downstream contract.
+Its check name is a workflow gate keyed to the standard family. A green
+check with only that name now fails closed: the check must also match the
+selected Standard object's edition and Source Lock digest. These check
+fields are still caller-supplied workflow data, not an Assurance seal or
+proof of actual verifier inputs. Accountable Host admission and source-byte
+binding remain separate acceptance gates.
+
+When an application configures an Assurance Host source reader, issuance and
+currentness recheck all declared verifier inputs against current source bytes.
+The configured verification operation receives Host-materialized POO input
+values as a fourth argument, including a copy of each validated payload; the
+Host rechecks identities, revisions, digests and payloads after the operation.
+Without a reader, the operation keeps its three-argument contract.
+Observed byte drift invalidates prior admissions, so returning to the old bytes
+requires fresh verification. This strengthens the Host boundary but does not
+authenticate the source repository or prove what a verifier process actually
+consumed; those remain application Host responsibilities.
+
+* Composition semantics
+
+The default path composes maintained POO Profile values; advanced users may
+extend those values with ordinary POO slot operations before composition.
+Profile selection preserves Module definition, instance, Profile identity,
+revision and generation in Agentic AI Lab selection proofs. The resulting Case owns
+one execution-plan projection and fresh Sessions. Importing or composing
+values has no Runtime effect.
+
+The official =aitia= Case is a maintained object graph, not an empty template.
+Its Project Profile declares Software Engineering responsibilities and
+selection of GitOps, SDLC, NASA, ADR/RFC, assurance and formal-method
+obligations. The Project declaration does not yet prove that all downstream
+slots, verifier bindings and no-import UX are complete.
+
+[[file:0004-sdlc-design-and-causal-trajectories.org][RFC 0004]] places these selections inside the complete SDLC. Design alternatives,
+implementation strategies, testing, operation and revision use the same
+maintained composition boundary. A Recipe composes existing POO declarations
+for applicability, source-bound assets, operations and required checks. An
+advanced replacement must preserve those checks or open explicit obligations;
+changing a Profile cannot silently weaken a requirement or reuse stale support.
+Recipe qualification and behavior/design trajectory projection remain pending.
+
+* Ownership and trust
+
+| Owner | Responsibility |
+|-------+----------------|
+| Aitia | Software Engineering/NASA semantics, maintained Profiles and Case, qualification scenarios |
+| Agentic AI Lab | Module/Profile algebra, composition, Graph, Case admission, Session and Runtime handoff |
+| Application Host | source reads, verifier execution, authority and effects |
+
+The Python project under =bindings/python= consumes Aitia's native C ABI; it
+does not parse a second configuration model or recreate SDLC semantics.
+Versioned NASA source identities are provenance facts, not namespace segments
+that ordinary users must type.
* Acceptance gates
-- [ ] An =aitia.ss= containing only =(use-composition aitia)= evaluates to one
- admitted Case without explicit import, export or binding forms.
-- [ ] The zero-override Case includes GitOps, NASA SDLC, ADR/RFC, assurance and
- formal-method obligation slots through the default Project Profile.
-- [ ] An ordinary Project clause lowers to POO-native slot operations.
-- [ ] An advanced POO override extends the same default Project Profile.
-- [ ] Composition/Module namespace collision and use of the reserved =aitia=
- namespace by a user Composition fail at expansion.
-- [ ] Loading and =doctor= perform no Runtime effect.
-- [ ] Reference, qualification and regression Scenarios use the public value
- path rather than private constructors.
-- [ ] Direct compilation, atomic behavior tests, a real Aitia Scenario and the
- existing composition macro scale gate pass with exact receipts.
-
-* Relationship to other decisions
-
-- RFC 0001 defines the causal assurance vocabulary carried by the default
- Composition.
-- RFC 0002 defines the immutable AssuranceSnapshot and invalidation boundary.
-- ADR 0007 keeps POO Flow as the public mechanism library consumed here.
-- ADR 0006 keeps Python as the production SDLC Runtime rather than a second
- configuration authority.
+- [X] Official Aitia and NASA identities lower through Agentic AI Lab's public
+ =user-composition=, =use-module= and Profile algebra.
+- [X] The maintained Aitia Case and GitOps/NASA Scenario construct without
+ Runtime execution and have focused tests.
+- [ ] A zero-override downstream file can select =aitia= without imports or
+ exposing POO internals, through a Agentic AI Lab-owned public mechanism.
+- [ ] An advanced override extends the same maintained Project Profile and
+ preserves selection/provenance receipts.
+- [X] The pure GitOps decision rejects a same-name green check lacking the
+ selected edition or Source Lock digest, including a check for another edition.
+- [ ] A Host-issued NASA assessment binds actual verifier inputs, source bytes,
+ exact edition and Source Lock digest before it can count as Assurance support.
+- [ ] Case, C ABI and Python project consume one canonical composition cut in
+ a clean checkout across both repositories.
+- [ ] Source-located diagnostics, doctor presentation and scale receipts pass
+ for the current POO-native expression path.
+
+* Related decisions
+
+- RFC 0001 defines the Assurance vocabulary carried by the Project Profile.
+- RFC 0002 defines canonical snapshots and invalidation.
+- RFC 0004 defines lifecycle design, trajectory scope and reusable Recipes.
+- ADR 0007 keeps Agentic AI Lab as the mechanism library.
+- ADR 0006 keeps Python as a production Runtime consumer, not a second
+ semantic owner.
diff --git a/docs/rfcs/0004-sdlc-design-and-causal-trajectories.org b/docs/rfcs/0004-sdlc-design-and-causal-trajectories.org
new file mode 100644
index 0000000..299e307
--- /dev/null
+++ b/docs/rfcs/0004-sdlc-design-and-causal-trajectories.org
@@ -0,0 +1,612 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: RFC 0004 — SDLC Design, Causal Assurance and Trajectories
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-rfc-0004
+:STATUS: draft
+:DATE: 2026-09-24
+:UPDATED: 2026-09-24
+:PARENT_RFC: lambda-aitia-rfc-0001
+:IMPLEMENTS: lambda-aitia-rfc-0001
+:END:
+
+* Decision summary and scope
+
+The complete Software Development Life Cycle (SDLC) is Aitia's organizing
+framework. Requirements, engineering design, algorithm and implementation
+strategies, verification and testing, delivery, operation, maintenance and
+retirement all participate in that lifecycle. Causal Assurance maintains the
+justification of engineering conclusions as these activities change the system.
+
+Software design receives early engineering investment because cheaper code
+generation increases the value of deciding what to build, under which
+assumptions, with which responsibilities and guarantees. This is a product
+direction to evaluate through qualification cases, not a claim that code cost
+or design quality has already been measured.
+
+The eight-step =change -> invalidate -> plan -> verify -> admit -> decide ->
+authorize -> effect= flow is the existing assurance/execution protocol. It can
+be used at multiple lifecycle points; it is not an enumeration of the entire
+SDLC. The overall lifecycle contains feedback, concurrent activities and
+repeated revisions. A bounded execution plan may be a DAG without turning the
+whole lifecycle into one fixed pipeline.
+
+This RFC records the agreed direction and pending executable acceptance work.
+Its draft status does not promote the capabilities below to implemented APIs.
+
+[[file:0005-org-native-engineering-workspace.org][RFC 0005]] specifies the native Org engineering work surface and source-bound
+Agent review, with generic Org integration owned by Agentic AI Lab. Its initial
+authoring checks are distinct from the pending connected execution loop.
+
+The lifecycle workflow below names engineering states, not implementation
+milestones. Transitions require attributable revisions and receipts; an arrow
+does not itself grant assurance or authority. Feedback can reopen earlier
+activities, and independent obligations may proceed concurrently.
+
+#+begin_export mermaid
+stateDiagram-v2
+ state "Requirements: scoped" as Requirements
+ state "Design: alternatives proposed" as Design
+ state "ADR: option selected" as Selected
+ state "Implementation: candidate" as Implementation
+ state "Verification: obligations pending" as Verification
+ state "Assurance: supported at a bound cut" as Supported
+ state "Delivery: effect authorized" as Authorized
+ state "Operation: behavior observed" as Operation
+ state "Maintenance: reassessment pending" as Reassessment
+ state "Retirement: obligations pending" as Retirement
+ state "Retired: closure recorded" as Retired
+ [*] --> Requirements
+ Requirements --> Design: scope and constraints recorded
+ Design --> Selected: alternatives reviewed
+ Selected --> Implementation: strategy chosen
+ Implementation --> Verification: candidate and checks bound
+ Verification --> Supported: scoped evidence admitted
+ Verification --> Design: finding challenges design
+ Supported --> Authorized: current decision and effect gate
+ Authorized --> Operation: execution receipt and observations
+ Authorized --> Reassessment: revoked, expired or premise changed
+ Supported --> Reassessment: premise changes or late evidence
+ Operation --> Reassessment
+ Reassessment --> Requirements: requirement revision
+ Reassessment --> Design: decision revision
+ Reassessment --> Verification: renewed obligations
+ Operation --> Retirement
+ Retirement --> Retired: residual obligations discharged
+#+end_export
+
+These states summarize activity, not a single global status enum. Multiple
+claims may have different support states at the same cut. Pending or stale
+support blocks the affected effect; an accepted ADR alone is not authorization.
+Operational findings or changed context trigger reassessment; an accountable
+retirement decision opens retirement obligations before closure is recorded.
+
+* Formal challenge gates before persistence integration
+
+The immediate design-validation priority is to challenge lifecycle assumptions
+using reviewed upstream failure reports, not to add storage. Keep reported
+behavior, our proposed transfer and locally executed evidence distinct in the
+[[file:../plans/engineering-case-source-inventory.org][source inventory]]. An Issue being closed does not qualify our design.
+
+Quint is organized into reusable work and grant predicates with independently
+runnable finite models and a separate ingress composition lane. Each safety boundary
+needs positive exploration, a reachable-state control and a deliberately
+weakened guard that produces the expected counterexample. Do not duplicate a
+shared action in every scenario, discard environment interference to obtain a
+green atomic test, or infer composite correctness from leaf checks alone.
+
+The [[file:../../proof/quint/README.org][maintained Quint slice]] separates cancellation/work observations from retirement
+review. It requires final-cut quiescence and known inventory: a cancellation
+request, an earlier accepted review, or missing history is insufficient.
+Lean proves safety preservation for an abstract retirement transition relation;
+it does not yet prove Scheme or Quint refinement. The
+[[file:../receipts/2026-09-24-retirement-formal-review.org][historical TLA+ receipt]] records the earlier checks and parser boundary.
+
+The historical [[file:../receipts/2026-09-24-formal-source-qualification.org][source qualification]] checked TLA+ syntax/byte-roundtrip. The
+maintained Quint CLI checks Quint syntax and binds both current source views
+to one POO design declaration, revision and
+source cut using existing SDLC/Assurance links. A model, proof or premise
+change invalidates old bindings. This is source correspondence, not a proof of
+semantic refinement or Host evidence admission. Independent replay and
+semantic correspondence remain required for closure.
+The isolated review terminal state assumes no later
+ingress; the [[file:../receipts/2026-09-24-retirement-ingress-review.org][bounded ingress composition]] challenges this by permitting requests
+after retirement. It requires closing grant issuance and advancing the epoch
+before finalization, and rechecking the cached grant at effect start. The
+effect-admission predicate is extracted from the existing assurance model.
+This does not establish a deployed Cedar/Runtime binding, new grant issuance,
+distributed atomicity, repeated retries or eventual progress. Authorization,
+ingress exclusion and fairness still need their actual owner correspondences
+before any Runtime or eventual-retirement guarantee. Persistence remains
+deferred; passing these abstract checks does not authorize its implementation.
+
+** Correspondence gate across design, formal views and execution
+
+A source digest proves which bytes were checked, not that the checked formula
+means the declared guarantee. Each claimed correspondence therefore needs a
+reviewable interpretation, an owner and an adversarial check:
+
+| Boundary | Required correspondence | Falsifying control |
+|----------+-------------------------+--------------------|
+| POO design contract → Quint | Map each relevant assumption and guarantee to named state predicates/actions, including the environment and modeled client bound | weaken a fence, inventory or ingress premise and require the expected reachable counterexample |
+| POO design contract → Lean | State theorem premises and conclusion against the same declaration; audit imported axioms and excluded behaviors | remove a needed premise and demonstrate that the claim is no longer established |
+| Quint/Lean → Scheme and Runtime | Identify the concrete state/effect transitions represented by the abstract ones and document omitted transitions | replay a concrete behavior outside the mapping and keep conformance unknown or violated |
+| Tool result → Assurance Host | Bind actual tool/source/configuration identities and the exact proposition assessed | change an input or tool identity and reject reuse of the earlier admission |
+
+The current source-group links qualify identity and invalidation only. A
+matching name, digest, passing model configuration or axiom-free theorem does
+not fill an interpretation row. A counterexample in the abstract model is a
+model finding until its concrete correspondence is checked; an observed
+Runtime trace is not retroactively turned into a model execution. If a
+concrete transition has no modeled counterpart, record that coverage gap and
+reopen the design or model rather than narrowing the tested environment to
+make the check pass. No implementation-conformance or effect-authority flag
+may become true from these source mappings alone.
+
+For the maintained =job-executor/retirement= declaration, the first
+correspondence review has these concrete boundaries:
+
+| Declaration | Current formal representation | Remaining gap |
+|-------------+-------------------------------+---------------|
+| =atomic-epoch-fence= | Quint =CloseIngress= closes issuance and advances =epoch= in one action; Lean =Step.close= changes both fields | No concrete Host/Cedar/Runtime atomic transition is bound |
+| =known-inventory= and quiescence | Quint =Retire= requires =known= and =quiescent(work)=; Lean =Retirement.Step.finalize= requires =inventory=, =idle= and =drained= | Neither formal view proves the inventory is complete in production |
+| =no-new-grant= | The Quint composition has one fixed cached grant and no grant-issuance action; Lean has no issuance transition | This is an excluded environment behavior, not a proved revocation protocol |
+| =bounded-client= | Quint =pending= and =attempted= model one request/attempt; Lean's =requestOrReject= stutters | Multiple clients, responses and retry progress are outside the Lean theorem |
+| =retirement-safety/g1= | Quint checks =NoOutstandingWork= and =NoPostRetirementStart=; Lean proves =Retirement.Safe= and =RetirementIngress.Safe= for its own =Step= relation | These are two abstract checks, not a proof that either is a faithful refinement of the Scheme contract or deployed effects |
+
+The current source binding tracks changes to these files, but none of the
+remaining gaps can be closed by adding another digest link. In particular,
+the absent grant-issuance transition must be modeled and challenged before
+claiming that real new grants are excluded after retirement.
+
+* Design and implementation within the lifecycle
+
+| Activity | Engineering question | Attributable output |
+|----------+----------------------+---------------------|
+| Requirements and context | What outcome is needed, for whom and under what constraints? | revisioned requirements, scope and acceptance conditions |
+| Software and engineering design | Who owns state, responsibility, interfaces, failure handling and effects? | alternatives, assumptions, guarantees and RFC/ADR decisions |
+| Algorithms and implementation strategies | How can the chosen guarantees be realized within cost and resource constraints? | strategy choice, implementation mapping and measurements |
+| Verification and testing | Which precise propositions have supporting or contradicting evidence? | scoped proofs, model checks, tests, replay and review |
+| Delivery and operation | Which action is currently permitted, and what actually happened? | authority, execution receipts and observed trajectories |
+| Maintenance and retirement | Which assumptions changed, and what must be revised, migrated or stopped? | invalidation, new obligations and accountable successor decisions |
+
+Activities share one lifecycle subject and revision history. An algorithm
+change that alters consistency or failure guarantees is also a design
+decision. A performance optimization within the same contract still needs
+conformance and performance evidence. Estimated cost, human judgment and
+measured behavior retain distinct evidence kinds and scopes.
+
+Design work relates existing POO values through:
+
+#+begin_export mermaid
+flowchart TD
+ R["Requirements and constraints
scoped"] --> A["Assumptions and alternatives
proposed"]
+ A --> D["Responsibilities, state, interfaces and effects
selected in RFC / ADR"]
+ D --> G["Conditional guarantees
declared, not yet supported"]
+ G --> I["Implementation strategy
candidate"]
+ G --> O["Verification obligations
open"]
+ I --> E["Tool results and observations
candidate evidence"]
+ O --> E
+ E --> C{"Scoped admission and assessment"}
+ C -->|support established| S["Guarantee supported
at this revision and cut"]
+ C -->|failed or unresolved| F["Finding / unknown frontier
requires review"]
+ F --> A
+ S -->|premise changes| X["Prior support stale
reassessment required"]
+ X --> O
+#+end_export
+
+A guarantee states its subject, predicate and scope under named assumptions.
+An assumption states a premise, its owner and the conditions requiring review.
+An ADR records considered options and their consequences; acceptance records
+the design choice, while current assurance requires separately admitted
+evidence. Relaxing a requirement is an explicit requirement revision and
+review, not a repair technique that silently turns a failed check green.
+
+The existing =SdlcDesignContract= supplies responsibilities, owned state,
+allowed effects, assumptions, guarantees, variations and a decision identity.
+Its replacement review admits exact declaration comparisons only. Logical
+implication between different statements, model/code correspondence and
+cross-component guarantees require additional obligations with attributable
+checks. Neither name equality nor two successful component checks establishes
+the safety of their composition.
+
+* System behavior and design evolution trajectories
+
+Agentic AI Lab owns Temporal Causality, event graphs, causal cuts, trajectory
+contracts, witness paths and traversal. Aitia supplies software event meaning
+and the links from behavior to requirements, assumptions, design decisions and
+assurance. Python transports observations and invokes tools through the owned
+runtime boundary.
+
+Two related trajectories are required:
+
+- system behavior: requests, state transitions, retries, effects, failures and
+ recovery in an explicitly identified environment;
+- design and assurance evolution: hypotheses, RFC/ADR choices, checks,
+ findings, invalidation, revision and renewed acceptance.
+
+Evidence and checked projections connect these trajectories. A runtime event
+can challenge an assumption; a reviewed explanation can motivate an ADR
+revision. Structural impact, temporal precedence and graph reachability do not
+by themselves establish a causal explanation. Agent-proposed explanations
+remain hypotheses until their supporting checks are admitted.
+
+#+begin_export mermaid
+flowchart TD
+ subgraph Behavior["System behavior trajectory"]
+ O["Execution events
observed in a bound environment"] --> R["Replay / checks
scoped results"]
+ end
+ subgraph Design["Design and assurance trajectory"]
+ G["Guarantee
declared"] --> F["Finding
open"]
+ F --> H["Causal explanation
hypothesized"]
+ H --> C["Explanation checks
pending"]
+ C --> A["ADR revision
proposed for review"]
+ A --> N["Revalidation obligations
pending after selection"]
+ end
+ R -->|challenges within scope| F
+ R -->|evidence for assessment| C
+ N -->|requires a new bound run| O
+#+end_export
+
+The cross-trajectory links are evidence and obligation relations, not an
+automatic causal inference from event order. A proposed ADR retains its
+assumptions even when the explanation remains unresolved.
+
+| Trajectory source | Scope that must remain visible |
+|-------------------+--------------------------------|
+| Production or experimental execution | observed events in the named system or harness, with source and environment bindings |
+| TLC/model-check counterexample | behavior permitted by the exact model and checked configuration; implementation correspondence is a separate obligation |
+| Proposed intervention or alternative design | counterfactual branch under explicit assumptions and a bounded horizon |
+| RFC/ADR and assurance evolution | recorded choices and changes in justification, without rewriting earlier facts or granting runtime authority |
+
+An observed failure remains observed in its original environment. The current
+Agentic AI Lab trajectory contract reserves =error-event-paths= for uncommitted
+counterfactuals; actual bug replays must not be relabeled to fit that slot.
+Use the existing observed event graph, and place any missing generic trajectory
+mechanism in its Agentic AI Lab owner before exposing an Aitia projection.
+
+An assessment binds the event graph, immutable causal cut, explicit time
+observation, source/design/policy revisions and horizon. Occurrence order,
+ingress order and revision order must not be conflated. A late observation
+creates a new assessment cut and may invalidate current support while leaving
+the earlier cut intact. Missing causal parents, incompatible clock domains
+and incomplete coverage retain an unknown frontier. Cross-clock mapping or
+additional time axes require a qualified Agentic AI Lab contract; this RFC does not
+claim that every such mapping already exists.
+
+* Lifecycle Impact of introduction, change and retirement
+
+Design direction agreed on 2026-09-24; implementation qualification remains
+pending. Impact is a lifecycle view of a change, not only a list of files to
+rebuild. It asks which historical interpretations and obligations, current
+conditions, and future options are changed by introducing, modifying or
+retiring a capability. Agentic AI Lab retains generic Impact and Temporal Causality
+ownership; Aitia supplies Software/SDLC relations and domain obligations.
+
+| Perspective | Introduce or modify a capability | Retire a capability |
+|-------------+---------------------------------+---------------------|
+| Past assets and commitments | check old data against new assumptions; reassess the applicability of earlier evidence | preserve interpretation/replay of old results and outstanding commitments |
+| Current code and operation | inspect consumers, interfaces, deployment conditions, authority and resource interactions | identify remaining consumers, running instances, in-flight work and configuration references |
+| Future work and obligations | open verification, migration, monitoring and maintenance obligations | migrate consumers, prevent new use where required, drain/cancel queued work and verify residual duties |
+
+Impact on the past never changes an observed historical fact. Distinguish
+evidence that was valid under its original conditions but is no longer
+applicable from evidence whose original justification is now challenged.
+The latter opens correction and retrospective review, not silent deletion of
+the original receipt. Record when a condition applied separately from when
+it was learned or corrected.
+
+** Inputs, meaning and receipt boundary
+
+Assessments bind the proposed change and before/after source/design snapshots,
+affected capability identities, deployment scope, selected typed relations,
+explicit causal cut/time observation, horizon and inventory completeness.
+An unexecuted change remains proposed or counterfactual; it is not an observed
+production event merely because its impact has been computed.
+
+Relevant relations include implementation dependencies, data/protocol usage,
+assumption/guarantee support, evidence applicability and accountable ownership.
+Every relation needs a source and declared meaning. Org ancestry, organization
+hierarchy, code references and causal relations are not interchangeable.
+An unchanged function signature does not imply an unchanged guarantee: a
+retention, permission or consistency change can alter assurance without an
+API change.
+
+For each affected subject, present its identity, witness path, applicable
+versions/environment/time bounds, evidence modality, unresolved conditions,
+recommended obligation and responsible role. This is an analysis/proposal,
+not execution authority. Existing Cedar/Runtime admission remains necessary
+before a proposed migration, cancellation or other external effect.
+
+The existing Agentic AI Lab classifier partitions events by logical position.
+That alone does not establish current exposure: an old task, authorization or
+stored object can still be active now. Current applicability needs an explicit
+state or validity-interval projection, including its source and uncertainty.
+Any missing generic mechanism belongs in Agentic AI Lab, not a parallel Aitia engine.
+
+Dynamic callers, unregistered deployments, external consumers and missing
+history remain an unknown frontier. No discovered dependency is not evidence
+of no dependency. Completeness is relative to the declared inventory and scope.
+
+** Retirement preserves history and discharges remaining obligations
+
+Deletion is not the inverse of introduction. Analyze the old snapshot as well
+as the candidate one: deleting an object and its edges before analysis can
+hide precisely the consumers that need migration. Preserve the capability's
+historical identity and provenance after removal from the active surface;
+record retirement and any successor explicitly. A semantically different
+replacement does not inherit identity merely by keeping the same display name.
+
+The maintained Composition selects applicable retirement stages. The following
+workflow is a qualification target, not an implemented global state machine:
+
+#+begin_export mermaid
+flowchart TD
+ P["Retirement
proposed"] --> I["Impact
scoped; unknowns retained"]
+ I --> R["Migration and residual duties
owner review pending"]
+ R --> A["Selected actions
authorization pending"]
+ A --> E["Migration / drain / cancellation
execution receipts required"]
+ E --> V["Residual obligations
verification pending"]
+ V -->|unresolved| R
+ V -->|closure conditions satisfied| C["Retired
historical identity retained"]
+#+end_export
+
+An accepted retirement proposal neither cancels queued work nor rewrites
+historical evidence. Required operations use the existing effect boundary;
+irreversible effects may require explicit compensation or unresolved duties
+rather than a claim that rollback erased them.
+
+** Next qualification: retire one job-executor capability
+
+Pair the existing repair case with a bounded retirement experiment using the
+same job-executor subject. Select one concrete capability and bind its consumers
+before implementing the experiment; this RFC does not order a production
+removal. Include an old persisted job/result, a current consumer or in-flight
+job, and queued future work. Preserve one unrelated consumer as a negative
+control and one deliberately unknown external-consumer boundary.
+
+The experiment must show pre/post snapshot witnesses, explicit handling of
+still-active old work, proposed migration/drain obligations and actual receipts
+where execution is claimed. Replaying an old result must retain its original
+version/scope; a replacement cannot silently acquire the old evidence.
+
+The [[file:../receipts/2026-09-24-retirement-impact.org][first bounded analysis receipt]] exercises the automatic-retry fixture through
+Agentic AI Lab's existing public mechanisms. It uses synthetic facts and does not
+close the persisted-state, obligation derivation or execution requirements above.
+
+* Historical engineering cases as design inputs
+
+Issues, design discussions, incident reports and engineering articles can
+contribute before implementation begins. Preserve the reasoning that connects
+context, requirements, assumptions, alternatives and consequences, rather than
+only a summary or a recommended pattern. Include successful designs, rejected
+proposals and withdrawn fixes as well as failures.
+
+| Use | Contribution | Admission boundary |
+|-----+--------------+--------------------|
+| Inspiration | proposes a question, assumption, alternative or failure scenario | similarity does not establish applicability or a local defect |
+| Judgment | supports an accountable choice under explicit conditions and tradeoffs | record matching conditions, differences, counterevidence, owner and review triggers |
+| Verification asset | supplies a model, checker, harness or regression | qualify the exact asset and proposition before admitting support for the current subject |
+
+These are uses, not automatic stages of increasing trust. A useful article
+need not contain a replay program. A human cost or maintainability judgment
+need not become a mechanical theorem, but must retain attribution, scope and
+reconsideration conditions. Neither judgment nor author reputation grants an
+effect capability.
+
+The reusable case records context/version/workload, intended guarantee,
+explicit and inferred assumptions, reported events, proposed explanations,
+considered alternatives, consequences and transfer conditions. Every extracted
+claim points to its source passage or comment and available revision. Keep
+original URL, author, publication/update and retrieval times; record digest and
+reuse permissions when retaining source bytes or executable assets. A mutable
+URL is not a pinned artifact. This phase references sources and records our
+analysis; it does not vendor articles or assume all public material is licensed
+for code/data redistribution.
+
+Before applying a case, compare state/effect ownership, failure model,
+identity, timing/retention, workload and recovery requirements against the
+current design. Record the correspondence as a reviewable proposal with
+supporting and contradicting observations. Search similarity, citation count,
+Issue closure and Agent confidence cannot discharge that applicability review.
+Multiple articles repeating the same incident are not independent evidence.
+
+#+begin_export mermaid
+flowchart TD
+ S["External material
reported and attributed"] --> Q["Design question / alternative
proposed"]
+ Q --> M["Applicability mapping
pending review"]
+ M --> J["Design judgment
scoped, with explicit unknowns"]
+ J --> D["RFC / ADR choice
proposed for accountable review"]
+ D --> O["Verification obligations
open"]
+ S --> A["Reusable assets
unqualified"]
+ A --> V["Actual checks
candidate results"]
+ O --> V
+ V --> E["Evidence admission
required for supported claims"]
+ S --> N["Correction / new report
applicability reassessment pending"]
+ N --> M
+#+end_export
+
+An external report is evidence of what its author reports, not a local observed
+execution. Separate the system-event timeline from the history of what became
+known: publication, correction, retrieval and design review. A later explanation
+creates a new assessment and can reopen a decision; it does not rewrite the
+earlier knowledge cut. Unknown timestamps remain unknown. Do not give a whole
+case one =verified= flag: a reported failure, hypothesized cause, tested repair
+and unreviewed transfer can coexist.
+
+Use existing Artifact, Claim, Assumption, Finding, Evidence, Decision and
+Obligation projections and POO composition. These conceptual correspondences
+are not new implemented constructors or permission to add arbitrary edge names.
+Agentic AI Lab retains generic temporal/causal and query ownership. No parallel case
+graph engine, universal crawler, confidence scorer or MRR integration is
+required to qualify the first case.
+
+** First application and mechanism reuse
+
+[[file:../adrs/0008-stable-operation-key-after-lost-ack.org][ADR 0008]] applies this method to logical-operation identity. The AWS idempotency
+article supplies design questions, not evidence that Aitia or the fixture meets
+the AWS contract. The source/coverage matrix in that ADR distinguishes the
+existing replay from untested parameter, retention and crash boundaries.
+
+Authorization conditions belong in the existing Agentic AI Lab Cedar Provider, using
+trusted context supplied by the Host; do not create an Aitia policy evaluator.
+Cedar decides whether an action is allowed for the supplied principal, resource
+and context. Runtime must enforce that decision at use. Provider-side atomic
+deduplication and durable effects remain execution obligations: two concurrent
+requests can both be allowed without an execution-time uniqueness mechanism.
+An =Allow= does not establish that a previous attempt failed or did not commit.
+
+The current =assurance-host-cedar-request= and its currentness predicate are
+preflight projections, not a connected Runtime gate. Preserve their owner and
+reuse the existing effect-token machinery; qualify the missing handoff instead
+of treating the whole authorization design as absent. An operation identity
+survives retries, while a new attempt still requires the applicable current
+authorization. Outcome-unknown retries require provider reconciliation and
+idempotency guarantees, not an invented success or automatic fresh commit.
+
+* Reuse existing verification methods and engineering assets
+
+A Recipe is a composition of existing POO objects and slots describing
+applicability, bound inputs, operations, required checks, expected artifacts
+and failure handling. It is not a new configuration language or a separate
+workflow engine. RFC 0003 governs its maintained and advanced expression paths.
+
+Reuse existing functions, packages, scripts, models, harnesses and tool
+commands at a boundary that preserves their correctness conditions. The reuse
+unit includes the checking implementation, necessary dependencies, real
+execution path and relevant regression tests. When those pieces are coupled,
+first qualify the existing boundary or contribute a focused upstream change.
+Add a new implementation only for an identified capability gap.
+
+For every selected component or asset, record exact source revision/digest,
+original attribution and license, applicability assumptions, dependencies and
+the check establishing that it works in Aitia. The integration inventory must
+distinguish candidates from qualified reuse. Package layout alone does not
+establish a stable SDK or independent checker entry point.
+
+The maintained finite-state route is Quint with a pinned TLC backend; Lean
+retains its separate theorem lane. TLC state exploration and Lean theorem
+checking make different claims. Existing proof evidence kinds can name
+different producers without adding a parallel semantic schema for each tool.
+
+Specula and its case-study archive are candidate sources of verification tools,
+models, harnesses, traces and reproductions. The archive stores experiment
+records; each selected record needs a replay and attribution audit. The full
+Specula application is optional, not the required workflow owner. Calling an
+upstream script or bounded tool command is a legitimate reuse choice.
+Specula already provides continuous and incremental verification, so Aitia's
+proposed value must be demonstrated through design decisions, composition
+obligations and changing justification rather than that feature alone.
+
+* Runtime ownership and future MRR work
+
+The production Aitia Python Runtime under =bindings/python= serves all Aitia
+capabilities across the SDLC. AnyIO is its asynchronous foundation for task
+lifetime, cancellation, bounded concurrency and I/O. Agentic AI Lab continues to own
+generic Graph/FunFlow execution and temporal/causal algorithms. Scheme/POO owns
+Aitia's semantic composition, and the C ABI carries typed projections.
+Native session thread affinity must be preserved at asynchronous boundaries.
+Declaring the AnyIO dependency does not establish async execution or Host
+admission of a tool observation.
+
+MRR is deferred beyond the current Python implementation stage. A later design
+will evaluate relation queries, derivation and lineage over lifecycle
+snapshots; its role is broader than storing trace logs. Preserve identities,
+revisions, typed relations, modalities, cuts, witnesses and unknown frontiers
+now so a later integration can project them without redefining Aitia meaning.
+Do not add an MRR dependency, query adapter, storage framework or new Python
+inference engine in this phase. Future query results must retain snapshot and
+lineage bindings and pass the applicable admission boundary before use.
+
+* Qualification sequence and observable value
+
+The primary deliverable is one connected lifecycle experiment. The current
+job-executor case is a known-fault seed: per-key deduplication can succeed
+while a logical operation commits twice after acknowledgement loss. Its
+existing ADR 0008 and design-contract tests supply a starting point, not full
+causal or Host closure.
+
+1. Bind requirements for completion and unique logical effects, assumptions,
+ source, model when available, and at least two design alternatives.
+2. Replay the known failure through existing tools and preserve the actual
+ experimental trajectory. Record the proposed explanation and check its
+ relationship to the original per-key guarantee.
+3. Compare disabling retries with preserving a stable operation identity;
+ completion and provider retention assumptions remain explicit.
+4. Record the chosen revision and derive its obligations. Run the appropriate
+ reused tools, establish required source/model correspondence and consume
+ actual Host admission where a supported conclusion is claimed.
+5. Change a retention or retry assumption, or admit a late observation. Show
+ the new cut, affected guarantees, explanation paths and renewed obligations.
+6. Apply an implementation optimization and check both contract preservation
+ and measured benefit under the same workload and environment scope.
+
+Qualify one sufficiently complete upstream bug case as a reusable method.
+A known-answer replay is regression evidence; novel discovery needs a separate
+evaluation with unexposed answers.
+
+* Pending acceptance gates
+
+- [ ] One historical case records source attribution, applicability and
+ counterevidence, the design judgment it changed, and the resulting obligation.
+ Demonstrate a source correction reopening review without overwriting history.
+- [ ] ADR 0008's owner/coverage matrix is qualified, including the existing
+ Cedar/Runtime path and provider-side parameter, retention and crash boundaries;
+ documentation of a gap is not its executable closure.
+- [ ] Upstream reuse inventory binds selected files, revisions, dependencies,
+ licenses, required checks and replay evidence.
+- [ ] A maintained POO Composition selects the qualified Recipe and an
+ advanced override preserves mandatory checks or opens new obligations.
+- [ ] The connected lifecycle case compares design alternatives against the
+ same requirements, including safety and progress where applicable.
+- [ ] System, model, counterfactual and design trajectories preserve scope;
+ missing parents and late evidence have explicit negative cases.
+- [ ] A changed assumption yields attributable invalidation witnesses and
+ prevents stale support from being reused.
+- [ ] Introduction/change/retirement Impact binds pre/post snapshots, typed
+ relations and explicit temporal scope; proposal and observed effect remain
+ separate. Generic analysis stays in Agentic AI Lab.
+- [ ] The retirement case covers historical data/results, current consumers
+ and queued work; old-but-active subjects are not lost to past-event filtering.
+ Removed graph nodes cannot hide their old dependents. Unrelated controls are
+ not reopened, and incomplete external-consumer inventory remains unknown.
+- [ ] Historical validity, current applicability and later correction are
+ distinct; missing inventory and out-of-horizon effects cannot certify safe
+ deletion. Migration or compensation requires its own authorized receipts.
+- [ ] Frozen Python tool observations reach the actual Scheme Host admission
+ path; serialized success cannot substitute for that path.
+- [ ] The maintained POO contract's assumptions and guarantees have reviewed
+ Quint/Lean interpretations and falsifying controls, followed by concrete
+ Scheme/Runtime transition correspondence. Source identity alone is not
+ semantic refinement.
+- [ ] A contract-preserving optimization has conformance and performance
+ evidence, with no unreviewed weakening of the target requirement.
+- [ ] Compare the same upstream tools/assets with and without Aitia's design
+ and assurance links: check missed obligations, unnecessary reruns and the
+ ability to explain why a conclusion changed. Record limitations and costs.
+
+The upstream entry points, connected trajectory projection and Host bridge
+remain unqualified by this documentation change. Existing bounded primitives
+and their receipts retain their existing scope.
+
+* References
+
+- [[file:0001-causal-assurance-core.org][RFC 0001 — Causal Assurance Core]]
+- [[file:0002-snapshot-and-invalidation-kernel.org][RFC 0002 — Snapshot and Invalidation Kernel]]
+- [[file:0003-composition-value-interface.org][RFC 0003 — Composition Value Interface]]
+- [[file:0005-org-native-engineering-workspace.org][RFC 0005 — Org-native Engineering Workspace]]
+- [[file:../adrs/0006-production-python-sdlc-runtime.org][ADR 0006 — Aitia Python Runtime]]
+- [[file:../adrs/0008-stable-operation-key-after-lost-ack.org][ADR 0008 — Stable logical-operation identity]]
+- [[file:../../ROADMAP.org][Roadmap and current implementation evidence]]
+- [[file:../plans/engineering-case-source-inventory.org][Engineering case sources and transfer judgments]]
+- Agentic AI Lab =src/modules/temporal-causality/interface.ss= and architecture
+ =161-temporal-causality-and-causal-trajectory-architecture.org= own the generic
+ mechanism; Aitia consumes the pinned public library.
+- [[https://github.com/specula-org/Specula#continuous-verification][Specula continuous verification]]
+- [[https://github.com/specula-org/specula-case-studies][Specula experiment archive]]
+
+Upstream references were inspected on 2026-09-24. They identify reuse
+candidates, not pinned or qualified dependencies of this project.
diff --git a/docs/rfcs/0005-org-native-engineering-workspace.org b/docs/rfcs/0005-org-native-engineering-workspace.org
new file mode 100644
index 0000000..12c9045
--- /dev/null
+++ b/docs/rfcs/0005-org-native-engineering-workspace.org
@@ -0,0 +1,361 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: RFC 0005 — Org-native engineering workspace
+#+startup: overview
+
+:PROPERTIES:
+:ID: lambda-aitia-rfc-0005
+:STATUS: draft
+:DATE: 2026-09-24
+:PARENT_RFC: lambda-aitia-rfc-0004
+:IMPLEMENTS: lambda-aitia-rfc-0004
+:END:
+
+* Decision and ownership
+
+Native Org is a maintained engineering work surface, not a Markdown document
+decorated with execution commands. Requirements, assumptions, alternatives,
+review work and receipts remain addressable parts of the same design history.
+Orgize owns syntax, lossless structure and semantic queries. Agentic AI Lab owns
+generic composition, organization, causal/temporal mechanisms and the reusable
+Org integration. Aitia owns Software/SDLC interpretations and workspaces.
+Existing Cedar and Runtime mechanisms retain effect authority and execution.
+
+The agreed dependency owner is Agentic AI Lab. The target is for its =gerbil.pkg=
+to declare a qualified Orgize Scheme package once; the current source graph
+cannot support that edge. Rust/Rowan runtime delivery is a long-term runtime
+direction, not an interim substitute for this package target and not the
+current Python milestone. Aitia, Lambda
+and other Agentic AI Lab consumers must not each acquire an independent Org parser
+or duplicate its package pin.
+Package availability does not mean implicit Scheme symbol imports: a public
+Agentic AI Lab module/composition still controls what consumers receive.
+
+The C ABI is a transport, not a new semantic owner. Orgize owns Org language
+semantics, and its Scheme/Gambit package owns the generic Org C ABI. Agentic AI Lab
+inherits Orgize once and exposes the POO-native Org facade;
+its existing downstream native boundary may forward qualified Org operations
+without redefining their semantics. Aitia depends on Agentic AI Lab and does not
+invent a separate Org wire protocol or pin Orgize independently. Rust can call
+the Orgize C ABI when it needs that Scheme runtime boundary, while native Rust
+consumers can continue using the Scheme-generated AOT library API directly.
+Neither path makes the other an implicit fallback or a second authority.
+
+The first maintained surface is [[file:../../user-interface/workspaces/job-executor.org][the job-executor workspace]], connected to
+[[file:../adrs/0008-stable-operation-key-after-lost-ack.org][ADR 0008]]. Its [[file:../../user-interface/contracts/engineering-workspace.org][authoring contract]] uses Orgize's existing =org-contract=
+implementation, not an Aitia parser or evaluator.
+
+** Scheme source authority and Rowan delivery
+
+The selected upstream surface is =scheme :org-elements= and
+=scheme :org-contract=. Org properties hold identity and scope metadata;
+the block markers select bounded Scheme declarations. Org Elements supplies
+POO query values and selection semantics. Org Contract supplies POO assertion
+values and evaluation semantics. Its hygienic forms admit the declarations
+before the upstream Scheme generators emit Rust AOT plans.
+
+Rust consumes these plans over the Scheme-declared lossless Rowan graph.
+The public =parse_org_aot= and generated query/contract packs are the consumer
+path. A legacy =orgize lint= or =contract trace= executable is not evidence
+that this path works, even if its source checkout is on the correct branch.
+Do not build a Python evaluator or translate the old contract syntax into a
+second authority. Our contracts use the upstream Scheme forms directly.
+
+** Implementation horizons
+
+The current executable milestone is Aitia's production, uv-managed Python
+Runtime. It consumes the existing Scheme/C ABI, runs real verification tools
+with AnyIO-owned task lifetimes, and must carry frozen source-bound observations
+to the actual Scheme Host admission path. For this Org workspace, Python may
+coordinate an upstream-qualified Org query/contract result as an observation;
+it must not parse Org independently, evaluate =org-contract= independently,
+or treat a successful CLI exit as admission. Org-specific Python consumption
+remains pending until its upstream result and source identity can be conveyed
+through a qualified boundary.
+
+The current Orgize PR has Scheme declarations and generated Rust/Rowan
+consumer APIs, but no =gerbil.pkg=/=build.ss= Scheme package entrypoint,
+Scheme-exported =c-define= surface, or installed shared-library contract.
+Its Rust =org_aot_edit::apply_org_source_edits= is a typed library function,
+not that ABI. Aitia's existing Scheme/Gambit C ABI proves the mechanism is
+available locally, but does not make Orgize's semantics available through it.
+The initial Scheme ABI must be scoped to semantics that Scheme actually runs
+over admitted graph values, such as Element selection and Contract evaluation;
+do not label it a source-parser ABI until source-to-graph execution and its
+ownership, errors and lifetime are implemented and tested through that path.
+
+The later Rust/Rowan runtime is the intended durable execution path for
+Scheme-generated Org artifacts. Its source, generated packs, Rust consumer,
+the Scheme-owned ABI and Agentic AI Lab facade require their own qualification. Its direction
+does not make a Rust FFI build a prerequisite for the current Python/Host work.
+The Scheme package-cycle audit below is a separate dependency-design gate;
+neither postponing it nor qualifying Rust alone satisfies the requested
+=gerbil.pkg= inheritance.
+
+* Native syntax and proposed semantic projection
+
+| Native Org element | Aitia interpretation | Boundary |
+|--------------------+----------------------+----------|
+| Heading and =ID= property | addressable design or review node | title and nesting do not grant identity authority |
+| Property drawer | revision, kind, owner-role and subject references | custom properties below are proposed conventions |
+| TODO keyword and checkboxes | authoring/review work state | DONE is neither assurance support nor authorization |
+| Links and tables | source references and alternative comparison | a link does not admit evidence |
+| LOGBOOK | attributed design-revision narrative | not a substitute for trusted execution receipts |
+| Source/export block | typed content owned by its language/backend | parsing or rendering must not execute it |
+
+=AITIA_KIND=, =OWNER_ROLE= and =SUBJECT_ID= are project conventions in this
+draft, not existing Orgize built-ins or registered POO principal identities.
+Resolve them through an explicit, validated POO-native projection. Reject
+duplicate IDs and unresolved required references instead of guessing a role
+from the heading hierarchy. User-facing defaults belong to the maintained
+Composition; advanced consumers may extend its POO slots.
+
+* Agent collaboration without ambient authority
+
+A role-scoped context contains the selected design node, relevant assumptions,
+alternatives, contrary material and evidence bounds. Organization Bundle
+identities and delegated visibility must be resolved before an Agent runs.
+No heading, TODO transition or =OWNER_ROLE= declaration spawns an Agent.
+
+An edit proposal binds the source digest, stable node ID, original source range
+and expected old content. The owner reviews the proposal before application.
+Any digest/content conflict requires re-query and review; never patch a stale
+offset. Preserve unrelated text, property drawers and comments through Orgize's
+source-owned representation. A new design revision reopens the affected
+obligations through existing Agentic AI Lab causal mechanisms, not a parallel graph.
+
+Design status, scoped evidence support, authorization and observed execution
+remain independent. Agent review cannot certify its own external guarantees.
+Historical cases may inspire a judgment; only qualified checks support a claim.
+
+#+begin_export mermaid
+flowchart TD
+ A["Org source
authored"] --> Q["Orgize projection
source-bound"]
+ Q --> R["Role-scoped review
proposed"]
+ R --> P["Edit proposal
owner review pending"]
+ P --> C{"Source still matches?"}
+ C -->|no| Q
+ C -->|yes, accepted| D["Design revision
obligations reopened"]
+ D --> V["Verification
scoped evidence pending"]
+ V --> G["Cedar / Runtime admission
effect authority pending"]
+ G --> E["Execution
receipt observed"]
+ E --> A
+#+end_export
+
+The diagram specifies intended interactions. The authoring/query checks below
+do not qualify this complete loop.
+
+* Package boundary audit — blocking direct installation
+
+At the first 2026-09-24 audit, the selected Orgize branch was
+=codex/scheme-rowan-org-cutover= at
+=4a94883bd47196a175a88f552410d59102f34d24=. Its Scheme definitions live under
+=languages/org/v1/=; =modules/org-elements/interface.ss= exports POO query
+objects and functions. The branch has no root =gerbil.pkg= or =build.ss=.
+Do not infer an installable Gerbil package from the presence of these sources.
+
+The fetched Orgize branch now includes consumer-owned Contract import
+generation at =5cc02a1c5f882a3b182461ce803b8c76c4772c36= and pins
+gerbil-parser to =ca01627c0c5ba1d460c0de83b060bc90d3b961e8=. That
+parser revision's Scheme =gerbil.pkg= still depends on Agentic AI Lab at
+=2ce55a9810f8559cc0f40a6c877a52ab7893c166=. In particular,
+=graph-projection-objects.ss= and =line-structure-objects.ss= use Agentic AI Lab's
+contract admission and object-family declarations. This is an actual source
+dependency, not just a stale manifest entry.
+
+Adding a source-package edge now would produce:
+
+#+begin_export mermaid
+flowchart LR
+ P["Agentic AI Lab"] -. "requested, not installed" .-> O["Orgize Scheme package
entrypoint missing"]
+ O -->|parser declarations| G["gerbil-parser"]
+ G -->|contracts and object families| P
+#+end_export
+
+The integration must first establish an acyclic build/runtime package boundary.
+Two options require review: separate generator dependencies from the delivered
+Org runtime package, or relocate genuinely generic shared foundations below
+both packages. Do not copy POO contracts into Orgize, silently delete parser
+dependencies, or maintain a second parser. This RFC does not authorize or claim
+completion of that cross-repository restructuring.
+
+This cycle concerns installing the Scheme source-package graph. It does not
+describe the existing Cargo runtime graph: committed Scheme-generated AOT
+artifacts are already consumed by Rust without a Gerbil runtime dependency.
+Do not block qualification of that existing consumer path on a hypothetical
+source-package installation, or conflate generator dependencies with delivery.
+
+After a reviewed boundary is qualified, pin the Orgize Scheme dependency in
+Agentic AI Lab, expose a public unversioned consumer interface, and verify a clean
+downstream install using only Agentic AI Lab. Qualification of the later Rust runtime
+is independent of this source-package gate. Internal grammar versions are not
+consumer namespace versions.
+
+** Source-package cycle cut and qualification order
+
+The requested Scheme source-package direction would be lower-level POO
+primitives → =gerbil-parser= → Orgize → Agentic AI Lab → Aitia. At the selected
+Orgize cut, =org-elements/types.ss= imports parser-owned graph projection
+objects. The parser has seven Scheme modules importing Agentic AI Lab. These imports
+are not merely incidental helpers: they use =AgenticAILabContract.= and
+=AgenticAILabNativeObjectContract.=, evidence-bearing validation and admission,
+=defpoo-object-family=, and the Agentic AI Lab debug trace. Replacing them with bare
+=clan/poo= would change semantics; moving or copying those facilities below
+Agentic AI Lab is not an approved mechanical refactor.
+
+| Parser source modules | Agentic AI Lab-owned dependency | Required observation to retain |
+|-----------------------+---------------------------+--------------------------------|
+| =types.ss=, =graph-projection-types.ss=, =line-structure-types.ss= | contract prototypes, classification and evidence admission | typed values and rejected candidates keep their current identities and failure semantics |
+| =objects.ss=, =graph-projection-objects.ss=, =line-structure-objects.ss= | object-family declaration and evidence-gated constructors | public POO prototypes, slots and constructor rejection remain unchanged |
+| =runtime/observability.ss= | debug trace policy and emission | disabled/enabled phase behavior and receipt shape remain unchanged |
+
+This is a source-level inventory, not a test receipt proving equivalence after
+a refactor. The exact consumer graph and all negative cases must be captured
+before moving ownership.
+
+These are distinct future engineering tracks, neither yet delivered:
+
+1. *Rust/Rowan runtime delivery (long-term target, not current Python work).* Keep
+ Orgize's Scheme declarations and generators in their current source/tooling
+ lane. Package the Scheme-generated Rust AOT consumer as an immutable,
+ independently consumable runtime. It may consume a qualified Scheme C ABI
+ where that is the right runtime boundary, or expose its own native Rust
+ library API; do not require an Orgize-Rust-owned C ABI merely to serve
+ Aitia Python. Orgize already exposes =parse_org_aot=, Element records,
+ source receipts, query and contract evaluation as Rust library APIs, but
+ this is not yet a C ABI, a Gerbil package, or an installed Agentic AI Lab
+ dependency. Agentic AI Lab owns the POO-native facade and admission; it must call
+ upstream semantics, not reimplement Org queries or contracts.
+ Pin generator and runtime revisions/digests together and qualify a clean
+ binary/runtime install. This can supply a durable Agentic AI Lab-owned runtime
+ dependency for downstreams, but it does *not* fulfill the separate request
+ that Orgize Scheme source be inherited through =gerbil.pkg=.
+2. *Scheme source-graph refactor (the stated package target).* Keep the desired
+ source-package inheritance only after resolving parser → Agentic AI Lab without
+ losing its contract/evidence, object-family and observability behavior.
+ An existing lower library may own genuinely generic mechanisms only if
+ authority and public observations move together; otherwise the dependency
+ direction must be redesigned. Do not fork these semantics, create a second
+ AST, or add compatibility forwarding simply to make installation pass.
+
+Qualify the stated Scheme package target in this order:
+
+1. Lock positive and negative observations for the seven parser imports,
+ including contract admission, object-family behavior and debug traces.
+2. Review the actual authority-preserving source-graph cut. Only after it is
+ accepted, remove parser → Agentic AI Lab and replay parser/compiler/runtime tests
+ from a clean dependency closure.
+3. Add Orgize's source-owned Gerbil package/build entrypoint and qualify its
+ Scheme Elements/Contract declarations and Rowan/AOT generation against
+ that parser revision.
+4. Pin Orgize once in Agentic AI Lab's =gerbil.pkg=, expose its POO-native unversioned
+ Org interface, and replay an Aitia workspace with Agentic AI Lab as its sole
+ direct Org dependency. Prove clean installation without ambient
+ =GERBIL_LOADPATH= or an old compiled module.
+
+When the later Rust runtime track begins, qualify exact generated
+pack/source/parser identity and stale-pack rejection first; then define an
+upstream-owned stable FFI with explicit ownership, errors and memory limits.
+A Rust =pub fn= or prebuilt executable alone is not that boundary. That runtime
+must not be relabeled as Scheme source-package closure. The existing =4a94883=
+Cargo/AOT checks remain independent evidence, not evidence that either
+package or FFI gate has closed. RFC 0005 stays draft until those gates pass.
+
+* Acceptance and evidence scope
+
+1. Authoring: upstream Rowan/CST tangling reads the native Org metadata and
+ tagged Scheme declarations. Scheme admission and AOT generation qualify the
+ six document and five decision-local assertions. No legacy CLI substitution.
+2. Query/evaluation: run those generated plans over the actual workspace and
+ negative fixtures. Missing content, a single alternative, content under
+ another decision and a receipt link in the wrong section must fail the
+ intended assertion. This checks structure, not evidence truth or authority.
+3. Package: clean, acyclic Orgize Scheme source → Agentic AI Lab inheritance;
+ downstreams declare only Agentic AI Lab. The later Rust/Rowan runtime has a
+ separate delivery gate. Both remain open, neither blocks the present
+ Python/Host admission work.
+4. Projection: POO-native identity/reference/role resolution plus negative
+ duplicate, missing-reference and unauthorized-visibility tests. Pending.
+5. Mutation: Aitia Python rejects moved spans, stale source digests and
+ overlapping proposals before owner review. Orgize PR #15 now has a
+ Scheme-AOT-graph-backed candidate source transformation that checks unique
+ node =:ID:= ownership, rejects wrong-node spans and preserves unrelated
+ bytes. The transport from Aitia Python to that API and reviewed persistence
+ are still pending; neither preflight nor a candidate is authorization.
+6. Lifecycle: an accepted edit reopens an actual obligation, a real tool runs
+ through existing admission, and its scoped receipt feeds a design review.
+ Pending; a TODO transition or successful lint is not this receipt.
+
+** Correction of the initial receipt — 2026-09-24
+
+The earlier authoring receipt used an installed CLI at
+=52d315155ebbba917f0694068444d3bbde5f9920=, not the selected Scheme/Rowan
+consumer path. Its six passing assertions and task queries do not qualify
+this integration. The later cross-decision negative tests on that old path
+also failed. Neither result establishes behavior of the new Scheme modules.
+The legacy CLI recipe and its Python qualification test have been withdrawn;
+the contract source now uses upstream Scheme declarations.
+
+The earlier fetch/rebase confirmed that =codex/scheme-rowan-org-cutover= and
+its remote were both at =4a94883bd47196a175a88f552410d59102f34d24= at
+that time. The mistake was the
+consumer path, not an unrebased HEAD. New evidence must identify the source
+revision, generated artifact and actual consumer entrypoint separately.
+
+** Correct-path bounded receipt — 2026-09-24
+
+At the fetched/rebased =4a94883= revision, the following upstream checks passed
+using locked, offline Cargo dependencies and two build workers:
+
+| Check | Result | Scope |
+|-------+--------+-------|
+| =integration_test org_parser_aot= | 21 passed | Scheme-generated parser, Rowan graph and existing generated contract execution |
+| =integration_test org_element_query= | 3 passed | generated queries, consumer pack, scope and fail-closed checks |
+| =--example org_contract_tangle= | 5 passed | Scheme block extraction, metadata and ancestry rejection |
+| =--example org_elements_tangle= | 5 passed | Scheme query extraction and existing consumer source/artifact consistency |
+| Upstream =org_contract_tangle= on Aitia's registry | 2 definitions / 11 assertions extracted | actual Org CST to Scheme source, not Scheme admission or AOT execution |
+
+The first build selected Nix's =cc= and failed to link =iconv=. Retrying with
+process-local =CC=/usr/bin/cc= and
+=CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER=/usr/bin/cc= passed; no global
+environment or toolchain configuration was changed. Commands also unset
+=SDKROOT= for that process and set =CARGO_BUILD_JOBS= to 2.
+
+At that earlier cut, the extracted Aitia source was temporary and had not
+been compiled/evaluated: the extractor emitted upstream-relative interface
+imports. Consumer-owned module location, Scheme admission, AOT generation and
+cross-decision negatives were still required. The 34 upstream passes did not
+constitute Aitia end-to-end completion.
+
+** Consumer-owned Scheme source and AOT plan slice — 2026-09-24
+
+At the later fetched Orgize =5cc02a1= cut, =org_contract_tangle= accepts an
+optional Contract and Element interface pair. The default output remains
+byte-for-byte equal to upstream's committed generated Scheme file. Six
+generator tests pass, including empty-interface rejection and consumer-owned
+imports. Running that generator on Aitia's actual
+=engineering-workspace.org= yielded two definitions and eleven assertions.
+Gerbil then constructed these declarations and the upstream Scheme AOT
+generator emitted a plan with the current Org graph projection digest
+=sha256:f26d350a0456114b37a9af347b5b4694a9eff8dd787df988296814f1a60f29a8=.
+
+This is a bounded source/plan result, not actual Aitia workspace evaluation.
+The isolated invocation still emitted a Agentic AI Lab observability warning from
+mixed local Gerbil objects. A clean package closure and consumer-side Rust
+evaluation with cross-decision negatives remain unqualified. The direct
+Orgize source-package cycle described above is unchanged; do not promote the
+generated plan or this warning-bearing local check to a published interface.
+
+** Source-owned mutation implementation on Orgize PR #15 — 2026-09-24
+
+[[https://github.com/tao3k/orgize/pull/15][Orgize PR #15]] now includes commit =54de4fe=, which adds
+=org_aot_edit::apply_org_source_edits=. It consumes the Scheme-AOT Element
+graph, validates exact source digest, unique headline =:ID:=, UTF-8 byte
+range, expected old text and non-overlap, then reparses the candidate source.
+It does not call the old =Org::replace_range= path or write a file. Local
+integration tests passed 367/367 with two ignored; focused mutation tests
+passed 4/4, and strict Clippy plus formatting passed. This closes the
+Orgize-owned candidate transformation, not Aitia's transport or an
+owner-approved persistent edit. The PR itself remains draft for the broader
+parser cutover and dependency gates.
diff --git a/gerbil.pkg b/gerbil.pkg
index d69b502..95cee32 100644
--- a/gerbil.pkg
+++ b/gerbil.pkg
@@ -4,4 +4,4 @@
;;; Native contributor package identity. Importing the package does not run
;;; verification, authorize release, or execute an effect.
-(package: poo-flow/lambda-aitia)
+(package: agentic-ai-lab/lambda-aitia)
diff --git a/justfile b/justfile
index 81c7d0e..4f2777a 100644
--- a/justfile
+++ b/justfile
@@ -10,7 +10,8 @@ self_root := justfile_directory()
export GERBIL_PATH := env_var_or_default("GERBIL_PATH", self_root + "/.gerbil")
export GERBIL_LOADPATH := env_var_or_default("GERBIL_LOADPATH", self_root + ":" + GERBIL_PATH + "/lib")
native_root := GERBIL_PATH + "/native"
-native_library := native_root + "/libpoo_flow_aitia.dylib"
+native_library := native_root + "/libagentic_ai_lab_aitia.dylib"
+python_native_dir := self_root + "/bindings/python/src/lambda_aitia/_native"
gerbil_env := if os() == "macos" { "env -u SDKROOT" } else { "env" }
export UV_CACHE_DIR := env_var_or_default("UV_CACHE_DIR", self_root + "/.cache/uv")
darwin_cc := if os() == "macos" { "/usr/bin/cc" } else { "cc" }
@@ -22,7 +23,7 @@ export MACOSX_DEPLOYMENT_TARGET := env_var_or_default("MACOSX_DEPLOYMENT_TARGET"
default:
@just --list
-# Build this Gerbil package against the installed POO Flow mechanisms.
+# Build this Gerbil package against the installed Agentic AI Lab mechanisms.
[group('build')]
build-scheme:
GERBIL_BUILD_VERBOSE=1 {{ gerbil_env }} gerbil build
@@ -59,10 +60,53 @@ check-semantic:
just test-scheme gitops
just test-scheme modules
-# Build the Aitia-owned assurance laws independently of POO Flow's proof package.
+# Build the Aitia-owned assurance laws independently of Agentic AI Lab's proof package.
[group('check')]
check-proof:
- cd proof/lean && lake build LambdaAitiaModuleAssuranceProof
+ cd proof/lean && lake build LambdaAitiaModuleAssuranceProof LambdaAitiaModuleSdlcProof
+ cd proof/lean && output="$(lake env lean AxiomAudit.lean)" && printf '%s\n' "$output" && ! grep -q 'sorryAx' <<< "$output"
+
+# Quint 0.33.0 and its Apalache 0.62.1 TLC backend are explicit inputs.
+# The checker exhausts each bounded model and requires negative-control traces.
+[group('check')]
+check-quint module='all':
+ python3 proof/quint/check_contract.py '{{module}}'
+
+# Pinned Quint MBT traces, native Scheme execution, and explicit fault refusals.
+[group('check')]
+check-quint-scheme:
+ python3 proof/quint/check_scheme_replay.py
+
+# Complete reachable lifecycle states, named actions, and fault refusals.
+[group('check')]
+check-lifecycle-scheme: build-scheme
+ python3 proof/quint/test_lifecycle_replay.py
+ python3 proof/quint/check_lifecycle_replay.py
+
+# Every gate must run; none substitutes for semantic implementation refinement.
+[group('check')]
+check-formal:
+ just test-scheme-atomic formal retirement-binding-test.ss
+ just test-scheme-atomic formal retirement-execution-test.ss
+ just check-quint-scheme
+ just check-lifecycle-scheme
+ just check-quint
+ just check-proof
+
+# Refresh the in-place Python extension without rebuilding Agentic AI Lab.
+[group('dev')]
+dev-python:
+ test -f '{{ GERBIL_PATH }}/pkg/github.com/tao3k/orgize/bindings/c/include/orgize.h' || { echo 'Orgize C header missing from GERBIL_PATH; install the declared Agentic AI Lab Gerbil dependencies first' >&2; exit 1; }
+ just clean-python-cffi
+ cd bindings/python && {{ gerbil_env }} uv sync --locked --extra test
+ cd bindings/python && {{ gerbil_env }} uv run --locked --extra test python src/lambda_aitia/_native/_build.py
+ cd bindings/python && {{ gerbil_env }} uv run --locked --extra test python -c 'from lambda_aitia._native._aitia_cffi import ffi; ffi.typeof("orgize_element_row"); print("aitia-cffi-current")'
+
+# Remove only generated CFFI artifacts, not Python sources or the uv venv.
+[group('clean')]
+clean-python-cffi:
+ find '{{ python_native_dir }}' -maxdepth 1 -type f -name '_aitia_cffi.*' -delete
+ if test -d '{{ python_native_dir }}/_build_temp'; then find '{{ python_native_dir }}/_build_temp' -depth -delete; fi
# Aitia owns its native ABI and Python Runtime checks.
[group('check')]
@@ -77,9 +121,16 @@ check-native:
'{{ native_root }}/aitia_dynamic_harness' '{{ native_library }}'
just test-scheme bindings
cd bindings/python && {{ gerbil_env }} uv lock --check
+ just clean-python-cffi
cd bindings/python && {{ gerbil_env }} uv run --locked --extra test python src/lambda_aitia/_native/_build.py
cd bindings/python && LAMBDA_AITIA_NATIVE_LIBRARY='{{ native_library }}' {{ gerbil_env }} uv run --locked --extra test pytest
just build-python-wheel '{{ native_library }}'
+ just check-installed-wheel
+
+# Exercise the delivered wheel from a fresh environment outside the checkout.
+[group('check')]
+check-installed-wheel:
+ cd bindings/python && {{ gerbil_env }} uv run --locked --extra test pytest tests/installed_wheel_qualification.py
# Build the production wheel from Aitia's locked uv environment. The preceding
# sync makes the declared PEP 517 backend available without a second isolated
@@ -87,12 +138,12 @@ check-native:
[group('build')]
build-python-wheel native_library:
test -f '{{ native_library }}'
- cd bindings/python && LAMBDA_AITIA_NATIVE_LIBRARY='{{ native_library }}' env -u SDKROOT uv sync --locked --extra test
- cd bindings/python && LAMBDA_AITIA_NATIVE_LIBRARY='{{ native_library }}' env -u SDKROOT uv build --wheel --offline --no-build-isolation
+ cd bindings/python && LAMBDA_AITIA_NATIVE_LIBRARY='{{ native_library }}' {{ gerbil_env }} uv sync --locked --extra test
+ cd bindings/python && LAMBDA_AITIA_NATIVE_LIBRARY='{{ native_library }}' {{ gerbil_env }} uv build --wheel --offline --no-build-isolation
# Current repository closure. No recipe grants runtime authority.
[group('check')]
-check: check-license-contract check-semantic check-proof test-integration check-native
+check: check-license-contract check-semantic check-proof check-quint test-integration check-native
[group('check')]
check-all: check
diff --git a/modules/ADR/config.ss b/modules/ADR/config.ss
index c4d5244..3d1ae31 100644
--- a/modules/ADR/config.ss
+++ b/modules/ADR/config.ss
@@ -3,15 +3,15 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/src/module-system/declaration/interface
- :poo-flow/lambda-aitia/modules/ADR/funs)
+(import :yuanxu/module-system/selection/objects
+ :agentic-ai-lab/lambda-aitia/modules/ADR/funs)
(export ADR-config)
(def (ADR-config selection)
- (unless (and (poo-flow-user-module-selection? selection)
- (equal? (poo-flow-user-module-selection-key selection)
+ (unless (and (agentic-ai-lab-user-module-selection? selection)
+ (equal? (agentic-ai-lab-user-module-selection-key selection)
'(custom . ADR))
- (null? (poo-flow-user-module-selection-flags selection)))
+ (null? (agentic-ai-lab-user-module-selection-flags selection)))
(error "invalid ADR module selection"))
ADR-module)
diff --git a/modules/ADR/funs.ss b/modules/ADR/funs.ss
index 55bbb17..b5b3d19 100644
--- a/modules/ADR/funs.ss
+++ b/modules/ADR/funs.ss
@@ -4,13 +4,13 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :clan/poo/object .ref)
- (only-in :poo-flow/src/modules/governance/funs
- poo-flow-governance-contribution)
- :poo-flow/lambda-aitia/modules/ADR/types
- :poo-flow/lambda-aitia/modules/ADR/objects
- (only-in :poo-flow/lambda-aitia/modules/assurance/objects
+ (only-in :agentic-ai-lab/modules/governance/funs
+ agentic-ai-lab-governance-contribution)
+ :agentic-ai-lab/lambda-aitia/modules/ADR/types
+ :agentic-ai-lab/lambda-aitia/modules/ADR/objects
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/objects
assurance-decision)
- (only-in :poo-flow/lambda-aitia/modules/assurance/funs
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/funs
assurance-canonical-digest))
(export ADR-contribution ADR-module
@@ -19,7 +19,7 @@
(def (ADR-contribution profile)
(unless (ADR-profile? profile) (error "invalid ADR profile"))
- (poo-flow-governance-contribution
+ (agentic-ai-lab-governance-contribution
profile '(knowledge-governance) '()))
(def ADR-module (ADR-contribution ADRProfile))
diff --git a/modules/ADR/interface.ss b/modules/ADR/interface.ss
index baf11f2..05efcf3 100644
--- a/modules/ADR/interface.ss
+++ b/modules/ADR/interface.ss
@@ -3,11 +3,11 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/ADR/types)
-(export (import: :poo-flow/lambda-aitia/modules/ADR/types))
-(import :poo-flow/lambda-aitia/modules/ADR/objects)
-(export (import: :poo-flow/lambda-aitia/modules/ADR/objects))
-(import :poo-flow/lambda-aitia/modules/ADR/funs)
-(export (import: :poo-flow/lambda-aitia/modules/ADR/funs))
-(import :poo-flow/lambda-aitia/modules/ADR/config)
-(export (import: :poo-flow/lambda-aitia/modules/ADR/config))
+(import :agentic-ai-lab/lambda-aitia/modules/ADR/types)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/ADR/types))
+(import :agentic-ai-lab/lambda-aitia/modules/ADR/objects)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/ADR/objects))
+(import :agentic-ai-lab/lambda-aitia/modules/ADR/funs)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/ADR/funs))
+(import :agentic-ai-lab/lambda-aitia/modules/ADR/config)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/ADR/config))
diff --git a/modules/ADR/objects.ss b/modules/ADR/objects.ss
index 8769ec3..dab8ec0 100644
--- a/modules/ADR/objects.ss
+++ b/modules/ADR/objects.ss
@@ -4,16 +4,16 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :clan/poo/object .o)
- :poo-flow/src/module-system/contribution/model
- (only-in :poo-flow/src/modules/governance/objects
- PooFlowGovernanceProfile.
- poo-flow-governance-source)
- :poo-flow/lambda-aitia/modules/ADR/types)
+ :agentic-ai-lab/core/poo-clos/interface
+ (only-in :agentic-ai-lab/modules/governance/objects
+ AgenticAILabGovernanceProfile.
+ agentic-ai-lab-governance-source)
+ :agentic-ai-lab/lambda-aitia/modules/ADR/types)
(export ADRProfile ADR-link ADR-option ADR-consequence ADR-record)
(def ADRProfile
- (.o (:: @ PooFlowGovernanceProfile.) identity: "lambda-aitia/ADR"
+ (.o (:: @ AgenticAILabGovernanceProfile.) identity: "lambda-aitia/ADR"
revision: "1" owner: "lambda-aitia"
module-family: 'ADR
ontology: (.o decision-label: 'Decision reference-edge: 'REFERENCES
@@ -27,29 +27,29 @@
authority: (.o accepted-is-authority?: #f
effect-authorization: 'separate-receipt))
source-assets:
- (list (poo-flow-governance-source
+ (list (agentic-ai-lab-governance-source
"ADR/expired-reference-witnesses"
"modules/ADR/expired-references.gql" 'gql))))
(def (ADR-link relation-value target-value)
- (poo-flow-check-model
+ (poo-clos-check-model
ADRLink
- (.o (:: @ (poo-flow-model-prototype ADRLink))
+ (.o (:: @ (poo-clos-model-prototype ADRLink))
relation: relation-value target: target-value)))
(def (ADR-option identity-value title-value description-value
disposition-value pros-value cons-value)
- (poo-flow-check-model
+ (poo-clos-check-model
ADROption
- (.o (:: @ (poo-flow-model-prototype ADROption))
+ (.o (:: @ (poo-clos-model-prototype ADROption))
identity: identity-value title: title-value
description: description-value disposition: disposition-value
pros: pros-value cons: cons-value)))
(def (ADR-consequence sentiment-value statement-value)
- (poo-flow-check-model
+ (poo-clos-check-model
ADRConsequence
- (.o (:: @ (poo-flow-model-prototype ADRConsequence))
+ (.o (:: @ (poo-clos-model-prototype ADRConsequence))
sentiment: sentiment-value statement: statement-value)))
(def (ADR-record identity-value title-value status-value date-value
@@ -58,9 +58,9 @@
confirmation-value decision-makers-value consulted-value
informed-value links-value)
(let ((record
- (poo-flow-check-model
+ (poo-clos-check-model
ADRRecord
- (.o (:: @ (poo-flow-model-prototype ADRRecord))
+ (.o (:: @ (poo-clos-model-prototype ADRRecord))
identity: identity-value title: title-value status: status-value
date: date-value revision: revision-value context: context-value
decision: decision-value decision-drivers: drivers-value
diff --git a/modules/ADR/types.ss b/modules/ADR/types.ss
index 7e94194..09cbd43 100644
--- a/modules/ADR/types.ss
+++ b/modules/ADR/types.ss
@@ -5,9 +5,9 @@
(import (only-in :clan/poo/object .ref .slot?)
:std/list/list
- :poo-flow/src/module-system/contribution/model
- (only-in :poo-flow/src/modules/governance/types
- poo-flow-governance-profile?))
+ :agentic-ai-lab/core/poo-clos/interface
+ (only-in :agentic-ai-lab/modules/governance/types
+ agentic-ai-lab-governance-profile?))
(export ADR-profile?
ADR-text? ADR-date? ADR-status? ADR-link-relation?
@@ -95,10 +95,10 @@
(predicate-slot 'informed ADR-text-list?)
(predicate-slot 'links ADR-link-list?))))
-(def (ADR-link? value) (poo-flow-model? ADRLink value))
-(def (ADR-option? value) (poo-flow-model? ADROption value))
-(def (ADR-consequence? value) (poo-flow-model? ADRConsequence value))
-(def (ADR-record? value) (poo-flow-model? ADRRecord value))
+(def (ADR-link? value) (poo-clos-model? ADRLink value))
+(def (ADR-option? value) (poo-clos-model? ADROption value))
+(def (ADR-consequence? value) (poo-clos-model? ADRConsequence value))
+(def (ADR-record? value) (poo-clos-model? ADRRecord value))
(def (unique-by? projection input-values)
(length=? input-values
@@ -145,6 +145,6 @@
(else #f)))))
(def (ADR-profile? value)
- (and (poo-flow-governance-profile? value)
+ (and (agentic-ai-lab-governance-profile? value)
(.slot? value 'module-family)
(eq? (.ref value 'module-family) 'ADR)))
diff --git a/modules/assurance/config.ss b/modules/assurance/config.ss
index b9e2d69..06ff844 100644
--- a/modules/assurance/config.ss
+++ b/modules/assurance/config.ss
@@ -4,9 +4,12 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :clan/poo/object .o)
- :poo-flow/lambda-aitia/modules/assurance/types)
+ (only-in :gerbil/core list-sort)
+ :std/list/list
+ :agentic-ai-lab/core/poo-clos/interface
+ :agentic-ai-lab/lambda-aitia/modules/assurance/types)
-(export AssurancePolicy)
+(export AssurancePolicy assurance-verification-policy)
;;; Pure declared defaults. This value invokes no verifier and grants no
;;; authority.
@@ -18,3 +21,18 @@
conflict-resolution: 'explicit
planner-executes?: #f
grants-authority?: #f))
+
+(def (capability left right)
+ (string (symbol->string left) (symbol->string right)))
+
+;;; Capabilities describe available adapters; this value cannot invoke one.
+(def (assurance-verification-policy identity-value revision-value capability-values)
+ (unless (and (list? capability-values) (every symbol? capability-values))
+ (error "verification policy capabilities must be symbols" capability-values))
+ (poo-clos-check-model
+ AssuranceVerificationPolicy
+ (.o (:: @ (poo-clos-model-prototype AssuranceVerificationPolicy))
+ identity: identity-value revision: revision-value
+ capabilities:
+ (list-sort capability (delete-duplicates/hash capability-values))
+ planner-executes?: #f grants-authority?: #f)))
diff --git a/modules/assurance/effect-host.ss b/modules/assurance/effect-host.ss
new file mode 100644
index 0000000..c67a297
--- /dev/null
+++ b/modules/assurance/effect-host.ss
@@ -0,0 +1,144 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Local serialized integration boundary, not a Cedar evaluator or distributed
+;;; Runtime Host. Only configured runtime operations evaluate policy / deliver.
+;;; Editable preflights, requests, tokens and reports never issue capabilities.
+(import (only-in :clan/poo/object .o .ref)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/host
+ :agentic-ai-lab/modules/governance/policy/authorized-effect-token
+ (only-in :agentic-ai-lab/modules/authorization/providers/cedar/decision
+ agentic-ai-lab-cedar-decision-permit?
+ agentic-ai-lab-cedar-decision->semantic-root
+ agentic-ai-lab-cedar-decision->authorized-effect-token))
+(export assurance-effect-host assurance-effect-host-epoch
+ assurance-effect-host-authorize! assurance-effect-host-grant-current?
+ assurance-effect-host-reserve! assurance-effect-host-deliver!
+ assurance-effect-host-revoke!)
+
+(def hosts (make-hash-table-eq weak-keys: #t))
+(def grants (make-hash-table-eq weak-keys: #t))
+(def reservations (make-hash-table-eq weak-keys: #t))
+
+(def (entry host)
+ (let (state (hash-get hosts host))
+ (unless (and state (eq? (vector-ref state 0) (current-thread)))
+ (error "effect Host requires its exact serialized owner"))
+ (when (vector-ref state 7) (error "effect Host mutation during runtime handoff"))
+ state))
+(def (instant state)
+ (let (now ((vector-ref state 3)))
+ (unless (and (exact-integer? now) (>= now (vector-ref state 8)))
+ (error "effect Host clock must be monotonic and nonnegative"))
+ (vector-set! state 8 now)
+ now))
+(def (handoff state operation)
+ (dynamic-wind
+ (lambda () (vector-set! state 7 #t))
+ operation
+ (lambda () (vector-set! state 7 #f))))
+
+;;; Runtime authorize: Request -> CedarDecision or #f (deny/indeterminate).
+;;; Runtime deliver: Request Token -> delivered / failed / indeterminate.
+;;; 'delivered is an attributable acknowledgement, not inferred from start.
+(def (assurance-effect-host authorize deliver clock lease)
+ (unless (and (procedure? authorize) (procedure? deliver) (procedure? clock)
+ (exact-integer? lease) (> lease 0))
+ (error "invalid effect Host runtime configuration"))
+ (let (host (.o kind: 'aitia.effect-host.v1))
+ (hash-put! hosts host (vector (current-thread) authorize deliver clock lease 0 0 #f 0))
+ host))
+(def (assurance-effect-host-epoch host) (vector-ref (entry host) 5))
+(def (assurance-effect-host-revoke! host)
+ (let (state (entry host))
+ (vector-set! state 5 (+ 1 (vector-ref state 5)))))
+
+(def (grant-entry host grant)
+ (let (issued (hash-get grants grant))
+ (and issued (eq? host (vector-ref issued 0))
+ (equal? (.ref grant 'expires-at) (vector-ref issued 5))
+ (equal? (.ref grant 'epoch) (vector-ref issued 4))
+ (equal? (agentic-ai-lab-authorized-effect-token-digest (.ref grant 'token))
+ (vector-ref issued 6)) issued)))
+(def (current? state issued)
+ (and issued
+ (= (vector-ref state 5) (vector-ref issued 4))
+ (< (instant state) (vector-ref issued 5))
+ (assurance-host-cedar-request-current? (vector-ref issued 1) (vector-ref issued 2))
+ ;; Source validation may take time. Apply strict expiry to the same
+ ;; final instant passed to the token validator, whose endpoint is
+ ;; otherwise inclusive; an earlier clock sample must not authorize use.
+ (let (now (instant state))
+ (and (< now (vector-ref issued 5))
+ (.ref (agentic-ai-lab-authorized-effect-token-validate
+ (vector-ref issued 3)
+ (agentic-ai-lab-token-validation-context
+ (.ref (vector-ref issued 3) 'semantic-root)
+ (.ref (vector-ref issued 3) 'binding)
+ now (vector-ref state 5) '())) 'accepted?)))))
+(def (assurance-effect-host-grant-current? host grant)
+ (let (state (entry host))
+ (and (current? state (grant-entry host grant)) #t)))
+
+(def (assurance-effect-host-authorize! host verification-host request)
+ (let* ((state (entry host)) (now (instant state)) (epoch (vector-ref state 5)))
+ (and (assurance-host-cedar-request-current? verification-host request)
+ (let (decision (handoff state (lambda () ((vector-ref state 1) request))))
+ (and decision (agentic-ai-lab-cedar-decision-permit? decision)
+ (= epoch (vector-ref state 5))
+ (< (instant state) (+ now (vector-ref state 4)))
+ (assurance-host-cedar-request-current? verification-host request)
+ (let* ((next (+ 1 (vector-ref state 6)))
+ (context (.ref request 'context))
+ (bundle (.ref context 'aitia_snapshot_semantic_digest))
+ (intent (.ref request 'intent))
+ (root (agentic-ai-lab-cedar-decision->semantic-root decision bundle intent))
+ (binding
+ (agentic-ai-lab-effect-binding
+ bundle epoch (.ref decision 'policy-digest) (.ref decision 'entity-digest)
+ (.ref decision 'decision-digest) intent next (.ref request 'action)
+ 'configured-runtime 'local 1 1 'local 0 0 1 intent 'local))
+ (until (+ now (vector-ref state 4)))
+ (token (agentic-ai-lab-cedar-decision->authorized-effect-token
+ decision next next root binding
+ (agentic-ai-lab-token-validity now now until epoch)
+ 'strict 1 'configured-runtime "local-adapter"))
+ (grant (let ((token-value token) (epoch-value epoch))
+ (.o kind: 'aitia.effect-grant.v1 token: token-value epoch: epoch-value expires-at: until))))
+ (vector-set! state 6 next)
+ (hash-put! grants grant
+ (vector host verification-host request token epoch until
+ (agentic-ai-lab-authorized-effect-token-digest token) #f))
+ grant))))))
+
+;;; Reservation consumes the grant once, but executes no external effect.
+(def (assurance-effect-host-reserve! host grant)
+ (let* ((state (entry host)) (issued (grant-entry host grant)))
+ (and (current? state issued) (not (vector-ref issued 7))
+ (let (reservation (.o kind: 'aitia.effect-reservation.v1))
+ (vector-set! issued 7 #t)
+ (hash-put! reservations reservation (vector host grant issued #f))
+ reservation))))
+
+(def (delivery-receipt outcome-value invoked?)
+ (.o kind: 'aitia.effect-delivery.v1 outcome: outcome-value handoff-executed?: invoked?
+ delivered?: (eq? outcome-value 'delivered) durable?: #f distributed-authority?: #f))
+(def (assurance-effect-host-deliver! host reservation)
+ (let* ((state (entry host)) (issued (hash-get reservations reservation)))
+ (cond
+ ((or (not issued) (not (eq? host (vector-ref issued 0))) (vector-ref issued 3))
+ (delivery-receipt 'rejected #f))
+ (else
+ ;; Consume even on rejection / exception / unknown acknowledgement.
+ (vector-set! issued 3 #t)
+ (let (grant-state (vector-ref issued 2))
+ (if (and (grant-entry host (vector-ref issued 1)) (current? state grant-state))
+ (let (outcome
+ (handoff state
+ (lambda () ((vector-ref state 2) (vector-ref grant-state 2)
+ (vector-ref grant-state 3)))))
+ (unless (memq outcome '(delivered failed indeterminate))
+ (error "runtime delivery returned an invalid acknowledgement" outcome))
+ (delivery-receipt outcome #t))
+ (delivery-receipt 'rejected #f)))))))
diff --git a/modules/assurance/evidence-admission.ss b/modules/assurance/evidence-admission.ss
new file mode 100644
index 0000000..80fdf67
--- /dev/null
+++ b/modules/assurance/evidence-admission.ss
@@ -0,0 +1,291 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Pure eligibility and sealed support checks. The Host still owns adapter
+;;; identity, execution attestation and the transition to admitted evidence.
+(import (only-in :clan/poo/object .o .ref)
+ (only-in :gerbil/core list-sort)
+ (only-in :std/list/list find every)
+ :agentic-ai-lab/core/poo-clos/interface
+ (only-in :agentic-ai-lab/core/contribution/verification
+ agentic-ai-lab-verification-valid?)
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/funs
+ assurance-canonical-digest assurance-node-canonical
+ assurance-relation-canonical)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/types)
+
+(export assurance-verifier-input assurance-verifier-outcome
+ assurance-evaluate-evidence-admission
+ assurance-evidence-outcome-bound?
+ assurance-verification-subject
+ assurance-snapshot-semantic-digest
+ assurance-verification-subject-snapshot
+ assurance-candidate-support-structural?
+ assurance-support-sealed-under-adapter?)
+
+(def (assurance-verifier-input artifact)
+ (unless (assurance-artifact? artifact)
+ (error "verifier input requires an artifact"))
+ (poo-clos-check-model
+ AssuranceVerifierInput
+ (.o (:: @ (poo-clos-model-prototype AssuranceVerifierInput))
+ identity: (.ref artifact 'identity)
+ revision: (.ref artifact 'revision)
+ digest: (.ref artifact 'content-digest))))
+
+(def (assurance-verifier-outcome identity-value status-value
+ producer: producer-value tool: tool-value
+ tool-version: tool-version-value
+ obligation: obligation-value
+ subject: subject-value scope: scope-value
+ snapshot-revision: snapshot-revision-value
+ snapshot-context-digest: context-value
+ inputs: input-values
+ output-digest: (output-value #f)
+ accountable-authority: (authority-value #f)
+ review-scope: (review-scope-value #f))
+ (poo-clos-check-model
+ AssuranceVerifierOutcome
+ (.o (:: @ (poo-clos-model-prototype AssuranceVerifierOutcome))
+ identity: identity-value status: status-value
+ producer: producer-value tool: tool-value
+ tool-version: tool-version-value
+ obligation: obligation-value subject: subject-value scope: scope-value
+ snapshot-revision: snapshot-revision-value
+ snapshot-context-digest: context-value inputs: input-values
+ output-digest: output-value accountable-authority: authority-value
+ review-scope: review-scope-value)))
+
+(def (snapshot-node snapshot identity)
+ (find (lambda (node) (string=? (.ref node 'identity) identity))
+ (.ref snapshot 'nodes)))
+(def (current-input? snapshot input)
+ (let ((artifact (snapshot-node snapshot (.ref input 'identity))))
+ (and artifact (assurance-artifact? artifact)
+ (string=? (.ref input 'revision) (.ref artifact 'revision))
+ (string=? (.ref input 'digest) (.ref artifact 'content-digest)))))
+(def (duplicate-inputs? inputs)
+ (let loop ((rest inputs) (seen '()))
+ (and (pair? rest)
+ (let ((identity (.ref (car rest) 'identity)))
+ (or (member identity seen)
+ (loop (cdr rest) (cons identity seen)))))))
+
+(def (outcome-canonical reported-result)
+ (list (.ref reported-result 'identity) (.ref reported-result 'status)
+ (.ref reported-result 'producer) (.ref reported-result 'tool)
+ (.ref reported-result 'tool-version)
+ (.ref reported-result 'obligation) (.ref reported-result 'subject)
+ (.ref reported-result 'scope)
+ (.ref reported-result 'snapshot-revision)
+ (.ref reported-result 'snapshot-context-digest)
+ (map (lambda (input)
+ (list (.ref input 'identity) (.ref input 'revision)
+ (.ref input 'digest)))
+ (.ref reported-result 'inputs))
+ (.ref reported-result 'output-digest)
+ (.ref reported-result 'accountable-authority)
+ (.ref reported-result 'review-scope)))
+
+(def (assurance-verification-subject snapshot-value obligation-value
+ evidence-value outcome-value)
+ (poo-clos-check-model
+ AssuranceVerificationSubject
+ (.o (:: @ (poo-clos-model-prototype AssuranceVerificationSubject))
+ snapshot: snapshot-value obligation: obligation-value
+ evidence: evidence-value outcome: outcome-value)))
+
+(def (snapshot-semantic-fields snapshot-value)
+ (list (.ref snapshot-value 'identity)
+ (.ref snapshot-value 'revision)
+ (.ref snapshot-value 'graph-identity)
+ (.ref snapshot-value 'source-revisions)
+ (.ref snapshot-value 'claim-revisions)
+ (.ref snapshot-value 'fact-cut)
+ (.ref snapshot-value 'policy-identity)
+ (.ref snapshot-value 'policy-revision)
+ (.ref snapshot-value 'evidence-identities)
+ (.ref snapshot-value 'state)
+ (.ref snapshot-value 'context-digest)
+ (.ref snapshot-value 'digest)
+ (map assurance-node-canonical (.ref snapshot-value 'nodes))
+ (map assurance-relation-canonical
+ (.ref snapshot-value 'relations))
+ (.ref snapshot-value 'unresolved)
+ (.ref snapshot-value 'conflicts)))
+
+;;; Use the entire semantic snapshot, not its editable displayed digest slot,
+;;; when the Host detects a change and advances its invalidation epoch.
+(def (assurance-snapshot-semantic-digest snapshot-value)
+ (unless (assurance-snapshot? snapshot-value)
+ (error "invalid assurance snapshot"))
+ (assurance-canonical-digest
+ (cons 'lambda-aitia.snapshot-semantic
+ (snapshot-semantic-fields snapshot-value))))
+
+;;; Agentic AI Lab's adapter freezes this string before and after its host-trusted
+;;; operation. Recompute from every semantic field: mutating only a displayed
+;;; snapshot digest must not preserve an issued seal.
+(def (assurance-verification-subject-snapshot subject-value)
+ (unless (assurance-verification-subject? subject-value)
+ (error "invalid assurance verification subject"))
+ (assurance-canonical-digest
+ (append
+ (cons 'lambda-aitia.verification-subject
+ (snapshot-semantic-fields (.ref subject-value 'snapshot)))
+ (list (assurance-node-canonical (.ref subject-value 'obligation))
+ (assurance-node-canonical (.ref subject-value 'evidence))
+ (outcome-canonical (.ref subject-value 'outcome))))))
+
+(def (snapshot-relation snapshot-value identity-value)
+ (find (lambda (relation)
+ (string=? (.ref relation 'identity) identity-value))
+ (.ref snapshot-value 'relations)))
+(def (same-text-inventory? left right)
+ (and (= (length left) (length right))
+ (equal? (list-sort string left) (list-sort string right))))
+
+(def (assurance-evidence-outcome-bound? snapshot evidence outcome)
+ (and (assurance-snapshot? snapshot)
+ (assurance-evidence? evidence)
+ (assurance-verifier-outcome? outcome)
+ (let (current-evidence
+ (snapshot-node snapshot (.ref evidence 'identity)))
+ (and current-evidence (assurance-evidence? current-evidence)
+ (equal? (assurance-node-canonical current-evidence)
+ (assurance-node-canonical evidence))
+ (equal? (.ref evidence 'content-digest)
+ (.ref outcome 'output-digest))
+ (equal? (.ref evidence 'producer) (.ref outcome 'producer))
+ (equal? (.ref evidence 'tool) (.ref outcome 'tool))
+ (equal? (.ref evidence 'tool-version)
+ (.ref outcome 'tool-version))
+ (same-text-inventory?
+ (.ref evidence 'input-artifacts)
+ (map (lambda (input) (.ref input 'identity))
+ (.ref outcome 'inputs)))))))
+
+;;; Shape alone never grants support. This check is private to the sealed
+;;; admission boundary and cannot be used as a public authorization shortcut.
+(def (structural-support? relation evidence obligation admission-state)
+ (and (assurance-relation? relation)
+ (assurance-evidence? evidence)
+ (assurance-obligation? obligation)
+ (eq? (.ref relation 'plane) 'assurance)
+ (memq (.ref relation 'relation) '(supports discharges))
+ (equal? (.ref relation 'source) (.ref evidence 'identity))
+ (equal? (.ref relation 'target) (.ref obligation 'identity))
+ (equal? (.ref evidence 'obligation) (.ref obligation 'identity))
+ (equal? (.ref evidence 'subject) (.ref obligation 'subject))
+ (equal? (.ref evidence 'scope) (.ref obligation 'scope))
+ (equal? (.ref evidence 'revision) (.ref obligation 'revision))
+ (eq? (.ref evidence 'state) 'supported)
+ (eq? (.ref evidence 'admission-state) admission-state)
+ (not (memq (.ref relation 'modality) '(hypothesized counterfactual)))))
+
+;;; A relation is only a structural witness until a Host checks the separate
+;;; admission capability. The candidate state is never rewritten in the cut.
+(def (assurance-candidate-support-structural?
+ relation evidence obligation snapshot)
+ (and (structural-support? relation evidence obligation 'candidate)
+ (assurance-snapshot? snapshot)
+ (let (current
+ (snapshot-relation snapshot (.ref relation 'identity)))
+ (and current
+ (equal? (assurance-relation-canonical current)
+ (assurance-relation-canonical relation))))))
+
+;;; Conditional low-level check: this does not establish that the supplied
+;;; adapter and clock belong to the application-configured Host.
+(def (assurance-support-sealed-under-adapter?
+ relation evidence obligation snapshot outcome adapter issued-receipt now)
+ (and (structural-support? relation evidence obligation 'admitted)
+ (assurance-snapshot? snapshot)
+ (assurance-verifier-outcome? outcome)
+ (let ((current-relation
+ (snapshot-relation snapshot (.ref relation 'identity)))
+ (structural
+ (assurance-evaluate-evidence-admission
+ snapshot obligation outcome)))
+ (and (assurance-evidence-outcome-bound? snapshot evidence outcome)
+ current-relation
+ (equal? (assurance-relation-canonical current-relation)
+ (assurance-relation-canonical relation))
+ (.ref structural 'eligible?)
+ (agentic-ai-lab-verification-valid?
+ adapter issued-receipt
+ (assurance-verification-subject
+ snapshot obligation evidence outcome)
+ now)))))
+
+(def (assurance-evaluate-evidence-admission snapshot obligation outcome)
+ (unless (and (assurance-snapshot? snapshot)
+ (assurance-obligation? obligation)
+ (assurance-verifier-outcome? outcome))
+ (error "invalid evidence admission inputs"))
+ (let* ((reported-result outcome)
+ (required-obligation obligation)
+ (current-snapshot snapshot)
+ (inputs (.ref outcome 'inputs))
+ (current-obligation
+ (snapshot-node snapshot (.ref obligation 'identity)))
+ (admission-blocker
+ (cond
+ ((not (eq? (.ref outcome 'status) 'succeeded))
+ 'outcome-not-successful)
+ ((pair? (.ref snapshot 'conflicts)) 'snapshot-conflicted)
+ ((or (not current-obligation)
+ (not (assurance-obligation? current-obligation))
+ (not (equal? (assurance-node-canonical obligation)
+ (assurance-node-canonical current-obligation)))
+ (not (equal? (.ref obligation 'snapshot)
+ (.ref snapshot 'identity)))
+ (not (equal? (.ref obligation 'snapshot-revision)
+ (.ref snapshot 'revision)))
+ (not (equal? (.ref obligation 'snapshot-context-digest)
+ (.ref snapshot 'context-digest))))
+ 'stale-obligation)
+ ((or (not (equal? (.ref outcome 'obligation)
+ (.ref obligation 'identity)))
+ (not (equal? (.ref outcome 'subject)
+ (.ref obligation 'subject)))
+ (not (equal? (.ref outcome 'scope)
+ (.ref obligation 'scope)))
+ (not (equal? (.ref outcome 'snapshot-revision)
+ (.ref snapshot 'revision)))
+ (not (equal? (.ref outcome 'snapshot-context-digest)
+ (.ref snapshot 'context-digest))))
+ 'outcome-binding-mismatch)
+ ((not (.ref outcome 'output-digest)) 'missing-output)
+ ((null? inputs) 'missing-inputs)
+ ((duplicate-inputs? inputs) 'duplicate-inputs)
+ ((not (every (lambda (input) (current-input? snapshot input))
+ inputs))
+ 'input-binding-mismatch)
+ ((and (eq? (.ref obligation 'evidence-kind) 'human-review)
+ (or (not (.ref outcome 'accountable-authority))
+ (not (.ref outcome 'review-scope))
+ (not (equal? (.ref outcome 'review-scope)
+ (.ref obligation 'scope)))))
+ 'human-authority-missing)
+ (else #f)))
+ (reported-digest
+ (assurance-canonical-digest (outcome-canonical reported-result)))
+ (receipt-digest
+ (assurance-canonical-digest
+ (list 'lambda-aitia.evidence-admission
+ reported-digest (assurance-node-canonical required-obligation)
+ (.ref current-snapshot 'digest) admission-blocker))))
+ (poo-clos-check-model
+ AssuranceEvidenceAdmissionReceipt
+ (.o (:: @ (poo-clos-model-prototype AssuranceEvidenceAdmissionReceipt))
+ schema: "lambda-aitia.evidence-admission"
+ outcome: (.ref reported-result 'identity)
+ obligation: (.ref required-obligation 'identity)
+ outcome-digest: reported-digest
+ snapshot-digest: (.ref current-snapshot 'digest)
+ digest: receipt-digest
+ eligible?: (not admission-blocker) blocker: admission-blocker
+ verifier-executed?: #f release-authorized?: #f))))
diff --git a/modules/assurance/funs.ss b/modules/assurance/funs.ss
index d770a02..52da0b5 100644
--- a/modules/assurance/funs.ss
+++ b/modules/assurance/funs.ss
@@ -8,15 +8,27 @@
(only-in :gerbil/core list-sort string->utf8)
:std/list/list
(only-in :std/encoding/hex hex-encode)
- :poo-flow/src/module-system/contribution/model
- :poo-flow/lambda-aitia/modules/assurance/types
- (only-in :poo-flow/lambda-aitia/modules/assurance/invalidation-projection
- assurance-invalidation-analysis assurance-invalidation-graph))
+ (only-in :yuanxu/graph/algorithms
+ agentic-ai-lab-graph-cycle-path
+ agentic-ai-lab-graph-loop-analysis-receipt
+ agentic-ai-lab-graph-reachable-ids
+ agentic-ai-lab-graph-topological-order)
+ :agentic-ai-lab/core/poo-clos/interface
+ :agentic-ai-lab/lambda-aitia/modules/assurance/types
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/invalidation-projection
+ assurance-invalidation-analysis assurance-invalidation-graph)
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/verification-projection
+ assurance-verification-dependency-graph))
(export assurance-node-canonical assurance-relation-canonical
assurance-canonical-digest assurance-snapshot
- assurance-support-admissible? assurance-invalidation-graph
- assurance-invalidate)
+ assurance-snapshot-canonical?
+ assurance-bind-obligation-to-snapshot
+ assurance-invalidation-graph
+ assurance-invalidate assurance-derive-replacement-requirements
+ assurance-declare-replacement-obligation
+ assurance-plan-verification assurance-explain-verifier-choices
+ assurance-derive-composition-requirements)
(def (assurance-node-semantic-slots kind)
(case kind
@@ -28,7 +40,8 @@
((event) '(subject event-kind observation payload-digest modality
commitment-state causal-parents))
((action) '(subject action-kind requested-by scope))
- ((obligation) '(subject claim snapshot evidence-kind capability scope))
+ ((obligation) '(subject claim snapshot snapshot-revision
+ snapshot-context-digest evidence-kind capability scope))
((evidence) '(producer tool tool-version input-artifacts obligation subject
scope valid-from valid-until admission-state))
((counterexample) '(subject challenges evidence details-digest))
@@ -43,6 +56,16 @@
(.ref node 'state) (.ref node 'content-digest)
(map (lambda (name) (list name (.ref node name)))
(assurance-node-semantic-slots (.ref node 'kind)))))
+;;; The context projection excludes only the obligation's own binding slots.
+;;; Every other semantic change, including another obligation or relation,
+;;; changes the context digest without creating a self-referential hash.
+(def (assurance-node-context-canonical node)
+ (if (assurance-obligation? node)
+ (list (.ref node 'identity) (.ref node 'kind) (.ref node 'revision)
+ (.ref node 'state) (.ref node 'content-digest)
+ (map (lambda (name) (list name (.ref node name)))
+ '(subject claim snapshot evidence-kind capability scope)))
+ (assurance-node-canonical node)))
(def (assurance-relation-canonical relation)
(unless (assurance-relation? relation)
(error "invalid assurance relation" relation))
@@ -221,48 +244,85 @@
(memq 'hypothesized node-states)
(memq 'counterfactual node-states)) 'unknown)
(else 'supported)))
+ (context-canonical
+ (list 'lambda-aitia.assurance-snapshot-context
+ identity-value revision-value graph-identity-value
+ canonical-source-revisions canonical-claim-revisions
+ fact-cut-value policy-identity-value policy-revision-value
+ canonical-evidence-identities snapshot-state
+ (canonical-objects ordered-nodes
+ assurance-node-context-canonical)
+ (canonical-objects ordered-relations
+ assurance-relation-canonical)
+ missing all-conflicts))
+ (snapshot-context-digest
+ (assurance-canonical-digest context-canonical))
(canonical
(list 'lambda-aitia.assurance-snapshot identity-value revision-value
graph-identity-value canonical-source-revisions
canonical-claim-revisions
fact-cut-value policy-identity-value policy-revision-value
canonical-evidence-identities
- snapshot-state
+ snapshot-state snapshot-context-digest
(canonical-objects ordered-nodes assurance-node-canonical)
(canonical-objects ordered-relations assurance-relation-canonical)
missing all-conflicts))
(snapshot-digest (assurance-canonical-digest canonical)))
- (poo-flow-check-model
+ (poo-clos-check-model
AssuranceSnapshot
- (.o (:: @ (poo-flow-model-prototype AssuranceSnapshot))
+ (.o (:: @ (poo-clos-model-prototype AssuranceSnapshot))
identity: identity-value revision: revision-value
graph-identity: graph-identity-value
source-revisions: canonical-source-revisions
claim-revisions: canonical-claim-revisions fact-cut: fact-cut-value
policy-identity: policy-identity-value policy-revision: policy-revision-value
evidence-identities: canonical-evidence-identities
- state: snapshot-state digest: snapshot-digest
+ state: snapshot-state context-digest: snapshot-context-digest
+ digest: snapshot-digest
nodes: ordered-nodes relations: ordered-relations
unresolved: missing conflicts: all-conflicts)))))))))
-;;; Shape and a green-looking relation never grant support. The exact
-;;; evidence and obligation identities must match, and alternate modalities
-;;; cannot discharge an observed-fact obligation.
-(def (assurance-support-admissible? relation evidence obligation)
- (and (assurance-relation? relation)
- (assurance-evidence? evidence)
- (assurance-obligation? obligation)
- (eq? (.ref relation 'plane) 'assurance)
- (memq (.ref relation 'relation) '(supports discharges))
- (equal? (.ref relation 'source) (.ref evidence 'identity))
- (equal? (.ref relation 'target) (.ref obligation 'identity))
- (equal? (.ref evidence 'obligation) (.ref obligation 'identity))
- (equal? (.ref evidence 'subject) (.ref obligation 'subject))
- (equal? (.ref evidence 'scope) (.ref obligation 'scope))
- (equal? (.ref evidence 'revision) (.ref obligation 'revision))
- (eq? (.ref evidence 'state) 'supported)
- (eq? (.ref evidence 'admission-state) 'admitted)
- (not (memq (.ref relation 'modality) '(hypothesized counterfactual)))))
+;;; A Host source must supply a self-consistent snapshot, not an editable POO
+;;; presentation whose displayed digest/context no longer match its inventory.
+(def (assurance-snapshot-canonical? snapshot)
+ (and (assurance-snapshot? snapshot)
+ (let (rebuilt
+ (assurance-snapshot
+ (.ref snapshot 'identity) (.ref snapshot 'revision)
+ (.ref snapshot 'graph-identity)
+ (.ref snapshot 'source-revisions)
+ (.ref snapshot 'claim-revisions)
+ (.ref snapshot 'fact-cut)
+ (.ref snapshot 'policy-identity)
+ (.ref snapshot 'policy-revision)
+ (.ref snapshot 'nodes) (.ref snapshot 'relations)
+ evidence-identities: (.ref snapshot 'evidence-identities)
+ unresolved: (.ref snapshot 'unresolved)))
+ (and (equal? (.ref snapshot 'digest) (.ref rebuilt 'digest))
+ (equal? (.ref snapshot 'context-digest)
+ (.ref rebuilt 'context-digest))
+ (eq? (.ref snapshot 'state) (.ref rebuilt 'state))
+ (equal? (.ref snapshot 'conflicts) (.ref rebuilt 'conflicts))
+ (equal? (.ref snapshot 'unresolved)
+ (.ref rebuilt 'unresolved))))))
+
+;;; Binding is explicit: snapshot construction never silently upgrades an old
+;;; obligation. The caller must reconstruct the final snapshot with this value;
+;;; planning then compares both revision and non-circular context digest.
+(def (assurance-bind-obligation-to-snapshot obligation snapshot)
+ (unless (and (assurance-obligation? obligation)
+ (assurance-snapshot? snapshot)
+ (string=? (.ref obligation 'snapshot) (.ref snapshot 'identity))
+ (not (.ref obligation 'snapshot-revision))
+ (not (.ref obligation 'snapshot-context-digest)))
+ (error "obligation cannot bind to this snapshot"))
+ (let ((bound-revision (.ref snapshot 'revision))
+ (bound-context (.ref snapshot 'context-digest)))
+ (poo-clos-check-model
+ AssuranceObligation
+ (.o (:: @ obligation)
+ snapshot-revision: bound-revision
+ snapshot-context-digest: bound-context))))
(def (identity-member? identity values)
(if (member identity values) #t #f))
@@ -311,3 +371,669 @@
(impacted-kind-identities nodes impacted 'effect)
witnesses unresolved strong-components cyclic-components
#f #f #f)))))
+
+;;; This derives the need for fresh declarations from the old snapshot's
+;;; invalidation closure. It deliberately does not make a new obligation: a
+;;; revised claim or policy may require a different question or evidence kind,
+;;; and inserting an obligation would change the target snapshot context.
+(def (replacement-requirement-blocker source-obligation source target
+ change-unresolved)
+ (let ((source-claim
+ (node-by-identity (.ref source 'nodes)
+ (.ref source-obligation 'claim)))
+ (target-claim
+ (node-by-identity (.ref target 'nodes)
+ (.ref source-obligation 'claim))))
+ (cond
+ ((pair? (.ref source 'conflicts)) 'source-conflicted)
+ ((pair? (.ref source 'unresolved)) 'source-unresolved)
+ ((pair? change-unresolved) 'change-unresolved)
+ ((or (not (equal? (.ref source-obligation 'snapshot)
+ (.ref source 'identity)))
+ (not (equal? (.ref source-obligation 'snapshot-revision)
+ (.ref source 'revision)))
+ (not (equal? (.ref source-obligation 'snapshot-context-digest)
+ (.ref source 'context-digest))))
+ 'stale-source)
+ ((equal? (.ref source 'digest) (.ref target 'digest)) 'target-unchanged)
+ ((pair? (.ref target 'conflicts)) 'target-conflicted)
+ ((pair? (.ref target 'unresolved)) 'target-unresolved)
+ ((not (equal? (.ref source 'identity) (.ref target 'identity)))
+ 'target-identity-changed)
+ ((not (equal? (.ref source 'graph-identity)
+ (.ref target 'graph-identity)))
+ 'graph-changed)
+ ((or (not (equal? (.ref source 'policy-identity)
+ (.ref target 'policy-identity)))
+ (not (equal? (.ref source 'policy-revision)
+ (.ref target 'policy-revision))))
+ 'policy-changed)
+ ((not (assurance-claim? target-claim)) 'claim-missing)
+ ((or (not (assurance-claim? source-claim))
+ (not (equal? (assurance-node-canonical source-claim)
+ (assurance-node-canonical target-claim))))
+ 'claim-changed)
+ (else #f))))
+
+(def (assurance-derive-replacement-requirements derivation-identity source target
+ changed-identities)
+ (unless (and (assurance-text? derivation-identity)
+ (assurance-snapshot? source)
+ (assurance-snapshot? target))
+ (error "invalid replacement derivation input"))
+ (let* ((invalidation
+ (assurance-invalidate
+ (string-append derivation-identity "/invalidation")
+ source changed-identities))
+ (changed-values
+ (assurance-invalidation-receipt-ref invalidation 'changed))
+ (change-witnesses
+ (assurance-invalidation-receipt-ref invalidation 'witnesses))
+ (change-unresolved
+ (assurance-invalidation-receipt-ref invalidation 'unresolved))
+ (obligation-ids
+ (assurance-invalidation-receipt-ref
+ invalidation 'required-obligations))
+ (derived-requirements
+ (map
+ (lambda (obligation-id)
+ (let ((obligation
+ (node-by-identity (.ref source 'nodes) obligation-id)))
+ (poo-clos-check-model
+ AssuranceReplacementRequirement
+ (.o (:: @ (poo-clos-model-prototype
+ AssuranceReplacementRequirement))
+ source-obligation: obligation-id
+ source-revision: (.ref obligation 'revision)
+ claim: (.ref obligation 'claim)
+ subject: (.ref obligation 'subject)
+ evidence-kind: (.ref obligation 'evidence-kind)
+ capability: (.ref obligation 'capability)
+ scope: (.ref obligation 'scope)
+ blocker:
+ (replacement-requirement-blocker
+ obligation source target change-unresolved)))))
+ obligation-ids))
+ (derivation-digest
+ (assurance-canonical-digest
+ (list "lambda-aitia.replacement-requirements"
+ derivation-identity
+ (.ref source 'digest) (.ref target 'digest)
+ changed-values change-witnesses change-unresolved
+ (map (lambda (requirement)
+ (list (.ref requirement 'source-obligation)
+ (.ref requirement 'source-revision)
+ (.ref requirement 'claim)
+ (.ref requirement 'subject)
+ (.ref requirement 'evidence-kind)
+ (.ref requirement 'capability)
+ (.ref requirement 'scope)
+ (.ref requirement 'blocker)))
+ derived-requirements)))))
+ (poo-clos-check-model
+ AssuranceReplacementDerivation
+ (.o (:: @ (poo-clos-model-prototype AssuranceReplacementDerivation))
+ schema: "lambda-aitia.replacement-requirements"
+ identity: derivation-identity
+ source-snapshot-digest: (.ref source 'digest)
+ target-snapshot-digest: (.ref target 'digest)
+ changed: changed-values
+ witnesses: change-witnesses
+ unresolved: change-unresolved
+ requirements: derived-requirements digest: derivation-digest
+ verifier-executed?: #f release-authorized?: #f))))
+
+;;; The new obligation, revised claim and supports edge must already be present
+;;; in the caller's draft. Only its snapshot binding is filled here. The
+;;; derivation is replayed against exact source/draft digests so a forged or
+;;; unrelated receipt cannot be used to promote a candidate.
+(def (snapshot-canonical? snapshot)
+ (let ((rebuilt
+ (assurance-snapshot
+ (.ref snapshot 'identity) (.ref snapshot 'revision)
+ (.ref snapshot 'graph-identity)
+ (.ref snapshot 'source-revisions) (.ref snapshot 'claim-revisions)
+ (.ref snapshot 'fact-cut) (.ref snapshot 'policy-identity)
+ (.ref snapshot 'policy-revision)
+ (.ref snapshot 'nodes) (.ref snapshot 'relations)
+ evidence-identities: (.ref snapshot 'evidence-identities)
+ unresolved: (.ref snapshot 'unresolved))))
+ (and (equal? (.ref rebuilt 'digest) (.ref snapshot 'digest))
+ (equal? (.ref rebuilt 'context-digest)
+ (.ref snapshot 'context-digest)))))
+
+(def (replacement-declaration-blocker derivation source draft
+ source-id candidate-id)
+ (let* ((expected
+ (assurance-derive-replacement-requirements
+ (.ref derivation 'identity) source draft (.ref derivation 'changed)))
+ (requirement
+ (find (lambda (item)
+ (equal? (.ref item 'source-obligation) source-id))
+ (.ref derivation 'requirements)))
+ (candidate (node-by-identity (.ref draft 'nodes) candidate-id))
+ (claim (and (assurance-obligation? candidate)
+ (node-by-identity (.ref draft 'nodes)
+ (.ref candidate 'claim))))
+ (support-links
+ (filter (lambda (relation)
+ (and (eq? (.ref relation 'relation) 'supports)
+ (equal? (.ref relation 'source) candidate-id)
+ (assurance-obligation? candidate)
+ (equal? (.ref relation 'target)
+ (.ref candidate 'claim))))
+ (.ref draft 'relations))))
+ (cond
+ ((or (not (snapshot-canonical? source))
+ (not (snapshot-canonical? draft))
+ (not (equal? (.ref derivation 'source-snapshot-digest)
+ (.ref source 'digest)))
+ (not (equal? (.ref derivation 'target-snapshot-digest)
+ (.ref draft 'digest)))
+ (not (equal? (.ref derivation 'digest) (.ref expected 'digest))))
+ 'derivation-mismatch)
+ ((not requirement) 'source-requirement-missing)
+ ((not (memq (.ref requirement 'blocker) '(#f claim-changed)))
+ 'source-requirement-blocked)
+ ((or (pair? (.ref draft 'unresolved)) (pair? (.ref draft 'conflicts)))
+ 'target-frontier)
+ ((not (assurance-obligation? candidate)) 'candidate-missing)
+ ((node-by-identity (.ref source 'nodes) candidate-id)
+ 'candidate-not-fresh)
+ ((or (not (equal? (.ref candidate 'snapshot) (.ref draft 'identity)))
+ (.ref candidate 'snapshot-revision)
+ (.ref candidate 'snapshot-context-digest))
+ 'candidate-not-unbound)
+ ((not (eq? (.ref candidate 'state) 'unknown)) 'candidate-not-unknown)
+ ((not (equal? (.ref candidate 'claim) (.ref requirement 'claim)))
+ 'candidate-claim-mismatch)
+ ((not (assurance-claim? claim)) 'candidate-claim-mismatch)
+ ((not (equal? (.ref candidate 'subject) (.ref claim 'subject)))
+ 'candidate-subject-mismatch)
+ ((not (equal? (.ref candidate 'scope) (.ref claim 'scope)))
+ 'candidate-scope-mismatch)
+ ((not (member candidate-id (.ref claim 'support-requirements)))
+ 'claim-not-declared)
+ ((null? support-links) 'support-link-missing)
+ ((not (find (lambda (relation)
+ (memq (.ref relation 'modality)
+ '(observed declared derived)))
+ support-links))
+ 'support-link-hypothetical)
+ (else #f))))
+
+(def (assurance-declare-replacement-obligation declaration-identity source draft derivation
+ source-id candidate-id)
+ (unless (and (assurance-text? declaration-identity)
+ (assurance-text? source-id) (assurance-text? candidate-id)
+ (assurance-snapshot? source) (assurance-snapshot? draft)
+ (assurance-replacement-derivation? derivation))
+ (error "invalid replacement declaration input"))
+ (let* ((declaration-blocker
+ (replacement-declaration-blocker
+ derivation source draft source-id candidate-id))
+ (final-snapshot
+ (and (not declaration-blocker)
+ (let* ((candidate
+ (node-by-identity (.ref draft 'nodes) candidate-id))
+ (bound
+ (assurance-bind-obligation-to-snapshot candidate draft)))
+ (assurance-snapshot
+ (.ref draft 'identity) (.ref draft 'revision)
+ (.ref draft 'graph-identity)
+ (.ref draft 'source-revisions) (.ref draft 'claim-revisions)
+ (.ref draft 'fact-cut) (.ref draft 'policy-identity)
+ (.ref draft 'policy-revision)
+ (map (lambda (node)
+ (if (equal? (.ref node 'identity) candidate-id)
+ bound node))
+ (.ref draft 'nodes))
+ (.ref draft 'relations)
+ evidence-identities: (.ref draft 'evidence-identities)
+ unresolved: (.ref draft 'unresolved)))))
+ (final-digest (and final-snapshot (.ref final-snapshot 'digest)))
+ (receipt-digest
+ (assurance-canonical-digest
+ (list "lambda-aitia.replacement-declaration" declaration-identity
+ (.ref derivation 'digest) (.ref source 'digest)
+ (.ref draft 'digest) final-digest
+ source-id candidate-id declaration-blocker)))
+ (receipt
+ (poo-clos-check-model
+ AssuranceReplacementDeclarationReceipt
+ (.o (:: @ (poo-clos-model-prototype
+ AssuranceReplacementDeclarationReceipt))
+ schema: "lambda-aitia.replacement-declaration"
+ identity: declaration-identity
+ derivation-digest: (.ref derivation 'digest)
+ source-snapshot-digest: (.ref source 'digest)
+ draft-snapshot-digest: (.ref draft 'digest)
+ final-snapshot-digest: final-digest
+ source-obligation: source-id target-obligation: candidate-id
+ blocker: declaration-blocker digest: receipt-digest
+ verifier-executed?: #f release-authorized?: #f))))
+ (when (and final-snapshot
+ (not (equal? (.ref final-snapshot 'context-digest)
+ (.ref draft 'context-digest))))
+ (error "replacement binding changed snapshot context"))
+ (values final-snapshot receipt)))
+
+;;; A structural 'composes edge declares a composite claim's components.
+;;; Only an independent, explicitly linked and current obligation can answer
+;;; its composition question; this receipt never discharges that obligation.
+(def (composition-component-ids snapshot composition-id)
+ (ordered-unique-text
+ (map (lambda (relation) (.ref relation 'target))
+ (filter (lambda (relation)
+ (and (eq? (.ref relation 'relation) 'composes)
+ (equal? (.ref relation 'source) composition-id)))
+ (.ref snapshot 'relations)))))
+
+(def (composition-direct-obligations snapshot composition-id claim-node)
+ (if (not (assurance-claim? claim-node))
+ '()
+ (ordered-unique-text
+ (map
+ (lambda (obligation) (.ref obligation 'identity))
+ (filter
+ (lambda (obligation)
+ (and (assurance-obligation? obligation)
+ (equal? (.ref obligation 'claim) composition-id)
+ (equal? (.ref obligation 'subject)
+ (.ref claim-node 'subject))
+ (equal? (.ref obligation 'scope)
+ (.ref claim-node 'scope))
+ (member (.ref obligation 'identity)
+ (.ref claim-node 'support-requirements))
+ (find
+ (lambda (relation)
+ (and (eq? (.ref relation 'relation) 'supports)
+ (eq? (.ref relation 'plane) 'assurance)
+ (memq (.ref relation 'modality)
+ '(declared observed derived))
+ (equal? (.ref relation 'source)
+ (.ref obligation 'identity))
+ (equal? (.ref relation 'target) composition-id)))
+ (.ref snapshot 'relations))))
+ (.ref snapshot 'nodes))))))
+
+(def (composition-current-obligation? snapshot obligation-id)
+ (let ((obligation (node-by-identity (.ref snapshot 'nodes) obligation-id)))
+ (and (assurance-obligation? obligation)
+ (equal? (.ref obligation 'snapshot) (.ref snapshot 'identity))
+ (equal? (.ref obligation 'snapshot-revision)
+ (.ref snapshot 'revision))
+ (equal? (.ref obligation 'snapshot-context-digest)
+ (.ref snapshot 'context-digest)))))
+
+(def (composition-requirement-blocker snapshot composition-claim
+ component-ids direct-ids current-ids)
+ (cond
+ ((pair? (.ref snapshot 'conflicts)) 'conflicted-snapshot)
+ ((pair? (.ref snapshot 'unresolved)) 'unresolved-frontier)
+ ((not (assurance-claim? composition-claim))
+ 'invalid-composition-claim)
+ ((< (length component-ids) 2) 'insufficient-components)
+ ((find (lambda (component-id)
+ (not (assurance-claim?
+ (node-by-identity (.ref snapshot 'nodes) component-id))))
+ component-ids)
+ 'invalid-component-claim)
+ ((pair? current-ids) #f)
+ ((pair? direct-ids) 'stale-direct-obligation)
+ (else 'missing-direct-obligation)))
+
+(def (assurance-derive-composition-requirements derivation-identity snapshot)
+ (unless (and (assurance-text? derivation-identity)
+ (assurance-snapshot? snapshot))
+ (error "invalid composition derivation input"))
+ (let* ((composition-ids
+ (ordered-unique-text
+ (map (lambda (relation) (.ref relation 'source))
+ (filter
+ (lambda (relation)
+ (eq? (.ref relation 'relation) 'composes))
+ (.ref snapshot 'relations)))))
+ (derived-requirements
+ (map
+ (lambda (composition-id)
+ (let* ((composition-claim
+ (node-by-identity (.ref snapshot 'nodes)
+ composition-id))
+ (component-ids
+ (composition-component-ids snapshot composition-id))
+ (direct-ids
+ (composition-direct-obligations
+ snapshot composition-id composition-claim))
+ (current-ids
+ (filter
+ (lambda (obligation-id)
+ (composition-current-obligation?
+ snapshot obligation-id))
+ direct-ids))
+ (blocker-value
+ (composition-requirement-blocker
+ snapshot composition-claim component-ids
+ direct-ids current-ids)))
+ (poo-clos-check-model
+ AssuranceCompositionRequirement
+ (.o (:: @ (poo-clos-model-prototype
+ AssuranceCompositionRequirement))
+ composition-claim: composition-id
+ component-claims: component-ids
+ direct-obligations: direct-ids
+ current-obligations: current-ids
+ blocker: blocker-value))))
+ composition-ids))
+ (derivation-digest
+ (assurance-canonical-digest
+ (list "lambda-aitia.composition-requirements"
+ derivation-identity (.ref snapshot 'digest)
+ (map (lambda (requirement)
+ (list (.ref requirement 'composition-claim)
+ (.ref requirement 'component-claims)
+ (.ref requirement 'direct-obligations)
+ (.ref requirement 'current-obligations)
+ (.ref requirement 'blocker)))
+ derived-requirements)))))
+ (poo-clos-check-model
+ AssuranceCompositionDerivation
+ (.o (:: @ (poo-clos-model-prototype AssuranceCompositionDerivation))
+ schema: "lambda-aitia.composition-requirements"
+ identity: derivation-identity
+ snapshot-digest: (.ref snapshot 'digest)
+ requirements: derived-requirements
+ digest: derivation-digest
+ verifier-executed?: #f release-authorized?: #f))))
+
+;;; Phase 3 selection boundary. This plan names only obligations already bound
+;;; to the supplied snapshot. Deriving replacement revisions and invoking
+;;; verifiers belong to later phases; neither can be inferred from a change.
+(def (verification-base-blocker obligation snapshot capabilities
+ unresolved conflicts cyclic-ids
+ prerequisites planned-ids)
+ (cond
+ ((pair? conflicts) 'conflicted-snapshot)
+ ((pair? unresolved) 'unresolved-frontier)
+ ((member (.ref obligation 'identity) cyclic-ids) 'dependency-cycle)
+ ((or (not (string=? (.ref obligation 'snapshot)
+ (.ref snapshot 'identity)))
+ (not (equal? (.ref obligation 'snapshot-revision)
+ (.ref snapshot 'revision)))
+ (not (equal? (.ref obligation 'snapshot-context-digest)
+ (.ref snapshot 'context-digest))))
+ 'stale-obligation)
+ ((not (memq (.ref obligation 'capability) capabilities))
+ 'capability-unavailable)
+ ((find (lambda (id) (not (member id planned-ids))) prerequisites)
+ 'dependency-unplanned)
+ (else #f)))
+
+(def (assurance-plan-verification identity snapshot changed-identities policy)
+ (unless (and (assurance-text? identity)
+ (assurance-snapshot? snapshot)
+ (assurance-verification-policy? policy))
+ (error "invalid assurance verification planning input"))
+ (unless (and (string=? (.ref policy 'identity)
+ (.ref snapshot 'policy-identity))
+ (string=? (.ref policy 'revision)
+ (.ref snapshot 'policy-revision)))
+ (error "verification policy does not match the snapshot"))
+ (let* ((invalidation
+ (assurance-invalidate
+ (string-append identity "/invalidation")
+ snapshot changed-identities))
+ (obligation-ids
+ (assurance-invalidation-receipt-ref
+ invalidation 'required-obligations))
+ (changed
+ (assurance-invalidation-receipt-ref invalidation 'changed))
+ (impacted
+ (assurance-invalidation-receipt-ref invalidation 'impacted))
+ (blocked-effects
+ (assurance-invalidation-receipt-ref invalidation 'blocked-effects))
+ (witnesses
+ (assurance-invalidation-receipt-ref invalidation 'witnesses))
+ (unresolved
+ (assurance-invalidation-receipt-ref invalidation 'unresolved))
+ (conflicts (.ref snapshot 'conflicts))
+ (capabilities (.ref policy 'capabilities)))
+ (let-values (((dependency-graph prerequisites)
+ (assurance-verification-dependency-graph
+ snapshot obligation-ids)))
+ (let* ((cycle-path
+ (or (agentic-ai-lab-graph-cycle-path dependency-graph) '()))
+ (cyclic-components
+ (.ref (agentic-ai-lab-graph-loop-analysis-receipt dependency-graph)
+ 'cyclic-components))
+ (cyclic-ids (concatenate cyclic-components))
+ (cycle-blocked
+ (agentic-ai-lab-graph-reachable-ids dependency-graph cyclic-ids))
+ (base-blockers
+ (map
+ (lambda (obligation-id)
+ (cons
+ obligation-id
+ (verification-base-blocker
+ (node-by-identity (.ref snapshot 'nodes) obligation-id)
+ snapshot capabilities unresolved conflicts cyclic-ids
+ (cdr (assoc obligation-id prerequisites)) obligation-ids)))
+ obligation-ids))
+ (blocked-closure
+ (agentic-ai-lab-graph-reachable-ids
+ dependency-graph
+ (append cycle-blocked
+ (map car (filter (lambda (entry) (cdr entry))
+ base-blockers)))))
+ (available-ids
+ (filter (lambda (id) (not (member id blocked-closure)))
+ obligation-ids))
+ (available-order
+ (let-values (((available-graph _)
+ (assurance-verification-dependency-graph
+ snapshot available-ids)))
+ (agentic-ai-lab-graph-topological-order available-graph)))
+ (blocked-order
+ (filter (lambda (id) (member id blocked-closure))
+ (if (null? cycle-path)
+ (agentic-ai-lab-graph-topological-order dependency-graph)
+ obligation-ids)))
+ (ordered-ids (append available-order blocked-order))
+ (requests
+ (map
+ (lambda (obligation-id)
+ (let* ((obligation
+ (node-by-identity (.ref snapshot 'nodes)
+ obligation-id))
+ (base-reason (cdr (assoc obligation-id base-blockers)))
+ (request-reason
+ (or base-reason
+ (and (member obligation-id blocked-closure)
+ 'dependency-blocked)))
+ (request-id obligation-id)
+ (request-dependencies
+ (cdr (assoc obligation-id prerequisites))))
+ (poo-clos-check-model
+ AssuranceVerificationRequest
+ (.o (:: @ (poo-clos-model-prototype
+ AssuranceVerificationRequest))
+ obligation-identity: request-id
+ subject: (.ref obligation 'subject)
+ claim: (.ref obligation 'claim)
+ snapshot-digest: (.ref snapshot 'digest)
+ evidence-kind: (.ref obligation 'evidence-kind)
+ capability: (.ref obligation 'capability)
+ dependencies: request-dependencies
+ selected?: (not request-reason)
+ blocker: request-reason))))
+ ordered-ids))
+ (blocked
+ (map (lambda (request) (.ref request 'obligation-identity))
+ (filter (lambda (request) (not (.ref request 'selected?)))
+ requests)))
+ (selected
+ (map (lambda (request) (.ref request 'obligation-identity))
+ (filter (lambda (request) (.ref request 'selected?))
+ requests)))
+ (request-projection
+ (map (lambda (request)
+ (list (.ref request 'obligation-identity)
+ (.ref request 'subject) (.ref request 'claim)
+ (.ref request 'evidence-kind)
+ (.ref request 'capability)
+ (.ref request 'dependencies)
+ (.ref request 'selected?) (.ref request 'blocker)))
+ requests))
+ (digest
+ (assurance-canonical-digest
+ (list "lambda-aitia.planning-result" identity
+ (.ref snapshot 'digest)
+ (.ref policy 'identity) (.ref policy 'revision)
+ (.ref policy 'capabilities)
+ changed impacted blocked-effects witnesses
+ cycle-path cyclic-components
+ selected blocked request-projection
+ unresolved conflicts))))
+ (let ((plan-identity identity)
+ (plan-digest digest)
+ (plan-selected selected)
+ (plan-blocked blocked)
+ (plan-changed changed)
+ (plan-impacted impacted)
+ (plan-blocked-effects blocked-effects)
+ (plan-cycle-path cycle-path)
+ (plan-cyclic-components cyclic-components)
+ (plan-witnesses witnesses)
+ (plan-requests requests)
+ (plan-unresolved unresolved)
+ (plan-conflicts conflicts))
+ (poo-clos-check-model
+ AssuranceVerificationPlan
+ (.o (:: @ (poo-clos-model-prototype AssuranceVerificationPlan))
+ schema: "lambda-aitia.planning-result"
+ identity: plan-identity snapshot-digest: (.ref snapshot 'digest)
+ policy-identity: (.ref policy 'identity)
+ policy-revision: (.ref policy 'revision)
+ digest: plan-digest
+ selected-obligations: plan-selected
+ blocked-obligations: plan-blocked
+ changed: plan-changed impacted: plan-impacted
+ blocked-effects: plan-blocked-effects
+ cycle-path: plan-cycle-path
+ cyclic-components: plan-cyclic-components
+ witnesses: plan-witnesses
+ requests: plan-requests
+ unresolved: plan-unresolved conflicts: plan-conflicts
+ verifier-executed?: #f release-authorized?: #f
+ runtime-executed?: #f)))))))
+
+;;; Candidate selection is a pure explanation over explicit declarations.
+;;; It does not establish that an adapter is installed, runnable or trusted.
+(def (verifier-candidate-matches? candidate request)
+ (and (memq (.ref request 'evidence-kind)
+ (.ref candidate 'evidence-kinds))
+ (eq? (.ref request 'capability) (.ref candidate 'capability))))
+
+(def (verifier-choice-reason candidate request selected-candidate)
+ (cond
+ ((not (.ref request 'selected?)) 'request-blocked)
+ ((not (memq (.ref request 'evidence-kind)
+ (.ref candidate 'evidence-kinds)))
+ 'evidence-kind-unsupported)
+ ((not (eq? (.ref request 'capability)
+ (.ref candidate 'capability)))
+ 'capability-mismatch)
+ ((and selected-candidate
+ (equal? (.ref candidate 'identity)
+ (.ref selected-candidate 'identity)))
+ 'chosen)
+ (else 'lower-priority)))
+
+(def (assurance-explain-verifier-choices explanation-identity plan candidates)
+ (unless (and (assurance-text? explanation-identity)
+ (assurance-verification-plan? plan)
+ (list? candidates)
+ (every assurance-verifier-candidate? candidates))
+ (error "invalid verifier choice input"))
+ (let* ((ordered-candidates
+ (list-sort
+ (lambda (left right)
+ (or (< (.ref left 'priority) (.ref right 'priority))
+ (and (= (.ref left 'priority) (.ref right 'priority))
+ (string (.ref left 'identity)
+ (.ref right 'identity)))))
+ candidates))
+ (candidate-ids (map (lambda (candidate)
+ (.ref candidate 'identity))
+ ordered-candidates)))
+ (unless (= (length candidate-ids)
+ (length (delete-duplicates/hash candidate-ids)))
+ (error "duplicate verifier candidate identity" candidate-ids))
+ (let* ((requests (.ref plan 'requests))
+ (candidate-choices
+ (concatenate
+ (map
+ (lambda (request)
+ (let ((selected-candidate
+ (and (.ref request 'selected?)
+ (find (lambda (candidate)
+ (verifier-candidate-matches?
+ candidate request))
+ ordered-candidates))))
+ (map
+ (lambda (candidate)
+ (let ((choice-reason
+ (verifier-choice-reason
+ candidate request selected-candidate)))
+ (poo-clos-check-model
+ AssuranceVerifierChoice
+ (.o (:: @ (poo-clos-model-prototype
+ AssuranceVerifierChoice))
+ obligation-identity:
+ (.ref request 'obligation-identity)
+ candidate-identity: (.ref candidate 'identity)
+ selected?: (eq? choice-reason 'chosen)
+ reason: choice-reason))))
+ ordered-candidates)))
+ requests)))
+ (unassigned-ids
+ (map
+ (lambda (request) (.ref request 'obligation-identity))
+ (filter
+ (lambda (request)
+ (and (.ref request 'selected?)
+ (not (find
+ (lambda (candidate)
+ (verifier-candidate-matches?
+ candidate request))
+ ordered-candidates))))
+ requests)))
+ (explanation-digest
+ (assurance-canonical-digest
+ (list "lambda-aitia.verifier-choices"
+ explanation-identity (.ref plan 'digest)
+ (map (lambda (candidate)
+ (list (.ref candidate 'identity)
+ (.ref candidate 'revision)
+ (.ref candidate 'priority)
+ (.ref candidate 'evidence-kinds)
+ (.ref candidate 'capability)))
+ ordered-candidates)
+ (map (lambda (choice)
+ (list (.ref choice 'obligation-identity)
+ (.ref choice 'candidate-identity)
+ (.ref choice 'selected?)
+ (.ref choice 'reason)))
+ candidate-choices)
+ unassigned-ids))))
+ (poo-clos-check-model
+ AssuranceVerifierChoiceReceipt
+ (.o (:: @ (poo-clos-model-prototype AssuranceVerifierChoiceReceipt))
+ schema: "lambda-aitia.verifier-choices"
+ identity: explanation-identity
+ plan-digest: (.ref plan 'digest)
+ candidates: ordered-candidates
+ choices: candidate-choices
+ unassigned-obligations: unassigned-ids
+ digest: explanation-digest
+ verifier-executed?: #f release-authorized?: #f)))))
diff --git a/modules/assurance/host.ss b/modules/assurance/host.ss
new file mode 100644
index 0000000..8c2d8e1
--- /dev/null
+++ b/modules/assurance/host.ss
@@ -0,0 +1,728 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; An application-configured capability for verification. Adapter, clock and
+;;; lease are private to the exact issued Host object; neither an editable POO
+;;; presentation nor a per-call time argument selects authority.
+(import (only-in :clan/poo/object .o .ref .slot? .alist object?)
+ (only-in :std/list/list find every filter delete-duplicates/hash)
+ (only-in :std/hash/misc hash-remove!)
+ :agentic-ai-lab/core/poo-clos/interface
+ (only-in :agentic-ai-lab/core/contribution/verification
+ agentic-ai-lab-verification-adapter agentic-ai-lab-verify
+ agentic-ai-lab-verification-valid?
+ agentic-ai-lab-revoke-verification!)
+ (only-in :yuanxu/feature-system/source-lock-feature
+ source-lock-payload-digest)
+ (only-in :agentic-ai-lab/modules/authorization/providers/cedar/interface
+ agentic-ai-lab-cedar-runtime-handoff?
+ agentic-ai-lab-cedar-authorization-request
+ agentic-ai-lab-cedar-authorization-request?)
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/types
+ assurance-snapshot? assurance-artifact? assurance-claim?
+ assurance-obligation?
+ assurance-decision? assurance-decision-preflight?
+ AssuranceRequiredSupport AssessmentRequiredSupport
+ AssuranceDecisionPreflight)
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/funs
+ assurance-snapshot-canonical? assurance-node-canonical
+ assurance-canonical-digest)
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/evidence-admission
+ assurance-evaluate-evidence-admission
+ assurance-evidence-outcome-bound?
+ assurance-verification-subject
+ assurance-snapshot-semantic-digest
+ assurance-verification-subject-snapshot
+ assurance-candidate-support-structural?
+ assurance-support-sealed-under-adapter?))
+
+(export assurance-verification-host assurance-host-verify
+ assurance-host-sealed-support? assurance-host-revoke!
+ assurance-host-admit assurance-host-admit-verified
+ assurance-host-verification-current? assurance-host-admission-current?
+ assurance-host-source-current?
+ assurance-host-admitted-support?
+ assurance-host-required-support
+ assurance-host-preflight-decision
+ assurance-host-decision-preflight-current?
+ assurance-host-cedar-request assurance-host-cedar-request-current?
+ assurance-host-revoke-decision-preflight!
+ assurance-host-revoke-admission!)
+
+(def issued-hosts (make-hash-table-eq weak-keys: #t))
+(def issued-host-receipts (make-hash-table-eq weak-keys: #t))
+(def issued-admissions (make-hash-table-eq weak-keys: #t))
+(def issued-decision-preflights (make-hash-table-eq weak-keys: #t))
+(def issued-cedar-requests (make-hash-table-eq weak-keys: #t))
+
+(def (host-entry host)
+ (let (entry (hash-get issued-hosts host))
+ (and entry (object? host) (.slot? host 'identity)
+ (equal? (.ref host 'identity) (vector-ref entry 0))
+ entry)))
+
+(def (required-host-entry host)
+ (or (host-entry host)
+ (error "unissued or modified assurance verification Host")))
+
+(def (host-instant entry)
+ (let (now ((vector-ref entry 2)))
+ (unless (and (exact-integer? now) (>= now 0))
+ (error "assurance Host clock must return a nonnegative instant"))
+ (when (< now (vector-ref entry 4))
+ (error "assurance Host clock moved backwards"))
+ (vector-set! entry 4 now)
+ now))
+
+(def (invalidate-host-cut! entry)
+ ;; A weak receipt index avoids retaining every old seal for the Host's life.
+ ;; The epoch blocks all prior seals at this Host even if the old cut returns.
+ (vector-set! entry 8 (+ (vector-ref entry 8) 1)))
+
+(def (host-current-snapshot entry)
+ (let (snapshot ((vector-ref entry 5)))
+ (unless (and (assurance-snapshot? snapshot)
+ (assurance-snapshot-canonical? snapshot))
+ (invalidate-host-cut! entry)
+ (error "assurance Host snapshot source returned a noncanonical snapshot"))
+ (let ((current-digest (assurance-snapshot-semantic-digest snapshot))
+ (previous-digest (vector-ref entry 7)))
+ (when (and previous-digest
+ (not (equal? previous-digest current-digest)))
+ (invalidate-host-cut! entry))
+ (vector-set! entry 7 (string-copy current-digest)))
+ snapshot))
+
+(def (host-snapshot-current? entry snapshot obligation evidence outcome)
+ (equal?
+ (assurance-verification-subject-snapshot
+ (assurance-verification-subject snapshot obligation evidence outcome))
+ (assurance-verification-subject-snapshot
+ (assurance-verification-subject
+ (host-current-snapshot entry) obligation evidence outcome))))
+
+(def (assurance-verification-host
+ identity-value operation clock lease snapshot-source
+ source-reader: (source-reader #f))
+ (unless (and (string? identity-value)
+ (> (string-length identity-value) 0)
+ (procedure? operation) (procedure? clock)
+ (exact-integer? lease) (> lease 0)
+ (procedure? snapshot-source)
+ (or (not source-reader) (procedure? source-reader)))
+ (error "invalid assurance verification Host configuration"))
+ (let* ((host (.o identity: (string-copy identity-value)))
+ (adapter
+ (agentic-ai-lab-verification-adapter
+ identity-value
+ (lambda (subject now until)
+ (if source-reader
+ (let (inputs
+ (host-materialized-inputs
+ host (.ref subject 'snapshot) (.ref subject 'outcome)))
+ (and inputs
+ (let (expected
+ (map (lambda (input)
+ (vector (string-copy (.ref input 'identity))
+ (string-copy (.ref input 'revision))
+ (string-copy (.ref input 'digest))))
+ inputs))
+ (and (eq? (operation subject now until inputs) #t)
+ (host-handed-inputs-current? inputs expected)))))
+ (operation subject now until)))
+ assurance-verification-subject-snapshot)))
+ (hash-put! issued-hosts host
+ (vector (string-copy identity-value) adapter clock lease -1
+ snapshot-source 0 #f 0 source-reader))
+ host))
+
+;;; An eligible report alone is never an issued seal. The configured operation
+;;; must independently return #t over the complete frozen semantic subject.
+(def (assurance-host-verify host snapshot obligation evidence outcome)
+ (let* ((entry (required-host-entry host))
+ (eligibility
+ (assurance-evaluate-evidence-admission snapshot obligation outcome)))
+ (and (.ref eligibility 'eligible?)
+ (assurance-evidence-outcome-bound? snapshot evidence outcome)
+ (host-snapshot-current? entry snapshot obligation evidence outcome)
+ (host-outcome-inputs-current? host snapshot outcome)
+ (let (now (host-instant entry))
+ (let (receipt
+ (agentic-ai-lab-verify
+ (vector-ref entry 1)
+ (assurance-verification-subject
+ snapshot obligation evidence outcome)
+ now (+ now (vector-ref entry 3))))
+ (and receipt
+ (if (host-outcome-inputs-current? host snapshot outcome)
+ (begin
+ (hash-put! issued-host-receipts receipt
+ (vector host (vector-ref entry 8)))
+ receipt)
+ (begin
+ (agentic-ai-lab-revoke-verification! (vector-ref entry 1)
+ receipt)
+ #f))))))))
+
+;;; This checks a Host-issued seal; it does not promote evidence or grant an effect.
+(def (assurance-host-sealed-support?
+ host relation evidence obligation snapshot outcome receipt)
+ (let (entry (required-host-entry host))
+ (let (issued (hash-get issued-host-receipts receipt))
+ (and issued (eq? host (vector-ref issued 0))
+ (host-snapshot-current? entry snapshot obligation evidence outcome)
+ (host-outcome-inputs-current? host snapshot outcome)
+ (= (vector-ref issued 1) (vector-ref entry 8))
+ (assurance-support-sealed-under-adapter?
+ relation evidence obligation snapshot outcome
+ (vector-ref entry 1) receipt (host-instant entry))))))
+
+(def (assurance-host-revoke! host receipt)
+ (let* ((entry (required-host-entry host))
+ (issued (hash-get issued-host-receipts receipt)))
+ (unless (and issued (eq? host (vector-ref issued 0)))
+ (error "receipt was not issued by this assurance Host"))
+ (hash-remove! issued-host-receipts receipt)
+ (agentic-ai-lab-revoke-verification! (vector-ref entry 1) receipt)))
+
+;;; Admission is a separate Host-issued capability over the candidate cut.
+;;; It does not mutate AssuranceEvidence or the snapshot that the outcome names.
+(def (assurance-host-admit host obligation evidence outcome)
+ (let* ((entry (required-host-entry host))
+ (snapshot (host-current-snapshot entry)))
+ (and (assurance-evidence-outcome-bound? snapshot evidence outcome)
+ (eq? (.ref evidence 'admission-state) 'candidate)
+ (let (receipt (assurance-host-verify host snapshot obligation evidence outcome))
+ (and receipt
+ (assurance-host-admit-verified host obligation evidence outcome receipt))))))
+
+;;; Verify and Admit can be separate lifecycle stages. Admission consumes an
+;;; exact current Host-issued seal; it must not execute a verifier again or
+;;; refresh an expired seal from a submitted success report.
+(def (assurance-host-verification-current? host receipt snapshot obligation evidence outcome)
+ (let* ((entry (required-host-entry host))
+ (issued (hash-get issued-host-receipts receipt)))
+ (and issued (eq? host (vector-ref issued 0))
+ (host-snapshot-current? entry snapshot obligation evidence outcome)
+ (= (vector-ref issued 1) (vector-ref entry 8))
+ (host-outcome-inputs-current? host snapshot outcome)
+ (assurance-evidence-outcome-bound? snapshot evidence outcome)
+ (agentic-ai-lab-verification-valid?
+ (vector-ref entry 1) receipt
+ (assurance-verification-subject snapshot obligation evidence outcome)
+ (host-instant entry))
+ (= (vector-ref issued 1) (vector-ref entry 8)))))
+
+(def (assurance-host-admit-verified host obligation evidence outcome receipt)
+ (let* ((entry (required-host-entry host))
+ (snapshot (host-current-snapshot entry)))
+ (and (assurance-evidence-outcome-bound? snapshot evidence outcome)
+ (eq? (.ref evidence 'admission-state) 'candidate)
+ (assurance-host-verification-current?
+ host receipt snapshot obligation evidence outcome)
+ (if (host-snapshot-current? entry snapshot obligation evidence outcome)
+ (let* ((next (+ (vector-ref entry 6) 1))
+ (identity-value
+ (string-append (vector-ref entry 0) "/admission/" (number->string next)))
+ (subject-digest-value
+ (assurance-verification-subject-snapshot
+ (assurance-verification-subject snapshot obligation evidence outcome)))
+ (issued-at-value (.ref receipt 'issued-at))
+ (expires-at-value (.ref receipt 'expires-at))
+ (admission
+ (.o identity: identity-value issuer: (vector-ref entry 0)
+ issued-at: issued-at-value expires-at: expires-at-value
+ subject-digest: subject-digest-value)))
+ (vector-set! entry 6 next)
+ (hash-put! issued-admissions admission
+ (vector host receipt identity-value (vector-ref entry 0)
+ issued-at-value expires-at-value subject-digest-value
+ obligation evidence outcome (vector-ref entry 8)))
+ admission)
+ (begin (assurance-host-revoke! host receipt) #f)))))
+
+(def (admission-entry host admission)
+ (let (entry (hash-get issued-admissions admission))
+ (and entry (eq? host (vector-ref entry 0))
+ (object? admission)
+ (.slot? admission 'identity) (.slot? admission 'issuer)
+ (.slot? admission 'issued-at) (.slot? admission 'expires-at)
+ (.slot? admission 'subject-digest)
+ (equal? (.ref admission 'identity) (vector-ref entry 2))
+ (equal? (.ref admission 'issuer) (vector-ref entry 3))
+ (equal? (.ref admission 'issued-at) (vector-ref entry 4))
+ (equal? (.ref admission 'expires-at) (vector-ref entry 5))
+ (equal? (.ref admission 'subject-digest) (vector-ref entry 6))
+ entry)))
+
+(def (current-admission-snapshot host-state issued)
+ (and issued
+ (let* ((now (host-instant host-state))
+ (snapshot (host-current-snapshot host-state))
+ (obligation (vector-ref issued 7))
+ (evidence (vector-ref issued 8))
+ (outcome (vector-ref issued 9))
+ (eligibility
+ (assurance-evaluate-evidence-admission
+ snapshot obligation outcome))
+ (subject
+ (assurance-verification-subject
+ snapshot obligation evidence outcome)))
+ (and (= (vector-ref issued 10) (vector-ref host-state 8))
+ (<= (vector-ref issued 4) now)
+ (< now (vector-ref issued 5))
+ (.ref eligibility 'eligible?)
+ (assurance-evidence-outcome-bound?
+ snapshot evidence outcome)
+ (host-outcome-inputs-current?
+ (vector-ref issued 0) snapshot outcome)
+ (eq? (.ref evidence 'admission-state) 'candidate)
+ (equal? (assurance-verification-subject-snapshot subject)
+ (vector-ref issued 6))
+ (agentic-ai-lab-verification-valid?
+ (vector-ref host-state 1) (vector-ref issued 1)
+ subject now)
+ snapshot))))
+
+(def (assurance-host-admission-current? host admission)
+ (let (host-state (required-host-entry host))
+ (and (current-admission-snapshot
+ host-state (admission-entry host admission)) #t)))
+
+;;; Consume an exact Host admission as one current assurance-edge witness.
+;;; This does not close the claim's full support set or authorize a Decision.
+(def (assurance-host-admitted-support? host relation admission)
+ (let* ((host-state (required-host-entry host))
+ (issued (admission-entry host admission)))
+ (and issued
+ (let (snapshot (current-admission-snapshot host-state issued))
+ (and snapshot
+ (assurance-candidate-support-structural?
+ relation (vector-ref issued 8) (vector-ref issued 7)
+ snapshot))))))
+
+(def (snapshot-node snapshot identity)
+ (find (lambda (node) (equal? (.ref node 'identity) identity))
+ (.ref snapshot 'nodes)))
+
+;;; Source bytes come only from the Host's configured reader. This is a
+;;; conditional application trust boundary, not a claim about Git provenance
+;;; or the verifier's actual process inputs. Re-read and recheck the cut after
+;;; materialization so a moving snapshot cannot qualify an old source.
+(def (host-source-payload host snapshot artifact)
+ (let* ((entry (required-host-entry host))
+ (reader (vector-ref entry 9)))
+ (and reader
+ (assurance-snapshot? snapshot)
+ (assurance-snapshot-canonical? snapshot)
+ (assurance-artifact? artifact)
+ (let* ((current (host-current-snapshot entry))
+ (expected-cut (assurance-snapshot-semantic-digest snapshot))
+ (current-artifact
+ (snapshot-node current (.ref artifact 'identity)))
+ (revision (assoc (.ref artifact 'identity)
+ (.ref current 'source-revisions))))
+ (and (equal? expected-cut
+ (assurance-snapshot-semantic-digest current))
+ current-artifact
+ (assurance-artifact? current-artifact)
+ (equal? (assurance-node-canonical current-artifact)
+ (assurance-node-canonical artifact))
+ revision
+ (equal? (cdr revision) (.ref artifact 'revision))
+ (eq? (.ref artifact 'state) 'supported)
+ (let (payload (reader (.ref artifact 'identity)))
+ (let (matches?
+ (and (or (string? payload) (u8vector? payload))
+ (equal? (source-lock-payload-digest payload)
+ (.ref artifact 'content-digest))))
+ (unless matches? (invalidate-host-cut! entry))
+ (and matches?
+ (equal? expected-cut
+ (assurance-snapshot-semantic-digest
+ (host-current-snapshot entry)))
+ payload))))))))
+
+(def (assurance-host-source-current? host snapshot artifact)
+ (and (host-source-payload host snapshot artifact) #t))
+
+;;; The configured operation receives these POO values as its fourth argument
+;;; when source-reader: is present. The Host, not the operation, selects and
+;;; validates the bytes. It rehashes the handed values after the operation.
+(def (host-materialized-inputs host snapshot outcome)
+ (let loop ((remaining (.ref outcome 'inputs)) (collected '()))
+ (if (null? remaining)
+ (reverse collected)
+ (let* ((input (car remaining))
+ (artifact (snapshot-node snapshot (.ref input 'identity)))
+ (payload-value (and artifact
+ (host-source-payload host snapshot artifact)))
+ (handed-payload
+ (and payload-value
+ (if (string? payload-value)
+ (string-copy payload-value)
+ (u8vector-copy payload-value)))))
+ (and payload-value
+ (loop (cdr remaining)
+ (cons (.o identity: (.ref input 'identity)
+ revision: (.ref input 'revision)
+ digest: (.ref input 'digest)
+ payload: handed-payload)
+ collected)))))))
+
+(def (host-handed-inputs-current? inputs expected)
+ (let loop ((remaining inputs) (original expected))
+ (cond
+ ((null? remaining) (null? original))
+ ((null? original) #f)
+ (else
+ (let ((input (car remaining)) (fields (car original)))
+ (and (equal? (.ref input 'identity) (vector-ref fields 0))
+ (equal? (.ref input 'revision) (vector-ref fields 1))
+ (equal? (.ref input 'digest) (vector-ref fields 2))
+ (let (payload-value (.ref input 'payload))
+ (and (or (string? payload-value) (u8vector? payload-value))
+ (equal? (source-lock-payload-digest payload-value)
+ (vector-ref fields 2))))
+ (loop (cdr remaining) (cdr original))))))))
+
+;;; An optional Host source reader strengthens issuance and currentness for
+;;; every declared verifier input. With no configured reader the old Host
+;;; remains a verification Host, but it cannot claim source-byte checking.
+(def (host-outcome-inputs-current? host snapshot outcome)
+ (let (entry (required-host-entry host))
+ (or (not (vector-ref entry 9))
+ (every (lambda (input)
+ (let (artifact (snapshot-node snapshot
+ (.ref input 'identity)))
+ (and artifact
+ (assurance-host-source-current?
+ host snapshot artifact))))
+ (.ref outcome 'inputs)))))
+
+(def (required-support-link? snapshot obligation claim)
+ (find (lambda (relation)
+ (and (eq? (.ref relation 'plane) 'assurance)
+ (eq? (.ref relation 'relation) 'supports)
+ (equal? (.ref relation 'source) (.ref obligation 'identity))
+ (equal? (.ref relation 'target) (.ref claim 'identity))
+ (not (memq (.ref relation 'modality)
+ '(hypothesized counterfactual)))))
+ (.ref snapshot 'relations)))
+
+(def (admitted-requirement-blocker host host-state snapshot obligation admissions)
+ (let* ((matching
+ (filter (lambda (admission)
+ (let (issued (admission-entry host admission))
+ (and issued
+ (equal? (.ref (vector-ref issued 7) 'identity)
+ (.ref obligation 'identity)))))
+ admissions)))
+ (if (null? matching)
+ 'admission-missing
+ (let loop ((remaining matching) (saw-current? #f))
+ (if (null? remaining)
+ (if saw-current? 'evidence-link-missing 'admission-invalid)
+ (let* ((issued (admission-entry host (car remaining)))
+ (current (current-admission-snapshot host-state issued)))
+ (if (and current
+ (equal? (assurance-snapshot-semantic-digest current)
+ (assurance-snapshot-semantic-digest snapshot)))
+ (if (find (lambda (relation)
+ (assurance-candidate-support-structural?
+ relation (vector-ref issued 8) obligation snapshot))
+ (.ref snapshot 'relations))
+ #f
+ (loop (cdr remaining) #t))
+ (loop (cdr remaining) saw-current?))))))))
+
+(def (required-support-row host host-state snapshot claim-value identity admissions)
+ (let* ((obligation (snapshot-node snapshot identity))
+ (reason
+ (cond
+ ((not (and obligation (assurance-obligation? obligation)))
+ 'obligation-missing)
+ ((or (not (equal? (.ref obligation 'claim) (.ref claim-value 'identity)))
+ (not (equal? (.ref obligation 'subject) (.ref claim-value 'subject)))
+ (not (equal? (.ref obligation 'scope) (.ref claim-value 'scope)))
+ (not (equal? (.ref obligation 'snapshot)
+ (.ref snapshot 'identity)))
+ (not (equal? (.ref obligation 'snapshot-revision)
+ (.ref snapshot 'revision)))
+ (not (equal? (.ref obligation 'snapshot-context-digest)
+ (.ref snapshot 'context-digest)))
+ (memq (.ref obligation 'state)
+ '(violated stale conflicted hypothesized counterfactual
+ not-applicable)))
+ 'obligation-stale)
+ ((not (required-support-link? snapshot obligation claim-value))
+ 'support-link-missing)
+ (else
+ (admitted-requirement-blocker
+ host host-state snapshot obligation admissions)))))
+ (poo-clos-check-model
+ AssessmentRequiredSupport
+ (.o (:: @ (poo-clos-model-prototype AssessmentRequiredSupport))
+ obligation: identity supported?: (not reason) blocker: reason))))
+
+;;; Inert, explainable input for a later Decision evaluator. Completion means
+;;; only that every declared support requirement has a current Host witness;
+;;; it does not resolve policy, validity intervals or Runtime effect authority.
+(def (assurance-host-required-support host claim-value admissions)
+ (unless (and (assurance-claim? claim-value) (list? admissions))
+ (error "invalid required-support inputs"))
+ (let* ((host-state (required-host-entry host))
+ (snapshot (host-current-snapshot host-state))
+ (initial-epoch (vector-ref host-state 8))
+ (current-claim (snapshot-node snapshot (.ref claim-value 'identity)))
+ (required-identities (.ref claim-value 'support-requirements))
+ (rows
+ (map (lambda (identity)
+ (required-support-row
+ host host-state snapshot claim-value identity admissions))
+ required-identities))
+ (global-blockers
+ (append
+ (if (pair? (.ref snapshot 'conflicts)) '(snapshot-conflicted) '())
+ (if (pair? (.ref snapshot 'unresolved)) '(snapshot-unresolved) '())
+ (if (and current-claim (assurance-claim? current-claim)
+ (equal? (assurance-node-canonical claim-value)
+ (assurance-node-canonical current-claim))
+ (member (cons (.ref claim-value 'identity)
+ (.ref claim-value 'revision))
+ (.ref snapshot 'claim-revisions)))
+ '() '(claim-not-current))
+ (if (null? required-identities) '(no-requirements) '())
+ (if (= (length required-identities)
+ (length (delete-duplicates/hash required-identities)))
+ '() '(duplicate-requirements))
+ (if (pair? (.ref claim-value 'assumptions))
+ '(assumptions-unresolved) '())
+ (if (pair? (.ref claim-value 'defeaters))
+ '(defeaters-unresolved) '())
+ (if (memq (.ref claim-value 'state)
+ '(violated stale conflicted hypothesized counterfactual
+ not-applicable))
+ '(claim-state-blocked) '())
+ (if (find (lambda (node)
+ (and (memq (.ref node 'kind)
+ '(counterexample finding))
+ (equal? (.ref node 'challenges)
+ (.ref claim-value 'identity))))
+ (.ref snapshot 'nodes))
+ '(challenge-unresolved) '())))
+ (final-snapshot (host-current-snapshot host-state))
+ (final-blockers
+ (append global-blockers
+ (if (and (= initial-epoch (vector-ref host-state 8))
+ (equal?
+ (assurance-snapshot-semantic-digest snapshot)
+ (assurance-snapshot-semantic-digest final-snapshot)))
+ '() '(source-changed)))))
+ (poo-clos-check-model
+ AssuranceRequiredSupport
+ (.o (:: @ (poo-clos-model-prototype AssuranceRequiredSupport))
+ schema: "lambda-aitia.required-support"
+ claim: (.ref claim-value 'identity)
+ snapshot-digest: (.ref snapshot 'digest)
+ requirements: rows blockers: final-blockers
+ complete?: (and (null? final-blockers)
+ (pair? rows)
+ (every (lambda (row) (.ref row 'supported?)) rows))
+ release-authorized?: #f))))
+
+(def (decision-depends-on-claim? snapshot decision-value claim-value)
+ (find (lambda (relation)
+ (and (eq? (.ref relation 'plane) 'structural)
+ (eq? (.ref relation 'relation) 'depends-on)
+ (equal? (.ref relation 'source)
+ (.ref decision-value 'identity))
+ (equal? (.ref relation 'target)
+ (.ref claim-value 'identity))
+ (not (memq (.ref relation 'modality)
+ '(hypothesized counterfactual)))))
+ (.ref snapshot 'relations)))
+
+(def (decision-preflight-bound? snapshot decision-value claim-value)
+ (and (assurance-decision? decision-value)
+ (assurance-claim? claim-value)
+ (let ((current-decision
+ (snapshot-node snapshot (.ref decision-value 'identity)))
+ (current-claim
+ (snapshot-node snapshot (.ref claim-value 'identity))))
+ (and current-decision (assurance-decision? current-decision)
+ current-claim (assurance-claim? current-claim)
+ (equal? (assurance-node-canonical current-decision)
+ (assurance-node-canonical decision-value))
+ (equal? (assurance-node-canonical current-claim)
+ (assurance-node-canonical claim-value))))
+ (eq? (.ref decision-value 'outcome) 'unknown)
+ (eq? (.ref decision-value 'state) 'unknown)
+ (equal? (.ref decision-value 'subject)
+ (.ref claim-value 'subject))
+ (equal? (.ref decision-value 'snapshot)
+ (.ref snapshot 'identity))
+ (equal? (.ref decision-value 'policy)
+ (.ref snapshot 'policy-identity))
+ (decision-depends-on-claim? snapshot decision-value claim-value)))
+
+(def (same-host-cut? host-state snapshot-value epoch-value)
+ (and (= epoch-value (vector-ref host-state 8))
+ (equal? (assurance-snapshot-semantic-digest snapshot-value)
+ (assurance-snapshot-semantic-digest
+ (host-current-snapshot host-state)))
+ (= epoch-value (vector-ref host-state 8))))
+
+;;; This capability attests a currently bound *undecided* Decision candidate.
+;;; It cannot be projected as Cedar permit or Runtime effect authorization.
+(def (assurance-host-preflight-decision
+ host decision-value claim-value admissions)
+ (unless (list? admissions)
+ (error "Decision preflight requires an admission list"))
+ (let* ((host-state (required-host-entry host))
+ (snapshot-value (host-current-snapshot host-state))
+ (epoch-value (vector-ref host-state 8)))
+ (and (decision-preflight-bound?
+ snapshot-value decision-value claim-value)
+ (.ref (assurance-host-required-support
+ host claim-value admissions)
+ 'complete?)
+ (same-host-cut? host-state snapshot-value epoch-value)
+ (let* ((next (+ (vector-ref host-state 6) 1))
+ (identity-value
+ (string-append (vector-ref host-state 0) "/decision-preflight/"
+ (number->string next)))
+ (issuer-value (vector-ref host-state 0))
+ (decision-identity-value (.ref decision-value 'identity))
+ (claim-identity-value (.ref claim-value 'identity))
+ (snapshot-digest-value (.ref snapshot-value 'digest))
+ (semantic-digest-value
+ (assurance-snapshot-semantic-digest snapshot-value))
+ (preflight
+ (poo-clos-check-model
+ AssuranceDecisionPreflight
+ (.o (:: @ (poo-clos-model-prototype
+ AssuranceDecisionPreflight))
+ schema: "lambda-aitia.decision-preflight"
+ identity: identity-value issuer: issuer-value
+ decision: decision-identity-value
+ claim: claim-identity-value
+ snapshot-digest: snapshot-digest-value
+ release-authorized?: #f))))
+ (vector-set! host-state 6 next)
+ (hash-put! issued-decision-preflights preflight
+ (vector host identity-value issuer-value
+ decision-identity-value claim-identity-value
+ snapshot-digest-value semantic-digest-value
+ epoch-value decision-value claim-value
+ admissions))
+ preflight))))
+
+(def (decision-preflight-entry host preflight)
+ (let (issued (hash-get issued-decision-preflights preflight))
+ (and issued (eq? host (vector-ref issued 0))
+ (assurance-decision-preflight? preflight)
+ (equal? (.ref preflight 'identity) (vector-ref issued 1))
+ (equal? (.ref preflight 'issuer) (vector-ref issued 2))
+ (equal? (.ref preflight 'decision) (vector-ref issued 3))
+ (equal? (.ref preflight 'claim) (vector-ref issued 4))
+ (equal? (.ref preflight 'snapshot-digest) (vector-ref issued 5))
+ issued)))
+
+(def (assurance-host-decision-preflight-current? host preflight)
+ (let* ((host-state (required-host-entry host))
+ (issued (decision-preflight-entry host preflight)))
+ (and issued
+ (= (vector-ref issued 7) (vector-ref host-state 8))
+ (let (snapshot-value (host-current-snapshot host-state))
+ (and (= (vector-ref issued 7) (vector-ref host-state 8))
+ (equal? (.ref snapshot-value 'digest)
+ (vector-ref issued 5))
+ (equal? (assurance-snapshot-semantic-digest snapshot-value)
+ (vector-ref issued 6))
+ (decision-preflight-bound?
+ snapshot-value (vector-ref issued 8) (vector-ref issued 9))
+ (.ref (assurance-host-required-support
+ host (vector-ref issued 9) (vector-ref issued 10))
+ 'complete?)
+ (same-host-cut?
+ host-state snapshot-value (vector-ref issued 7)))))))
+
+;;; Project a current preflight into Agentic AI Lab's inert Cedar request family.
+;;; The request is editable input, not a Host seal, Cedar outcome or effect grant.
+;;; The Runtime Host must independently validate the current source cut at use.
+(def (cedar-request-fingerprint request)
+ ;; Freeze a value digest, not aliases to caller-visible mutable strings.
+ (assurance-canonical-digest
+ (list (.ref request 'principal) (.ref request 'action)
+ (.ref request 'resource) (.alist (.ref request 'context))
+ (.ref request 'intent) (.alist (.ref request 'handoff)))))
+
+(def (assurance-host-cedar-request host preflight action-value intent-value
+ handoff-value)
+ (unless (agentic-ai-lab-cedar-runtime-handoff? handoff-value)
+ (error "Decision Cedar projection requires a Agentic AI Lab runtime handoff"))
+ (let* ((host-state (required-host-entry host))
+ (issued (decision-preflight-entry host preflight)))
+ (and issued
+ (assurance-host-decision-preflight-current? host preflight)
+ (let* ((snapshot-value (host-current-snapshot host-state))
+ (epoch-value (vector-ref host-state 8))
+ (decision-value (vector-ref issued 8))
+ (claim-value (vector-ref issued 9))
+ (context-value
+ (.o aitia_schema: "lambda-aitia.cedar-preflight.v1"
+ agentic_ai_lab_preflight_only: #t
+ aitia_preflight: (vector-ref issued 1)
+ aitia_decision: (vector-ref issued 3)
+ aitia_claim: (vector-ref issued 4)
+ aitia_snapshot_digest: (vector-ref issued 5)
+ aitia_snapshot_semantic_digest: (vector-ref issued 6)
+ aitia_policy: (.ref decision-value 'policy)
+ aitia_policy_revision: (.ref snapshot-value 'policy-revision)
+ aitia_preflight_only: #t))
+ (request
+ (agentic-ai-lab-cedar-authorization-request
+ (.ref decision-value 'authority) action-value
+ (.ref claim-value 'subject) context-value intent-value
+ handoff-value)))
+ (and (= epoch-value (vector-ref issued 7))
+ (same-host-cut? host-state snapshot-value epoch-value)
+ (assurance-host-decision-preflight-current? host preflight)
+ (begin
+ (hash-put! issued-cedar-requests request
+ (vector host preflight epoch-value
+ (cedar-request-fingerprint request)))
+ request))))))
+
+;;; Source-owned use-time check for the exact Host-issued request. This does
+;;; not evaluate Cedar or permit an effect. A future Runtime integration must
+;;; call it at use and retain authorization and effect-handoff ownership.
+(def (assurance-host-cedar-request-current? host request)
+ (let* ((host-state (required-host-entry host))
+ (issued (hash-get issued-cedar-requests request)))
+ (and issued
+ (eq? host (vector-ref issued 0))
+ (agentic-ai-lab-cedar-authorization-request? request)
+ (object? (.ref request 'context))
+ (agentic-ai-lab-cedar-runtime-handoff? (.ref request 'handoff))
+ (= (vector-ref issued 2) (vector-ref host-state 8))
+ (equal? (cedar-request-fingerprint request) (vector-ref issued 3))
+ (assurance-host-decision-preflight-current?
+ host (vector-ref issued 1))
+ (= (vector-ref issued 2) (vector-ref host-state 8)))))
+
+(def (assurance-host-revoke-decision-preflight! host preflight)
+ (required-host-entry host)
+ (unless (decision-preflight-entry host preflight)
+ (error "unissued or modified assurance Decision preflight"))
+ (hash-remove! issued-decision-preflights preflight))
+
+(def (assurance-host-revoke-admission! host admission)
+ (required-host-entry host)
+ (let (issued (admission-entry host admission))
+ (unless issued (error "unissued or modified assurance admission"))
+ (assurance-host-revoke! host (vector-ref issued 1))
+ (hash-remove! issued-admissions admission)))
diff --git a/modules/assurance/interface.ss b/modules/assurance/interface.ss
index cfe8620..3e0be08 100644
--- a/modules/assurance/interface.ss
+++ b/modules/assurance/interface.ss
@@ -3,11 +3,17 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/assurance/types)
-(export (import: :poo-flow/lambda-aitia/modules/assurance/types))
-(import :poo-flow/lambda-aitia/modules/assurance/objects)
-(export (import: :poo-flow/lambda-aitia/modules/assurance/objects))
-(import :poo-flow/lambda-aitia/modules/assurance/funs)
-(export (import: :poo-flow/lambda-aitia/modules/assurance/funs))
-(import :poo-flow/lambda-aitia/modules/assurance/config)
-(export (import: :poo-flow/lambda-aitia/modules/assurance/config))
+(import :agentic-ai-lab/lambda-aitia/modules/assurance/types)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/assurance/types))
+(import :agentic-ai-lab/lambda-aitia/modules/assurance/objects)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/assurance/objects))
+(import :agentic-ai-lab/lambda-aitia/modules/assurance/funs)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/assurance/funs))
+(import :agentic-ai-lab/lambda-aitia/modules/assurance/evidence-admission)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/assurance/evidence-admission))
+(import :agentic-ai-lab/lambda-aitia/modules/assurance/host)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/assurance/host))
+(import :agentic-ai-lab/lambda-aitia/modules/assurance/effect-host)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/assurance/effect-host))
+(import :agentic-ai-lab/lambda-aitia/modules/assurance/config)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/assurance/config))
diff --git a/modules/assurance/invalidation-projection.ss b/modules/assurance/invalidation-projection.ss
index 8792612..2b9e80a 100644
--- a/modules/assurance/invalidation-projection.ss
+++ b/modules/assurance/invalidation-projection.ss
@@ -3,25 +3,25 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-;;; Boundary: Aitia only maps assurance relation semantics onto a POO Flow
+;;; Boundary: Aitia only maps assurance relation semantics onto a Agentic AI Lab
;;; Graph. Impact traversal, relation trajectories, and SCC analysis remain
-;;; owned by POO Flow.
+;;; owned by Agentic AI Lab.
(import (only-in :clan/poo/object .ref)
- (only-in :poo-flow/src/graph/algorithms
- poo-flow-graph-loop-analysis-receipt)
- (only-in :poo-flow/src/graph/types
- poo-flow-graph poo-flow-graph-edge poo-flow-graph-node)
- (only-in :poo-flow/src/modules/temporal-causality/funs
- poo-flow-structural-impact-analyze)
+ (only-in :yuanxu/graph/algorithms
+ agentic-ai-lab-graph-loop-analysis-receipt)
+ (only-in :yuanxu/graph/types
+ agentic-ai-lab-graph agentic-ai-lab-graph-edge agentic-ai-lab-graph-node)
+ (only-in :agentic-ai-lab/modules/temporal-causality/funs
+ agentic-ai-lab-structural-impact-analyze)
(only-in :gerbil/core list-sort)
:std/list/list
- :poo-flow/lambda-aitia/modules/assurance/types)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/types)
(export assurance-invalidation-graph assurance-invalidation-analysis)
(def +assurance-invalidation-relations+
- '(depends-on implements tests refines supports discharges
+ '(depends-on composes implements tests refines supports discharges
invalidates defeats authorizes denies requires-review))
(def (invalidation-graph-id identity)
@@ -31,7 +31,7 @@
(let ((plane (.ref relation 'plane)) (kind (.ref relation 'relation)))
(cond
((and (eq? plane 'structural)
- (memq kind '(depends-on implements tests refines)))
+ (memq kind '(depends-on composes implements tests refines)))
(cons (.ref relation 'target) (.ref relation 'source)))
((and (eq? plane 'assurance) (memq kind '(supports discharges)))
(cons (.ref relation 'target) (.ref relation 'source)))
@@ -54,7 +54,7 @@
(relations (.ref snapshot 'relations))
(graph-nodes
(map (lambda (node)
- (poo-flow-graph-node
+ (agentic-ai-lab-graph-node
(invalidation-graph-id (.ref node 'identity)) (.ref node 'kind)
(list (cons 'semantic-owner 'lambda-aitia)
(cons 'assurance-identity (.ref node 'identity))
@@ -63,7 +63,7 @@
(graph-edges
(map (lambda (entry)
(let ((relation (car entry)) (direction (cdr entry)))
- (poo-flow-graph-edge
+ (agentic-ai-lab-graph-edge
(invalidation-graph-id (car direction))
(invalidation-graph-id (cdr direction))
(.ref relation 'relation)
@@ -74,11 +74,11 @@
(map (lambda (relation)
(cons relation (invalidation-direction relation)))
relations)))))
- (poo-flow-graph
+ (agentic-ai-lab-graph
(invalidation-graph-id (.ref snapshot 'graph-identity))
graph-nodes graph-edges
(list (cons 'semantic-owner 'lambda-aitia)
- (cons 'graph-owner 'poo-flow)
+ (cons 'graph-owner 'agentic-ai-lab)
(cons 'purpose 'structural-invalidation)))))
(def (components->identities components)
@@ -94,13 +94,13 @@
(def (assurance-invalidation-analysis snapshot seeds)
(let* ((graph-value (assurance-invalidation-graph snapshot))
- (loop-analysis (poo-flow-graph-loop-analysis-receipt graph-value)))
+ (loop-analysis (agentic-ai-lab-graph-loop-analysis-receipt graph-value)))
(if (null? seeds)
(values '() '()
(components->identities (.ref loop-analysis 'components))
(components->identities (.ref loop-analysis 'cyclic-components)))
(let* ((impact
- (poo-flow-structural-impact-analyze
+ (agentic-ai-lab-structural-impact-analyze
graph-value
(map invalidation-graph-id seeds)
+assurance-invalidation-relations+
diff --git a/modules/assurance/objects.ss b/modules/assurance/objects.ss
index a3c57f8..394a61c 100644
--- a/modules/assurance/objects.ss
+++ b/modules/assurance/objects.ss
@@ -4,20 +4,22 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :clan/poo/object .o)
- :poo-flow/src/module-system/contribution/model
- :poo-flow/lambda-aitia/modules/assurance/types)
+ (only-in :gerbil/core list-sort)
+ :std/list/list
+ :agentic-ai-lab/core/poo-clos/interface
+ :agentic-ai-lab/lambda-aitia/modules/assurance/types)
(export assurance-artifact assurance-claim assurance-assumption
assurance-observation assurance-event assurance-action
assurance-obligation assurance-evidence assurance-counterexample
assurance-finding assurance-decision assurance-effect
- assurance-relation)
+ assurance-relation assurance-verifier-candidate)
(def (assurance-artifact identity-value revision-value state-value digest-value
owner: owner-value media-kind: media-kind-value
provenance: (provenance-values '()))
- (poo-flow-check-model AssuranceArtifact
- (.o (:: @ (poo-flow-model-prototype AssuranceArtifact))
+ (poo-clos-check-model AssuranceArtifact
+ (.o (:: @ (poo-clos-model-prototype AssuranceArtifact))
identity: identity-value kind: 'artifact revision: revision-value
state: state-value content-digest: digest-value owner: owner-value
media-kind: media-kind-value provenance: provenance-values)))
@@ -28,8 +30,8 @@
support-requirements: (support-values '())
scope: scope-value valid-from: valid-from-value
valid-until: (valid-until-value #f))
- (poo-flow-check-model AssuranceClaim
- (.o (:: @ (poo-flow-model-prototype AssuranceClaim))
+ (poo-clos-check-model AssuranceClaim
+ (.o (:: @ (poo-clos-model-prototype AssuranceClaim))
identity: identity-value kind: 'claim revision: revision-value
state: state-value content-digest: digest-value subject: subject-value
predicate: predicate-value assumptions: assumption-values
@@ -40,8 +42,8 @@
owner: owner-value scope: scope-value
review-policy: review-policy-value
expires-at: (expires-at-value #f))
- (poo-flow-check-model AssuranceAssumption
- (.o (:: @ (poo-flow-model-prototype AssuranceAssumption))
+ (poo-clos-check-model AssuranceAssumption
+ (.o (:: @ (poo-clos-model-prototype AssuranceAssumption))
identity: identity-value kind: 'assumption revision: revision-value
state: state-value content-digest: digest-value owner: owner-value
scope: scope-value review-policy: review-policy-value
@@ -50,8 +52,8 @@
subject: subject-value source: source-value
clock-role: clock-role-value
logical-position: logical-position-value)
- (poo-flow-check-model AssuranceObservation
- (.o (:: @ (poo-flow-model-prototype AssuranceObservation))
+ (poo-clos-check-model AssuranceObservation
+ (.o (:: @ (poo-clos-model-prototype AssuranceObservation))
identity: identity-value kind: 'observation revision: revision-value
state: state-value content-digest: digest-value subject: subject-value
source: source-value clock-role: clock-role-value
@@ -61,8 +63,8 @@
observation: observation-value payload-digest: payload-digest-value
modality: modality-value commitment-state: commitment-value
causal-parents: (causal-parent-values '()))
- (poo-flow-check-model AssuranceEvent
- (.o (:: @ (poo-flow-model-prototype AssuranceEvent))
+ (poo-clos-check-model AssuranceEvent
+ (.o (:: @ (poo-clos-model-prototype AssuranceEvent))
identity: identity-value kind: 'event revision: revision-value
state: state-value content-digest: digest-value subject: subject-value
event-kind: event-kind-value observation: observation-value
@@ -71,8 +73,8 @@
(def (assurance-action identity-value revision-value state-value digest-value
subject: subject-value action-kind: action-kind-value
requested-by: requested-by-value scope: scope-value)
- (poo-flow-check-model AssuranceAction
- (.o (:: @ (poo-flow-model-prototype AssuranceAction))
+ (poo-clos-check-model AssuranceAction
+ (.o (:: @ (poo-clos-model-prototype AssuranceAction))
identity: identity-value kind: 'action revision: revision-value
state: state-value content-digest: digest-value subject: subject-value
action-kind: action-kind-value requested-by: requested-by-value
@@ -80,12 +82,16 @@
(def (assurance-obligation identity-value revision-value state-value digest-value
subject: subject-value claim: claim-value
snapshot: snapshot-value evidence-kind: evidence-kind-value
- capability: capability-value scope: scope-value)
- (poo-flow-check-model AssuranceObligation
- (.o (:: @ (poo-flow-model-prototype AssuranceObligation))
+ capability: capability-value scope: scope-value
+ snapshot-revision: (snapshot-revision-value #f)
+ snapshot-context-digest: (snapshot-context-value #f))
+ (poo-clos-check-model AssuranceObligation
+ (.o (:: @ (poo-clos-model-prototype AssuranceObligation))
identity: identity-value kind: 'obligation revision: revision-value
state: state-value content-digest: digest-value subject: subject-value
claim: claim-value snapshot: snapshot-value evidence-kind: evidence-kind-value
+ snapshot-revision: snapshot-revision-value
+ snapshot-context-digest: snapshot-context-value
capability: capability-value scope: scope-value)))
(def (assurance-evidence identity-value revision-value state-value digest-value
producer: producer-value tool: tool-value
@@ -95,8 +101,8 @@
scope: scope-value valid-from: valid-from-value
valid-until: (valid-until-value #f)
admission-state: admission-state-value)
- (poo-flow-check-model AssuranceEvidence
- (.o (:: @ (poo-flow-model-prototype AssuranceEvidence))
+ (poo-clos-check-model AssuranceEvidence
+ (.o (:: @ (poo-clos-model-prototype AssuranceEvidence))
identity: identity-value kind: 'evidence revision: revision-value
state: state-value content-digest: digest-value producer: producer-value
tool: tool-value tool-version: tool-version-value
@@ -106,8 +112,8 @@
(def (assurance-counterexample identity-value revision-value state-value digest-value
subject: subject-value challenges: challenges-value
evidence: evidence-value details-digest: details-digest-value)
- (poo-flow-check-model AssuranceCounterexample
- (.o (:: @ (poo-flow-model-prototype AssuranceCounterexample))
+ (poo-clos-check-model AssuranceCounterexample
+ (.o (:: @ (poo-clos-model-prototype AssuranceCounterexample))
identity: identity-value kind: 'counterexample revision: revision-value
state: state-value content-digest: digest-value subject: subject-value
challenges: challenges-value evidence: evidence-value
@@ -115,8 +121,8 @@
(def (assurance-finding identity-value revision-value state-value digest-value
subject: subject-value challenges: challenges-value
evidence: evidence-value finding-kind: finding-kind-value)
- (poo-flow-check-model AssuranceFinding
- (.o (:: @ (poo-flow-model-prototype AssuranceFinding))
+ (poo-clos-check-model AssuranceFinding
+ (.o (:: @ (poo-clos-model-prototype AssuranceFinding))
identity: identity-value kind: 'finding revision: revision-value
state: state-value content-digest: digest-value subject: subject-value
challenges: challenges-value evidence: evidence-value
@@ -125,8 +131,8 @@
subject: subject-value snapshot: snapshot-value
policy: policy-value authority: authority-value
outcome: outcome-value)
- (poo-flow-check-model AssuranceDecision
- (.o (:: @ (poo-flow-model-prototype AssuranceDecision))
+ (poo-clos-check-model AssuranceDecision
+ (.o (:: @ (poo-clos-model-prototype AssuranceDecision))
identity: identity-value kind: 'decision revision: revision-value
state: state-value content-digest: digest-value subject: subject-value
snapshot: snapshot-value policy: policy-value authority: authority-value
@@ -134,8 +140,8 @@
(def (assurance-effect identity-value revision-value state-value digest-value
subject: subject-value decision: decision-value
effect-kind: effect-kind-value effect-state: effect-state-value)
- (poo-flow-check-model AssuranceEffect
- (.o (:: @ (poo-flow-model-prototype AssuranceEffect))
+ (poo-clos-check-model AssuranceEffect
+ (.o (:: @ (poo-clos-model-prototype AssuranceEffect))
identity: identity-value kind: 'effect revision: revision-value
state: state-value content-digest: digest-value subject: subject-value
decision: decision-value effect-kind: effect-kind-value
@@ -149,8 +155,27 @@
(unless (eq? plane-value owned-plane)
(error "assurance relation crosses its owned plane"
relation-value plane-value owned-plane))
- (poo-flow-check-model
+ (poo-clos-check-model
AssuranceRelation
- (.o (:: @ (poo-flow-model-prototype AssuranceRelation))
+ (.o (:: @ (poo-clos-model-prototype AssuranceRelation))
identity: identity-value plane: plane-value relation: relation-value
source: source-value target: target-value modality: modality-value))))
+
+(def (assurance-verifier-candidate identity-value revision-value
+ priority-value evidence-kind-values
+ capability-value)
+ (unless (and (list? evidence-kind-values)
+ (pair? evidence-kind-values)
+ (every assurance-evidence-kind? evidence-kind-values))
+ (error "invalid verifier evidence kinds" evidence-kind-values))
+ (poo-clos-check-model
+ AssuranceVerifierCandidate
+ (.o (:: @ (poo-clos-model-prototype AssuranceVerifierCandidate))
+ identity: identity-value revision: revision-value
+ priority: priority-value
+ evidence-kinds:
+ (list-sort
+ (lambda (left right)
+ (string (symbol->string left) (symbol->string right)))
+ (delete-duplicates/hash evidence-kind-values))
+ capability: capability-value)))
diff --git a/modules/assurance/types.ss b/modules/assurance/types.ss
index 800c9bc..f5bacc0 100644
--- a/modules/assurance/types.ss
+++ b/modules/assurance/types.ss
@@ -4,27 +4,51 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :clan/poo/object .o .ref .slot? object?)
- :poo-flow/src/module-system/contribution/model
+ :agentic-ai-lab/core/poo-clos/interface
:std/list/list)
(export assurance-text? assurance-digest?
assurance-node-kind? assurance-state? assurance-relation-plane?
assurance-relation-kind? assurance-relation-kind-plane
- assurance-modality?
+ assurance-modality? assurance-evidence-kind?
+assurance-node-kinds+ +assurance-states+
+assurance-relation-planes+ +assurance-modalities+
+ +assurance-evidence-kinds+
AssuranceNode AssuranceArtifact AssuranceClaim AssuranceAssumption
AssuranceObservation AssuranceEvent AssuranceAction
AssuranceObligation AssuranceEvidence AssuranceCounterexample
AssuranceFinding AssuranceDecision AssuranceEffect
AssuranceRelation AssuranceSnapshot
+ AssuranceReplacementRequirement AssuranceReplacementDerivation
+ AssuranceReplacementDeclarationReceipt
+ AssuranceVerificationPolicy AssuranceVerificationRequest
+ AssuranceVerificationPlan AssuranceVerifierCandidate
+ AssuranceVerifierChoice AssuranceVerifierChoiceReceipt
+ AssuranceVerifierInput AssuranceVerifierOutcome
+ AssuranceEvidenceAdmissionReceipt AssuranceVerificationSubject
+ AssuranceRequiredSupport AssessmentRequiredSupport
+ AssuranceDecisionPreflight
+ AssuranceCompositionRequirement AssuranceCompositionDerivation
make-assurance-invalidation-receipt-record
assurance-node? assurance-artifact? assurance-claim?
assurance-assumption? assurance-observation? assurance-event?
assurance-action? assurance-obligation? assurance-evidence?
assurance-counterexample? assurance-finding? assurance-decision?
assurance-effect? assurance-relation? assurance-snapshot?
- assurance-invalidation-receipt? assurance-invalidation-receipt-ref)
+ assurance-replacement-requirement?
+ assurance-replacement-derivation?
+ assurance-replacement-declaration-receipt?
+ assurance-invalidation-receipt? assurance-invalidation-receipt-ref
+ assurance-verification-policy? assurance-verification-request?
+ assurance-verification-plan? assurance-verifier-candidate?
+ assurance-verifier-choice? assurance-verifier-choice-receipt?
+ assurance-verifier-input? assurance-verifier-outcome?
+ assurance-evidence-admission-receipt?
+ assurance-required-support? assessment-required-support?
+ assurance-decision-preflight?
+ assurance-verification-subject?
+ assurance-composition-requirement?
+ assurance-composition-derivation?)
(def +assurance-node-kinds+
'(artifact claim assumption observation event action obligation evidence
@@ -36,6 +60,9 @@
'(provenance structural causal assurance authority))
(def +assurance-modalities+
'(observed declared derived hypothesized counterfactual))
+(def +assurance-evidence-kinds+
+ '(proof model-check replay unit-test integration-test native-test
+ static-analysis authorization-differential human-review))
(def +assurance-relation-kind-planes+
'((derived-from . provenance)
@@ -43,6 +70,7 @@
(cites . provenance)
(used . provenance)
(depends-on . structural)
+ (composes . structural)
(implements . structural)
(tests . structural)
(refines . structural)
@@ -73,6 +101,8 @@
(def (assurance-relation-plane? value)
(if (memq value +assurance-relation-planes+) #t #f))
(def (assurance-modality? value) (if (memq value +assurance-modalities+) #t #f))
+(def (assurance-evidence-kind? value)
+ (if (memq value +assurance-evidence-kinds+) #t #f))
(def (assurance-relation-kind-plane value)
(let ((entry (assq value +assurance-relation-kind-planes+)))
(and entry (cdr entry))))
@@ -84,8 +114,45 @@
(def (enum-slot name predicate)
(poo-clos-direct-slot-definition name type-predicate: predicate))
(def (maybe-text? value) (or (not value) (assurance-text? value)))
+(def (maybe-digest? value) (or (not value) (assurance-digest? value)))
(def (text-list? values)
(and (list? values) (every assurance-text? values)))
+(def (symbol-list? values)
+ (and (list? values) (every symbol? values)))
+(def (evidence-kind-list? values)
+ (and (list? values) (pair? values)
+ (every assurance-evidence-kind? values)))
+(def (verifier-choice-reason? value)
+ (memq value '(chosen request-blocked evidence-kind-unsupported
+ capability-mismatch lower-priority)))
+(def (composition-blocker? value)
+ (or (not value)
+ (memq value '(conflicted-snapshot unresolved-frontier
+ invalid-composition-claim insufficient-components
+ invalid-component-claim missing-direct-obligation
+ stale-direct-obligation))))
+(def (verification-blocker? value)
+ (or (not value)
+ (memq value '(conflicted-snapshot unresolved-frontier
+ capability-unavailable stale-obligation
+ dependency-unplanned dependency-blocked
+ dependency-cycle))))
+(def (replacement-blocker? value)
+ (or (not value)
+ (memq value '(source-conflicted source-unresolved change-unresolved
+ stale-source
+ target-unchanged target-conflicted target-unresolved
+ target-identity-changed graph-changed
+ policy-changed claim-missing claim-changed))))
+(def (replacement-declaration-blocker? value)
+ (or (not value)
+ (memq value '(derivation-mismatch source-requirement-missing
+ source-requirement-blocked target-frontier
+ candidate-missing candidate-not-fresh candidate-not-unbound
+ candidate-not-unknown candidate-claim-mismatch
+ candidate-subject-mismatch candidate-scope-mismatch
+ claim-not-declared support-link-missing
+ support-link-hypothetical))))
(def (revision-bindings? values)
(and (list? values)
(every (lambda (binding)
@@ -95,6 +162,15 @@
values)))
(def (witness-list? values)
(and (list? values) (every text-list? values)))
+(def (invalidation-trajectories? values)
+ (and (list? values)
+ (every (lambda (entry)
+ (and (list? entry)
+ (= (length entry) 3)
+ (assurance-text? (car entry))
+ (text-list? (cadr entry))
+ (text-list? (caddr entry))))
+ values)))
(def (nonnegative-integer? value)
(and (integer? value) (>= value 0)))
(def (one-of values)
@@ -151,7 +227,10 @@
(semantic-node-class
'aitia/obligation
(list (text-slot 'subject) (text-slot 'claim) (text-slot 'snapshot)
- (enum-slot 'evidence-kind symbol?) (enum-slot 'capability symbol?)
+ (enum-slot 'snapshot-revision maybe-text?)
+ (enum-slot 'snapshot-context-digest maybe-digest?)
+ (enum-slot 'evidence-kind assurance-evidence-kind?)
+ (enum-slot 'capability symbol?)
(text-slot 'scope))))
(def AssuranceEvidence
(semantic-node-class
@@ -213,12 +292,288 @@
(text-slot 'policy-revision)
(enum-slot 'evidence-identities text-list?)
(enum-slot 'state assurance-state?)
+ (enum-slot 'context-digest assurance-digest?)
(enum-slot 'digest assurance-digest?)
(enum-slot 'nodes node-list?)
(enum-slot 'relations relation-list?)
(enum-slot 'unresolved text-list?)
(enum-slot 'conflicts text-list?))))
+;;; A derivation names questions requiring a fresh declaration; it does not
+;;; construct, bind, discharge or authorize a replacement obligation.
+(def AssuranceReplacementRequirement
+ (poo-clos-class 'aitia/replacement-requirement
+ direct-slots:
+ (list (text-slot 'source-obligation)
+ (text-slot 'source-revision)
+ (text-slot 'claim)
+ (text-slot 'subject)
+ (enum-slot 'evidence-kind assurance-evidence-kind?)
+ (enum-slot 'capability symbol?)
+ (text-slot 'scope)
+ (enum-slot 'blocker replacement-blocker?))))
+(def (replacement-requirement-list? values)
+ (and (list? values) (every assurance-replacement-requirement? values)))
+(def AssuranceReplacementDerivation
+ (poo-clos-class 'aitia/replacement-derivation
+ direct-slots:
+ (list (enum-slot 'schema
+ (lambda (value)
+ (equal? value "lambda-aitia.replacement-requirements")))
+ (text-slot 'identity)
+ (enum-slot 'source-snapshot-digest assurance-digest?)
+ (enum-slot 'target-snapshot-digest assurance-digest?)
+ (enum-slot 'changed text-list?)
+ (enum-slot 'witnesses invalidation-trajectories?)
+ (enum-slot 'unresolved text-list?)
+ (enum-slot 'requirements replacement-requirement-list?)
+ (enum-slot 'digest assurance-digest?)
+ (enum-slot 'verifier-executed? (one-of '(#f)))
+ (enum-slot 'release-authorized? (one-of '(#f))))))
+
+;;; A caller-authored target obligation is checked and bound, never invented.
+;;; This receipt is inert even when its blocker is false.
+(def AssuranceReplacementDeclarationReceipt
+ (poo-clos-class 'aitia/replacement-declaration-receipt
+ direct-slots:
+ (list (enum-slot 'schema
+ (lambda (value)
+ (equal? value "lambda-aitia.replacement-declaration")))
+ (text-slot 'identity)
+ (enum-slot 'derivation-digest assurance-digest?)
+ (enum-slot 'source-snapshot-digest assurance-digest?)
+ (enum-slot 'draft-snapshot-digest assurance-digest?)
+ (enum-slot 'final-snapshot-digest maybe-digest?)
+ (text-slot 'source-obligation)
+ (text-slot 'target-obligation)
+ (enum-slot 'blocker replacement-declaration-blocker?)
+ (enum-slot 'digest assurance-digest?)
+ (enum-slot 'verifier-executed? (one-of '(#f)))
+ (enum-slot 'release-authorized? (one-of '(#f))))))
+
+;;; Public planning values remain POO-native and contain no executable hook.
+(def AssuranceVerificationPolicy
+ (poo-clos-class 'aitia/verification-policy
+ direct-slots:
+ (list (text-slot 'identity)
+ (text-slot 'revision)
+ (enum-slot 'capabilities symbol-list?)
+ (enum-slot 'planner-executes? (one-of '(#f)))
+ (enum-slot 'grants-authority? (one-of '(#f))))))
+(def AssuranceVerificationRequest
+ (poo-clos-class 'aitia/verification-request
+ direct-slots:
+ (list (text-slot 'obligation-identity)
+ (text-slot 'subject)
+ (text-slot 'claim)
+ (enum-slot 'snapshot-digest assurance-digest?)
+ (enum-slot 'evidence-kind assurance-evidence-kind?)
+ (enum-slot 'capability symbol?)
+ (enum-slot 'dependencies text-list?)
+ (enum-slot 'selected? boolean?)
+ (enum-slot 'blocker verification-blocker?))))
+(def (verification-request-list? values)
+ (and (list? values)
+ (every (lambda (value)
+ (assurance-verification-request? value))
+ values)))
+(def AssuranceVerificationPlan
+ (poo-clos-class 'aitia/verification-plan
+ direct-slots:
+ (list (enum-slot 'schema
+ (lambda (value)
+ (equal? value "lambda-aitia.planning-result")))
+ (text-slot 'identity)
+ (enum-slot 'snapshot-digest assurance-digest?)
+ (text-slot 'policy-identity)
+ (text-slot 'policy-revision)
+ (enum-slot 'digest assurance-digest?)
+ (enum-slot 'selected-obligations text-list?)
+ (enum-slot 'blocked-obligations text-list?)
+ (enum-slot 'changed text-list?)
+ (enum-slot 'impacted text-list?)
+ (enum-slot 'blocked-effects text-list?)
+ (enum-slot 'cycle-path text-list?)
+ (enum-slot 'cyclic-components witness-list?)
+ (enum-slot 'witnesses invalidation-trajectories?)
+ (enum-slot 'requests verification-request-list?)
+ (enum-slot 'unresolved text-list?)
+ (enum-slot 'conflicts text-list?)
+ (enum-slot 'verifier-executed? (one-of '(#f)))
+ (enum-slot 'release-authorized? (one-of '(#f)))
+ (enum-slot 'runtime-executed? (one-of '(#f))))))
+
+;;; These are declared candidates and inert explanation values, never adapter
+;;; handles or execution receipts.
+(def AssuranceVerifierCandidate
+ (poo-clos-class 'aitia/verifier-candidate
+ direct-slots:
+ (list (text-slot 'identity)
+ (text-slot 'revision)
+ (enum-slot 'priority nonnegative-integer?)
+ (enum-slot 'evidence-kinds evidence-kind-list?)
+ (enum-slot 'capability symbol?))))
+(def (verifier-candidate-list? values)
+ (and (list? values) (every assurance-verifier-candidate? values)))
+(def AssuranceVerifierChoice
+ (poo-clos-class 'aitia/verifier-choice
+ direct-slots:
+ (list (text-slot 'obligation-identity)
+ (text-slot 'candidate-identity)
+ (enum-slot 'selected? boolean?)
+ (enum-slot 'reason verifier-choice-reason?))))
+(def (verifier-choice-list? values)
+ (and (list? values) (every assurance-verifier-choice? values)))
+(def AssuranceVerifierChoiceReceipt
+ (poo-clos-class 'aitia/verifier-choice-receipt
+ direct-slots:
+ (list (enum-slot 'schema
+ (lambda (value)
+ (equal? value "lambda-aitia.verifier-choices")))
+ (text-slot 'identity)
+ (enum-slot 'plan-digest assurance-digest?)
+ (enum-slot 'candidates verifier-candidate-list?)
+ (enum-slot 'choices verifier-choice-list?)
+ (enum-slot 'unassigned-obligations text-list?)
+ (enum-slot 'digest assurance-digest?)
+ (enum-slot 'verifier-executed? (one-of '(#f)))
+ (enum-slot 'release-authorized? (one-of '(#f))))))
+
+;;; A reported tool result is not an admission. Input bindings carry both the
+;;; source revision and digest so a green exit cannot float across snapshots.
+(def AssuranceVerifierInput
+ (poo-clos-class 'aitia/verifier-input
+ direct-slots:
+ (list (text-slot 'identity) (text-slot 'revision)
+ (enum-slot 'digest assurance-digest?))))
+(def (verifier-input-list? values)
+ (and (list? values) (every assurance-verifier-input? values)))
+(def AssuranceVerifierOutcome
+ (poo-clos-class 'aitia/verifier-outcome
+ direct-slots:
+ (list (text-slot 'identity)
+ (enum-slot 'status
+ (one-of '(succeeded failed timed-out unavailable indeterminate)))
+ (text-slot 'producer) (text-slot 'tool) (text-slot 'tool-version)
+ (text-slot 'obligation) (text-slot 'subject) (text-slot 'scope)
+ (text-slot 'snapshot-revision)
+ (enum-slot 'snapshot-context-digest assurance-digest?)
+ (enum-slot 'inputs verifier-input-list?)
+ (enum-slot 'output-digest maybe-digest?)
+ (enum-slot 'accountable-authority maybe-text?)
+ (enum-slot 'review-scope maybe-text?))))
+(def AssuranceEvidenceAdmissionReceipt
+ (poo-clos-class 'aitia/evidence-admission-receipt
+ direct-slots:
+ (list (enum-slot 'schema
+ (lambda (value)
+ (equal? value "lambda-aitia.evidence-admission")))
+ (text-slot 'outcome) (text-slot 'obligation)
+ (enum-slot 'outcome-digest assurance-digest?)
+ (enum-slot 'snapshot-digest assurance-digest?)
+ (enum-slot 'digest assurance-digest?)
+ (enum-slot 'eligible? boolean?)
+ (enum-slot 'blocker
+ (lambda (value)
+ (or (not value)
+ (memq value
+ '(outcome-not-successful snapshot-conflicted
+ stale-obligation
+ outcome-binding-mismatch missing-output
+ missing-inputs duplicate-inputs
+ input-binding-mismatch
+ human-authority-missing)))))
+ (enum-slot 'verifier-executed? (one-of '(#f)))
+ (enum-slot 'release-authorized? (one-of '(#f))))))
+
+;;; Exact subject for a Host-owned Agentic AI Lab verification adapter. No
+;;; caller-authored presentation slot is an execution attestation by itself.
+(def AssuranceVerificationSubject
+ (poo-clos-class 'aitia/verification-subject
+ direct-slots:
+ (list (enum-slot 'snapshot (lambda (value) (assurance-snapshot? value)))
+ (enum-slot 'obligation (lambda (value) (assurance-obligation? value)))
+ (enum-slot 'evidence (lambda (value) (assurance-evidence? value)))
+ (enum-slot 'outcome
+ (lambda (value) (assurance-verifier-outcome? value))))))
+
+;;; Host-checked support inventory is an input to Decision evaluation, not a
+;;; Decision or an authority receipt. A POO presentation cannot grant release.
+(def (required-support-blocker? value)
+ (or (not value)
+ (memq value '(obligation-missing obligation-stale support-link-missing
+ admission-missing admission-invalid
+ evidence-link-missing))))
+(def AssessmentRequiredSupport
+ (poo-clos-class 'aitia/required-support-assessment
+ direct-slots:
+ (list (text-slot 'obligation)
+ (enum-slot 'supported? boolean?)
+ (enum-slot 'blocker required-support-blocker?))))
+(def (required-support-list? values)
+ (and (list? values) (every assessment-required-support? values)))
+(def (required-support-global-blocker? value)
+ (memq value '(snapshot-conflicted snapshot-unresolved claim-not-current
+ no-requirements duplicate-requirements
+ assumptions-unresolved defeaters-unresolved
+ claim-state-blocked challenge-unresolved source-changed)))
+(def (required-support-global-blockers? values)
+ (and (list? values)
+ (every required-support-global-blocker? values)))
+(def AssuranceRequiredSupport
+ (poo-clos-class 'aitia/required-support
+ direct-slots:
+ (list (enum-slot 'schema
+ (lambda (value)
+ (equal? value "lambda-aitia.required-support")))
+ (text-slot 'claim)
+ (enum-slot 'snapshot-digest assurance-digest?)
+ (enum-slot 'requirements required-support-list?)
+ (enum-slot 'blockers required-support-global-blockers?)
+ (enum-slot 'complete? boolean?)
+ (enum-slot 'release-authorized? (one-of '(#f))))))
+
+;;; A Host-issued preflight proves only that an undecided Decision and its
+;;; required support were current at issuance. Cedar/Runtime own authority.
+(def AssuranceDecisionPreflight
+ (poo-clos-class 'aitia/decision-preflight
+ direct-slots:
+ (list (enum-slot 'schema
+ (lambda (value)
+ (equal? value "lambda-aitia.decision-preflight")))
+ (text-slot 'identity)
+ (text-slot 'issuer)
+ (text-slot 'decision)
+ (text-slot 'claim)
+ (enum-slot 'snapshot-digest assurance-digest?)
+ (enum-slot 'release-authorized? (one-of '(#f))))))
+
+;;; A composition needs its own snapshot-bound obligation. Component support
+;;; remains separate and cannot discharge this structural requirement.
+(def AssuranceCompositionRequirement
+ (poo-clos-class 'aitia/composition-requirement
+ direct-slots:
+ (list (text-slot 'composition-claim)
+ (enum-slot 'component-claims text-list?)
+ (enum-slot 'direct-obligations text-list?)
+ (enum-slot 'current-obligations text-list?)
+ (enum-slot 'blocker composition-blocker?))))
+(def (composition-requirement-list? values)
+ (and (list? values)
+ (every assurance-composition-requirement? values)))
+(def AssuranceCompositionDerivation
+ (poo-clos-class 'aitia/composition-derivation
+ direct-slots:
+ (list (enum-slot 'schema
+ (lambda (value)
+ (equal? value "lambda-aitia.composition-requirements")))
+ (text-slot 'identity)
+ (enum-slot 'snapshot-digest assurance-digest?)
+ (enum-slot 'requirements composition-requirement-list?)
+ (enum-slot 'digest assurance-digest?)
+ (enum-slot 'verifier-executed? (one-of '(#f)))
+ (enum-slot 'release-authorized? (one-of '(#f))))))
+
(defstruct assurance-invalidation-receipt-record
(identity snapshot-digest changed impacted invalidated-evidence
required-obligations invalidated-decisions blocked-effects witnesses unresolved
@@ -227,22 +582,22 @@
transparent: #t)
(def (node-of-kind? class kind value)
- (and (poo-flow-model? class value) (eq? (.ref value 'kind) kind)))
+ (and (poo-clos-model? class value) (eq? (.ref value 'kind) kind)))
(def (assurance-node? value)
(and (object? value) (.slot? value 'kind)
(case (.ref value 'kind)
- ((artifact) (poo-flow-model? AssuranceArtifact value))
- ((claim) (poo-flow-model? AssuranceClaim value))
- ((assumption) (poo-flow-model? AssuranceAssumption value))
- ((observation) (poo-flow-model? AssuranceObservation value))
- ((event) (poo-flow-model? AssuranceEvent value))
- ((action) (poo-flow-model? AssuranceAction value))
- ((obligation) (poo-flow-model? AssuranceObligation value))
- ((evidence) (poo-flow-model? AssuranceEvidence value))
- ((counterexample) (poo-flow-model? AssuranceCounterexample value))
- ((finding) (poo-flow-model? AssuranceFinding value))
- ((decision) (poo-flow-model? AssuranceDecision value))
- ((effect) (poo-flow-model? AssuranceEffect value))
+ ((artifact) (poo-clos-model? AssuranceArtifact value))
+ ((claim) (poo-clos-model? AssuranceClaim value))
+ ((assumption) (poo-clos-model? AssuranceAssumption value))
+ ((observation) (poo-clos-model? AssuranceObservation value))
+ ((event) (poo-clos-model? AssuranceEvent value))
+ ((action) (poo-clos-model? AssuranceAction value))
+ ((obligation) (poo-clos-model? AssuranceObligation value))
+ ((evidence) (poo-clos-model? AssuranceEvidence value))
+ ((counterexample) (poo-clos-model? AssuranceCounterexample value))
+ ((finding) (poo-clos-model? AssuranceFinding value))
+ ((decision) (poo-clos-model? AssuranceDecision value))
+ ((effect) (poo-clos-model? AssuranceEffect value))
(else #f))))
(def (assurance-artifact? value) (node-of-kind? AssuranceArtifact 'artifact value))
(def (assurance-claim? value) (node-of-kind? AssuranceClaim 'claim value))
@@ -264,10 +619,69 @@
(node-of-kind? AssuranceDecision 'decision value))
(def (assurance-effect? value) (node-of-kind? AssuranceEffect 'effect value))
(def (assurance-relation? value)
- (and (poo-flow-model? AssuranceRelation value)
+ (and (poo-clos-model? AssuranceRelation value)
(eq? (.ref value 'plane)
(assurance-relation-kind-plane (.ref value 'relation)))))
-(def (assurance-snapshot? value) (poo-flow-model? AssuranceSnapshot value))
+(def (assurance-snapshot? value) (poo-clos-model? AssuranceSnapshot value))
+(def (assurance-replacement-requirement? value)
+ (poo-clos-model? AssuranceReplacementRequirement value))
+(def (assurance-replacement-derivation? value)
+ (poo-clos-model? AssuranceReplacementDerivation value))
+(def (assurance-replacement-declaration-receipt? value)
+ (and (poo-clos-model? AssuranceReplacementDeclarationReceipt value)
+ (eq? (not (.ref value 'blocker))
+ (if (.ref value 'final-snapshot-digest) #t #f))))
+(def (assurance-verification-policy? value)
+ (poo-clos-model? AssuranceVerificationPolicy value))
+(def (assurance-verification-request? value)
+ (and (poo-clos-model? AssuranceVerificationRequest value)
+ (eq? (.ref value 'selected?)
+ (not (.ref value 'blocker)))))
+(def (assurance-verification-plan? value)
+ (and (poo-clos-model? AssuranceVerificationPlan value)
+ (equal?
+ (.ref value 'selected-obligations)
+ (map (lambda (request) (.ref request 'obligation-identity))
+ (filter (lambda (request) (.ref request 'selected?))
+ (.ref value 'requests))))
+ (equal?
+ (.ref value 'blocked-obligations)
+ (map (lambda (request) (.ref request 'obligation-identity))
+ (filter (lambda (request) (not (.ref request 'selected?)))
+ (.ref value 'requests))))))
+(def (assurance-verifier-candidate? value)
+ (poo-clos-model? AssuranceVerifierCandidate value))
+(def (assurance-verifier-choice? value)
+ (and (poo-clos-model? AssuranceVerifierChoice value)
+ (eq? (.ref value 'selected?)
+ (eq? (.ref value 'reason) 'chosen))))
+(def (assurance-verifier-choice-receipt? value)
+ (poo-clos-model? AssuranceVerifierChoiceReceipt value))
+(def (assurance-verifier-input? value)
+ (poo-clos-model? AssuranceVerifierInput value))
+(def (assurance-verifier-outcome? value)
+ (poo-clos-model? AssuranceVerifierOutcome value))
+(def (assurance-evidence-admission-receipt? value)
+ (and (poo-clos-model? AssuranceEvidenceAdmissionReceipt value)
+ (eq? (.ref value 'eligible?) (not (.ref value 'blocker)))))
+(def (assessment-required-support? value)
+ (and (poo-clos-model? AssessmentRequiredSupport value)
+ (eq? (.ref value 'supported?) (not (.ref value 'blocker)))))
+(def (assurance-required-support? value)
+ (and (poo-clos-model? AssuranceRequiredSupport value)
+ (eq? (.ref value 'complete?)
+ (and (null? (.ref value 'blockers))
+ (pair? (.ref value 'requirements))
+ (every (lambda (item) (.ref item 'supported?))
+ (.ref value 'requirements))))))
+(def (assurance-decision-preflight? value)
+ (poo-clos-model? AssuranceDecisionPreflight value))
+(def (assurance-verification-subject? value)
+ (poo-clos-model? AssuranceVerificationSubject value))
+(def (assurance-composition-requirement? value)
+ (poo-clos-model? AssuranceCompositionRequirement value))
+(def (assurance-composition-derivation? value)
+ (poo-clos-model? AssuranceCompositionDerivation value))
(def (assurance-invalidation-receipt? value)
(assurance-invalidation-receipt-record? value))
(def (assurance-invalidation-receipt-ref receipt name)
diff --git a/modules/assurance/verification-projection.ss b/modules/assurance/verification-projection.ss
new file mode 100644
index 0000000..205519d
--- /dev/null
+++ b/modules/assurance/verification-projection.ss
@@ -0,0 +1,73 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Aitia owns the meaning of obligation dependencies; Agentic AI Lab owns Graph
+;;; ordering, reachability and cycle algorithms. No verifier runs here.
+
+(import (only-in :clan/poo/object .ref)
+ (only-in :gerbil/core list-sort)
+ :std/list/list
+ (only-in :yuanxu/graph/types
+ agentic-ai-lab-graph agentic-ai-lab-graph-edge agentic-ai-lab-graph-node)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/types)
+
+(export assurance-verification-dependency-graph)
+
+(def (canonical-ids ids)
+ (list-sort string (delete-duplicates/hash ids)))
+
+(def (obligation-node? nodes identity)
+ (let ((node
+ (find (lambda (candidate)
+ (string=? (.ref candidate 'identity) identity))
+ nodes)))
+ (and node (assurance-obligation? node))))
+
+;;; Returns a POO Graph and the direct prerequisite IDs for each planned
+;;; obligation. A prerequisite outside the affected set remains visible to
+;;; the planner; it is never presumed discharged by an older plan.
+(def (assurance-verification-dependency-graph snapshot obligation-ids)
+ (unless (and (assurance-snapshot? snapshot)
+ (list? obligation-ids)
+ (every assurance-text? obligation-ids))
+ (error "invalid verification dependency projection"))
+ (let* ((ids (canonical-ids obligation-ids))
+ (nodes (.ref snapshot 'nodes))
+ (relations (.ref snapshot 'relations))
+ (prerequisites
+ (map
+ (lambda (id)
+ (cons id
+ (canonical-ids
+ (map (lambda (relation) (.ref relation 'target))
+ (filter
+ (lambda (relation)
+ (and (eq? (.ref relation 'plane) 'structural)
+ (eq? (.ref relation 'relation) 'depends-on)
+ (string=? (.ref relation 'source) id)
+ (obligation-node?
+ nodes (.ref relation 'target))))
+ relations)))))
+ ids))
+ (edges
+ (concatenate
+ (map
+ (lambda (entry)
+ (map (lambda (prerequisite)
+ (agentic-ai-lab-graph-edge prerequisite (car entry)
+ 'depends-on))
+ (filter (lambda (prerequisite)
+ (member prerequisite ids))
+ (cdr entry))))
+ prerequisites)))
+ (graph-value
+ (agentic-ai-lab-graph
+ (string-append (.ref snapshot 'graph-identity) "/verification")
+ (map agentic-ai-lab-graph-node ids)
+ edges
+ (list (cons 'semantic-owner 'lambda-aitia)
+ (cons 'graph-owner 'agentic-ai-lab)
+ (cons 'purpose 'verification-dependencies)))))
+ (values graph-value prerequisites)))
diff --git a/modules/formal-methods/config.ss b/modules/formal-methods/config.ss
index 038f90f..1b769c5 100644
--- a/modules/formal-methods/config.ss
+++ b/modules/formal-methods/config.ss
@@ -3,25 +3,25 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-;;; Boundary: Aitia-owned formal-method providers over the POO Flow Proof core.
+;;; Boundary: Aitia-owned formal-method providers over the Agentic AI Lab Proof core.
;;; Invariant: provider declarations create obligations; they never claim that
;;; an engine ran or that a proof/model/policy was admitted.
(import (only-in :clan/poo/object .o)
- (only-in :poo-flow/src/modules/proof/interface
- poo-flow-proof-module)
+ (only-in :agentic-ai-lab/modules/proof/interface
+ agentic-ai-lab-proof-module)
"types.ss"
"objects.ss"
"funs.ss")
-(export aitia-tla-plus-provider
+(export aitia-quint-provider
aitia-lean-provider
aitia-cedar-provider
aitia-formal-methods-module)
-(def aitia-tla-plus-provider
+(def aitia-quint-provider
(aitia-formal-method-provider
- 'tla+
+ 'quint
'state-transition-model-checking
'(module model-checking-configuration trace receipt)))
@@ -38,8 +38,8 @@
'(schema policy entities request validation-receipt)))
(def aitia-formal-methods-module
- (poo-flow-proof-module
+ (agentic-ai-lab-proof-module
"lambda-aitia/modules/formal-methods"
- (.o (tla+ aitia-tla-plus-provider)
+ (.o (quint aitia-quint-provider)
(lean aitia-lean-provider)
(cedar aitia-cedar-provider))))
diff --git a/modules/formal-methods/interface.ss b/modules/formal-methods/interface.ss
index 5682b09..98559cb 100644
--- a/modules/formal-methods/interface.ss
+++ b/modules/formal-methods/interface.ss
@@ -3,11 +3,11 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/formal-methods/types
- :poo-flow/lambda-aitia/modules/formal-methods/objects
- :poo-flow/lambda-aitia/modules/formal-methods/funs
- :poo-flow/lambda-aitia/modules/formal-methods/config)
-(export (import: :poo-flow/lambda-aitia/modules/formal-methods/types)
- (import: :poo-flow/lambda-aitia/modules/formal-methods/objects)
- (import: :poo-flow/lambda-aitia/modules/formal-methods/funs)
- (import: :poo-flow/lambda-aitia/modules/formal-methods/config))
+(import :agentic-ai-lab/lambda-aitia/modules/formal-methods/types
+ :agentic-ai-lab/lambda-aitia/modules/formal-methods/objects
+ :agentic-ai-lab/lambda-aitia/modules/formal-methods/funs
+ :agentic-ai-lab/lambda-aitia/modules/formal-methods/config)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/formal-methods/types)
+ (import: :agentic-ai-lab/lambda-aitia/modules/formal-methods/objects)
+ (import: :agentic-ai-lab/lambda-aitia/modules/formal-methods/funs)
+ (import: :agentic-ai-lab/lambda-aitia/modules/formal-methods/config))
diff --git a/modules/gitops/config.ss b/modules/gitops/config.ss
index 20d4725..6dd1374 100644
--- a/modules/gitops/config.ss
+++ b/modules/gitops/config.ss
@@ -3,15 +3,15 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
;;; -*- Gerbil -*-
-(import :poo-flow/src/module-system/declaration/interface
- :poo-flow/lambda-aitia/modules/gitops/objects)
+(import :yuanxu/module-system/selection/objects
+ :agentic-ai-lab/lambda-aitia/modules/gitops/objects)
(export gitops-config)
(def (gitops-config selection)
- (unless (and (poo-flow-user-module-selection? selection)
- (equal? (poo-flow-user-module-selection-key selection)
+ (unless (and (agentic-ai-lab-user-module-selection? selection)
+ (equal? (agentic-ai-lab-user-module-selection-key selection)
'(custom . gitops)))
(error "expected a custom/gitops selection"))
- (let (flags (poo-flow-user-module-selection-flags selection))
+ (let (flags (agentic-ai-lab-user-module-selection-flags selection))
(unless (or (null? flags) (equal? flags '(+open-gitops)))
(error "unsupported GitOps feature" flags))
GitOpsModule))
diff --git a/modules/gitops/funs.ss b/modules/gitops/funs.ss
index c9afd81..cec45cd 100644
--- a/modules/gitops/funs.ss
+++ b/modules/gitops/funs.ss
@@ -7,45 +7,65 @@
(import (only-in :clan/poo/object .ref .slot?)
(only-in :clan/poo/mop .new validate)
:std/list/list
- (only-in :poo-flow/src/core/funcs
- poo-flow-make-value-index poo-flow-value-index-put!
- poo-flow-value-index-ref)
- :poo-flow/src/module-system/poo-clos/interface
- :poo-flow/lambda-aitia/modules/gitops/types
- :poo-flow/lambda-aitia/modules/gitops/objects)
+ (only-in :yuanxu/utilities/algorithms
+ agentic-ai-lab-make-value-index agentic-ai-lab-value-index-put!
+ agentic-ai-lab-value-index-ref)
+ :agentic-ai-lab/core/poo-clos/interface
+ :agentic-ai-lab/lambda-aitia/modules/gitops/types
+ :agentic-ai-lab/lambda-aitia/modules/gitops/objects)
(export GitOpsDefaultEvaluationMethod GitOpsDefaultEvaluationMethods
gitops-evaluate-default)
(def (composition-gitops-profiles composition)
(filter gitops-profile? (.ref composition 'profiles)))
-(def (composition-standard-names composition)
- (map (lambda (profile) (.ref profile 'name))
+(def (composition-standard-bindings composition)
+ (map (lambda (profile)
+ (let (standards (.ref profile 'standards))
+ (unless (and (list? standards) (= (length standards) 1))
+ (error "standard Profile must bind exactly one Standard"
+ (.ref profile 'name)))
+ (cons (.ref profile 'name) (car standards))))
(filter (lambda (profile)
(and (.slot? profile 'role)
(eq? (.ref profile 'role) 'standard)))
(.ref composition 'profiles))))
+(def (standard-check-current? check standard)
+ (and (.slot? standard 'edition)
+ (.slot? standard 'source-lock-digest)
+ (equal? (.ref check 'standard-edition) (.ref standard 'edition))
+ (equal? (.ref check 'source-lock-digest)
+ (.ref standard 'source-lock-digest))))
(def (check-index checks)
- (let (index (poo-flow-make-value-index))
+ (let (index (agentic-ai-lab-make-value-index))
(for-each
(lambda (check)
(validate GitOpsCheck check)
(let-values (((present? previous)
- (poo-flow-value-index-ref index (.ref check 'name))))
+ (agentic-ai-lab-value-index-ref index (.ref check 'name))))
(when present? (error "duplicate GitOps check" (.ref check 'name)))
- (poo-flow-value-index-put! index (.ref check 'name) check)))
+ (agentic-ai-lab-value-index-put! index (.ref check 'name) check)))
checks)
index))
-(def (gitops-profile-decision profile standards change checks)
+(def (gitops-profile-decision profile standard-bindings change checks)
(let* ((required (.ref profile 'required-checks))
+ (standards (map car standard-bindings))
(index (check-index checks))
- (missing '()) (failed '()) (stale '()))
+ (missing '()) (failed '()) (stale '())
+ (revision-mismatch? #f)
+ (standard-mismatch? #f))
(for-each
(lambda (name)
- (let-values (((present? check) (poo-flow-value-index-ref index name)))
+ (let-values (((present? check) (agentic-ai-lab-value-index-ref index name)))
(cond ((not present?) (set! missing (cons name missing)))
((or (not (equal? (.ref check 'repository) (.ref change 'repository)))
(not (equal? (.ref check 'revision) (.ref change 'revision))))
- (set! stale (cons name stale)))
+ (set! stale (cons name stale))
+ (set! revision-mismatch? #t))
+ ((let (binding (assoc name standard-bindings))
+ (and binding
+ (not (standard-check-current? check (cdr binding)))))
+ (set! stale (cons name stale))
+ (set! standard-mismatch? #t))
((not (eq? (.ref check 'conclusion) 'success))
(set! failed (cons name failed))))))
(append required standards))
@@ -61,7 +81,10 @@
stale-checks: (reverse stale)
reasons: (append (if (null? missing) '() '(required-check-missing))
(if (null? failed) '() '(required-check-failed))
- (if (null? stale) '() '(check-revision-mismatch))))))))
+ (if revision-mismatch?
+ '(check-revision-mismatch) '())
+ (if standard-mismatch?
+ '(standard-assessment-mismatch) '())))))))
(def (gitops-unmatched-decision change)
(validate GitOpsDecision
(.new GitOpsDecision
@@ -80,7 +103,7 @@
(composition-gitops-profiles composition)))
(if profile
(gitops-profile-decision
- profile (composition-standard-names composition) change checks)
+ profile (composition-standard-bindings composition) change checks)
(gitops-unmatched-decision change))))
(def GitOpsDefaultEvaluationMethod
diff --git a/modules/gitops/interface.ss b/modules/gitops/interface.ss
index 4995e8d..f3c36f9 100644
--- a/modules/gitops/interface.ss
+++ b/modules/gitops/interface.ss
@@ -2,13 +2,13 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/gitops/types
- :poo-flow/lambda-aitia/modules/gitops/objects
- :poo-flow/lambda-aitia/modules/gitops/funs
- :poo-flow/lambda-aitia/modules/gitops/syntax
- :poo-flow/lambda-aitia/modules/gitops/config)
-(export (import: :poo-flow/lambda-aitia/modules/gitops/types)
- (import: :poo-flow/lambda-aitia/modules/gitops/objects)
- (import: :poo-flow/lambda-aitia/modules/gitops/funs)
- (import: :poo-flow/lambda-aitia/modules/gitops/syntax)
- (import: :poo-flow/lambda-aitia/modules/gitops/config))
+(import :agentic-ai-lab/lambda-aitia/modules/gitops/types
+ :agentic-ai-lab/lambda-aitia/modules/gitops/objects
+ :agentic-ai-lab/lambda-aitia/modules/gitops/funs
+ :agentic-ai-lab/lambda-aitia/modules/gitops/syntax
+ :agentic-ai-lab/lambda-aitia/modules/gitops/config)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/gitops/types)
+ (import: :agentic-ai-lab/lambda-aitia/modules/gitops/objects)
+ (import: :agentic-ai-lab/lambda-aitia/modules/gitops/funs)
+ (import: :agentic-ai-lab/lambda-aitia/modules/gitops/syntax)
+ (import: :agentic-ai-lab/lambda-aitia/modules/gitops/config))
diff --git a/modules/gitops/objects.ss b/modules/gitops/objects.ss
index f46354d..0fa5d98 100644
--- a/modules/gitops/objects.ss
+++ b/modules/gitops/objects.ss
@@ -7,15 +7,15 @@
;;; evaluator strategy axis where provider/runtime specializers may combine.
(import (only-in :clan/poo/object .def .o)
(only-in :clan/poo/mop .defgeneric .new)
- (only-in :poo-flow/src/module-system/poo-clos/interface
+ (only-in :agentic-ai-lab/core/poo-clos/interface
poo-clos-call
poo-clos-class
poo-clos-generic-function
poo-clos-generic-protocol
poo-clos-make-instance)
- (only-in :poo-flow/src/module-system/contribution/objects
+ (only-in :agentic-ai-lab/core/contribution/objects
make-contribution)
- :poo-flow/lambda-aitia/modules/gitops/types)
+ :agentic-ai-lab/lambda-aitia/modules/gitops/types)
(export GitOpsEvaluator GitOpsDefaultEvaluator
GitOpsEvaluationProtocol GitOpsEvaluationGeneric
GitOpsProfile OpenGitOpsProfile GitOpsModule
@@ -71,6 +71,10 @@
provider: provider-value event: event-value repository: repository-value
revision: revision-value source-ref: source-ref-value
target-ref: target-ref-value pull-request: pull-request-value))
-(def (gitops-check name-value repository-value revision-value conclusion-value)
+(def (gitops-check name-value repository-value revision-value conclusion-value
+ standard-edition: (standard-edition #f)
+ source-lock-digest: (source-lock-digest #f))
(.new GitOpsCheck name: name-value repository: repository-value
- revision: revision-value conclusion: conclusion-value))
+ revision: revision-value conclusion: conclusion-value
+ standard-edition: standard-edition
+ source-lock-digest: source-lock-digest))
diff --git a/modules/gitops/syntax.ss b/modules/gitops/syntax.ss
index 6ee4f2b..847ca84 100644
--- a/modules/gitops/syntax.ss
+++ b/modules/gitops/syntax.ss
@@ -5,8 +5,8 @@
;;; -*- Gerbil -*-
;;; Thin one-pattern projection to an ordinary POO Profile declaration.
(import (only-in :clan/poo/object .def .ref)
- :poo-flow/lambda-aitia/modules/gitops/types
- :poo-flow/lambda-aitia/modules/gitops/objects)
+ :agentic-ai-lab/lambda-aitia/modules/gitops/types
+ :agentic-ai-lab/lambda-aitia/modules/gitops/objects)
(export define-gitops-profile)
(defrule (define-gitops-profile profile-name base
environment: environment-value
diff --git a/modules/gitops/types.ss b/modules/gitops/types.ss
index cb5aa2c..27f2a5f 100644
--- a/modules/gitops/types.ss
+++ b/modules/gitops/types.ss
@@ -33,7 +33,9 @@
{name: {type: Symbol}
repository: {type: NonEmptyString}
revision: {type: NonEmptyString}
- conclusion: {type: GitOpsCheckConclusion}})
+ conclusion: {type: GitOpsCheckConclusion}
+ standard-edition: {type: (Or False NonEmptyString)}
+ source-lock-digest: {type: (Or False NonEmptyString)}})
(define-type (GitOpsDecision @ Class.)
slots: =>.+
{repository: {type: NonEmptyString}
diff --git a/modules/sdlc/README.org b/modules/sdlc/README.org
index 0dfd17f..f9dd08f 100644
--- a/modules/sdlc/README.org
+++ b/modules/sdlc/README.org
@@ -13,41 +13,107 @@ Projects may select multiple standards. No standard is automatically activated.
The activity vocabulary does not impose a waterfall sequence; projects own the
ordering, iteration and release process.
+* Design contracts and replacement review
+
+=design.ss= adds POO-native component design declarations under the SDLC owner.
+A contract names its ADR decision, responsibilities, owned state, allowed
+effects, assumptions, guarantees and variation points. Each clause has an
+identity, revision and statement; a variation declares which guarantees its
+change may affect. These are engineering declarations, not executable logical
+predicates or admitted evidence. Accepting the named ADR does not establish a
+guarantee.
+
+=sdlc-design-replacement-review= compares two revisions of the same contract.
+Its intentionally narrow declaration-level rule permits only exact clause
+identity/revision/statement matches: a candidate may require no new assumption
+and may discard no old guarantee. Added effects, changed state ownership,
+responsibility, ADR decision or variation declarations remain visible blockers.
+The receipt lists changed identities and guarantees requiring fresh checking;
+it never admits evidence or grants release authority. An unchanged declaration
+at a new revision still requires re-verification. Textual similarity is not
+treated as logical implication, and a =declared-substitutable?= candidate is
+not a proof of implementation refinement.
+
+Consumers may feed =changed-identities= into the existing
+=sdlc-change-impact= projection, which delegates trajectory analysis to POO
+Flow Graph. The job-executor regression does this for a retry-policy change:
+only the explicitly affected unique-effect guarantee and its verification
+are selected by the declared graph. If a variation omits a necessary
+dependency, this slice cannot discover it; model-to-implementation conformance
+and independent acceptance remain further qualification work.
+An alternative local-deduplication candidate changes state ownership,
+responsibility and the ADR decision. It is therefore blocked for design review
+even though its guarantee statements have the same text as the original.
+
+=implementation.ss= adds an inert design-to-source link. A link binds one
+guarantee revision to an Assurance artifact identity/revision/digest and the
+canonical Assurance snapshot context in which that source appears. The review
+requires every guarantee to have a current link and rejects changed contracts,
+guarantees, snapshots, source digests and unresolved/conflicted snapshot cuts.
+It reuses the Assurance snapshot owner rather than defining another source
+ledger. A current mapping means only that the declaration is consistent with
+the supplied snapshot. It does not validate the bytes behind an artifact,
+prove the implementation satisfies the guarantee, admit evidence or authorize
+release. Independent verifier/Host acceptance remains a separate gate.
+
+=verification.ss= projects a design guarantee through the existing Assurance
+Host. It requires a current implementation mapping, an exact current Claim
+whose predicate is the guarantee statement and whose assumptions match the
+design contract, a declared Claim-to-source edge,
+and a Host admission whose verifier input names that same source
+identity/revision/digest. The Host must also report the Claim's full required
+support set current. Missing source dependencies, unrelated inputs, copied or
+revoked admissions fail closed. The projection issues no admission and grants
+no release authority. Its =source-bound-support-current?= result is conditional
+on the application-configured Host; it does not establish verifier
+independence, semantic implementation conformance or trusted deployment.
+An application may configure the Assurance Host's =source-reader:= capability.
+With that reader, Host issuance and currentness check every declared verifier
+input against its Artifact SHA-256 using Agentic AI Lab's Source Lock algorithm.
+The configured verification operation then receives Host-materialized POO input
+values as its fourth argument, each with =identity=, =revision=, =digest= and a
+copy of the validated =payload=. The Host rechecks those values after the
+operation; replacing both payload and digest cannot retain a seal. Without a
+reader, the operation retains its three-argument contract.
+A byte mismatch or moving snapshot blocks issuance; observed byte drift
+invalidates previously issued receipts, which cannot revive merely because
+the bytes later return. =source-bytes-checked-support-current?= additionally
+requires the mapped design source to pass that check. Without the Host reader,
+the stronger result fails closed. SDLC review callers cannot supply replacement
+payloads. The application still owns the reader's repository/provenance trust
+and the verifier's actual process inputs; matching bytes alone proves neither
+Host independence nor semantic implementation conformance.
+
SDLC does not own CI providers or deployment environments. It contributes the
standard, project, obligation, evidence, traceability, tailoring and lifecycle
-models. Applications combine this module with POO Flow-owned workflow modules
-through =use-composition=.
+models. Applications combine these POO-native Profiles through Agentic AI Lab's
+=use-module= and =compose profiles=.
#+begin_export mermaid
flowchart LR
- Core[Existing POO Flow] --> SDLC[SDLC contribution]
+ Core[Existing Agentic AI Lab] --> SDLC[SDLC contribution]
SDLC --> Project[Project profile]
NASA[NASA standard profile] --> Project
Other[Other standard profiles] --> Project
Project --> Consumer[Application assessment and execution]
- Workflow[POO Flow workflow module] --> Consumer
+ Workflow[Agentic AI Lab workflow module] --> Consumer
Consumer -->|"host-owned execution"| Runtime[GitHub Actions or another CI host]
#+end_export
-The user-owned POO Flow =user-interface/init.ss= selects SDLC using the existing
-custom module syntax (paths are relative to that user directory):
+The maintained software-engineering Project selects base SDLC and NASA's
+standard-family contribution separately:
#+begin_src scheme
-(poo-flow!
- :custom
- (sdlc +nasa-7150-2d))
+(agentic-ai-lab-user-module-selection 'software-engineering 'sdlc '())
+(agentic-ai-lab-user-module-selection 'nasa 'sdlc '(+npr-7150.2))
#+end_src
-Here =sdlc= resolves through POO Flow's trusted contribution registry. A user
-can instead load a complete private collection with =(@ "./modules")=.
-
-Omit =+nasa-7150-2d= to select SDLC without NASA. =config.ss= owns the pure
-=sdlc-config= projection from a native module selection to a contribution.
-Unknown and duplicate flags fail explicitly. POO Flow's user-owned
-=user-interface/sdlc.ss= consumes the root init selections and exports
-=poo-flow-user-sdlc-contributions=. Consumers import that projection when needed;
-importing root init alone still only declares module selections. There is no
-automatic runtime activation. No example project is part of the SDLC build.
+Omit the NASA selection for standard-free SDLC. =config.ss= owns the pure
+=sdlc-config= projection; it rejects unsupported feature flags. The public
+profile identifies the standard family as =nasa/sdlc/npr-7150.2=. The selected
+edition =D= belongs to the Standard descriptor and source lock, so later
+editions need not change the family-level composition name. Composition does
+not activate a runtime.
=standards/nasa-7150-2d-profile.ss= owns the standard descriptor used by
=config.ss= and scenario Profiles. It contains the immutable source/catalog
@@ -85,10 +151,10 @@ does not assume all NASA requirements apply to every software project.
[[https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=Chapter2][Chapter 2]] governs tailoring and authority; a local profile override is not
approval. No automatic NASA compliance or certification claim is produced.
-** POO Flow Standards Provider boundary
+** Agentic AI Lab Standards Provider boundary
=standards/nasa-standard-provider.ss= projects this vertical into the
-domain-neutral POO Flow Standards module. It owns one exact NPR 7150.2D
+domain-neutral Agentic AI Lab Standards module. It owns one exact NPR 7150.2D
=StandardEdition=, six lightweight source =ArtifactRef= values, one
=StandardConstraintProfile= containing the 130 reviewed requirements, and a
fail-closed validation Provider identity. Import and exact resolution perform
@@ -102,7 +168,7 @@ not a compliance or certification decision: an authenticated execution engine,
the lifecycle evidence, and the authority verification boundary remain
separate.
-Source identity is supplied by the reusable POO Flow Sources Lock Feature.
+Source identity is supplied by the reusable Agentic AI Lab Sources Lock Feature.
=standards/sources.ss= is the concise, editable POO declaration of the NASA
source identities and locations. =standards/source.lock.ss= is an include-only,
generated artifact containing the observed digest and byte count for every
@@ -149,16 +215,16 @@ selection, duplicate/malformed selection rejection and source-only admission.
optional NASA flag and rejected selections. The parent application keeps its
actual init-to-contribution integration test separately under
=t/contribution/integration/sdlc-ui-test.ss=; child tests do not import it.
-Run =just test-scheme= after building against installed POO Flow.
+Run =just test-scheme= after building against installed Agentic AI Lab.
No GQL, gerbil-parser, Rust or Python is needed by this module or its tests.
The application owns separate tests for evidence freshness, missing traceability
under complete/incomplete scopes, unauthorized tailoring and standard conflicts.
2026-09-12 working-source qualification after the init integration: native child
-build passed with the POO Flow contribution and module declaration libraries.
+build passed with the Agentic AI Lab contribution and module declaration libraries.
=gxtest t/sdlc/unit/sdlc-test.ss t/sdlc/unit/sdlc-config-test.ss= passed 17 SDLC and 7 config checks.
The earlier 18 governance checks are recorded in =t/qualification/authoring.org=.
-The child lane uses isolated output plus POO Flow library paths and does not
+The child lane uses isolated output plus Agentic AI Lab library paths and does not
import the parent user configuration. The separate application lane passed
4 checks using the actual parent init and user projection sources. Its compiled
init attempt exposed source-form .ssi artifacts under the local parent library;
@@ -194,7 +260,7 @@ outside this contribution module.
* Change impact
=impact.ss= owns the SDLC projection for =sdlc-change-impact= over explicitly
-supplied trace nodes/edges. POO Flow Graph owns traversal, cycle termination and
+supplied trace nodes/edges. Agentic AI Lab Graph owns traversal, cycle termination and
shortest relation trajectories; Aitia projects revision-scoped SDLC facts into
that mechanism and retains its POO-native relation trajectory witnesses. Callers select
changed node identities and relation names. Edges are traversed source-to-target
@@ -218,7 +284,7 @@ chain and keeps an unrelated verification outside the impact set.
* CLOS model ownership
=types.ss= declares native =poo-clos= classes. Evidence and trace objects reuse
subject/revision/scope, clause references and identity through class inheritance.
-The POO Flow =contribution/model= interface checks native prototype ancestry
+The Agentic AI Lab =contribution/model= interface checks native prototype ancestry
and all effective-slot predicates. =objects.ss= constructs immutable-by-convention
POO snapshots; callers derive new values with =.o= rather than mutate them.
=review.ss= and the trace/impact functions recheck contracts at their boundaries,
@@ -230,7 +296,7 @@ owned =t/sdlc/unit/sdlc-model-test.ss= covers inherited constraints, impersonati
invalid overrides and preservation of the previous snapshot.
* Complete source review surface
-=:poo-flow/lambda-aitia/modules/sdlc/standards/nasa-review= exports:
+=:agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-review= exports:
- =nasa-requirement-criteria=: authoritative paragraph and subparagraph criteria,
bound to a source URL and SHA-256 snapshot. Notes are preserved separately.
@@ -256,7 +322,7 @@ invalid overrides and preservation of the previous snapshot.
=user-interface/scenarios/nasa-audit.ss= is the independent complex example. Its synthetic
planning evidence, safety gaps and claimed tailoring signature yield a review
packet, not a NASA compliance or release decision. All module contracts remain
-pure Scheme and use existing POO Flow/CLOS primitives. Full natural-language
+pure Scheme and use existing Agentic AI Lab/CLOS primitives. Full natural-language
proof, external NASA standards and signature authentication are not claimed by
paragraph-level evidence coverage.
@@ -279,7 +345,7 @@ appropriate to the request purpose. Supplying a digest or an approved flag does
not perform this verification. Trust configuration and the clock belong to the
host, outside submitted project facts.
-The generic issuance/revocation mechanism belongs to POO Flow's
+The generic issuance/revocation mechanism belongs to Agentic AI Lab's
=contribution/verification=; NASA request projection belongs here. Receipts are
session-local capabilities: clones, stale snapshots, altered fields, expired
intervals and revoked receipts are rejected. They are not persistent signatures
diff --git a/modules/sdlc/config.ss b/modules/sdlc/config.ss
index 3d694ae..89d2c36 100644
--- a/modules/sdlc/config.ss
+++ b/modules/sdlc/config.ss
@@ -2,12 +2,13 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-;;; User selection projection. Importing this module enables no standard.
-(import :poo-flow/src/module-system/declaration/interface
- :poo-flow/lambda-aitia/modules/sdlc/types
- :poo-flow/lambda-aitia/modules/sdlc/objects
- :poo-flow/lambda-aitia/modules/sdlc/funs
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-profile
+;;; Legacy module-selection projection is standard-free. The NASA Standard is
+;;; selected through its own typed nasa/sdlc Module Profile, not an SDLC flag.
+(import :yuanxu/module-system/selection/objects
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/objects
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/funs
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-profile
:std/list/list)
(export sdlc-config sdlc-nasa-7150-profile)
@@ -17,13 +18,10 @@
(sdlc-with-standards SdlcProfile (list Nasa7150_2D)))
(def (sdlc-config selection)
- (unless (and (poo-flow-user-module-selection? selection)
- (equal? (poo-flow-user-module-selection-key selection) '(custom . sdlc)))
+ (unless (and (agentic-ai-lab-user-module-selection? selection)
+ (equal? (agentic-ai-lab-user-module-selection-key selection) '(custom . sdlc)))
(error "expected a custom/sdlc selection"))
- (let ((flags (poo-flow-user-module-selection-flags selection)))
- (unless (every (lambda (flag) (eq? flag '+nasa-7150-2d)) flags)
- (error "unsupported SDLC feature" flags))
- (unless (<= (length flags) 1)
- (error "duplicate SDLC feature" flags))
- (sdlc-contribution
- (if (null? flags) SdlcProfile sdlc-nasa-7150-profile))))
+ (let ((flags (agentic-ai-lab-user-module-selection-flags selection)))
+ (unless (null? flags)
+ (error "SDLC has no feature flags; select standards as Modules" flags))
+ (sdlc-contribution SdlcProfile)))
diff --git a/modules/sdlc/design.ss b/modules/sdlc/design.ss
new file mode 100644
index 0000000..55b90d1
--- /dev/null
+++ b/modules/sdlc/design.ss
@@ -0,0 +1,239 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Aitia owns software-design meaning; Agentic AI Lab owns graph traversal and
+;;; runtime authority. This is an inert declaration-level replacement check.
+(import (only-in :clan/poo/object .o .ref)
+ (only-in :gerbil/core list-sort)
+ :std/list/list
+ :agentic-ai-lab/core/poo-clos/interface
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/funs
+ assurance-canonical-digest)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types)
+
+(export SdlcDesignClause SdlcDesignVariation SdlcDesignContract
+ sdlc-design-clause? sdlc-design-variation? sdlc-design-contract?
+ sdlc-design-assumption sdlc-design-guarantee
+ sdlc-design-variation sdlc-design-contract
+ sdlc-design-contract-digest
+ sdlc-design-replacement-review)
+
+(def (text-list? values)
+ (and (list? values) (every sdlc-text? values)
+ (= (length values) (length (delete-duplicates/hash values)))))
+(def (nonempty-text-list? values)
+ (and (text-list? values) (pair? values)))
+(def (identified-list? values predicate)
+ (and (list? values) (every predicate values)
+ (let (ids (map (lambda (value) (.ref value 'identity)) values))
+ (= (length ids) (length (delete-duplicates/hash ids))))))
+(def (clause-list? kind)
+ (lambda (values)
+ (and (identified-list? values sdlc-design-clause?)
+ (every (lambda (value) (eq? (.ref value 'kind) kind)) values))))
+(def (variation-list? values)
+ (identified-list? values sdlc-design-variation?))
+(def (slot name predicate)
+ (poo-clos-direct-slot-definition name type-predicate: predicate))
+
+(def SdlcDesignClause
+ (poo-clos-class 'sdlc/design-clause
+ direct-slots:
+ (list (slot 'identity sdlc-text?) (slot 'revision sdlc-text?)
+ (slot 'kind (lambda (value) (if (memq value '(assumption guarantee)) #t #f)))
+ (slot 'statement sdlc-text?))))
+(def SdlcDesignVariation
+ (poo-clos-class 'sdlc/design-variation
+ direct-slots:
+ (list (slot 'identity sdlc-text?) (slot 'revision sdlc-text?)
+ (slot 'affects-guarantees nonempty-text-list?))))
+(def SdlcDesignContract
+ (poo-clos-class 'sdlc/design-contract
+ direct-slots:
+ (list (slot 'identity sdlc-text?) (slot 'revision sdlc-text?)
+ (slot 'decision sdlc-text?)
+ (slot 'responsibilities text-list?)
+ (slot 'owned-state text-list?)
+ (slot 'allowed-effects text-list?)
+ (slot 'assumptions (clause-list? 'assumption))
+ (slot 'guarantees (clause-list? 'guarantee))
+ (slot 'variations variation-list?))))
+
+(def (sdlc-design-clause? value)
+ (poo-clos-model? SdlcDesignClause value))
+(def (sdlc-design-variation? value)
+ (poo-clos-model? SdlcDesignVariation value))
+(def (sdlc-design-contract? value)
+ (and (poo-clos-model? SdlcDesignContract value)
+ (pair? (.ref value 'responsibilities))
+ (pair? (.ref value 'guarantees))
+ (let (guarantees (map (lambda (clause) (.ref clause 'identity))
+ (.ref value 'guarantees)))
+ (every (lambda (variation)
+ (every (lambda (id) (member id guarantees))
+ (.ref variation 'affects-guarantees)))
+ (.ref value 'variations)))))
+
+(def (design-clause kind-value id revision-value statement-value)
+ (poo-clos-check-model
+ SdlcDesignClause
+ (.o (:: @ (poo-clos-model-prototype SdlcDesignClause))
+ identity: id revision: revision-value kind: kind-value
+ statement: statement-value)))
+(def (sdlc-design-assumption id revision-value statement-value)
+ (design-clause 'assumption id revision-value statement-value))
+(def (sdlc-design-guarantee id revision-value statement-value)
+ (design-clause 'guarantee id revision-value statement-value))
+(def (sdlc-design-variation id revision-value affected-guarantees)
+ (poo-clos-check-model
+ SdlcDesignVariation
+ (.o (:: @ (poo-clos-model-prototype SdlcDesignVariation))
+ identity: id revision: revision-value
+ affects-guarantees: affected-guarantees)))
+(def (sdlc-design-contract id revision-value decision-value responsibility-values
+ owned-state-values effect-values assumption-values
+ guarantee-values variation-values)
+ (let (value
+ (poo-clos-check-model
+ SdlcDesignContract
+ (.o (:: @ (poo-clos-model-prototype SdlcDesignContract))
+ identity: id revision: revision-value decision: decision-value
+ responsibilities: responsibility-values
+ owned-state: owned-state-values
+ allowed-effects: effect-values assumptions: assumption-values
+ guarantees: guarantee-values variations: variation-values)))
+ (unless (sdlc-design-contract? value)
+ (error "design contract lacks a responsibility or guarantee, or a variation references an undeclared guarantee" id))
+ value))
+
+(def (ordered-ids values)
+ (list-sort string (delete-duplicates/hash values)))
+(def (clause-key value)
+ (list (.ref value 'identity) (.ref value 'revision)
+ (.ref value 'kind) (.ref value 'statement)))
+(def (variation-key value)
+ (list (.ref value 'identity) (.ref value 'revision)
+ (ordered-ids (.ref value 'affects-guarantees))))
+(def (ordered-keys values key)
+ (list-sort (lambda (left right) (string (car left) (car right)))
+ (map key values)))
+(def (contract-body value)
+ (list (.ref value 'decision)
+ (ordered-ids (.ref value 'responsibilities))
+ (ordered-ids (.ref value 'owned-state))
+ (ordered-ids (.ref value 'allowed-effects))
+ (ordered-keys (.ref value 'assumptions) clause-key)
+ (ordered-keys (.ref value 'guarantees) clause-key)
+ (ordered-keys (.ref value 'variations) variation-key)))
+(def (sdlc-design-contract-digest value)
+ (unless (sdlc-design-contract? value)
+ (error "invalid design contract for digest"))
+ (assurance-canonical-digest
+ (list 'lambda-aitia.sdlc-design-contract
+ (.ref value 'identity) (.ref value 'revision)
+ (contract-body value))))
+(def (changed-ids old-values new-values key)
+ (ordered-ids
+ (append
+ (map (lambda (value) (.ref value 'identity))
+ (filter (lambda (value) (not (member (key value) (map key new-values))))
+ old-values))
+ (map (lambda (value) (.ref value 'identity))
+ (filter (lambda (value) (not (member (key value) (map key old-values))))
+ new-values)))))
+(def (subset? left right)
+ (every (lambda (value) (member value right)) left))
+(def (clause-subset? left right)
+ (subset? (map clause-key left) (map clause-key right)))
+(def (variation-affected values ids)
+ (concatenate
+ (map (lambda (variation)
+ (if (member (.ref variation 'identity) ids)
+ (.ref variation 'affects-guarantees) '()))
+ values)))
+
+;;; Exact clause equality is the only declaration-level entailment admitted:
+;;; old assumptions must cover every new assumption, while new guarantees
+;;; must retain every old guarantee. No textual/logical equivalence is inferred.
+;;; Selected guarantees are re-verification requests, never admitted evidence.
+(def (sdlc-design-replacement-review old new)
+ (unless (and (sdlc-design-contract? old)
+ (sdlc-design-contract? new)
+ (equal? (.ref old 'identity) (.ref new 'identity)))
+ (error "design replacement requires two valid versions of one contract"))
+ (when (and (equal? (.ref old 'revision) (.ref new 'revision))
+ (not (equal? (contract-body old) (contract-body new))))
+ (error "design declaration changed without a revision change"))
+ (let* ((old-assumptions (.ref old 'assumptions))
+ (new-assumptions (.ref new 'assumptions))
+ (old-guarantees (.ref old 'guarantees))
+ (new-guarantees (.ref new 'guarantees))
+ (changed-assumptions
+ (changed-ids old-assumptions new-assumptions clause-key))
+ (changed-guarantees
+ (changed-ids old-guarantees new-guarantees clause-key))
+ (changed-variations
+ (changed-ids (.ref old 'variations) (.ref new 'variations)
+ variation-key))
+ (responsibilities-changed?
+ (not (equal? (ordered-ids (.ref old 'responsibilities))
+ (ordered-ids (.ref new 'responsibilities)))))
+ (state-changed?
+ (not (equal? (ordered-ids (.ref old 'owned-state))
+ (ordered-ids (.ref new 'owned-state)))))
+ (effects-changed?
+ (not (equal? (ordered-ids (.ref old 'allowed-effects))
+ (ordered-ids (.ref new 'allowed-effects)))))
+ (decision-changed?
+ (not (equal? (.ref old 'decision) (.ref new 'decision))))
+ (all-guarantees
+ (ordered-ids (append (map (lambda (v) (.ref v 'identity)) old-guarantees)
+ (map (lambda (v) (.ref v 'identity)) new-guarantees))))
+ (broad-change?
+ (or (pair? changed-assumptions) responsibilities-changed?
+ state-changed? effects-changed? decision-changed?))
+ (affected
+ (ordered-ids
+ (if broad-change?
+ all-guarantees
+ (append changed-guarantees
+ (variation-affected (.ref old 'variations)
+ changed-variations)
+ (variation-affected (.ref new 'variations)
+ changed-variations)))))
+ (blocker-values
+ (append
+ (if (clause-subset? new-assumptions old-assumptions) '()
+ '(stronger-or-changed-assumption))
+ (if (clause-subset? old-guarantees new-guarantees) '()
+ '(weaker-or-changed-guarantee))
+ (if (subset? (.ref new 'allowed-effects) (.ref old 'allowed-effects))
+ '() '(new-effect))
+ (if responsibilities-changed? '(responsibility-changed) '())
+ (if state-changed? '(state-ownership-changed) '())
+ (if decision-changed? '(decision-changed) '())
+ (if (pair? changed-variations) '(variation-changed) '()))))
+ (.o kind: 'sdlc.design-replacement-review
+ contract: (.ref old 'identity)
+ from-revision: (.ref old 'revision)
+ to-revision: (.ref new 'revision)
+ declared-substitutable?: (null? blocker-values)
+ blockers: blocker-values
+ changed-identities:
+ (ordered-ids
+ (append changed-assumptions changed-guarantees changed-variations
+ (if (or responsibilities-changed? state-changed? effects-changed?
+ decision-changed?
+ (and (not (equal? (.ref old 'revision)
+ (.ref new 'revision)))
+ (equal? (contract-body old)
+ (contract-body new))))
+ (list (.ref old 'identity)) '())))
+ recheck-guarantees:
+ (if (and (not (equal? (.ref old 'revision) (.ref new 'revision)))
+ (equal? (contract-body old) (contract-body new)))
+ all-guarantees affected)
+ evidence-admitted?: #f
+ release-authorized?: #f
+ runtime-executed?: #f)))
diff --git a/modules/sdlc/funs.ss b/modules/sdlc/funs.ss
index 25877a7..5e4f4b2 100644
--- a/modules/sdlc/funs.ss
+++ b/modules/sdlc/funs.ss
@@ -3,19 +3,19 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :clan/poo/object .o .ref)
- (only-in :poo-flow/src/graph/algorithms
- poo-flow-graph-cycle-path
- poo-flow-graph-topological-order)
- (only-in :poo-flow/src/graph/types
- poo-flow-graph poo-flow-graph-edge poo-flow-graph-node)
- (only-in :poo-flow/src/modules/governance/funs
- poo-flow-governance-contribution)
+ (only-in :yuanxu/graph/algorithms
+ agentic-ai-lab-graph-cycle-path
+ agentic-ai-lab-graph-topological-order)
+ (only-in :yuanxu/graph/types
+ agentic-ai-lab-graph agentic-ai-lab-graph-edge agentic-ai-lab-graph-node)
+ (only-in :agentic-ai-lab/modules/governance/funs
+ agentic-ai-lab-governance-contribution)
:std/list/list)
-(import :poo-flow/lambda-aitia/modules/sdlc/types :poo-flow/lambda-aitia/modules/sdlc/objects)
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/types :agentic-ai-lab/lambda-aitia/modules/sdlc/objects)
(export sdlc-with-standards sdlc-contribution sdlc-module
+sdlc-flow-stages+ sdlc-flow-graph sdlc-flow-plan)
-;;; Aitia owns the SDLC phase vocabulary; POO Flow owns Graph and DAG analysis.
+;;; Aitia owns the SDLC phase vocabulary; Agentic AI Lab owns Graph and DAG analysis.
;;; This projection is inert and does not execute a verifier or grant authority.
(def +sdlc-flow-stages+
'(change invalidate plan verify admit decide authorize effect))
@@ -29,30 +29,30 @@
(error "SDLC flow requires a non-empty lifecycle identity" lifecycle-id))
(let ((nodes
(map (lambda (stage)
- (poo-flow-graph-node
+ (agentic-ai-lab-graph-node
(sdlc-flow-node-id lifecycle-id stage)
stage
(list (cons 'semantic-owner 'lambda-aitia))))
+sdlc-flow-stages+))
(edges
(map (lambda (source-stage target-stage)
- (poo-flow-graph-edge
+ (agentic-ai-lab-graph-edge
(sdlc-flow-node-id lifecycle-id source-stage)
(sdlc-flow-node-id lifecycle-id target-stage)
'sdlc-next
(list (cons 'semantic-owner 'lambda-aitia))))
+sdlc-flow-stages+
(cdr +sdlc-flow-stages+))))
- (poo-flow-graph
+ (agentic-ai-lab-graph
lifecycle-id nodes edges
(list (cons 'semantic-owner 'lambda-aitia)
- (cons 'runtime-owner 'poo-flow)))))
+ (cons 'runtime-owner 'agentic-ai-lab)))))
(def (sdlc-flow-plan lifecycle-identity)
(let* ((graph-value (sdlc-flow-graph lifecycle-identity))
- (detected-cycle-path (poo-flow-graph-cycle-path graph-value))
+ (detected-cycle-path (agentic-ai-lab-graph-cycle-path graph-value))
(order (and (not detected-cycle-path)
- (poo-flow-graph-topological-order graph-value))))
+ (agentic-ai-lab-graph-topological-order graph-value))))
(.o schema: 'lambda-aitia.sdlc-flow-plan
lifecycle-id: lifecycle-identity
graph: graph-value
@@ -61,7 +61,7 @@
cycle-path: detected-cycle-path
accepted?: (and order #t)
semantic-owner: 'lambda-aitia
- runtime-owner: 'poo-flow
+ runtime-owner: 'agentic-ai-lab
release-authorized?: #f
runtime-executed?: #f)))
(def (sdlc-with-standards profile-value standard-values)
@@ -75,7 +75,7 @@
(def (sdlc-contribution profile-value)
(unless (sdlc-profile? profile-value)
(error "invalid SDLC profile" profile-value))
- (poo-flow-governance-contribution
+ (agentic-ai-lab-governance-contribution
profile-value '(lifecycle-governance) '()))
(def sdlc-module (sdlc-contribution SdlcProfile))
diff --git a/modules/sdlc/impact.ss b/modules/sdlc/impact.ss
index 1a0202a..a583eeb 100644
--- a/modules/sdlc/impact.ss
+++ b/modules/sdlc/impact.ss
@@ -4,13 +4,13 @@
;;; Finite source-inventory impact projection, not a graph runtime or approval.
(import (only-in :clan/poo/object .o .ref)
- :poo-flow/lambda-aitia/modules/sdlc/types
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
:std/list/list
:gerbil/core
- (only-in :poo-flow/src/graph/types
- poo-flow-graph poo-flow-graph-edge poo-flow-graph-node)
- (only-in :poo-flow/src/modules/temporal-causality/funs
- poo-flow-structural-impact-analyze))
+ (only-in :yuanxu/graph/types
+ agentic-ai-lab-graph agentic-ai-lab-graph-edge agentic-ai-lab-graph-node)
+ (only-in :agentic-ai-lab/modules/temporal-causality/funs
+ agentic-ai-lab-structural-impact-analyze))
(export sdlc-change-impact)
(def (same-snapshot? value project)
(every (lambda (slot) (equal? (.ref value slot) (.ref project slot))) '(subject revision scope)))
@@ -47,26 +47,26 @@
(unless (every (lambda (id) (member id ids)) seeds)
(error "changed object missing from selected snapshot"))
;; Traversal, cycle termination and shortest relation trajectories belong
- ;; to POO Flow Graph. Aitia only projects its revision-scoped SDLC facts
+ ;; to Agentic AI Lab Graph. Aitia only projects its revision-scoped SDLC facts
;; into that mechanism and retains its native trajectory witnesses.
(let* ((graph
- (poo-flow-graph
+ (agentic-ai-lab-graph
(impact-symbol
(string-append (.ref project 'subject) "@"
(.ref project 'revision) ":"
(.ref project 'scope)))
(map (lambda (node)
- (poo-flow-graph-node
+ (agentic-ai-lab-graph-node
(impact-symbol (.ref node 'identity))))
current)
(map (lambda (edge)
- (poo-flow-graph-edge
+ (agentic-ai-lab-graph-edge
(impact-symbol (.ref edge 'source))
(impact-symbol (.ref edge 'target))
(impact-symbol (.ref edge 'relation))))
selected)))
(structural
- (poo-flow-structural-impact-analyze
+ (agentic-ai-lab-structural-impact-analyze
graph (map impact-symbol seeds)
(map impact-symbol selected-relation-values)
'dependencies (.ref project 'complete?)))
diff --git a/modules/sdlc/implementation.ss b/modules/sdlc/implementation.ss
new file mode 100644
index 0000000..139f349
--- /dev/null
+++ b/modules/sdlc/implementation.ss
@@ -0,0 +1,141 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; An inert, snapshot-bound design-to-source declaration. Source currentness
+;;; is checked against Assurance; semantic conformance is not inferred.
+(import (only-in :clan/poo/object .o .ref)
+ (only-in :gerbil/core list-sort)
+ :std/list/list
+ :agentic-ai-lab/core/poo-clos/interface
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/interface
+ assurance-artifact? assurance-digest?
+ assurance-snapshot? assurance-snapshot-canonical?)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/design)
+
+(export SdlcDesignImplementationLink sdlc-design-implementation-link?
+ sdlc-design-implementation-link sdlc-design-implementation-review)
+
+(def (text-slot name)
+ (poo-clos-direct-slot-definition name type-predicate: sdlc-text?))
+(def (digest-slot name)
+ (poo-clos-direct-slot-definition name type-predicate: assurance-digest?))
+
+(def SdlcDesignImplementationLink
+ (poo-clos-class 'sdlc/design-implementation-link
+ direct-slots:
+ (list (text-slot 'contract) (text-slot 'contract-revision)
+ (digest-slot 'contract-digest)
+ (text-slot 'guarantee) (text-slot 'guarantee-revision)
+ (text-slot 'source) (text-slot 'source-revision)
+ (digest-slot 'source-digest)
+ (text-slot 'snapshot) (text-slot 'snapshot-revision)
+ (digest-slot 'snapshot-context-digest))))
+
+(def (sdlc-design-implementation-link? value)
+ (poo-clos-model? SdlcDesignImplementationLink value))
+
+(def (sdlc-design-implementation-link contract-value guarantee-value
+ source-value snapshot-value)
+ (unless (and (sdlc-design-contract? contract-value)
+ (sdlc-design-clause? guarantee-value)
+ (eq? (.ref guarantee-value 'kind) 'guarantee)
+ (assurance-artifact? source-value)
+ (assurance-snapshot-canonical? snapshot-value))
+ (error "invalid design implementation link input"))
+ (poo-clos-check-model
+ SdlcDesignImplementationLink
+ (.o (:: @ (poo-clos-model-prototype SdlcDesignImplementationLink))
+ contract: (.ref contract-value 'identity)
+ contract-revision: (.ref contract-value 'revision)
+ contract-digest: (sdlc-design-contract-digest contract-value)
+ guarantee: (.ref guarantee-value 'identity)
+ guarantee-revision: (.ref guarantee-value 'revision)
+ source: (.ref source-value 'identity)
+ source-revision: (.ref source-value 'revision)
+ source-digest: (.ref source-value 'content-digest)
+ snapshot: (.ref snapshot-value 'identity)
+ snapshot-revision: (.ref snapshot-value 'revision)
+ snapshot-context-digest: (.ref snapshot-value 'context-digest))))
+
+(def (ordered-ids values)
+ (list-sort string (delete-duplicates/hash values)))
+(def (find-id values id)
+ (find (lambda (value) (equal? (.ref value 'identity) id)) values))
+(def (bound-source snapshot id)
+ (let ((binding (assoc id (.ref snapshot 'source-revisions)))
+ (node (find-id (.ref snapshot 'nodes) id)))
+ (and binding node (assurance-artifact? node)
+ (equal? (cdr binding) (.ref node 'revision)) node)))
+
+(def (link-blocker contract snapshot link)
+ (let ((guarantee (find-id (.ref contract 'guarantees)
+ (.ref link 'guarantee)))
+ (source (bound-source snapshot (.ref link 'source))))
+ (cond
+ ((or (not (equal? (.ref link 'contract) (.ref contract 'identity)))
+ (not (equal? (.ref link 'contract-revision)
+ (.ref contract 'revision)))
+ (not (equal? (.ref link 'contract-digest)
+ (sdlc-design-contract-digest contract))))
+ 'contract-changed)
+ ((not guarantee) 'guarantee-undeclared)
+ ((not (equal? (.ref link 'guarantee-revision)
+ (.ref guarantee 'revision)))
+ 'guarantee-revision-changed)
+ ((or (not (equal? (.ref link 'snapshot) (.ref snapshot 'identity)))
+ (not (equal? (.ref link 'snapshot-revision)
+ (.ref snapshot 'revision)))
+ (not (equal? (.ref link 'snapshot-context-digest)
+ (.ref snapshot 'context-digest))))
+ 'snapshot-changed)
+ ((not source) 'source-unbound)
+ ((or (not (equal? (.ref link 'source-revision)
+ (.ref source 'revision)))
+ (not (equal? (.ref link 'source-digest)
+ (.ref source 'content-digest)))
+ (not (eq? (.ref source 'state) 'supported)))
+ 'source-changed)
+ (else #f))))
+
+(def (sdlc-design-implementation-review contract-value snapshot-value links)
+ (unless (and (sdlc-design-contract? contract-value)
+ (assurance-snapshot? snapshot-value)
+ (assurance-snapshot-canonical? snapshot-value)
+ (list? links)
+ (every sdlc-design-implementation-link? links))
+ (error "invalid design implementation review input"))
+ (let* ((checks
+ (map (lambda (link)
+ (.o guarantee: (.ref link 'guarantee)
+ source: (.ref link 'source)
+ blocker: (link-blocker contract-value snapshot-value link)))
+ links))
+ (current-guarantees
+ (ordered-ids
+ (map (lambda (check) (.ref check 'guarantee))
+ (filter (lambda (check) (not (.ref check 'blocker))) checks))))
+ (unmapped
+ (ordered-ids
+ (filter (lambda (id) (not (member id current-guarantees)))
+ (map (lambda (guarantee) (.ref guarantee 'identity))
+ (.ref contract-value 'guarantees)))))
+ (blocked (filter (lambda (check) (.ref check 'blocker)) checks))
+ (frontier? (or (pair? (.ref snapshot-value 'conflicts))
+ (pair? (.ref snapshot-value 'unresolved)))))
+ (.o kind: 'sdlc.design-implementation-review
+ contract: (.ref contract-value 'identity)
+ contract-revision: (.ref contract-value 'revision)
+ snapshot: (.ref snapshot-value 'identity)
+ snapshot-revision: (.ref snapshot-value 'revision)
+ snapshot-digest: (.ref snapshot-value 'digest)
+ mapping-current?: (and (null? blocked) (null? unmapped)
+ (not frontier?))
+ mapped-guarantees: current-guarantees
+ unmapped-guarantees: unmapped
+ blocked-links: blocked
+ snapshot-frontier?: frontier?
+ implementation-conforms?: #f
+ evidence-admitted?: #f
+ release-authorized?: #f)))
diff --git a/modules/sdlc/interface.ss b/modules/sdlc/interface.ss
index 3c99b44..959905a 100644
--- a/modules/sdlc/interface.ss
+++ b/modules/sdlc/interface.ss
@@ -2,15 +2,21 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/sdlc/types)
-(export (import: :poo-flow/lambda-aitia/modules/sdlc/types))
-(import :poo-flow/lambda-aitia/modules/sdlc/objects)
-(export (import: :poo-flow/lambda-aitia/modules/sdlc/objects))
-(import :poo-flow/lambda-aitia/modules/sdlc/funs)
-(export (import: :poo-flow/lambda-aitia/modules/sdlc/funs))
-(import :poo-flow/lambda-aitia/modules/sdlc/config)
-(export (import: :poo-flow/lambda-aitia/modules/sdlc/config))
-(import :poo-flow/lambda-aitia/modules/sdlc/review)
-(export (import: :poo-flow/lambda-aitia/modules/sdlc/review))
-(import :poo-flow/lambda-aitia/modules/sdlc/impact)
-(export (import: :poo-flow/lambda-aitia/modules/sdlc/impact))
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/types)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/types))
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/objects)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/objects))
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/funs)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/funs))
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/config)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/config))
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/review)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/review))
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/impact)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/impact))
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/design)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/design))
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/implementation)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/implementation))
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/verification)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/verification))
diff --git a/modules/sdlc/objects.ss b/modules/sdlc/objects.ss
index 2869afc..c8137f6 100644
--- a/modules/sdlc/objects.ss
+++ b/modules/sdlc/objects.ss
@@ -3,13 +3,13 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :clan/poo/object .o .ref)
- (only-in :poo-flow/src/modules/governance/objects
- PooFlowGovernanceProfile.)
- :poo-flow/src/module-system/contribution/model
- :poo-flow/lambda-aitia/modules/sdlc/types)
+ (only-in :agentic-ai-lab/modules/governance/objects
+ AgenticAILabGovernanceProfile.)
+ (only-in :yuanxu/poo-clos/model poo-clos-check-model poo-clos-model-prototype)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types)
(export StandardProfile. SdlcProfile)
(def StandardProfile.
- (.o (:: @ (poo-flow-model-prototype SdlcStandard)) kind: 'lambda-aitia.sdlc-standard coverage: 'partial
+ (.o (:: @ (poo-clos-model-prototype SdlcStandard)) kind: 'lambda-aitia.sdlc-standard coverage: 'partial
requirements: '() assessment: 'not-evaluated))
(def sdlc-ontology
(.o entities: '(LifecycleActivity Requirement Artifact Verification Evidence
@@ -17,7 +17,7 @@
relations: '(REFINES IMPLEMENTS VERIFIES EVIDENCES REVIEWS BASELINED_IN
DERIVED_FROM REQUESTS_RELIEF APPROVED_BY)))
(def SdlcProfile
- (.o (:: @ PooFlowGovernanceProfile.) identity: "lambda-aitia/sdlc"
+ (.o (:: @ AgenticAILabGovernanceProfile.) identity: "lambda-aitia/sdlc"
revision: "1" owner: "lambda-aitia"
ontology: sdlc-ontology standards: '()
activities: '(planning requirements architecture design implementation
@@ -33,17 +33,17 @@
(export sdlc-trace-node sdlc-trace-edge sdlc-trace-rule)
(def (sdlc-trace-rule id source-kind target-kind)
- (let ((value (.o (:: @ (poo-flow-model-prototype SdlcTraceRule)) identity: id source-category: source-kind target-category: target-kind)))
+ (let ((value (.o (:: @ (poo-clos-model-prototype SdlcTraceRule)) identity: id source-category: source-kind target-category: target-kind)))
(unless (sdlc-trace-rule? value) (error "invalid trace rule")) value))
(def (sdlc-trace-node id category-value project)
(unless (sdlc-bound-fact? project) (error "invalid trace project"))
- (let ((value (.o (:: @ (poo-flow-model-prototype SdlcTraceNode)) kind: 'sdlc.trace-node identity: id category: category-value
+ (let ((value (.o (:: @ (poo-clos-model-prototype SdlcTraceNode)) kind: 'sdlc.trace-node identity: id category: category-value
subject: (.ref project 'subject) revision: (.ref project 'revision)
scope: (.ref project 'scope))))
(unless (sdlc-trace-node? value) (error "invalid trace node")) value))
(def (sdlc-trace-edge id relation-value source-value target-value project)
(unless (sdlc-bound-fact? project) (error "invalid trace project"))
- (let ((value (.o (:: @ (poo-flow-model-prototype SdlcTraceEdge)) kind: 'sdlc.trace-edge identity: id relation: relation-value
+ (let ((value (.o (:: @ (poo-clos-model-prototype SdlcTraceEdge)) kind: 'sdlc.trace-edge identity: id relation: relation-value
source: source-value target: target-value
subject: (.ref project 'subject) revision: (.ref project 'revision)
scope: (.ref project 'scope))))
@@ -51,21 +51,21 @@
(export sdlc-project sdlc-obligation sdlc-evidence sdlc-tailoring-request)
(def (sdlc-project subject-value revision-value scope-value complete-value)
- (poo-flow-check-model SdlcProject
- (.o (:: @ (poo-flow-model-prototype SdlcProject)) kind: 'sdlc.project subject: subject-value revision: revision-value
+ (poo-clos-check-model SdlcProject
+ (.o (:: @ (poo-clos-model-prototype SdlcProject)) kind: 'sdlc.project subject: subject-value revision: revision-value
scope: scope-value complete?: complete-value)))
(def (sdlc-obligation standard-value requirement-value applicability-value)
- (poo-flow-check-model SdlcObligation
- (.o (:: @ (poo-flow-model-prototype SdlcObligation)) kind: 'sdlc.obligation standard: standard-value requirement: requirement-value
+ (poo-clos-check-model SdlcObligation
+ (.o (:: @ (poo-clos-model-prototype SdlcObligation)) kind: 'sdlc.obligation standard: standard-value requirement: requirement-value
applicability: applicability-value)))
(def (sdlc-evidence identity-value subject-value revision-value scope-value
standard-value requirement-value producer-value outcome-value)
- (poo-flow-check-model SdlcEvidence
- (.o (:: @ (poo-flow-model-prototype SdlcEvidence)) kind: 'sdlc.evidence identity: identity-value subject: subject-value
+ (poo-clos-check-model SdlcEvidence
+ (.o (:: @ (poo-clos-model-prototype SdlcEvidence)) kind: 'sdlc.evidence identity: identity-value subject: subject-value
revision: revision-value scope: scope-value standard: standard-value
requirement: requirement-value producer: producer-value outcome: outcome-value)))
(def (sdlc-tailoring-request subject-value revision-value standard-value
requirement-value rationale-value)
- (poo-flow-check-model SdlcTailoringRequest
- (.o (:: @ (poo-flow-model-prototype SdlcTailoringRequest)) kind: 'sdlc.tailoring-request subject: subject-value revision: revision-value
+ (poo-clos-check-model SdlcTailoringRequest
+ (.o (:: @ (poo-clos-model-prototype SdlcTailoringRequest)) kind: 'sdlc.tailoring-request subject: subject-value revision: revision-value
standard: standard-value requirement: requirement-value rationale: rationale-value)))
diff --git a/modules/sdlc/retirement-host.ss b/modules/sdlc/retirement-host.ss
new file mode 100644
index 0000000..b65a486
--- /dev/null
+++ b/modules/sdlc/retirement-host.ss
@@ -0,0 +1,244 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Explicit, single-owner Scheme Host for the bounded retirement-ingress cut.
+;;; Pure POO state transitions are committed only at this local Host boundary.
+;;; This does not issue grants or claim durable, distributed, or Marlin authority.
+(import (only-in :clan/poo/object .o .ref .slot? object?))
+(export aitia-retirement-host
+ aitia-retirement-host-snapshot
+ aitia-retirement-effect-handoff
+ aitia-retirement-host-request-cancellation!
+ aitia-retirement-host-observe-completion!
+ aitia-retirement-host-observe-queue-drained!
+ aitia-retirement-host-complete-inventory!
+ aitia-retirement-host-review-cut!
+ aitia-retirement-host-observe-late-activity!
+ aitia-retirement-host-observe-inventory-gap!
+ aitia-retirement-host-close-ingress!
+ aitia-retirement-host-request-start!
+ aitia-retirement-host-attempt-start!
+ aitia-retirement-host-retire!)
+
+;;; The live state is keyed by host identity, never returned to callers.
+(def retirement-host-states (make-hash-table-eq weak-keys: #t))
+
+(def (host-state host)
+ (let (state (and (object? host) (hash-get retirement-host-states host)))
+ (unless (and state
+ (eq? (.ref state 'owner-thread) (current-thread)))
+ (error "retirement Host requires its serialized owner thread"))
+ state))
+
+(def (mutation-state host)
+ (let (current-state (host-state host))
+ (when (.ref current-state 'handoff-in-progress?)
+ (error "retirement Host mutation during effect handoff"))
+ current-state))
+
+(def (state-view state)
+ (.o kind: 'aitia.retirement-ingress-state.v1
+ active?: (.ref state 'active?)
+ queued?: (.ref state 'queued?)
+ inventory-known?: (.ref state 'inventory-known?)
+ reviewed?: (.ref state 'reviewed?)
+ cancellation-requested?: (.ref state 'cancellation-requested?)
+ late-activity-found?: (.ref state 'late-activity-found?)
+ inventory-gap-found?: (.ref state 'inventory-gap-found?)
+ retired?: (.ref state 'retired?)
+ ingress-open?: (.ref state 'ingress-open?)
+ authority-epoch: (.ref state 'authority-epoch)
+ cached-grant-epoch: (.ref state 'cached-grant-epoch)
+ pending?: (.ref state 'pending?)
+ attempted?: (.ref state 'attempted?)
+ handoff-in-progress?: (.ref state 'handoff-in-progress?)))
+
+(def (receipt action-name current-state was-accepted? rejection-reason did-handoff?)
+ (.o kind: 'aitia.retirement-ingress-receipt.v1
+ action: action-name accepted?: was-accepted? reason: rejection-reason
+ state: (state-view current-state)
+ handoff-executed?: did-handoff?
+ durable?: #f distributed-authority?: #f))
+
+(def (publish host action state accepted? reason)
+ (hash-put! retirement-host-states host state)
+ (receipt action state accepted? reason #f))
+
+(def (aitia-retirement-host)
+ (let ((host (.o kind: 'aitia.retirement-ingress-host.v1))
+ (creator-thread (current-thread)))
+ (let (state (.o owner-thread: creator-thread
+ active?: #t queued?: #t inventory-known?: #f
+ reviewed?: #f cancellation-requested?: #f
+ late-activity-found?: #f inventory-gap-found?: #f
+ retired?: #f ingress-open?: #t
+ authority-epoch: 0 cached-grant-epoch: 0
+ pending?: #f attempted?: #f
+ handoff-in-progress?: #f))
+ (hash-put! retirement-host-states host state)
+ host)))
+
+(def (aitia-retirement-host-snapshot host)
+ (state-view (host-state host)))
+
+;;; The named POO handoff is the only effect escape hatch. Its callback is
+;;; invoked only after the Host has consumed a current pending request.
+(def (aitia-retirement-effect-handoff callback)
+ (unless (procedure? callback) (error "retirement handoff requires a procedure"))
+ (.o kind: 'aitia.retirement-effect-handoff.v1 run: callback))
+
+(def (aitia-retirement-host-request-cancellation! host)
+ (let (state (mutation-state host))
+ (cond
+ ((.ref state 'retired?)
+ (receipt 'request-cancellation state #f 'already-retired #f))
+ ((.ref state 'cancellation-requested?)
+ (receipt 'request-cancellation state #f 'already-requested #f))
+ (else
+ (publish host 'request-cancellation
+ (.o (:: @ state) cancellation-requested?: #t)
+ #t 'recorded)))))
+
+(def (aitia-retirement-host-observe-completion! host)
+ (let (state (mutation-state host))
+ (cond
+ ((.ref state 'retired?)
+ (receipt 'observe-completion state #f 'already-retired #f))
+ ((not (.ref state 'active?))
+ (receipt 'observe-completion state #f 'not-active #f))
+ (else
+ (publish host 'observe-completion
+ (.o (:: @ state) active?: #f) #t 'observed)))))
+
+(def (aitia-retirement-host-observe-queue-drained! host)
+ (let (state (mutation-state host))
+ (cond
+ ((.ref state 'retired?)
+ (receipt 'observe-queue-drained state #f 'already-retired #f))
+ ((not (.ref state 'queued?))
+ (receipt 'observe-queue-drained state #f 'already-drained #f))
+ (else
+ (publish host 'observe-queue-drained
+ (.o (:: @ state) queued?: #f) #t 'observed)))))
+
+(def (aitia-retirement-host-complete-inventory! host)
+ (let (state (mutation-state host))
+ (cond
+ ((.ref state 'retired?)
+ (receipt 'complete-inventory state #f 'already-retired #f))
+ ((.ref state 'inventory-known?)
+ (receipt 'complete-inventory state #f 'already-known #f))
+ (else
+ (publish host 'complete-inventory
+ (.o (:: @ state) inventory-known?: #t) #t 'observed)))))
+
+(def (aitia-retirement-host-review-cut! host)
+ (let (state (mutation-state host))
+ (cond
+ ((.ref state 'retired?)
+ (receipt 'review-cut state #f 'already-retired #f))
+ ((.ref state 'active?)
+ (receipt 'review-cut state #f 'active-work #f))
+ ((.ref state 'queued?)
+ (receipt 'review-cut state #f 'queued-work #f))
+ ((not (.ref state 'inventory-known?))
+ (receipt 'review-cut state #f 'inventory-unknown #f))
+ ((.ref state 'reviewed?)
+ (receipt 'review-cut state #f 'already-reviewed #f))
+ (else
+ (publish host 'review-cut (.o (:: @ state) reviewed?: #t)
+ #t 'reviewed)))))
+
+(def (aitia-retirement-host-observe-late-activity! host)
+ (let (state (mutation-state host))
+ (cond
+ ((or (.ref state 'retired?) (not (.ref state 'reviewed?))
+ (.ref state 'late-activity-found?))
+ (receipt 'observe-late-activity state #f 'not-admissible #f))
+ (else
+ (publish host 'observe-late-activity
+ (.o (:: @ state) active?: #t late-activity-found?: #t)
+ #t 'observed)))))
+
+(def (aitia-retirement-host-observe-inventory-gap! host)
+ (let (state (mutation-state host))
+ (cond
+ ((or (.ref state 'retired?) (not (.ref state 'reviewed?))
+ (.ref state 'inventory-gap-found?))
+ (receipt 'observe-inventory-gap state #f 'not-admissible #f))
+ (else
+ (publish host 'observe-inventory-gap
+ (.o (:: @ state) inventory-known?: #f inventory-gap-found?: #t)
+ #t 'observed)))))
+
+;;; Closure and epoch advancement are one synchronous Host state publication.
+(def (aitia-retirement-host-close-ingress! host)
+ (let (state (mutation-state host))
+ (if (.ref state 'ingress-open?)
+ (publish host 'close-ingress
+ (.o (:: @ state) ingress-open?: #f
+ authority-epoch: (+ 1 (.ref state 'authority-epoch)))
+ #t 'fenced)
+ (receipt 'close-ingress state #f 'already-closed #f))))
+
+(def (aitia-retirement-host-request-start! host)
+ (let (state (host-state host))
+ (if (or (.ref state 'handoff-in-progress?)
+ (.ref state 'pending?) (.ref state 'attempted?))
+ (receipt 'request-start state #f 'request-already-consumed #f)
+ (publish host 'request-start (.o (:: @ state) pending?: #t)
+ #t 'pending))))
+
+(def (aitia-retirement-host-attempt-start! host handoff)
+ (let (state (mutation-state host))
+ (unless (and (object? handoff) (.slot? handoff 'kind)
+ (eq? (.ref handoff 'kind)
+ 'aitia.retirement-effect-handoff.v1)
+ (.slot? handoff 'run) (procedure? (.ref handoff 'run)))
+ (error "invalid retirement effect handoff"))
+ (unless (.ref state 'pending?)
+ (error "retirement start requires a pending request"))
+ (let (consumed (.o (:: @ state) pending?: #f attempted?: #t))
+ (cond
+ ((not (= (.ref state 'cached-grant-epoch)
+ (.ref state 'authority-epoch)))
+ (publish host 'attempt-start consumed #f 'stale-grant))
+ ((or (.ref state 'retired?) (not (.ref state 'ingress-open?)))
+ (publish host 'attempt-start consumed #f 'ingress-closed))
+ (else
+ ;; Consume before handoff so a reentrant call cannot start twice.
+ (let (started (.o (:: @ consumed) active?: #t
+ handoff-in-progress?: #t))
+ (hash-put! retirement-host-states host started)
+ ;; A failed callback is not completion. Keep work active and the
+ ;; request consumed, but release the transient reentrancy fence even
+ ;; when the callback raises. The original failure still propagates.
+ (dynamic-wind
+ void
+ (lambda () ((.ref handoff 'run)))
+ (lambda ()
+ (hash-put! retirement-host-states host
+ (.o (:: @ started) handoff-in-progress?: #f))))
+ (receipt 'attempt-start (host-state host) #t 'started #t)))))))
+
+(def (aitia-retirement-host-retire! host)
+ (let (state (mutation-state host))
+ (cond
+ ((.ref state 'retired?)
+ (receipt 'retire state #f 'already-retired #f))
+ ((.ref state 'active?)
+ (receipt 'retire state #f 'active-work #f))
+ ((.ref state 'queued?)
+ (receipt 'retire state #f 'queued-work #f))
+ ((not (.ref state 'inventory-known?))
+ (receipt 'retire state #f 'inventory-unknown #f))
+ ((not (.ref state 'reviewed?))
+ (receipt 'retire state #f 'review-missing #f))
+ ((.ref state 'ingress-open?)
+ (receipt 'retire state #f 'ingress-open #f))
+ ((= (.ref state 'cached-grant-epoch) (.ref state 'authority-epoch))
+ (receipt 'retire state #f 'grant-current #f))
+ (else
+ (publish host 'retire (.o (:: @ state) retired?: #t)
+ #t 'retired)))))
diff --git a/modules/sdlc/review-authority.ss b/modules/sdlc/review-authority.ss
new file mode 100644
index 0000000..02d16b8
--- /dev/null
+++ b/modules/sdlc/review-authority.ss
@@ -0,0 +1,122 @@
+;;; -*- Gerbil -*-
+;;; Native SDLC authority review. Technical success and authority are separate.
+(import :clan/poo/object :std/list/list
+ (only-in :yuanxu/poo-clos/model poo-clos-check-model poo-clos-model-prototype poo-clos-model?)
+ (only-in :yuanxu/poo-clos/classes poo-clos-class poo-clos-direct-slot-definition) :yuanxu/contribution/verification
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types)
+(export SdlcHistorySource SdlcHistoryDiscovery sdlc-history-source sdlc-history-discovery
+ sdlc-history-request sdlc-review-approval sdlc-approval-request
+ sdlc-review-authority-adapter sdlc-review-authority-gate sdlc-review-authority-snapshot)
+(def (texts names) (map (lambda (name) (poo-clos-direct-slot-definition name type-predicate: sdlc-text?)) names))
+(def SdlcHistorySource
+ (poo-clos-class 'sdlc/history-source direct-superclasses: (list SdlcIdentified)
+ direct-slots: (append (texts '(owner view artifact-digest))
+ (list (poo-clos-direct-slot-definition 'available? type-predicate: boolean?)))))
+(def (source? value) (poo-clos-model? SdlcHistorySource value))
+(def SdlcHistoryDiscovery
+ (poo-clos-class 'sdlc/history-discovery direct-superclasses: (list SdlcBoundFact SdlcIdentified)
+ direct-slots: (append (texts '(directory policy artifact-digest))
+ (list
+ (poo-clos-direct-slot-definition 'required type-predicate:
+ (lambda (xs) (and (pair? xs) (list? xs) (every sdlc-text? xs) (= (length xs) (length (delete-duplicates/hash xs))))))
+ (poo-clos-direct-slot-definition 'sources type-predicate:
+ (lambda (xs) (and (list? xs) (every source? xs))))))))
+(def (bound? a b) (every (lambda (key) (equal? (.ref a key) (.ref b key))) '(subject revision scope)))
+(def (slots value names) (map (lambda (key) (.ref value key)) names))
+(def (sdlc-history-source id owner-value view-value digest-value available-value)
+ (poo-clos-check-model SdlcHistorySource
+ (.o (:: @ (poo-clos-model-prototype SdlcHistorySource)) identity: (string-copy id)
+ owner: (string-copy owner-value) view: (string-copy view-value) artifact-digest: (string-copy digest-value) available?: available-value)))
+(def (sdlc-history-discovery id project directory-value policy-value required-values source-values digest-value)
+ (unless (sdlc-project? project) (error "history discovery requires an SDLC project"))
+ (poo-clos-check-model SdlcHistoryDiscovery
+ (.o (:: @ (poo-clos-model-prototype SdlcHistoryDiscovery)) identity: (string-copy id)
+ subject: (string-copy (.ref project 'subject)) revision: (string-copy (.ref project 'revision)) scope: (string-copy (.ref project 'scope))
+ directory: (string-copy directory-value) policy: (string-copy policy-value) required: (map string-copy required-values) sources: (append source-values '()) artifact-digest: (string-copy digest-value))))
+(def (request project purpose-value payload)
+ (poo-clos-check-model SdlcVerificationRequest
+ (.o (:: @ (poo-clos-model-prototype SdlcVerificationRequest))
+ subject: (string-copy (.ref project 'subject)) revision: (string-copy (.ref project 'revision)) scope: (string-copy (.ref project 'scope))
+ purpose: purpose-value facts: payload)))
+(def (sdlc-history-request discovery)
+ (unless (poo-clos-model? SdlcHistoryDiscovery discovery) (error "invalid native history discovery"))
+ (request discovery 'history-discovery (let (selected-discovery discovery) (.o discovery: selected-discovery))))
+(def (sdlc-review-approval id project standard-value requirement-value signer-value record-value decision-value target-value)
+ (unless (sdlc-project? project) (error "approval requires an SDLC project"))
+ (poo-clos-check-model SdlcAuthorityAttestation
+ (.o (:: @ (poo-clos-model-prototype SdlcAuthorityAttestation)) identity: (string-copy id)
+ subject: (string-copy (.ref project 'subject)) revision: (string-copy (.ref project 'revision)) scope: (string-copy (.ref project 'scope))
+ standard: (string-copy standard-value) requirement: (string-copy requirement-value)
+ request: (string-copy target-value) authority: 'disposition-reviewer signer: (string-copy signer-value) record: (string-copy record-value) decision: decision-value)))
+(def (sdlc-approval-request approval discovery content-value policy-value supersedes: (prior-records '()) references: (reference-values '()))
+ (unless (and (sdlc-authority-attestation? approval) (poo-clos-model? SdlcHistoryDiscovery discovery)
+ (bound? approval discovery) (sdlc-text? content-value) (sdlc-text? policy-value)
+ (list? reference-values)
+ (every (lambda (r) (and (list? r) (= (length r) 2) (sdlc-text? (car r)) (sdlc-artifact-digest? (cadr r)))) reference-values)
+ (list? prior-records) (every sdlc-text? prior-records)
+ (= (length prior-records) (length (delete-duplicates/hash prior-records))))
+ (error "approval is not bound to native history/project"))
+ (let ((selected-approval approval) (selected-discovery discovery))
+ (request approval 'disposition-approval
+ (.o approval: selected-approval discovery: selected-discovery content: (string-copy content-value) policy: (string-copy policy-value) supersedes: (map string-copy prior-records) references: (map (lambda (pair) (map string-copy pair)) reference-values)))))
+(def (discovery-data discovery)
+ (append (slots discovery '(identity subject revision scope directory policy required artifact-digest))
+ (list (map (lambda (source) (slots source '(identity owner view artifact-digest available?))) (.ref discovery 'sources)))))
+(def (sdlc-review-authority-snapshot value)
+ (unless (sdlc-verification-request? value) (error "invalid native authority request"))
+ (def facts (.ref value 'facts))
+ (def discovery (.ref facts 'discovery))
+ (unless (and (poo-clos-model? SdlcHistoryDiscovery discovery) (bound? discovery value))
+ (error "history request binding differs"))
+ (def data
+ (case (.ref value 'purpose)
+ ((history-discovery) (discovery-data discovery))
+ ((disposition-approval)
+ (let (approval (.ref facts 'approval))
+ (unless (and (sdlc-authority-attestation? approval) (bound? approval value)) (error "approval binding differs"))
+ (list (discovery-data discovery) (.ref facts 'content) (.ref facts 'policy) (.ref facts 'supersedes) (.ref facts 'references)
+ (slots approval '(identity subject revision scope standard requirement request authority signer record decision)))))
+ (else (error "unsupported SDLC authority purpose"))))
+ (call-with-output-string (lambda (port) (write (list 'sdlc-review-authority/v1 (.ref value 'purpose) data) port))))
+(def (sdlc-review-authority-adapter id operation) (agentic-ai-lab-verification-adapter id operation sdlc-review-authority-snapshot))
+(def (complete? discovery)
+ (def required (.ref discovery 'required))
+ (def sources (.ref discovery 'sources))
+ (and (= (length sources) (length required))
+ (= (length sources) (length (delete-duplicates/hash (map (lambda (s) (.ref s 'identity)) sources))))
+ (every (lambda (s) (and (.ref s 'available?) (member (.ref s 'identity) required) #t)) sources)))
+(def (sdlc-review-authority-gate technical discovery approval-requests adapter receipts now policy: active-policy)
+ (unless (and (poo-clos-model? SdlcHistoryDiscovery discovery) (equal? active-policy (.ref discovery 'policy))
+ (list? approval-requests) (every sdlc-verification-request? approval-requests))
+ (error "invalid native authority gate binding"))
+ (def discovery-request (sdlc-history-request discovery))
+ (def discovered (and (complete? discovery)
+ (any (lambda (r) (agentic-ai-lab-verification-valid? adapter r discovery-request now)) receipts)))
+ (def (verified? request)
+ (and (eq? (.ref request 'purpose) 'disposition-approval) (bound? request discovery)
+ (equal? (discovery-data (.ref (.ref request 'facts) 'discovery)) (discovery-data discovery))
+ (any (lambda (r) (agentic-ai-lab-verification-valid? adapter r request now)) receipts)))
+ (def verified (filter verified? approval-requests))
+ (def approvals (filter (lambda (r)
+ (def facts (.ref r 'facts))
+ (and (equal? (.ref facts 'policy) active-policy)
+ (eq? (.ref (.ref facts 'approval) 'decision) 'approved))) verified))
+ ;; Negative decisions persist across policy changes. Only an authenticated
+ ;; current-policy approval explicitly naming their record can supersede them.
+ (def denials (filter (lambda (r)
+ (def approval (.ref (.ref r 'facts) 'approval))
+ (and (eq? (.ref approval 'decision) 'rejected)
+ (not (any (lambda (a) (member (.ref approval 'identity) (.ref (.ref a 'facts) 'supersedes))) approvals)))) verified))
+ (def missing-negative
+ (any (lambda (r) (and (eq? (.ref (.ref (.ref r 'facts) 'approval) 'decision) 'rejected)
+ (not (verified? r)))) approval-requests))
+ (def status-value
+ (cond ((not (.ref technical 'admitted?)) 'requirements-blocked)
+ ((not discovered) 'history-discovery-required)
+ ((pair? denials) 'approval-rejected)
+ ((or missing-negative (null? approvals)) 'approval-verification-required)
+ (else 'review-admitted)))
+ (let (selected-technical technical)
+ (.o status: status-value admitted?: (eq? status-value 'review-admitted)
+ technical: selected-technical history-verified?: (and discovered #t)
+ approval-verified?: (eq? status-value 'review-admitted) release-authorized?: #f)))
diff --git a/modules/sdlc/review.ss b/modules/sdlc/review.ss
index 42e15fc..de55adf 100644
--- a/modules/sdlc/review.ss
+++ b/modules/sdlc/review.ss
@@ -5,9 +5,9 @@
;;; Pure review preparation over explicitly supplied facts; no graph execution
;;; or authority authentication. A ready packet is never a compliance decision.
(import (only-in :clan/poo/object .o .ref .slot?)
- :poo-flow/lambda-aitia/modules/sdlc/types
- :poo-flow/lambda-aitia/modules/sdlc/objects
- :poo-flow/lambda-aitia/modules/sdlc/funs
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/objects
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/funs
:std/list/list)
(export sdlc-project sdlc-obligation sdlc-evidence sdlc-tailoring-request
sdlc-review)
diff --git a/modules/sdlc/standards/nasa-7150-2d-catalog.ss b/modules/sdlc/standards/nasa-7150-2d-catalog.ss
index ef53579..8ef49a5 100644
--- a/modules/sdlc/standards/nasa-7150-2d-catalog.ss
+++ b/modules/sdlc/standards/nasa-7150-2d-catalog.ss
@@ -20,7 +20,7 @@
(page (list-ref row 2)) (excerpt (list-ref row 3))
(parts (list-ref row 4)) (notes (list-ref row 5))
(matrix (list-ref row 6))
- (value (.o identity: id standard: "nasa/npr-7150.2d"
+ (value (.o identity: id standard: "nasa/sdlc/npr-7150.2"
section: section-value source-url: (string-append
"https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=" page)
source-excerpt: excerpt source-parts: parts source-notes: notes
diff --git a/modules/sdlc/standards/nasa-7150-2d-profile.ss b/modules/sdlc/standards/nasa-7150-2d-profile.ss
index e98f903..5479128 100644
--- a/modules/sdlc/standards/nasa-7150-2d-profile.ss
+++ b/modules/sdlc/standards/nasa-7150-2d-profile.ss
@@ -7,16 +7,19 @@
;;; Applicability, review, and certification algorithms live in their own
;;; standard modules and do not enter the Profile import closure.
-(import (only-in :clan/poo/object .o)
- :poo-flow/lambda-aitia/modules/sdlc/objects
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog)
+(import (only-in :clan/poo/object .o .ref)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/objects
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
+ (only-in :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/sources
+ Nasa7150_2DSourcesLock))
(export Nasa7150_2D)
(def chapter3-url
"https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=Chapter3")
(def Nasa7150_2D
- (.o (:: @ StandardProfile.) identity: "nasa/npr-7150.2d" edition: "D"
+ (.o (:: @ StandardProfile.) identity: "nasa/sdlc/npr-7150.2" edition: "D"
+ source-lock-digest: (.ref Nasa7150_2DSourcesLock 'digest)
source-url: chapter3-url verified-on: "2026-09-12"
effective-date: "2022-03-08" expiration-date: "2027-03-08"
applicability-source:
diff --git a/modules/sdlc/standards/nasa-7150-2d.ss b/modules/sdlc/standards/nasa-7150-2d.ss
index f6f759f..793515b 100644
--- a/modules/sdlc/standards/nasa-7150-2d.ss
+++ b/modules/sdlc/standards/nasa-7150-2d.ss
@@ -3,13 +3,13 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :clan/poo/object .o .ref .slot? object?)
- :poo-flow/lambda-aitia/modules/sdlc/types
- :poo-flow/lambda-aitia/modules/sdlc/objects
- :poo-flow/lambda-aitia/modules/sdlc/funs
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-profile
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/objects
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/funs
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-profile
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
(only-in :gerbil/runtime/hash list->hash-table-string))
-(export (import: :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-profile)
+(export (import: :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-profile)
nasa-requirement-by-id nasa-matrix-invocation)
;;; Complete requirement index and matrix; execution and approvals remain separate.
@@ -125,7 +125,7 @@
((eq? condition-value #t) 'applicable)
((eq? condition-value #f) 'condition-not-triggered)
(else 'context-review-required))))
- (.o kind: 'sdlc.applicability standard: "nasa/npr-7150.2d" requirement: identity-value
+ (.o kind: 'sdlc.applicability standard: "nasa/sdlc/npr-7150.2" requirement: identity-value
software-class: class-value status: status-value invocation: invocation-value
source-url: (.ref row 'source-url) section: (.ref row 'section)
tailoring: 'not-approved assessment: 'not-evaluated)))
diff --git a/modules/sdlc/standards/nasa-certification.ss b/modules/sdlc/standards/nasa-certification.ss
index 549e256..2689765 100644
--- a/modules/sdlc/standards/nasa-certification.ss
+++ b/modules/sdlc/standards/nasa-certification.ss
@@ -5,10 +5,10 @@
;;; NPR 7150.2D compliance dossier and independently verified authority decision.
;;; This module never impersonates NASA, authenticates a signer, or authorizes release.
(import (only-in :clan/poo/object .o .ref .slot? object?)
- :poo-flow/src/module-system/contribution/model
- :poo-flow/src/module-system/contribution/verification
- :poo-flow/lambda-aitia/modules/sdlc/types
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
+ :agentic-ai-lab/core/poo-clos/interface
+ :agentic-ai-lab/core/contribution/verification
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
:std/list/list
:std/list/list
(only-in :gerbil/runtime/hash list->hash-table-string))
@@ -51,9 +51,9 @@
'decision type-predicate:
(lambda (value) (if (memq value '(compliant noncompliant)) #t #f)))))))
(def (sdlc-compliance-dossier? value)
- (poo-flow-model? SdlcComplianceDossier value))
+ (poo-clos-model? SdlcComplianceDossier value))
(def (sdlc-certification-decision? value)
- (poo-flow-model? SdlcCertificationDecision value))
+ (poo-clos-model? SdlcCertificationDecision value))
(def (bound? value project)
(every (lambda (slot)
@@ -102,14 +102,14 @@
nasa-project-requirement-identities)
(eligible-gate? institution-gate-value 'institution
nasa-institution-requirement-identities))))
- (poo-flow-check-model
+ (poo-clos-check-model
SdlcComplianceDossier
- (.o (:: @ (poo-flow-model-prototype SdlcComplianceDossier))
+ (.o (:: @ (poo-clos-model-prototype SdlcComplianceDossier))
identity: identity-value
subject: (.ref project 'subject)
revision: (.ref project 'revision)
scope: (.ref project 'scope)
- standard: "nasa/npr-7150.2d"
+ standard: "nasa/sdlc/npr-7150.2"
edition: "NPR 7150.2D"
software-class: class-value
mapping-matrix-digest: matrix-digest
@@ -121,9 +121,9 @@
signer-value record-value decision-value)
(unless (sdlc-compliance-dossier? dossier-value)
(error "invalid NASA compliance dossier"))
- (poo-flow-check-model
+ (poo-clos-check-model
SdlcCertificationDecision
- (.o (:: @ (poo-flow-model-prototype SdlcCertificationDecision))
+ (.o (:: @ (poo-clos-model-prototype SdlcCertificationDecision))
identity: identity-value
subject: (.ref dossier-value 'subject)
revision: (.ref dossier-value 'revision)
@@ -141,9 +141,9 @@
(equal? (.ref decision-value 'dossier)
(.ref dossier-value 'identity)))
(error "certification decision is not bound to the dossier"))
- (poo-flow-check-model
+ (poo-clos-check-model
SdlcVerificationRequest
- (.o (:: @ (poo-flow-model-prototype SdlcVerificationRequest))
+ (.o (:: @ (poo-clos-model-prototype SdlcVerificationRequest))
subject: (.ref dossier-value 'subject)
revision: (.ref dossier-value 'revision)
scope: (.ref dossier-value 'scope)
@@ -186,7 +186,7 @@
'(chapter2 chapter3 chapter4 chapter5 chapter6 appendix-c)))
port)))))
(def (nasa-certification-verification-adapter identity-value operation)
- (poo-flow-verification-adapter
+ (agentic-ai-lab-verification-adapter
identity-value operation certification-request-snapshot))
(def (nasa-certification-review dossier-value decision-value adapter receipts now)
@@ -196,9 +196,9 @@
(error "invalid NASA certification review inputs"))
(let* ((request (nasa-certification-verification-request
dossier-value decision-value))
- (admission (poo-flow-verification-admission adapter receipts now))
+ (admission (agentic-ai-lab-verification-admission adapter receipts now))
(verified?
- (poo-flow-verification-admission-valid? admission request))
+ (agentic-ai-lab-verification-admission-valid? admission request))
(status-value
(cond
((not (.ref dossier-value 'complete?)) 'dossier-incomplete)
diff --git a/modules/sdlc/standards/nasa-coverage.ss b/modules/sdlc/standards/nasa-coverage.ss
index d8dc6ce..4a6d6fa 100644
--- a/modules/sdlc/standards/nasa-coverage.ss
+++ b/modules/sdlc/standards/nasa-coverage.ss
@@ -5,8 +5,8 @@
;;; Executable implementation ledger. Implementation completeness and a
;;; project's compliance decision are deliberately separate dimensions.
(import (only-in :clan/poo/object .o .ref)
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
:std/list/list
(only-in :gerbil/core string-contains))
(export nasa-implementation-matrix nasa-implementation-summary)
@@ -59,7 +59,7 @@
(not (eq? (.ref row 'implementation-status)
'implemented)))
rows)))
- (.o standard: "nasa/npr-7150.2d"
+ (.o standard: "nasa/sdlc/npr-7150.2"
requirement-count: (length rows)
implemented-count:
(length (filter (lambda (row)
diff --git a/modules/sdlc/standards/nasa-lifecycle.ss b/modules/sdlc/standards/nasa-lifecycle.ss
index 11f5ff7..454b828 100644
--- a/modules/sdlc/standards/nasa-lifecycle.ss
+++ b/modules/sdlc/standards/nasa-lifecycle.ss
@@ -4,15 +4,15 @@
;;; Pure lifecycle decisions consume receipts from an explicit trusted boundary.
(import (only-in :clan/poo/object .o .ref .slot? object?)
- :poo-flow/src/module-system/contribution/model
- :poo-flow/src/module-system/contribution/verification
- :poo-flow/lambda-aitia/modules/sdlc/types
- (only-in :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-policy
+ (only-in :yuanxu/poo-clos/model poo-clos-check-model poo-clos-model-prototype)
+ :yuanxu/contribution/verification
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
+ (only-in :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-policy
nasa-stage-policy
nasa-baseline-policy)
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-review
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-structured
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-review
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-structured
:std/list/list)
(export nasa-stage-policy nasa-baseline-policy nasa-context-request nasa-evidence-request
nasa-verifiable-evidence nasa-verification-adapter nasa-stage-gate nasa-inventory-request
@@ -35,8 +35,8 @@
(error "verifiable NASA evidence requires a SHA-256 artifact digest"))
(.o (:: @ evidence) artifact-digest: digest-value))
(def (request project purpose-value facts-value)
- (poo-flow-check-model SdlcVerificationRequest
- (.o (:: @ (poo-flow-model-prototype SdlcVerificationRequest))
+ (poo-clos-check-model SdlcVerificationRequest
+ (.o (:: @ (poo-clos-model-prototype SdlcVerificationRequest))
subject: (.ref project 'subject) revision: (.ref project 'revision) scope: (.ref project 'scope)
purpose: purpose-value facts: facts-value)))
(def (nasa-context-request project class-value context-value)
@@ -90,17 +90,17 @@
(slots value '(subject revision scope)) payload
(slots nasa-catalog-source-digests '(chapter2 chapter3 chapter4 chapter5 chapter6 appendix-c))) port)))))
(def (nasa-verification-adapter id operation)
- (poo-flow-verification-adapter id operation request-snapshot))
+ (agentic-ai-lab-verification-adapter id operation request-snapshot))
(def (verified? admission value)
- (poo-flow-verification-admission-valid? admission value))
+ (agentic-ai-lab-verification-admission-valid? admission value))
(def (nasa-stage-gate policy project class-value context evidence adapter receipts now
tailorings: (tailoring-values '()) inventories: (inventory-values '()))
(unless (and (sdlc-stage-policy? policy) (list? receipts) (list? tailoring-values)
(list? inventory-values)
(every (lambda (i) (or (sdlc-trace-inventory? i) (sdlc-safety-inventory? i))) inventory-values)
(exact-integer? now) (>= now 0)) (error "invalid stage gate inputs"))
- (let* ((report ((if (eq? (.ref policy 'assessment-scope) 'institution) nasa-assess-institution nasa-assess-project) class-value project context evidence))
- (admission (poo-flow-verification-admission adapter receipts now))
+ (let* ((report ((if (eq? (.ref policy 'assessment-scope) 'institution) nasa-assess-institution nasa-assess-project) class-value project context evidence requirements: (.ref policy 'requirements)))
+ (admission (agentic-ai-lab-verification-admission adapter receipts now))
(selected (map (lambda (id)
(or (find (lambda (r) (equal? (.ref r 'requirement) id)) (.ref report 'requirements))
(error "unknown stage requirement" id))) (.ref policy 'requirements)))
@@ -179,8 +179,8 @@
reported-failures: failed
admitted?: (eq? status-value 'stage-admitted) release-authorized?: #f)))
(def (make-state project stage-value)
- (poo-flow-check-model SdlcLifecycleState
- (.o (:: @ (poo-flow-model-prototype SdlcLifecycleState))
+ (poo-clos-check-model SdlcLifecycleState
+ (.o (:: @ (poo-clos-model-prototype SdlcLifecycleState))
subject: (.ref project 'subject) revision: (.ref project 'revision) scope: (.ref project 'scope)
stage: stage-value)))
(def (nasa-lifecycle-start project)
diff --git a/modules/sdlc/standards/nasa-policy.ss b/modules/sdlc/standards/nasa-policy.ss
index 323dbae..842b165 100644
--- a/modules/sdlc/standards/nasa-policy.ss
+++ b/modules/sdlc/standards/nasa-policy.ss
@@ -4,19 +4,19 @@
;;; NPR 7150.2D project/institution baseline policy construction.
(import (only-in :clan/poo/object .o .ref)
- :poo-flow/src/module-system/contribution/model
- :poo-flow/lambda-aitia/modules/sdlc/types
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
+ (only-in :yuanxu/poo-clos/model poo-clos-check-model poo-clos-model-prototype)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
:std/list/list)
(export nasa-stage-policy nasa-baseline-policy)
(def (nasa-stage-policy id requirements-value scope: (scope-value 'project))
(let (result
- (poo-flow-check-model
+ (poo-clos-check-model
SdlcStagePolicy
- (.o (:: @ (poo-flow-model-prototype SdlcStagePolicy))
+ (.o (:: @ (poo-clos-model-prototype SdlcStagePolicy))
identity: id assessment-scope: scope-value
requirements: requirements-value)))
(when (equal? id "unstarted")
diff --git a/modules/sdlc/standards/nasa-review.ss b/modules/sdlc/standards/nasa-review.ss
index 66eb3dd..9951aee 100644
--- a/modules/sdlc/standards/nasa-review.ss
+++ b/modules/sdlc/standards/nasa-review.ss
@@ -4,11 +4,11 @@
;;; Source-bound review across every catalog requirement. No authority execution.
(import (only-in :clan/poo/object .o .ref .slot? object?)
- :poo-flow/src/module-system/contribution/model
- :poo-flow/lambda-aitia/modules/sdlc/types
- :poo-flow/lambda-aitia/modules/sdlc/objects
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
+ (only-in :yuanxu/poo-clos/model poo-clos-check-model poo-clos-model-prototype)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/objects
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
:std/list/list)
(export nasa-requirement-criteria nasa-criterion-evidence nasa-assess-project
nasa-tailoring-requirements nasa-safety-component nasa-safety-review)
@@ -27,11 +27,11 @@
(unless (sdlc-project? project) (error "invalid NASA evidence project"))
(unless (member criterion-id (map (lambda (c) (.ref c 'identity)) (nasa-requirement-criteria requirement-id)))
(error "unknown NASA criterion" requirement-id criterion-id))
- (poo-flow-check-model SdlcCriterionEvidence
- (.o (:: @ (poo-flow-model-prototype SdlcCriterionEvidence))
+ (poo-clos-check-model SdlcCriterionEvidence
+ (.o (:: @ (poo-clos-model-prototype SdlcCriterionEvidence))
identity: id kind: 'sdlc.evidence
subject: (.ref project 'subject) revision: (.ref project 'revision) scope: (.ref project 'scope)
- standard: "nasa/npr-7150.2d" requirement: requirement-id criterion: criterion-id
+ standard: "nasa/sdlc/npr-7150.2" requirement: requirement-id criterion: criterion-id
source-digest: (row-digest (nasa-requirement-by-id requirement-id))
producer: producer-value outcome: outcome-value)))
(def (unique-ids? values)
@@ -76,14 +76,24 @@
(error "invalid NASA project assessment inputs"))
(for-each
(lambda (e)
- (unless (and (equal? (.ref e 'standard) "nasa/npr-7150.2d")
+ (unless (and (equal? (.ref e 'standard) "nasa/sdlc/npr-7150.2")
(member (.ref e 'criterion)
(map (lambda (c) (.ref c 'identity))
(nasa-requirement-criteria (.ref e 'requirement)))))
(error "evidence is not bound to a NASA criterion"))) evidence))
-(def (nasa-assess-project class-value project context evidence)
+;; A stage may request a finite subset. Input validation remains global, and
+;; every selected row uses the same assessment as a complete catalog review.
+(def (assessment-rows requirements)
+ (if requirements
+ (begin
+ (unless (and (list? requirements)
+ (= (length requirements) (length (delete-duplicates/hash requirements))))
+ (error "invalid assessment requirement selection"))
+ (map nasa-requirement-by-id requirements))
+ nasa-requirement-catalog))
+(def (nasa-assess-project class-value project context evidence requirements: (requirements #f))
(validate-review-inputs project context evidence)
- (let* ((rows (map (lambda (row) (assess-one row class-value project context evidence)) nasa-requirement-catalog))
+ (let* ((rows (map (lambda (row) (assess-one row class-value project context evidence)) (assessment-rows requirements)))
(pending-values (filter (lambda (r) (not (memq (.ref r 'status) '(evidence-present not-invoked)))) rows)))
(.o kind: 'sdlc.nasa-assessment subject: (.ref project 'subject)
revision: (.ref project 'revision) scope: (.ref project 'scope)
@@ -117,8 +127,8 @@
(def (nasa-safety-component id project safety-value coverage-value complexity-value)
(unless (sdlc-project? project) (error "invalid safety snapshot"))
- (poo-flow-check-model SdlcSafetyComponent
- (.o (:: @ (poo-flow-model-prototype SdlcSafetyComponent)) identity: id
+ (poo-clos-check-model SdlcSafetyComponent
+ (.o (:: @ (poo-clos-model-prototype SdlcSafetyComponent)) identity: id
subject: (.ref project 'subject) revision: (.ref project 'revision) scope: (.ref project 'scope)
safety-critical?: safety-value mcdc-percent: coverage-value cyclomatic-complexity: complexity-value)))
(def (nasa-safety-review project components)
@@ -144,23 +154,23 @@
(def (nasa-tailoring-packet id project requirement-id rationale-value risk-value mitigations-value acceptance-value archive-value)
(unless (sdlc-project? project) (error "invalid tailoring project"))
(nasa-requirement-by-id requirement-id)
- (poo-flow-check-model SdlcTailoringPacket
- (.o (:: @ (poo-flow-model-prototype SdlcTailoringPacket)) identity: id
+ (poo-clos-check-model SdlcTailoringPacket
+ (.o (:: @ (poo-clos-model-prototype SdlcTailoringPacket)) identity: id
subject: (.ref project 'subject) revision: (.ref project 'revision) scope: (.ref project 'scope)
- standard: "nasa/npr-7150.2d" requirement: requirement-id
+ standard: "nasa/sdlc/npr-7150.2" requirement: requirement-id
rationale: rationale-value risk: risk-value mitigations: mitigations-value
risk-acceptance: acceptance-value archived-matrix: archive-value)))
(def (nasa-authority-attestation id packet authority-value signer-value record-value decision-value)
(unless (sdlc-tailoring-packet? packet) (error "invalid tailoring packet"))
- (poo-flow-check-model SdlcAuthorityAttestation
- (.o (:: @ (poo-flow-model-prototype SdlcAuthorityAttestation)) identity: id
+ (poo-clos-check-model SdlcAuthorityAttestation
+ (.o (:: @ (poo-clos-model-prototype SdlcAuthorityAttestation)) identity: id
subject: (.ref packet 'subject) revision: (.ref packet 'revision) scope: (.ref packet 'scope)
standard: (.ref packet 'standard) requirement: (.ref packet 'requirement)
request: (.ref packet 'identity) authority: authority-value signer: signer-value
record: record-value decision: decision-value)))
(def (nasa-tailoring-review project class-value context packet attestations)
(unless (and (sdlc-project? project) (sdlc-tailoring-packet? packet)
- (bound? packet project) (equal? (.ref packet 'standard) "nasa/npr-7150.2d")
+ (bound? packet project) (equal? (.ref packet 'standard) "nasa/sdlc/npr-7150.2")
(list? attestations) (every sdlc-authority-attestation? attestations)
(unique-ids? attestations))
(error "invalid tailoring review inputs"))
@@ -196,10 +206,10 @@
(export nasa-assess-institution)
;;; Center/Agency source obligations have their own review scope, so project
;;; reports do not silently discharge duties belonging to institutional owners.
-(def (nasa-assess-institution class-value snapshot context evidence)
+(def (nasa-assess-institution class-value snapshot context evidence requirements: (requirements #f))
(validate-review-inputs snapshot context evidence)
(unless (memq class-value '(a b c d e f)) (error "invalid NASA software class"))
- (let* ((institutional (filter (lambda (r) (not (.slot? r 'class-matrix))) nasa-requirement-catalog))
+ (let* ((institutional (filter (lambda (r) (not (.slot? r 'class-matrix))) (assessment-rows requirements)))
(reviews
(map (lambda (r)
(let* ((id (.ref r 'identity))
diff --git a/modules/sdlc/standards/nasa-standard-provider.ss b/modules/sdlc/standards/nasa-standard-provider.ss
index 05c5777..8173f73 100644
--- a/modules/sdlc/standards/nasa-standard-provider.ss
+++ b/modules/sdlc/standards/nasa-standard-provider.ss
@@ -4,35 +4,35 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
;;; Boundary: Lambda Aitia projects NASA NPR 7150.2D into the domain-neutral
-;;; POO Flow Standards protocol. Source bytes remain behind an explicit POO
+;;; Agentic AI Lab Standards protocol. Source bytes remain behind an explicit POO
;;; Provider and are not read while the module, catalog, or Profile is loaded.
(import (only-in :clan/poo/object .o .ref .slot? object?)
(only-in :gerbil/core path-expand)
(only-in :std/misc/ports read-all-as-string)
- (only-in :poo-flow/src/feature-system/source-lock-feature
+ (only-in :yuanxu/feature-system/source-lock-feature
require-source-lock-payload)
- (only-in :poo-flow/src/modules/standards/interface
- PooFlowStandardValidationProvider.
- poo-flow-standard-artifact
- poo-flow-standard-artifact-ref
- poo-flow-standard-artifact-source
- poo-flow-standard-budget
- poo-flow-standard-catalog
- poo-flow-standard-digest
- poo-flow-standard-edition-ref
- poo-flow-standard-family
- poo-flow-standard-make-validation-closure
- poo-flow-standard-materialization-context
- poo-flow-standard-resolve
- poo-flow-standard-resolution-receipt-bundle
- poo-flow-standard-resolution-receipt-valid?
- poo-flow-standard-constraint-profile
- poo-flow-standard-materialize
- poo-flow-standard-materialization-receipt-valid?
- poo-flow-standards-module)
+ (only-in :agentic-ai-lab/modules/standards/interface
+ AgenticAILabStandardValidationProvider.
+ agentic-ai-lab-standard-artifact
+ agentic-ai-lab-standard-artifact-ref
+ agentic-ai-lab-standard-artifact-source
+ agentic-ai-lab-standard-budget
+ agentic-ai-lab-standard-catalog
+ agentic-ai-lab-standard-digest
+ agentic-ai-lab-standard-edition-ref
+ agentic-ai-lab-standard-family
+ agentic-ai-lab-standard-make-validation-closure
+ agentic-ai-lab-standard-materialization-context
+ agentic-ai-lab-standard-resolve
+ agentic-ai-lab-standard-resolution-receipt-bundle
+ agentic-ai-lab-standard-resolution-receipt-valid?
+ agentic-ai-lab-standard-constraint-profile
+ agentic-ai-lab-standard-materialize
+ agentic-ai-lab-standard-materialization-receipt-valid?
+ agentic-ai-lab-standards-module)
"sources.ss"
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog)
(export Nasa7150_2DStandardFamily
Nasa7150_2DSourceProvider.
@@ -44,11 +44,11 @@
nasa-7150-2d-validation-closure
nasa-7150-2d-materialize-sources)
-(def +nasa-7150-2d-provider-identity+ "lambda-aitia/nasa-npr-7150.2d")
+(def +nasa-7150-2d-provider-identity+ "lambda-aitia/nasa/sdlc/npr-7150.2/D")
(def Nasa7150_2DStandardFamily
- (poo-flow-standard-family
- "nasa/npr-7150.2" "NASA" 'software-engineering
+ (agentic-ai-lab-standard-family
+ "nasa/sdlc/npr-7150.2" "NASA" 'sdlc
'(html scheme) "publicly-available-nasa-directive"
'((contributor . lambda-aitia)
(authority . nasa-nodis))))
@@ -95,20 +95,20 @@
(lock-receipt-value
(require-source-lock-payload
lock-value identity-value payload-value)))
- (poo-flow-standard-artifact-source
+ (agentic-ai-lab-standard-artifact-source
identity-value digest-value representation-value
payload-value size-bytes-value
(list (cons 'source-path relative-path-value)
(cons 'source-lock-receipt lock-receipt-value))))))
(materializer-value
(lambda (source-value)
- (poo-flow-standard-artifact
+ (agentic-ai-lab-standard-artifact
identity-value digest-value representation-value
(.ref source-value 'payload)
(list (cons 'source-url (.ref spec-value 'canonical-uri))
(cons 'source-lock-digest
(.ref lock-value 'digest)))))))
- (poo-flow-standard-artifact-ref
+ (agentic-ai-lab-standard-artifact-ref
identity-value (.ref spec-value 'canonical-uri)
(.ref spec-value 'exact-version)
'normative-source representation-value digest-value '() size-bytes-value
@@ -125,10 +125,10 @@
(.ref lock 'entries)))
(artifact-identities (map (lambda (value) (.ref value 'identity)) artifacts))
(edition-digest
- (poo-flow-standard-digest
+ (agentic-ai-lab-standard-digest
(map (lambda (value) (.ref value 'digest)) artifacts)))
(edition-value
- (poo-flow-standard-edition-ref
+ (agentic-ai-lab-standard-edition-ref
+nasa-7150-2d-edition-identity+ Nasa7150_2DStandardFamily
+nasa-7150-2d-edition-canonical-uri+ "D"
"NPR 7150.2D" 'us-federal edition-digest
@@ -138,7 +138,7 @@
(list (cons 'owner 'lambda-aitia)
(cons 'sources-lock-digest (.ref lock 'digest)))))
(profile-value
- (poo-flow-standard-constraint-profile
+ (agentic-ai-lab-standard-constraint-profile
"lambda-aitia/nasa-npr-7150.2d/full" "2026-09-17"
(list +nasa-7150-2d-edition-identity+)
nasa-requirement-catalog '() artifact-identities '()
@@ -146,7 +146,7 @@
(cons 'owner 'lambda-aitia)
(cons 'sources-lock-digest (.ref lock 'digest)))
'source-reviewed)))
- (.o (:: @ PooFlowStandardValidationProvider.)
+ (.o (:: @ AgenticAILabStandardValidationProvider.)
identity: +nasa-7150-2d-provider-identity+
supported-families: (list (.ref Nasa7150_2DStandardFamily 'identity))
source-provider: source-provider-value
@@ -155,7 +155,7 @@
constraint-profile: profile-value)))
(def (nasa-7150-2d-standard-catalog provider)
- (poo-flow-standard-catalog
+ (agentic-ai-lab-standard-catalog
"lambda-aitia/nasa-npr-7150.2d/catalog"
(list (.ref provider 'edition))
'((selection . exact-edition))))
@@ -163,14 +163,14 @@
(def (nasa-7150-2d-standards-module source-provider)
(let* ((provider (nasa-7150-2d-standard-provider source-provider))
(catalog (nasa-7150-2d-standard-catalog provider)))
- (poo-flow-standards-module
+ (agentic-ai-lab-standards-module
"lambda-aitia/modules/sdlc/standards/nasa-npr-7150.2d"
catalog
- (poo-flow-standard-budget 1 6 2 250000 32)
+ (agentic-ai-lab-standard-budget 1 6 2 250000 32)
(.o nasa: provider))))
(def (nasa-7150-2d-resolve standards-module terminology-snapshot-digest)
- (poo-flow-standard-resolve
+ (agentic-ai-lab-standard-resolve
(.ref standards-module 'catalog)
(list +nasa-7150-2d-edition-identity+)
(.ref standards-module 'budget)
@@ -181,13 +181,13 @@
(let* ((resolution
(nasa-7150-2d-resolve
standards-module
- (poo-flow-standard-digest 'nasa-7150-2d/no-terminology)))
+ (agentic-ai-lab-standard-digest 'nasa-7150-2d/no-terminology)))
(provider (.ref (.ref standards-module 'providers) 'nasa)))
- (unless (poo-flow-standard-resolution-receipt-valid? resolution)
+ (unless (agentic-ai-lab-standard-resolution-receipt-valid? resolution)
(error "NASA Standard resolution failed" resolution))
- (poo-flow-standard-make-validation-closure
+ (agentic-ai-lab-standard-make-validation-closure
"lambda-aitia/nasa-npr-7150.2d/validation-closure"
- (poo-flow-standard-resolution-receipt-bundle resolution)
+ (agentic-ai-lab-standard-resolution-receipt-bundle resolution)
(.ref provider 'identity) subject-kind subject-snapshot-digest
(.ref (.ref provider 'constraint-profile) 'constraints))))
@@ -195,17 +195,17 @@
(let* ((resolution
(nasa-7150-2d-resolve
standards-module
- (poo-flow-standard-digest 'nasa-7150-2d/no-terminology)))
- (bundle (poo-flow-standard-resolution-receipt-bundle resolution))
+ (agentic-ai-lab-standard-digest 'nasa-7150-2d/no-terminology)))
+ (bundle (agentic-ai-lab-standard-resolution-receipt-bundle resolution))
(context
- (poo-flow-standard-materialization-context
+ (agentic-ai-lab-standard-materialization-context
"lambda-aitia/nasa-npr-7150.2d/materialization"
(.ref bundle 'artifacts))))
(map
(lambda (artifact)
(let (receipt
- (poo-flow-standard-materialize context (.ref artifact 'identity)))
- (unless (poo-flow-standard-materialization-receipt-valid? receipt)
+ (agentic-ai-lab-standard-materialize context (.ref artifact 'identity)))
+ (unless (agentic-ai-lab-standard-materialization-receipt-valid? receipt)
(error "NASA Standard materialization failed" receipt))
receipt))
(.ref bundle 'artifacts))))
diff --git a/modules/sdlc/standards/nasa-structured.ss b/modules/sdlc/standards/nasa-structured.ss
index 3c25c08..9f87cc7 100644
--- a/modules/sdlc/standards/nasa-structured.ss
+++ b/modules/sdlc/standards/nasa-structured.ss
@@ -4,11 +4,11 @@
;;; Deterministic local checks over authenticated inventory projections.
(import (only-in :clan/poo/object .o .ref)
- :poo-flow/src/module-system/contribution/model
- :poo-flow/lambda-aitia/modules/sdlc/types
- :poo-flow/lambda-aitia/modules/sdlc/funs
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-review
+ (only-in :yuanxu/poo-clos/model poo-clos-check-model poo-clos-model-prototype)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/types
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/funs
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-review
:std/list/list)
(export nasa-safety-inventory nasa-trace-inventory nasa-structured-requirement?
nasa-inventory-for? nasa-inventory-snapshot nasa-structured-review)
@@ -16,14 +16,14 @@
(every (lambda (s) (equal? (.ref value s) (.ref project s))) '(subject revision scope)))
(def (base class id project digest-value complete-value)
(unless (sdlc-project? project) (error "invalid inventory project"))
- (.o (:: @ (poo-flow-model-prototype class)) identity: id
+ (.o (:: @ (poo-clos-model-prototype class)) identity: id
subject: (.ref project 'subject) revision: (.ref project 'revision) scope: (.ref project 'scope)
artifact-digest: digest-value complete?: complete-value))
(def (nasa-safety-inventory id project digest-value components-value complete?: (complete-value #t))
- (poo-flow-check-model SdlcSafetyInventory
+ (poo-clos-check-model SdlcSafetyInventory
(.o (:: @ (base SdlcSafetyInventory id project digest-value complete-value)) components: components-value)))
(def (nasa-trace-inventory id project digest-value nodes-value edges-value complete?: (complete-value #t))
- (poo-flow-check-model SdlcTraceInventory
+ (poo-clos-check-model SdlcTraceInventory
(.o (:: @ (base SdlcTraceInventory id project digest-value complete-value)) nodes: nodes-value edges: edges-value)))
(def (nasa-structured-requirement? id)
(and (member id '("SWE-052" "SWE-219" "SWE-220")) #t))
diff --git a/modules/sdlc/standards/source.lock.ss b/modules/sdlc/standards/source.lock.ss
index a58732e..4cbc318 100644
--- a/modules/sdlc/standards/source.lock.ss
+++ b/modules/sdlc/standards/source.lock.ss
@@ -1,5 +1,5 @@
;;; -*- Gerbil -*-
-;;; @generated by POO Flow Sources Lock Feature; DO NOT EDIT.
+;;; @generated by Agentic AI Lab Sources Lock Feature; DO NOT EDIT.
;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
@@ -8,12 +8,12 @@
(def Nasa7150_2DSourcesLock
(sources-lock-value
- "lambda-aitia/nasa-npr-7150.2d/sources"
+ "lambda-aitia/nasa/sdlc/npr-7150.2/D/sources"
"2022-03-08"
- "sha256:286dbc723fbad0e596ad07593d95ce56f7bbdf6526d30719ab3bebd29bc772bb"
+ "sha256:cfb963b8cd81fd8e22e9b47251c1dc7927b85fcdf9ec9366057cd38cb94f338c"
(list
(.o (:: @ SourceLockEntry.)
- identity: "nasa/npr-7150.2d/appendix-c"
+ identity: "nasa/sdlc/npr-7150.2/D/appendix-c"
path: "modules/sdlc/standards/sources/appendix-c.html"
canonical-uri: "https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=AppendixC"
exact-version: "2022-03-08"
@@ -23,7 +23,7 @@
metadata: '((section . appendix-c))
)
(.o (:: @ SourceLockEntry.)
- identity: "nasa/npr-7150.2d/chapter2"
+ identity: "nasa/sdlc/npr-7150.2/D/chapter2"
path: "modules/sdlc/standards/sources/chapter2.html"
canonical-uri: "https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=Chapter2"
exact-version: "2022-03-08"
@@ -33,7 +33,7 @@
metadata: '((section . chapter-2))
)
(.o (:: @ SourceLockEntry.)
- identity: "nasa/npr-7150.2d/chapter3"
+ identity: "nasa/sdlc/npr-7150.2/D/chapter3"
path: "modules/sdlc/standards/sources/chapter3.html"
canonical-uri: "https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=Chapter3"
exact-version: "2022-03-08"
@@ -43,7 +43,7 @@
metadata: '((section . chapter-3))
)
(.o (:: @ SourceLockEntry.)
- identity: "nasa/npr-7150.2d/chapter4"
+ identity: "nasa/sdlc/npr-7150.2/D/chapter4"
path: "modules/sdlc/standards/sources/chapter4.html"
canonical-uri: "https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=Chapter4"
exact-version: "2022-03-08"
@@ -53,7 +53,7 @@
metadata: '((section . chapter-4))
)
(.o (:: @ SourceLockEntry.)
- identity: "nasa/npr-7150.2d/chapter5"
+ identity: "nasa/sdlc/npr-7150.2/D/chapter5"
path: "modules/sdlc/standards/sources/chapter5.html"
canonical-uri: "https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=Chapter5"
exact-version: "2022-03-08"
@@ -63,7 +63,7 @@
metadata: '((section . chapter-5))
)
(.o (:: @ SourceLockEntry.)
- identity: "nasa/npr-7150.2d/chapter6"
+ identity: "nasa/sdlc/npr-7150.2/D/chapter6"
path: "modules/sdlc/standards/sources/chapter6.html"
canonical-uri: "https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=Chapter6"
exact-version: "2022-03-08"
diff --git a/modules/sdlc/standards/sources.ss b/modules/sdlc/standards/sources.ss
index f5f3bef..8b74d40 100644
--- a/modules/sdlc/standards/sources.ss
+++ b/modules/sdlc/standards/sources.ss
@@ -7,7 +7,7 @@
;;; from the checked-in bytes into source.lock.ss.
(import (only-in :clan/poo/object .o)
- (only-in :poo-flow/src/feature-system/source-lock-feature
+ (only-in :yuanxu/feature-system/source-lock-feature
SourceReference. SourceLockEntry. SourcesLock.
sources-lock-value))
@@ -17,7 +17,7 @@
Nasa7150_2DSources
Nasa7150_2DSourcesLock)
-(def +nasa-7150-2d-edition-identity+ "nasa/npr-7150.2d/2022-03-08")
+(def +nasa-7150-2d-edition-identity+ "nasa/sdlc/npr-7150.2/D/2022-03-08")
(def +nasa-7150-2d-edition-canonical-uri+
"https://nodis3.gsfc.nasa.gov/N_PR_7150_002D_")
(def +nasa-7150-2d-source-ref+
@@ -34,17 +34,17 @@
metadata: (list (cons 'section section-value))))
(def Nasa7150_2DSources
- (list (nasa-source "nasa/npr-7150.2d/chapter2"
+ (list (nasa-source "nasa/sdlc/npr-7150.2/D/chapter2"
"chapter2.html" "Chapter2" 'chapter-2)
- (nasa-source "nasa/npr-7150.2d/chapter3"
+ (nasa-source "nasa/sdlc/npr-7150.2/D/chapter3"
"chapter3.html" "Chapter3" 'chapter-3)
- (nasa-source "nasa/npr-7150.2d/chapter4"
+ (nasa-source "nasa/sdlc/npr-7150.2/D/chapter4"
"chapter4.html" "Chapter4" 'chapter-4)
- (nasa-source "nasa/npr-7150.2d/chapter5"
+ (nasa-source "nasa/sdlc/npr-7150.2/D/chapter5"
"chapter5.html" "Chapter5" 'chapter-5)
- (nasa-source "nasa/npr-7150.2d/chapter6"
+ (nasa-source "nasa/sdlc/npr-7150.2/D/chapter6"
"chapter6.html" "Chapter6" 'chapter-6)
- (nasa-source "nasa/npr-7150.2d/appendix-c"
+ (nasa-source "nasa/sdlc/npr-7150.2/D/appendix-c"
"appendix-c.html" "AppendixC" 'appendix-c)))
(include "source.lock.ss")
diff --git a/modules/sdlc/types.ss b/modules/sdlc/types.ss
index 9868fa9..021ecf1 100644
--- a/modules/sdlc/types.ss
+++ b/modules/sdlc/types.ss
@@ -3,13 +3,14 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :clan/poo/object .ref .slot? object?)
- :poo-flow/src/module-system/contribution/model
- (only-in :poo-flow/src/modules/governance/types
- poo-flow-governance-profile?)
+ (only-in :yuanxu/poo-clos/model poo-clos-model?)
+ (only-in :yuanxu/poo-clos/classes poo-clos-class poo-clos-direct-slot-definition)
+ (only-in :agentic-ai-lab/modules/governance/types
+ agentic-ai-lab-governance-profile?)
:std/list/list
:std/list/list)
(export standard-profile? sdlc-profile? sdlc-text?
- SdlcStandard SdlcBoundFact SdlcProject SdlcObligation SdlcEvidence
+ SdlcStandard SdlcIdentified SdlcBoundFact SdlcProject SdlcObligation SdlcEvidence
SdlcTailoringRequest SdlcTraceNode SdlcTraceEdge SdlcTraceRule
sdlc-bound-fact? sdlc-project? sdlc-obligation? sdlc-evidence?
sdlc-tailoring-request? sdlc-trace-node? sdlc-trace-edge? sdlc-trace-rule?)
@@ -68,27 +69,27 @@
'(source-category target-category))))
(def (sdlc-profile? value)
- (and (poo-flow-governance-profile? value) (.slot? value 'standards)
+ (and (agentic-ai-lab-governance-profile? value) (.slot? value 'standards)
(list? (.ref value 'standards))
(every standard-profile? (.ref value 'standards))
(let ((ids (map (lambda (s) (.ref s 'identity)) (.ref value 'standards))))
(= (length ids) (length (delete-duplicates/hash ids))))))
-(def (standard-profile? value) (poo-flow-model? SdlcStandard value))
-(def (sdlc-bound-fact? value) (poo-flow-model? SdlcBoundFact value))
-(def (sdlc-project? value) (poo-flow-model? SdlcProject value))
-(def (sdlc-obligation? value) (poo-flow-model? SdlcObligation value))
-(def (sdlc-evidence? value) (poo-flow-model? SdlcEvidence value))
-(def (sdlc-tailoring-request? value) (poo-flow-model? SdlcTailoringRequest value))
-(def (sdlc-trace-node? value) (poo-flow-model? SdlcTraceNode value))
-(def (sdlc-trace-edge? value) (poo-flow-model? SdlcTraceEdge value))
-(def (sdlc-trace-rule? value) (poo-flow-model? SdlcTraceRule value))
+(def (standard-profile? value) (poo-clos-model? SdlcStandard value))
+(def (sdlc-bound-fact? value) (poo-clos-model? SdlcBoundFact value))
+(def (sdlc-project? value) (poo-clos-model? SdlcProject value))
+(def (sdlc-obligation? value) (poo-clos-model? SdlcObligation value))
+(def (sdlc-evidence? value) (poo-clos-model? SdlcEvidence value))
+(def (sdlc-tailoring-request? value) (poo-clos-model? SdlcTailoringRequest value))
+(def (sdlc-trace-node? value) (poo-clos-model? SdlcTraceNode value))
+(def (sdlc-trace-edge? value) (poo-clos-model? SdlcTraceEdge value))
+(def (sdlc-trace-rule? value) (poo-clos-model? SdlcTraceRule value))
(export SdlcCriterionEvidence sdlc-criterion-evidence?
SdlcSafetyComponent sdlc-safety-component?)
(def SdlcCriterionEvidence
(poo-clos-class 'sdlc/criterion-evidence direct-superclasses: (list SdlcEvidence)
direct-slots: (text-slots '(criterion source-digest))))
-(def (sdlc-criterion-evidence? value) (poo-flow-model? SdlcCriterionEvidence value))
+(def (sdlc-criterion-evidence? value) (poo-clos-model? SdlcCriterionEvidence value))
(def (coverage-or-unknown? value)
(or (eq? value 'unknown) (and (real? value) (<= 0 value 100))))
(def (complexity-or-unknown? value)
@@ -99,7 +100,7 @@
(poo-clos-direct-slot-definition 'safety-critical? type-predicate: boolean?)
(poo-clos-direct-slot-definition 'mcdc-percent type-predicate: coverage-or-unknown?)
(poo-clos-direct-slot-definition 'cyclomatic-complexity type-predicate: complexity-or-unknown?))))
-(def (sdlc-safety-component? value) (poo-flow-model? SdlcSafetyComponent value))
+(def (sdlc-safety-component? value) (poo-clos-model? SdlcSafetyComponent value))
(export SdlcTailoringPacket sdlc-tailoring-packet?
SdlcAuthorityAttestation sdlc-authority-attestation?)
@@ -113,8 +114,8 @@
direct-slots: (append (text-slots '(request signer record))
(list (poo-clos-direct-slot-definition 'authority type-predicate: symbol?)
(enum-slot 'decision '(approved rejected))))))
-(def (sdlc-tailoring-packet? value) (poo-flow-model? SdlcTailoringPacket value))
-(def (sdlc-authority-attestation? value) (poo-flow-model? SdlcAuthorityAttestation value))
+(def (sdlc-tailoring-packet? value) (poo-clos-model? SdlcTailoringPacket value))
+(def (sdlc-authority-attestation? value) (poo-clos-model? SdlcAuthorityAttestation value))
(export SdlcStagePolicy sdlc-stage-policy? SdlcLifecycleState sdlc-lifecycle-state?
SdlcVerificationRequest sdlc-verification-request?)
@@ -130,11 +131,11 @@
direct-slots: (text-slots '(stage))))
(def SdlcVerificationRequest
(poo-clos-class 'sdlc/verification-request direct-superclasses: (list SdlcBoundFact)
- direct-slots: (list (enum-slot 'purpose '(criterion-content classification-and-context tailoring-decision structured-inventory certification-decision))
+ direct-slots: (list (enum-slot 'purpose '(criterion-content classification-and-context tailoring-decision structured-inventory certification-decision history-discovery disposition-approval))
(poo-clos-direct-slot-definition 'facts type-predicate: object?))))
-(def (sdlc-stage-policy? value) (poo-flow-model? SdlcStagePolicy value))
-(def (sdlc-lifecycle-state? value) (poo-flow-model? SdlcLifecycleState value))
-(def (sdlc-verification-request? value) (poo-flow-model? SdlcVerificationRequest value))
+(def (sdlc-stage-policy? value) (poo-clos-model? SdlcStagePolicy value))
+(def (sdlc-lifecycle-state? value) (poo-clos-model? SdlcLifecycleState value))
+(def (sdlc-verification-request? value) (poo-clos-model? SdlcVerificationRequest value))
(export SdlcSafetyInventory SdlcTraceInventory sdlc-safety-inventory? sdlc-trace-inventory?
sdlc-artifact-digest?)
@@ -154,5 +155,5 @@
(def SdlcTraceInventory
(poo-clos-class 'sdlc/trace-inventory direct-superclasses: (list SdlcInventory)
direct-slots: (list (instances-slot 'nodes sdlc-trace-node?) (instances-slot 'edges sdlc-trace-edge?))))
-(def (sdlc-safety-inventory? value) (poo-flow-model? SdlcSafetyInventory value))
-(def (sdlc-trace-inventory? value) (poo-flow-model? SdlcTraceInventory value))
+(def (sdlc-safety-inventory? value) (poo-clos-model? SdlcSafetyInventory value))
+(def (sdlc-trace-inventory? value) (poo-clos-model? SdlcTraceInventory value))
diff --git a/modules/sdlc/verification.ss b/modules/sdlc/verification.ss
new file mode 100644
index 0000000..917e254
--- /dev/null
+++ b/modules/sdlc/verification.ss
@@ -0,0 +1,157 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Project a design guarantee onto existing Assurance Host admission.
+;;; This does not issue an admission, interpret a verifier, or authorize effects.
+(import (only-in :clan/poo/object .o .ref)
+ (only-in :gerbil/core list-sort)
+ :std/list/list
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/interface
+ assurance-claim? assurance-node-canonical
+ assurance-relation? assurance-snapshot-canonical?
+ assurance-verification-subject?
+ assurance-verification-subject-snapshot
+ assurance-host-admission-current?
+ assurance-host-source-current?
+ assurance-host-admitted-support?
+ assurance-host-required-support)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/design
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/implementation)
+
+(export sdlc-design-guarantee-support-review)
+
+(def (ordered-ids values)
+ (list-sort string values))
+(def (node-at snapshot-value identity-value)
+ (find (lambda (node)
+ (equal? (.ref node 'identity) identity-value))
+ (.ref snapshot-value 'nodes)))
+(def (same-claim? snapshot-value claim-value)
+ (let (current (node-at snapshot-value (.ref claim-value 'identity)))
+ (and current (assurance-claim? current)
+ (equal? (assurance-node-canonical current)
+ (assurance-node-canonical claim-value))
+ (member (cons (.ref claim-value 'identity)
+ (.ref claim-value 'revision))
+ (.ref snapshot-value 'claim-revisions)))))
+(def (source-dependency? snapshot-value claim-value source-id)
+ (find (lambda (relation)
+ (and (eq? (.ref relation 'plane) 'structural)
+ (eq? (.ref relation 'relation) 'depends-on)
+ (equal? (.ref relation 'source) (.ref claim-value 'identity))
+ (equal? (.ref relation 'target) source-id)
+ (not (memq (.ref relation 'modality)
+ '(hypothesized counterfactual)))))
+ (.ref snapshot-value 'relations)))
+(def (input-bound? outcome-value link-value)
+ (find (lambda (input)
+ (and (equal? (.ref input 'identity) (.ref link-value 'source))
+ (equal? (.ref input 'revision)
+ (.ref link-value 'source-revision))
+ (equal? (.ref input 'digest)
+ (.ref link-value 'source-digest))))
+ (.ref outcome-value 'inputs)))
+
+;;; One Host admission must bind a verifier outcome to at least one source
+;;; declared for this guarantee. All claim obligations still need Host support.
+;;; The returned value is an inert assessment, never an authority token.
+(def (sdlc-design-guarantee-support-review
+ host-value contract-value guarantee-value implementation-links
+ claim-value subject-value relation-value admission-value admissions)
+ (unless (and (sdlc-design-contract? contract-value)
+ (sdlc-design-clause? guarantee-value)
+ (eq? (.ref guarantee-value 'kind) 'guarantee)
+ (list? implementation-links)
+ (every sdlc-design-implementation-link? implementation-links)
+ (assurance-claim? claim-value)
+ (assurance-verification-subject? subject-value)
+ (assurance-relation? relation-value)
+ (list? admissions))
+ (error "invalid design guarantee support review input"))
+ (let* ((snapshot-value (.ref subject-value 'snapshot))
+ (obligation-value (.ref subject-value 'obligation))
+ (outcome-value (.ref subject-value 'outcome))
+ (mapping
+ (sdlc-design-implementation-review
+ contract-value snapshot-value implementation-links))
+ (guarantee-current?
+ (find (lambda (declared)
+ (and (equal? (.ref declared 'identity)
+ (.ref guarantee-value 'identity))
+ (equal? (.ref declared 'revision)
+ (.ref guarantee-value 'revision))
+ (equal? (.ref declared 'statement)
+ (.ref guarantee-value 'statement))))
+ (.ref contract-value 'guarantees)))
+ (claim-current-value
+ (and (assurance-snapshot-canonical? snapshot-value)
+ (same-claim? snapshot-value claim-value)
+ (equal? (.ref claim-value 'subject)
+ (.ref contract-value 'identity))
+ (equal? (.ref claim-value 'predicate)
+ (.ref guarantee-value 'statement))
+ (equal? (ordered-ids (.ref claim-value 'assumptions))
+ (ordered-ids
+ (map (lambda (assumption)
+ (.ref assumption 'identity))
+ (.ref contract-value 'assumptions))))
+ (member (.ref obligation-value 'identity)
+ (.ref claim-value 'support-requirements))))
+ (source-links
+ (filter (lambda (link)
+ (equal? (.ref link 'guarantee)
+ (.ref guarantee-value 'identity)))
+ implementation-links))
+ (source-bound?
+ (find (lambda (link)
+ (and (source-dependency?
+ snapshot-value claim-value (.ref link 'source))
+ (input-bound? outcome-value link)))
+ source-links))
+ (source-bytes-bound?
+ (find (lambda (link)
+ (and (source-dependency?
+ snapshot-value claim-value (.ref link 'source))
+ (input-bound? outcome-value link)
+ (let (source-value
+ (node-at snapshot-value (.ref link 'source)))
+ (and source-value
+ (assurance-host-source-current?
+ host-value snapshot-value source-value)))))
+ source-links))
+ (admission-current?
+ (and admission-value
+ (memq admission-value admissions)
+ (assurance-host-admission-current? host-value admission-value)
+ (equal? (.ref admission-value 'subject-digest)
+ (assurance-verification-subject-snapshot subject-value))
+ (assurance-host-admitted-support?
+ host-value relation-value admission-value)))
+ (support
+ (and (.ref mapping 'mapping-current?) guarantee-current?
+ claim-current-value source-bound? admission-current?
+ (assurance-host-required-support
+ host-value claim-value admissions)))
+ (support-current?
+ (and support (.ref support 'complete?)
+ (equal? (.ref support 'snapshot-digest)
+ (.ref snapshot-value 'digest)))))
+ (.o kind: 'sdlc.design-guarantee-support-review
+ contract: (.ref contract-value 'identity)
+ contract-digest: (sdlc-design-contract-digest contract-value)
+ guarantee: (.ref guarantee-value 'identity)
+ snapshot-digest: (.ref snapshot-value 'digest)
+ mapping-current?: (.ref mapping 'mapping-current?)
+ claim-current?: (and guarantee-current? claim-current-value #t)
+ source-input-bound?: (and source-bound? #t)
+ source-bytes-match?: (and source-bytes-bound? #t)
+ host-admission-current?: (and admission-current? #t)
+ required-support-current?: (and support-current? #t)
+ source-bound-support-current?: (and support-current? #t)
+ source-bytes-checked-support-current?:
+ (and support-current? source-bytes-bound? #t)
+ verifier-independence-established?: #f
+ implementation-conforms?: #f
+ release-authorized?: #f
+ runtime-executed?: #f)))
diff --git a/proof/lean/AxiomAudit.lean b/proof/lean/AxiomAudit.lean
new file mode 100644
index 0000000..9d871e1
--- /dev/null
+++ b/proof/lean/AxiomAudit.lean
@@ -0,0 +1,29 @@
+-- SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+--
+-- SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+import LambdaAitiaProof.Modules.Assurance
+import LambdaAitiaProof.Modules.Sdlc
+
+open LambdaAitiaProof.Modules
+
+#print axioms Assurance.Invalidation.impactMonotoneForFixedSnapshot
+#print axioms Assurance.Invalidation.unresolvedFrontierBlocksClosure
+#print axioms Assurance.Invalidation.inertReceiptGrantsNoAuthority
+#print axioms Assurance.Composition.componentOnlyEvidenceCannotSupportComposite
+#print axioms Assurance.Composition.directObligationNeeded
+#print axioms Assurance.Composition.directWitnessDiffersFromComponentObligation
+#print axioms Sdlc.Design.refinesRefl
+#print axioms Sdlc.Design.refinesTrans
+#print axioms Sdlc.Design.strongerAssumptionBlocks
+#print axioms Sdlc.Design.droppedGuaranteeBlocks
+#print axioms Sdlc.Retirement.initialSafe
+#print axioms Sdlc.Retirement.stepPreservesSafety
+#print axioms Sdlc.Retirement.reachableSafe
+#print axioms Sdlc.Retirement.cancellationDoesNotJustifyRetirement
+#print axioms Sdlc.Retirement.oldReviewDoesNotJustifyRetirement
+#print axioms Sdlc.Retirement.unknownInventoryBlocksRetirement
+#print axioms Sdlc.RetirementIngress.initialSafe
+#print axioms Sdlc.RetirementIngress.currentGrantExcludesRetirement
+#print axioms Sdlc.RetirementIngress.stepPreservesSafety
+#print axioms Sdlc.RetirementIngress.reachableSafe
diff --git a/proof/lean/LambdaAitiaProof.lean b/proof/lean/LambdaAitiaProof.lean
index b1278d1..7e65ffd 100644
--- a/proof/lean/LambdaAitiaProof.lean
+++ b/proof/lean/LambdaAitiaProof.lean
@@ -3,3 +3,4 @@
-- SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
import LambdaAitiaProof.Modules.Assurance
+import LambdaAitiaProof.Modules.Sdlc
diff --git a/proof/lean/LambdaAitiaProof/Modules/Assurance.lean b/proof/lean/LambdaAitiaProof/Modules/Assurance.lean
index d155daa..8a0da03 100644
--- a/proof/lean/LambdaAitiaProof/Modules/Assurance.lean
+++ b/proof/lean/LambdaAitiaProof/Modules/Assurance.lean
@@ -3,3 +3,4 @@
-- SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
import LambdaAitiaProof.Modules.Assurance.Invalidation
+import LambdaAitiaProof.Modules.Assurance.Composition
diff --git a/proof/lean/LambdaAitiaProof/Modules/Assurance/Composition.lean b/proof/lean/LambdaAitiaProof/Modules/Assurance/Composition.lean
new file mode 100644
index 0000000..1450e2b
--- /dev/null
+++ b/proof/lean/LambdaAitiaProof/Modules/Assurance/Composition.lean
@@ -0,0 +1,79 @@
+-- SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+--
+-- SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+/-!
+The composition law is independent of the Graph traversal implementation.
+It states the admission boundary: evidence for components does not discharge
+the separate, current obligation declared for their composite claim.
+-/
+
+namespace LambdaAitiaProof.Modules.Assurance.Composition
+
+structure Contract (Claim Obligation : Type) where
+ componentOf : Claim → Claim → Prop
+ componentObligation : Obligation → Claim → Prop
+ directObligation : Obligation → Claim → Prop
+ current : Obligation → Prop
+ discharged : Obligation → Prop
+ compositeSupported : Claim → Prop
+ directEvidenceRequired :
+ ∀ composite, compositeSupported composite →
+ ∃ obligation, directObligation obligation composite ∧
+ current obligation ∧ discharged obligation
+ independent :
+ ∀ obligation component composite,
+ componentOf component composite →
+ componentObligation obligation component →
+ ¬ directObligation obligation composite
+
+def ComponentOnlyEvidence {Claim Obligation : Type}
+ (contract : Contract Claim Obligation) (composite : Claim) : Prop :=
+ ∀ obligation,
+ contract.current obligation ∧ contract.discharged obligation →
+ ∃ component,
+ contract.componentOf component composite ∧
+ contract.componentObligation obligation component
+
+theorem componentOnlyEvidenceCannotSupportComposite
+ {Claim Obligation : Type}
+ (contract : Contract Claim Obligation) (composite : Claim)
+ (onlyComponents : ComponentOnlyEvidence contract composite) :
+ ¬ contract.compositeSupported composite := by
+ intro supported
+ obtain ⟨obligation, direct, current, discharged⟩ :=
+ contract.directEvidenceRequired composite supported
+ obtain ⟨component, part, componentEvidence⟩ :=
+ onlyComponents obligation ⟨current, discharged⟩
+ exact (contract.independent obligation component composite part componentEvidence) direct
+
+theorem directObligationNeeded
+ {Claim Obligation : Type}
+ (contract : Contract Claim Obligation) (composite : Claim)
+ (supported : contract.compositeSupported composite) :
+ ∃ obligation,
+ contract.directObligation obligation composite ∧
+ contract.current obligation ∧ contract.discharged obligation :=
+ contract.directEvidenceRequired composite supported
+
+theorem directWitnessDiffersFromComponentObligation
+ {Claim Obligation : Type}
+ (contract : Contract Claim Obligation)
+ (component composite : Claim) (componentEvidence : Obligation)
+ (part : contract.componentOf component composite)
+ (belongsToComponent : contract.componentObligation componentEvidence component)
+ (supported : contract.compositeSupported composite) :
+ ∃ directEvidence,
+ contract.directObligation directEvidence composite ∧
+ contract.current directEvidence ∧
+ contract.discharged directEvidence ∧
+ directEvidence ≠ componentEvidence := by
+ obtain ⟨directEvidence, direct, current, discharged⟩ :=
+ contract.directEvidenceRequired composite supported
+ refine ⟨directEvidence, direct, current, discharged, ?_⟩
+ intro same
+ subst directEvidence
+ exact (contract.independent componentEvidence component composite
+ part belongsToComponent) direct
+
+end LambdaAitiaProof.Modules.Assurance.Composition
diff --git a/proof/lean/LambdaAitiaProof/Modules/Assurance/Invalidation.lean b/proof/lean/LambdaAitiaProof/Modules/Assurance/Invalidation.lean
index 301ed35..400c303 100644
--- a/proof/lean/LambdaAitiaProof/Modules/Assurance/Invalidation.lean
+++ b/proof/lean/LambdaAitiaProof/Modules/Assurance/Invalidation.lean
@@ -3,7 +3,7 @@
-- SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
/-!
-Lambda Aitia owns these domain laws. POO Flow may implement graph traversal,
+Lambda Aitia owns these domain laws. Agentic AI Lab may implement graph traversal,
but its generic proof package is neither imported nor copied here.
-/
diff --git a/proof/lean/LambdaAitiaProof/Modules/Sdlc.lean b/proof/lean/LambdaAitiaProof/Modules/Sdlc.lean
new file mode 100644
index 0000000..18d1818
--- /dev/null
+++ b/proof/lean/LambdaAitiaProof/Modules/Sdlc.lean
@@ -0,0 +1,7 @@
+-- SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+--
+-- SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+import LambdaAitiaProof.Modules.Sdlc.Design
+import LambdaAitiaProof.Modules.Sdlc.Retirement
+import LambdaAitiaProof.Modules.Sdlc.RetirementIngress
diff --git a/proof/lean/LambdaAitiaProof/Modules/Sdlc/Design.lean b/proof/lean/LambdaAitiaProof/Modules/Sdlc/Design.lean
new file mode 100644
index 0000000..b43cffd
--- /dev/null
+++ b/proof/lean/LambdaAitiaProof/Modules/Sdlc/Design.lean
@@ -0,0 +1,53 @@
+-- SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+--
+-- SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+/-!
+A declaration-level substitution direction for software-design contracts.
+The predicates stand for exact, independently identified clauses. These laws
+do not prove that natural-language clauses hold in an implementation, that the
+Scheme comparison implements this relation, or that an effect is authorized.
+-/
+
+namespace LambdaAitiaProof.Modules.Sdlc.Design
+
+structure Contract (Clause : Type) where
+ assumptions : Clause → Prop
+ guarantees : Clause → Prop
+
+def Refines {Clause : Type} (old candidate : Contract Clause) : Prop :=
+ (∀ clause, candidate.assumptions clause → old.assumptions clause) ∧
+ (∀ clause, old.guarantees clause → candidate.guarantees clause)
+
+theorem refinesRefl {Clause : Type} (contract : Contract Clause) :
+ Refines contract contract := by
+ constructor <;> intro clause present <;> exact present
+
+theorem refinesTrans {Clause : Type}
+ (first second third : Contract Clause)
+ (firstToSecond : Refines first second)
+ (secondToThird : Refines second third) :
+ Refines first third := by
+ constructor
+ · intro clause required
+ exact firstToSecond.1 clause (secondToThird.1 clause required)
+ · intro clause promised
+ exact secondToThird.2 clause (firstToSecond.2 clause promised)
+
+theorem strongerAssumptionBlocks {Clause : Type}
+ (old candidate : Contract Clause) (clause : Clause)
+ (required : candidate.assumptions clause)
+ (notPreviouslyRequired : ¬ old.assumptions clause) :
+ ¬ Refines old candidate := by
+ intro replacement
+ exact notPreviouslyRequired (replacement.1 clause required)
+
+theorem droppedGuaranteeBlocks {Clause : Type}
+ (old candidate : Contract Clause) (clause : Clause)
+ (promised : old.guarantees clause)
+ (notPromised : ¬ candidate.guarantees clause) :
+ ¬ Refines old candidate := by
+ intro replacement
+ exact notPromised (replacement.2 clause promised)
+
+end LambdaAitiaProof.Modules.Sdlc.Design
diff --git a/proof/lean/LambdaAitiaProof/Modules/Sdlc/Retirement.lean b/proof/lean/LambdaAitiaProof/Modules/Sdlc/Retirement.lean
new file mode 100644
index 0000000..e01cee2
--- /dev/null
+++ b/proof/lean/LambdaAitiaProof/Modules/Sdlc/Retirement.lean
@@ -0,0 +1,81 @@
+-- SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+-- SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+/-!
+Design-level retirement safety. `Step.observe` overapproximates every
+pre-retirement observation, including late work and inventory loss; safety
+cannot rely on an old review. Terminal states admit no further observations.
+This is not a proof of Quint/Scheme correspondence, inventory truth, liveness,
+post-retirement ingress exclusion, persistence, or effect authorization.
+-/
+
+namespace LambdaAitiaProof.Modules.Sdlc.Retirement
+
+structure State where
+ active : Bool
+ queued : Bool
+ known : Bool
+ reviewed : Bool
+ cancelRequested : Bool
+ retired : Bool
+
+def Safe (s : State) : Prop :=
+ s.retired = true → s.active = false ∧ s.queued = false ∧ s.known = true
+
+def Initial : State := ⟨true, true, false, false, false, false⟩
+
+inductive Step : State → State → Prop where
+ | observe (s t : State) (before : s.retired = false)
+ (after : t.retired = false) : Step s t
+ | finalize (s : State) (before : s.retired = false)
+ (review : s.reviewed = true) (idle : s.active = false)
+ (drained : s.queued = false) (inventory : s.known = true) :
+ Step s { s with retired := true }
+ | terminal (s : State) (done : s.retired = true) : Step s s
+
+theorem initialSafe : Safe Initial := by
+ intro done
+ cases done
+
+theorem stepPreservesSafety {s t : State} (safe : Safe s)
+ (step : Step s t) : Safe t := by
+ cases step with
+ | observe t before after =>
+ intro done
+ have impossible : false = true := after.symm.trans done
+ cases impossible
+ | finalize before review idle drained inventory =>
+ intro _
+ exact ⟨idle, drained, inventory⟩
+ | terminal done => exact safe
+
+inductive Reachable : State → Prop where
+ | initial : Reachable Initial
+ | next {s t : State} : Reachable s → Step s t → Reachable t
+
+theorem reachableSafe {s : State} (reachable : Reachable s) : Safe s := by
+ induction reachable with
+ | initial => exact initialSafe
+ | next previous step inductionHypothesis =>
+ exact stepPreservesSafety inductionHypothesis step
+
+def CancellationOnly : State := ⟨true, true, true, false, true, true⟩
+def StaleReview : State := ⟨true, false, true, true, false, true⟩
+def UnknownInventory : State := ⟨false, false, false, true, false, true⟩
+
+theorem cancellationDoesNotJustifyRetirement : ¬ Safe CancellationOnly := by
+ intro safe
+ have impossible := (safe rfl).1
+ cases impossible
+
+theorem oldReviewDoesNotJustifyRetirement : ¬ Safe StaleReview := by
+ intro safe
+ have impossible := (safe rfl).1
+ cases impossible
+
+theorem unknownInventoryBlocksRetirement : ¬ Safe UnknownInventory := by
+ intro safe
+ have impossible := (safe rfl).2.2
+ cases impossible
+
+end LambdaAitiaProof.Modules.Sdlc.Retirement
diff --git a/proof/lean/LambdaAitiaProof/Modules/Sdlc/RetirementIngress.lean b/proof/lean/LambdaAitiaProof/Modules/Sdlc/RetirementIngress.lean
new file mode 100644
index 0000000..98a76fe
--- /dev/null
+++ b/proof/lean/LambdaAitiaProof/Modules/Sdlc/RetirementIngress.lean
@@ -0,0 +1,92 @@
+-- SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+-- SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+import LambdaAitiaProof.Modules.Sdlc.Retirement
+
+/-!
+An abstract extension of retirement review with an ingress fence. Requests
+and rejections may stutter after retirement; an effect with a current epoch
+cannot start there. Finalization requires a closed issuance boundary and an
+invalidated cached epoch. No proof of deployed revocation, Quint correspondence,
+grant issuance, fairness or persistent state is claimed.
+-/
+
+namespace LambdaAitiaProof.Modules.Sdlc.RetirementIngress
+
+structure State where
+ review : Retirement.State
+ ingressOpen : Bool
+ epoch : Nat
+ grantEpoch : Nat
+
+def Safe (s : State) : Prop :=
+ Retirement.Safe s.review ∧
+ (s.review.retired = true → s.ingressOpen = false ∧ s.grantEpoch ≠ s.epoch)
+
+def Initial : State := ⟨Retirement.Initial, true, 0, 0⟩
+
+theorem initialSafe : Safe Initial := by
+ constructor
+ · exact Retirement.initialSafe
+ · intro retired
+ cases retired
+
+theorem currentGrantExcludesRetirement {s : State} (safe : Safe s)
+ (current : s.grantEpoch = s.epoch) : s.review.retired ≠ true := by
+ intro retired
+ exact (safe.2 retired).2 current
+
+inductive Step : State → State → Prop where
+ | review (s : State) (t : Retirement.State)
+ (step : Retirement.Step s.review t) (beforeFinalization : t.retired = false) :
+ Step s {s with review := t}
+ | close (s : State) (notRetired : s.review.retired = false)
+ (wasOpen : s.ingressOpen = true) :
+ Step s {s with ingressOpen := false, epoch := s.epoch + 1}
+ | finalize (s : State)
+ (step : Retirement.Step s.review {s.review with retired := true})
+ (closed : s.ingressOpen = false) (revoked : s.grantEpoch ≠ s.epoch) :
+ Step s {s with review := {s.review with retired := true}}
+ | start (s : State) (current : s.grantEpoch = s.epoch) :
+ Step s {s with review := {s.review with active := true}}
+ | requestOrReject (s : State) : Step s s
+
+theorem stepPreservesSafety {s t : State} (safe : Safe s)
+ (step : Step s t) : Safe t := by
+ cases step with
+ | review t step beforeFinalization =>
+ constructor
+ · exact Retirement.stepPreservesSafety safe.1 step
+ · intro retired
+ have impossible : false = true := beforeFinalization.symm.trans retired
+ cases impossible
+ | close notRetired wasOpen =>
+ constructor
+ · exact safe.1
+ · intro retired
+ have impossible : false = true := notRetired.symm.trans retired
+ cases impossible
+ | finalize step closed revoked =>
+ constructor
+ · exact Retirement.stepPreservesSafety safe.1 step
+ · intro _
+ exact ⟨closed, revoked⟩
+ | start current =>
+ constructor
+ · intro retired
+ exact False.elim (currentGrantExcludesRetirement safe current retired)
+ · intro retired
+ exact False.elim (currentGrantExcludesRetirement safe current retired)
+ | requestOrReject => exact safe
+
+inductive Reachable : State → Prop where
+ | initial : Reachable Initial
+ | next {s t : State} : Reachable s → Step s t → Reachable t
+
+theorem reachableSafe {s : State} (reachable : Reachable s) : Safe s := by
+ induction reachable with
+ | initial => exact initialSafe
+ | next previous step inductionHypothesis =>
+ exact stepPreservesSafety inductionHypothesis step
+
+end LambdaAitiaProof.Modules.Sdlc.RetirementIngress
diff --git a/proof/lean/README.org b/proof/lean/README.org
index be6556f..c8bc4cd 100644
--- a/proof/lean/README.org
+++ b/proof/lean/README.org
@@ -1,10 +1,10 @@
# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-#+title: Lambda Aitia Assurance Proofs
+#+title: Lambda Aitia Assurance and SDLC Proofs
This is Lambda Aitia's source-owned Lean package. It states laws over Aitia
-assurance vocabulary and does not import or copy POO Flow's generic proof
+assurance vocabulary and does not import or copy Agentic AI Lab's generic proof
package.
Run the bounded proof target from the repository root:
@@ -22,3 +22,23 @@ that impact is monotone when the changed set expands over one fixed
reachability relation, that a non-empty unresolved frontier prevents closure,
and that an inert invalidation receipt grants no release authority or runtime
execution.
+
+=LambdaAitiaProof.Modules.Assurance.Composition= proves a separate admission
+law: current evidence belonging only to component obligations cannot support
+the composite claim. Any admitted composite has a current discharged direct
+obligation distinct from each component obligation. These theorems assume the
+explicit =Contract= fields; the Scheme acceptance tests check that the
+runtime projection observes the same boundary, rather than treating a Lean
+theorem as runtime authority.
+
+The independently selectable =LambdaAitiaModuleSdlcProof= library mirrors
+=modules/sdlc/design.ss=. Its =Design= module proves reflexivity and
+transitivity of the declaration-level assumption/guarantee replacement
+direction and shows that an added assumption or dropped guarantee blocks that
+relation. It does not certify natural-language clause meanings, the Scheme
+comparison implementation or any Runtime effect.
+
+=AxiomAudit.lean= prints the transitive axioms of every exported law. The
+=just check-proof= and CI gates reject =sorryAx= in that output; a successful
+compile alone is not accepted as evidence that theorems contain no admitted
+holes.
diff --git a/proof/lean/lakefile.lean b/proof/lean/lakefile.lean
index e320cef..e9cc7bb 100644
--- a/proof/lean/lakefile.lean
+++ b/proof/lean/lakefile.lean
@@ -19,3 +19,6 @@ explicit repository-wide integration aggregate.
@[default_target]
lean_lib LambdaAitiaModuleAssuranceProof where
roots := #[`LambdaAitiaProof.Modules.Assurance]
+
+lean_lib LambdaAitiaModuleSdlcProof where
+ roots := #[`LambdaAitiaProof.Modules.Sdlc]
diff --git a/proof/quint/AssuranceLifecycle.qnt b/proof/quint/AssuranceLifecycle.qnt
new file mode 100644
index 0000000..a70a685
--- /dev/null
+++ b/proof/quint/AssuranceLifecycle.qnt
@@ -0,0 +1,130 @@
+// SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+// SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+module AssuranceLifecycle {
+ import EffectAdmission.* from "./EffectAdmission"
+
+ // One obligation, two source revisions, four clock values, three epochs.
+ type Lifecycle = {revision: int, planned: int, verified: int, admitted: int,
+ decided: int, granted: int, grantEpoch: int, epoch: int, clock: int,
+ sealUntil: int, grantUntil: int, adapterInstalled: bool,
+ reportedSuccess: bool, effectStarted: bool, startSafe: bool,
+ reservationRevision: int, reservationEpoch: int, reservationUntil: int,
+ deliveryStatus: int, deliveryCalls: int, deliverySafe: bool}
+ var q: Lifecycle
+ pure val Initial = {revision: 1, planned: 0, verified: 0, admitted: 0,
+ decided: 0, granted: 0, grantEpoch: 0, epoch: 0, clock: 0,
+ sealUntil: 0, grantUntil: 0, adapterInstalled: false,
+ reportedSuccess: false, effectStarted: false, startSafe: true,
+ reservationRevision: 0, reservationEpoch: 0, reservationUntil: 0,
+ deliveryStatus: 0, deliveryCalls: 0, deliverySafe: true}
+ action init = q' = Initial
+ action InstallAdapter = all {not(q.adapterInstalled), q' = {...q, adapterInstalled: true}}
+ action ReportSuccess = all {not(q.reportedSuccess), q' = {...q, reportedSuccess: true}}
+ action Plan = all {q.planned != q.revision, q' = {...q, planned: q.revision}}
+ action Verify = all {q.adapterInstalled, q.planned == q.revision, q.clock < 3,
+ q' = {...q, verified: q.revision, sealUntil: q.clock + 1}}
+ action Admit = all {q.verified == q.revision, q.clock < q.sealUntil,
+ q.admitted != q.revision, q' = {...q, admitted: q.revision}}
+ action Decide = all {q.admitted == q.revision, q.decided != q.revision,
+ q' = {...q, decided: q.revision}}
+ action Authorize = all {q.decided == q.revision, q.admitted == q.revision,
+ q.granted != q.revision, q.clock < 3,
+ q' = {...q, granted: q.revision, grantEpoch: q.epoch, grantUntil: q.clock + 1}}
+ val Current = currentGrant(q.granted, q.revision, q.admitted, q.decided,
+ q.grantEpoch, q.epoch, q.clock, q.grantUntil)
+ action StartEffect = all {not(q.effectStarted), Current,
+ q' = {...q, effectStarted: true,
+ reservationRevision: q.revision, reservationEpoch: q.grantEpoch,
+ reservationUntil: q.grantUntil,
+ startSafe: currentGrant(q.granted, q.revision, q.admitted, q.decided,
+ q.grantEpoch, q.epoch, q.clock, q.grantUntil)}}
+ // Start is a one-shot reservation, not delivery or an acknowledgement.
+ val DeliveryCurrent = Current and q.reservationRevision == q.revision and
+ q.reservationEpoch == q.epoch and q.clock < q.reservationUntil
+ // 0 = pending/not-started, 1 = acknowledged, 2 = rejected, 3 = failed,
+ // 4 = unknown acknowledgement. Unknown never authorizes a blind retry.
+ action DeliverEffect = all {q.effectStarted, q.deliveryStatus == 0, DeliveryCurrent,
+ q' = {...q, deliveryStatus: 1, deliveryCalls: q.deliveryCalls + 1, deliverySafe: true}}
+ action RejectDelivery = all {q.effectStarted, q.deliveryStatus == 0, not(DeliveryCurrent),
+ q' = {...q, deliveryStatus: 2}}
+ action FailDelivery = all {q.effectStarted, q.deliveryStatus == 0, DeliveryCurrent,
+ q' = {...q, deliveryStatus: 3, deliveryCalls: q.deliveryCalls + 1}}
+ action UnknownDelivery = all {q.effectStarted, q.deliveryStatus == 0, DeliveryCurrent,
+ q' = {...q, deliveryStatus: 4, deliveryCalls: q.deliveryCalls + 1}}
+ action ChangeSource = all {q.revision == 1,
+ q' = {...q, revision: 2, planned: 0, verified: 0, admitted: 0,
+ decided: 0, granted: 0, sealUntil: 0, grantUntil: 0}}
+ action Tick = all {q.clock < 3,
+ q' = {...q, clock: q.clock + 1,
+ admitted: if (q.clock + 1 < q.sealUntil) q.admitted else 0,
+ decided: if (q.clock + 1 < q.sealUntil) q.decided else 0,
+ granted: if (q.clock + 1 < q.sealUntil and q.clock + 1 < q.grantUntil)
+ q.granted else 0}}
+ action Revoke = all {q.epoch < 2,
+ q' = {...q, epoch: q.epoch + 1, verified: 0, admitted: 0,
+ decided: 0, granted: 0, sealUntil: 0}}
+ action stableStep = any {InstallAdapter, ReportSuccess, Plan, Verify, Admit,
+ Decide, Authorize, StartEffect, DeliverEffect}
+ action Terminal = all {q.clock == 3, q.epoch == 2, q.revision == 2,
+ q.adapterInstalled, q.reportedSuccess, q.planned == q.revision,
+ (not(q.effectStarted) or q.deliveryStatus != 0), q' = q}
+ action step = any {stableStep, ChangeSource, Tick, Revoke, RejectDelivery,
+ FailDelivery, UnknownDelivery, Terminal}
+
+ // Each mutation is isolated by selecting its own step operator.
+ action UnsafeStart = all {q.reportedSuccess, not(q.effectStarted),
+ q' = {...q, effectStarted: true, startSafe: Current}}
+ action UnsafeLateAdmit = all {q.revision == 2, q.reportedSuccess,
+ q.admitted == 0, q' = {...q, admitted: 1}}
+ action UnsafeEarlyGrant = all {q.revision == 2, q.reportedSuccess,
+ q.admitted == 0, q.granted == 0, q.clock < 3,
+ q' = {...q, granted: q.revision, grantEpoch: q.epoch,
+ grantUntil: q.clock + 1}}
+ action UnsafeAfterRevoke = all {q.epoch > q.grantEpoch,
+ q.grantUntil > q.clock, q.granted == 0, not(q.effectStarted),
+ q' = {...q, effectStarted: true, startSafe: Current}}
+ action unsafeStep = any {step, UnsafeStart}
+ action lateAdmitStep = any {step, UnsafeLateAdmit}
+ action earlyGrantStep = any {step, UnsafeEarlyGrant}
+ action afterRevokeStep = any {step, UnsafeAfterRevoke}
+ action UnsafeDelivery = all {q.effectStarted, q.deliveryStatus == 0, not(DeliveryCurrent),
+ q' = {...q, deliveryStatus: 1, deliveryCalls: q.deliveryCalls + 1, deliverySafe: false}}
+ action UnsafeBeforeStart = all {q.reportedSuccess, not(q.effectStarted),
+ q' = {...q, deliveryStatus: 1, deliveryCalls: q.deliveryCalls + 1, deliverySafe: false}}
+ action UnsafeReplay = all {q.deliveryStatus == 1,
+ q' = {...q, deliveryCalls: q.deliveryCalls + 1}}
+ action unsafeDeliveryStep = any {step, UnsafeDelivery}
+ action beforeStartStep = any {step, UnsafeBeforeStart}
+ action replayStep = any {step, UnsafeReplay}
+
+ val TypeOK = q.revision >= 1 and q.revision <= 2 and
+ q.planned >= 0 and q.planned <= 2 and q.verified >= 0 and q.verified <= 2 and
+ q.admitted >= 0 and q.admitted <= 2 and q.decided >= 0 and q.decided <= 2 and
+ q.granted >= 0 and q.granted <= 2 and q.grantEpoch >= 0 and q.grantEpoch <= 2 and
+ q.epoch >= 0 and q.epoch <= 2 and q.clock >= 0 and q.clock <= 3 and
+ q.sealUntil >= 0 and q.sealUntil <= 4 and q.grantUntil >= 0 and q.grantUntil <= 4 and
+ q.reservationRevision >= 0 and q.reservationRevision <= 2 and
+ q.reservationEpoch >= 0 and q.reservationEpoch <= 2 and
+ q.reservationUntil >= 0 and q.reservationUntil <= 4 and
+ q.deliveryStatus >= 0 and q.deliveryStatus <= 4 and q.deliveryCalls >= 0 and q.deliveryCalls <= 1
+ val AdmissionIsCurrent = q.admitted == 0 or
+ (q.admitted == q.revision and q.verified == q.revision and q.clock < q.sealUntil)
+ val DecisionRequiresAdmission = q.decided == 0 or
+ (q.decided == q.revision and q.admitted == q.revision)
+ val GrantRequiresCurrentDecision = q.granted == 0 or
+ (q.granted == q.revision and q.decided == q.revision and
+ q.admitted == q.revision and q.grantEpoch == q.epoch and q.clock < q.grantUntil)
+ val NoUnsafeEffectStart = q.startSafe
+ val NoEffectStarted = not(q.effectStarted)
+ val NoUnsafeDelivery = q.deliverySafe
+ val DeliveryRequiresStart = q.deliveryCalls == 0 or q.effectStarted
+ val AtMostOneDelivery = q.deliveryCalls <= 1
+
+ temporal stableFairness = InstallAdapter.weakFair(q) and Plan.weakFair(q) and
+ Verify.weakFair(q) and Admit.weakFair(q) and Decide.weakFair(q) and
+ Authorize.weakFair(q) and StartEffect.weakFair(q) and DeliverEffect.weakFair(q)
+ temporal stableSpec = q == Initial and stableStep.orKeep(q).always() and stableFairness
+ temporal stableSpecNoFair = q == Initial and stableStep.orKeep(q).always()
+ temporal EventuallyEffect = q.effectStarted.eventually()
+ temporal EventuallyDelivery = (q.deliveryStatus == 1).eventually()
+}
diff --git a/proof/quint/EffectAdmission.qnt b/proof/quint/EffectAdmission.qnt
new file mode 100644
index 0000000..515d640
--- /dev/null
+++ b/proof/quint/EffectAdmission.qnt
@@ -0,0 +1,8 @@
+// SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+// SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+module EffectAdmission {
+ pure def currentGrant(granted: int, revision: int, admitted: int, decided: int,
+ grantEpoch: int, epoch: int, clock: int, grantUntil: int): bool =
+ granted == revision and admitted == revision and decided == revision and
+ grantEpoch == epoch and clock < grantUntil
+}
diff --git a/proof/quint/README.org b/proof/quint/README.org
new file mode 100644
index 0000000..161cda7
--- /dev/null
+++ b/proof/quint/README.org
@@ -0,0 +1,178 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Quint design-model qualification
+
+:PROPERTIES:
+:STATUS: design-validation-partial
+:DATE: 2026-10-11
+:END:
+
+* Model boundaries
+
+The maintained model source is Quint 0.33.0. =WorkCore.qnt= shares the
+cancellation/completion distinction; =EffectAdmission.qnt= shares the current
+grant predicate. Four finite models now check 25 contracts (including two
+temporal cases), extending the former TLA+ lane's 22 cases:
+
+| Lane | Safe check | Required negative/reachability controls |
+|------+------------+-----------------------------------------|
+| work | cancellation does not drain active or queued work | cancellation and quiescence reachable |
+| retirement | final cut requires quiescence and known inventory | cancellation-as-completion, stale review, unknown inventory, retirement reachable |
+| ingress | retirement fences epoch and rejects later stale authority | unfenced retirement, cached grant, rejection and valid start reachable |
+| lifecycle | current admission, decision, grant, one-shot reservation and delivery | untrusted report, late admission, early grant, after-revoke start, stale delivery, delivery before start, replay, valid start reachable, no-fair delivery counterexample |
+
+The =check_contract.py= runner checks all reachable finite states through
+Quint's TLC backend, requires a completed queue for safe cases, and requires
+the expected invariant failure and actual trace for each negative control.
+The lifecycle's weak-fairness case is checked by =check_progress.py=: it compiles
+the Quint source to a temporary TLA+ artifact and asks TLC to check
+=EventuallyDelivery= under the Quint-defined =stableSpec=. The same property
+fails under =stableSpecNoFair=. Generated TLA+ is a checker intermediate, not
+a second maintained model. Quint's ordinary =verify --temporal= path cannot
+select that fairness-bearing specification as TLC's =SPECIFICATION=.
+
+#+begin_src sh
+npm ci --prefix proof/quint
+AITIA_QUINT_BIN="$PWD/proof/quint/node_modules/.bin/quint" just check-quint
+AITIA_QUINT_BIN="$PWD/proof/quint/node_modules/.bin/quint" just check-quint ingress
+#+end_src
+
+The lockfile pins Quint 0.33.0 and its npm transitive graph. The checker
+requires Apalache 0.62.1's TLC backend, Java and a local loopback endpoint.
+Each check prints its name and result; a tool error or a stall is not a
+successful counterexample. No implicit dependency on the Agentic AI Lab ASCENT pin
+is introduced here: ASCENT belongs to the parent Agentic AI Lab dependency graph.
+
+* Claim boundary
+
+** Executable correspondence cut
+
+=just check-quint-scheme= runs Quint 0.33.0's TypeScript evaluator with native
+=--mbt= action metadata and ITF traces. A fixed seed (34), 512 samples and an
+18-step bound currently cover 177 of the TLC lane's 248 reachable ingress
+states and all 13 safe actions. This is reproducible sampled correspondence,
+not exhaustive Scheme refinement. The runner fails if sampled state coverage
+falls below 177, or any safe action or the post-retirement rejection witness
+is missing. Every projected field is checked
+after every action against the actual serialized Scheme Host; effect starts
+also check a real callback counter. Model schema changes fail closed.
+
+Two separately generated invariant-failure traces exercise =RetireWithoutFence=
+and =TrustCachedGrant=. Their safe prefixes must match Scheme, while the final
+unsafe transition must be rejected with no effect callback. A tool failure is
+not a negative control. ITF is translated to closed data, never evaluated as
+Scheme code. The tests retain Gerbil's native testing lifecycle and heap/time
+bounds. =check-formal= includes source binding, Host controls, MBT replay,
+exhaustive Quint checks and Lean checks; CI runs these distinct evidence lanes.
+
+=just check-lifecycle-scheme= exhausts the lifecycle TLC graph, requires its
+complete 19,042-state queue and 21-field schema, then replays 3,084 covering
+paths through real Scheme APIs. A DAG path cover plus real init prefixes covers every reachable
+state, plus all 16 named safe actions. Every field is compared after every
+step; model output is never used to manufacture Scheme receipts. This is
+complete bounded state coverage, not replay of all 62,345 graph edges or a
+general refinement proof. Renewal and terminal stutters remain explicit
+API witnesses. The cover executes 64,206 state steps; each native batch is
+bounded by 160 actual steps rather than a fixed number of traces. A single
+oversized trace fails instead of being split or given more time. Four native
+processes retain the existing per-test 1G heap / 60-second bound; failed batches,
+missing final =OK=, incomplete
+graphs, unknown actions and missing fault traces fail closed.
+
+Seven additional traces start at reachable states selected from that graph.
+Quint executes the original unsafe operator and must produce an actual
+invariant-failure ITF trace. Scheme must match the safe prefix, refuse the
+final unsafe operation, preserve the projected state and execute no delivery
+callback. This covers report-as-authority, stale admission, early grant,
+after-revoke start, stale delivery, pre-start delivery and delivery replay.
+The gate prints SHA-256 hashes of its declared model / Scheme source cut and
+rejects source changes during the run.
+Failed native inputs and partial diagnostics are preserved under
+=.cache/lifecycle-failures/=; the shared checker watchdog terminates the owned
+process group, not just its immediate launcher. Completion counters are
+emitted only after processing a real trace and do not replace final =OK= / exit status.
+
+| Lifecycle stage | Actual Scheme operation | Authority / effect observation |
+|-----------------+-------------------------+--------------------------------|
+| Plan | =assurance-plan-verification= | selects the real obligation, no authority |
+| Verify | =assurance-host-verify= | configured verifier runs and privately issues a seal |
+| Admit | =assurance-host-admit-verified= | exact current seal, no verifier rerun or expiry renewal |
+| Decide | =assurance-host-preflight-decision= | current admission becomes a preflight, not permission |
+| Authorize | =assurance-host-cedar-request= / =assurance-effect-host-authorize!= | exact current request plus configured permit issues a private grant |
+| StartEffect | =assurance-effect-host-reserve!= | consumes grant once; callback count stays zero |
+| Delivery | =assurance-effect-host-deliver!= | rechecks source / epoch / strict expiry; acknowledged, rejected, failed or unknown |
+
+=lifecycle-boundary-test.ss= also checks deny / indeterminate authorization
+(refusal stutters, never a grant), copied or foreign seals / requests / grants
+/ reservations, intent substitution, mutation of an actually issued token,
+in-place request intent / action / handoff payload mutation,
+observed source ABA, expiry exactly at the boundary, source change during
+authorization, throwing authorization / delivery, reentrancy and blind retry
+after failure or unknown acknowledgement. Unknown acknowledgement may coexist
+with a service-side effect, but is never reported as delivered or retry authority.
+Renewing verification or issuing a fresh grant cannot extend an existing
+reservation's source / epoch / deadline binding.
+
+| Quint cut | Scheme evidence | Remaining boundary |
+|-----------+-----------------+--------------------|
+| WorkCore / WorkLifecycle | cancellation, completion and queue observations in ingress replay; isolated queued-work refusal | fair completion is an environment assumption |
+| RetirementReview | review, late activity, inventory loss/recovery and retirement in replay; missing-review / unknown-inventory controls | inventory truth is supplied by the local caller |
+| RetirementIngress / EffectAdmission | 13 action projections, sampled state correspondence, unsafe-model refusals and real callbacks | one owner, cached grant, request and attempt only |
+| AssuranceLifecycle | all 19,042 projected states; 16 safe actions; seven actual unsafe-model refusals; additional authorization / delivery unit controls | one obligation / attempt, serialized local adapter assumptions; no native Cedar evaluator or deployed delivery qualification |
+
+The Host exception regression additionally verifies that a throwing callback
+propagates its failure and clears the transient handoff fence, without marking
+work complete or permitting a second start. Exceptions, continuation capture
+and process crashes are not transitions of the current Quint ingress model.
+
+** Qualification limits
+
+These are bounded design experiments, not generated projections of the POO
+Contract, proof of Scheme/Runtime refinement, or deployed authority. A separate
+local Scheme Host in =modules/sdlc/retirement-host.ss= executes the bounded
+ingress fence/start cut, including one real effect callback, and
+=t/formal/retirement-execution-test.ss= checks selected positive and negative
+behaviors. This is an executable correspondence check, not a general refinement
+proof or a deployed authority integration. The lifecycle bounds are two source revisions, four clock values
+and three epochs. Ingress isolates one cached grant, one request and one
+attempt; it does not model new grant issuance, multiple clients, persistence,
+crash recovery or inventory truth. Fair progress assumes a stable source and
+clock, no revocation, and weak fairness of each Host stage. It says nothing
+about progress under a changing environment.
+
+The lifecycle effect Host is an explicit local composition adapter, not a new
+Cedar policy engine or native Runtime Host. It composes existing Agentic AI Lab
+semantic-root / token validation primitives with private exact-identity
+issuance and one-shot reservation indexes. The configured authorization
+operation must evaluate policy for the frozen request; the configured delivery
+operation owns the actual effect and acknowledgement. The model's successful
+handoff assumes trusted, synchronous callbacks under one serialized owner;
+it does not prove atomic source / authority revalidation at a native service's
+physical effect linearization point. Deferred work or continuation reuse is
+outside this adapter contract. The lifecycle fixture supplies declared source
+snapshot metadata and a controlled verifier, not a proof of verifier truth or
+filesystem bytes. The existing evidence-admission tests remain a separate
+source-reader qualification lane. The model's successful
+authorization and fair delivery assume permit and eventual acknowledgement;
+refusal, failed and unknown outcomes do not satisfy that progress premise.
+The grant's synthetic local binding is not a native buffer / session capability.
+Pure Cedar decisions, token-shaped objects and editable delivery receipts have
+no issuing authority. A delivery receipt's =durable?= and
+=distributed-authority?= are explicitly false. Strict expiry requires
+=now < expires-at= even though the underlying pure token validator admits its
+inclusive endpoint.
+Strict expiry is rechecked at the final token-validation instant after source
+validation; a clock crossing the deadline within reserve or deliver rejects
+without a delivery callback. A native boundary control covers both operations
+with an advancing effect clock. This is additional within-operation coverage,
+not an asynchronous or physical-effect linearization proof.
+Native dual-engine Cedar evaluation, distributed
+deduplication, continuations, persistence and crash recovery are not qualified
+by this local test cut.
+
+The retirement binding test hashes the declared Lean, Quint and Scheme source
+cut. A current mapping alone is not semantic correspondence; the execution
+test supplies bounded behavioral evidence for this particular Host. Multi-owner
+concurrency, crash recovery, new grant issuance, and complete implementation
+conformance remain open.
diff --git a/proof/quint/RetirementIngress.qnt b/proof/quint/RetirementIngress.qnt
new file mode 100644
index 0000000..12b1cec
--- /dev/null
+++ b/proof/quint/RetirementIngress.qnt
@@ -0,0 +1,60 @@
+// SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+// SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+module RetirementIngress {
+ import WorkCore.* from "./WorkCore"
+ import EffectAdmission.* from "./EffectAdmission"
+
+ type Ingress = {work: Work, known: bool, reviewed: bool, retired: bool,
+ lateFound: bool, gapFound: bool, ingressOpen: bool, epoch: int,
+ grantEpoch: int, pending: bool, attempted: bool,
+ rejectedAfterRetirement: bool, startedAfterRetirement: bool}
+ var q: Ingress
+ action init = q' = {work: {active: true, queued: true, cancelRequested: false},
+ known: false, reviewed: false, retired: false, lateFound: false, gapFound: false,
+ ingressOpen: true, epoch: 0, grantEpoch: 0, pending: false, attempted: false,
+ rejectedAfterRetirement: false, startedAfterRetirement: false}
+
+ action RequestCancellation = all {not(q.retired), not(q.work.cancelRequested),
+ q' = {...q, work: cancel(q.work)}}
+ action ObserveCompletion = all {not(q.retired), q.work.active,
+ q' = {...q, work: complete(q.work)}}
+ action ObserveQueueDrained = all {not(q.retired), q.work.queued,
+ q' = {...q, work: drain(q.work)}}
+ action CompleteInventory = all {not(q.retired), not(q.known), q' = {...q, known: true}}
+ action ReviewCut = all {not(q.retired), not(q.reviewed), quiescent(q.work), q.known,
+ q' = {...q, reviewed: true}}
+ action ObserveLateActivity = all {not(q.retired), q.reviewed, not(q.lateFound),
+ q' = {...q, work: {...q.work, active: true}, lateFound: true}}
+ action ObserveInventoryGap = all {not(q.retired), q.reviewed, not(q.gapFound),
+ q' = {...q, known: false, gapFound: true}}
+ action Observe = any {RequestCancellation, ObserveCompletion, ObserveQueueDrained,
+ CompleteInventory, ReviewCut, ObserveLateActivity, ObserveInventoryGap}
+ action CloseIngress = all {q.ingressOpen, q' = {...q, ingressOpen: false, epoch: q.epoch + 1}}
+ action Request = all {not(q.pending), not(q.attempted), q' = {...q, pending: true}}
+ val Current = currentGrant(1, 1, 1, 1, q.grantEpoch, q.epoch, 0, 1)
+ action Start = all {q.pending, Current,
+ q' = {...q, work: {...q.work, active: true}, pending: false, attempted: true,
+ startedAfterRetirement: q.retired}}
+ action TrustCachedGrant = all {q.pending,
+ q' = {...q, work: {...q.work, active: true}, pending: false, attempted: true,
+ startedAfterRetirement: q.retired}}
+ action Reject = all {q.pending, not(Current),
+ q' = {...q, pending: false, attempted: true, rejectedAfterRetirement: q.retired}}
+ action Retire = all {not(q.ingressOpen), not(q.retired), q.reviewed,
+ quiescent(q.work), q.known, q' = {...q, retired: true}}
+ action RetireWithoutFence = all {not(q.retired), q.reviewed,
+ quiescent(q.work), q.known, q' = {...q, retired: true}}
+ action Terminal = all {q.retired, q.attempted, q' = q}
+ action Environment = any {Observe, CloseIngress, Request, Reject, Terminal}
+ action step = any {Environment, Start, Retire}
+ action unfencedStep = any {Environment, Start, RetireWithoutFence}
+ action cachedGrantStep = any {Environment, TrustCachedGrant, Retire}
+
+ val TypeOK = q.epoch >= 0 and q.epoch <= 1 and q.grantEpoch == 0
+ val RetiredIsFenced = q.retired implies (not(q.ingressOpen) and q.grantEpoch != q.epoch)
+ val NoPostRetirementStart = not(q.startedAfterRetirement)
+ val NoOutstandingWork = q.retired implies quiescent(q.work)
+ val InventoryKnown = q.retired implies q.known
+ val NeverRejectAfterRetirement = not(q.rejectedAfterRetirement)
+ val NeverStarted = not(q.attempted and not(q.rejectedAfterRetirement) and q.epoch == 0)
+}
diff --git a/proof/quint/RetirementReview.qnt b/proof/quint/RetirementReview.qnt
new file mode 100644
index 0000000..8b1a7ff
--- /dev/null
+++ b/proof/quint/RetirementReview.qnt
@@ -0,0 +1,45 @@
+// SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+// SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+module RetirementReview {
+ import WorkCore.* from "./WorkCore"
+
+ type Review = {work: Work, known: bool, reviewed: bool, retired: bool,
+ lateFound: bool, gapFound: bool}
+ var q: Review
+ action init = q' = {work: {active: true, queued: true, cancelRequested: false},
+ known: false, reviewed: false, retired: false, lateFound: false, gapFound: false}
+
+ action RequestCancellation = all {not(q.retired), not(q.work.cancelRequested),
+ q' = {...q, work: cancel(q.work)}}
+ action ObserveCompletion = all {not(q.retired), q.work.active,
+ q' = {...q, work: complete(q.work)}}
+ action ObserveQueueDrained = all {not(q.retired), q.work.queued,
+ q' = {...q, work: drain(q.work)}}
+ action CompleteInventory = all {not(q.retired), not(q.known), q' = {...q, known: true}}
+ action ReviewCut = all {not(q.retired), not(q.reviewed), quiescent(q.work), q.known,
+ q' = {...q, reviewed: true}}
+ action ObserveLateActivity = all {not(q.retired), q.reviewed, not(q.lateFound),
+ q' = {...q, work: {...q.work, active: true}, lateFound: true}}
+ action ObserveInventoryGap = all {not(q.retired), q.reviewed, not(q.gapFound),
+ q' = {...q, known: false, gapFound: true}}
+ action Observe = any {RequestCancellation, ObserveCompletion, ObserveQueueDrained,
+ CompleteInventory, ReviewCut, ObserveLateActivity, ObserveInventoryGap}
+ action Retire = all {not(q.retired), q.reviewed, quiescent(q.work), q.known,
+ q' = {...q, retired: true}}
+ action TrustCancellation = all {not(q.retired), q.work.cancelRequested, q.known,
+ q' = {...q, retired: true}}
+ action TrustOldReview = all {not(q.retired), q.reviewed, q.known,
+ q' = {...q, retired: true}}
+ action IgnoreInventoryGap = all {not(q.retired), q.reviewed, quiescent(q.work),
+ q' = {...q, retired: true}}
+ action Terminal = all {q.retired, q' = q}
+ action step = any {Observe, Retire, Terminal}
+ action cancellationStep = any {Observe, TrustCancellation, Terminal}
+ action staleStep = any {Observe, TrustOldReview, Terminal}
+ action unknownStep = any {Observe, IgnoreInventoryGap, Terminal}
+
+ val TypeOK = true
+ val NoOutstandingWork = q.retired implies quiescent(q.work)
+ val InventoryKnown = q.retired implies q.known
+ val NeverRetired = not(q.retired)
+}
diff --git a/proof/quint/WorkCore.qnt b/proof/quint/WorkCore.qnt
new file mode 100644
index 0000000..00e058e
--- /dev/null
+++ b/proof/quint/WorkCore.qnt
@@ -0,0 +1,9 @@
+// SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+// SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+module WorkCore {
+ type Work = {active: bool, queued: bool, cancelRequested: bool}
+ pure def cancel(w: Work): Work = {...w, cancelRequested: true}
+ pure def complete(w: Work): Work = {...w, active: false}
+ pure def drain(w: Work): Work = {...w, queued: false}
+ pure def quiescent(w: Work): bool = not(w.active) and not(w.queued)
+}
diff --git a/proof/quint/WorkLifecycle.qnt b/proof/quint/WorkLifecycle.qnt
new file mode 100644
index 0000000..7c243e4
--- /dev/null
+++ b/proof/quint/WorkLifecycle.qnt
@@ -0,0 +1,18 @@
+// SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+// SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+module WorkLifecycle {
+ import WorkCore.* from "./WorkCore"
+ // Cancellation is a request, never an observation of completion.
+ var q: Work
+ action init = q' = {active: true, queued: true, cancelRequested: false}
+ action RequestCancellation = all {not(q.cancelRequested), q' = cancel(q)}
+ action ObserveCompletion = all {q.active, q' = complete(q)}
+ action ObserveQueueDrained = all {q.queued, q' = drain(q)}
+ action Terminal = all {quiescent(q), q.cancelRequested, q' = q}
+ action step = any {RequestCancellation, ObserveCompletion, ObserveQueueDrained, Terminal}
+ action cancellationStep = any {RequestCancellation, all {q.cancelRequested, q' = q}}
+ val TypeOK = true
+ val WorkRemains = q.active and q.queued
+ val NeverCancelled = not(q.cancelRequested)
+ val NeverQuiescent = not(quiescent(q))
+}
diff --git a/proof/quint/check_contract.py b/proof/quint/check_contract.py
new file mode 100644
index 0000000..50c9c29
--- /dev/null
+++ b/proof/quint/check_contract.py
@@ -0,0 +1,98 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Exhaust Quint design models and require typed negative-control traces."""
+
+from __future__ import annotations
+
+import argparse
+import os
+from pathlib import Path
+import re
+import shutil
+import subprocess
+
+from process_runner import run
+
+
+ROOT = Path(__file__).resolve().parent
+QUINT = os.environ.get("AITIA_QUINT_BIN") or shutil.which("quint")
+COUNTS = re.compile(r"(\d+) states generated, (\d+) distinct states found, (\d+) states left on queue")
+SAFE_DISTINCT = {"work-safe": 8, "work-cancellation": 2,
+ "retirement-safe": 42, "ingress-safe": 248,
+ "lifecycle-safe": 19042}
+# lane, name, model, transition, invariant(s), expected counterexample
+CASES = (
+ ("work", "work-safe", "WorkLifecycle", "step", "TypeOK", False),
+ ("work", "work-cancellation", "WorkLifecycle", "cancellationStep", "WorkRemains", False),
+ ("work", "work-cancel-reachable", "WorkLifecycle", "cancellationStep", "NeverCancelled", True),
+ ("work", "work-quiescent-reachable", "WorkLifecycle", "step", "NeverQuiescent", True),
+ ("retirement", "retirement-safe", "RetirementReview", "step", "TypeOK,NoOutstandingWork,InventoryKnown", False),
+ ("retirement", "retirement-trust-cancel", "RetirementReview", "cancellationStep", "NoOutstandingWork", True),
+ ("retirement", "retirement-stale-review", "RetirementReview", "staleStep", "NoOutstandingWork", True),
+ ("retirement", "retirement-unknown-inventory", "RetirementReview", "unknownStep", "InventoryKnown", True),
+ ("retirement", "retirement-reachable", "RetirementReview", "step", "NeverRetired", True),
+ ("ingress", "ingress-safe", "RetirementIngress", "step", "TypeOK,RetiredIsFenced,NoPostRetirementStart,NoOutstandingWork,InventoryKnown", False),
+ ("ingress", "ingress-unfenced", "RetirementIngress", "unfencedStep", "NoPostRetirementStart", True),
+ ("ingress", "ingress-cached-grant", "RetirementIngress", "cachedGrantStep", "NoPostRetirementStart", True),
+ ("ingress", "ingress-reject-reachable", "RetirementIngress", "step", "NeverRejectAfterRetirement", True),
+ ("ingress", "ingress-start-reachable", "RetirementIngress", "step", "NeverStarted", True),
+ ("lifecycle", "lifecycle-safe", "AssuranceLifecycle", "step", "TypeOK,AdmissionIsCurrent,DecisionRequiresAdmission,GrantRequiresCurrentDecision,NoUnsafeEffectStart,NoUnsafeDelivery,DeliveryRequiresStart,AtMostOneDelivery", False),
+ ("lifecycle", "lifecycle-start-reachable", "AssuranceLifecycle", "step", "NoEffectStarted", True),
+ ("lifecycle", "lifecycle-untrusted-report", "AssuranceLifecycle", "unsafeStep", "NoUnsafeEffectStart", True),
+ ("lifecycle", "lifecycle-late-admission", "AssuranceLifecycle", "lateAdmitStep", "AdmissionIsCurrent", True),
+ ("lifecycle", "lifecycle-early-grant", "AssuranceLifecycle", "earlyGrantStep", "GrantRequiresCurrentDecision", True),
+ ("lifecycle", "lifecycle-after-revoke", "AssuranceLifecycle", "afterRevokeStep", "NoUnsafeEffectStart", True),
+ ("lifecycle", "lifecycle-stale-delivery", "AssuranceLifecycle", "unsafeDeliveryStep", "NoUnsafeDelivery", True),
+ ("lifecycle", "lifecycle-delivery-before-start", "AssuranceLifecycle", "beforeStartStep", "DeliveryRequiresStart", True),
+ ("lifecycle", "lifecycle-replay-delivery", "AssuranceLifecycle", "replayStep", "AtMostOneDelivery", True),
+)
+
+
+def check_case(case: tuple) -> None:
+ lane, name, model, transition, invariants, negative = case
+ print(f"QUINT-CHECK: {name}", flush=True)
+ command = [QUINT, "verify", str(ROOT / f"{model}.qnt"), "--backend", "tlc",
+ "--step", transition, "--tlc-config", str(ROOT / "tlc-config.json"),
+ "--verbosity", "3"]
+ if "," in invariants:
+ command += ["--invariants", *invariants.split(",")]
+ else:
+ command += ["--invariant", invariants]
+ status, output = run(command, ROOT, name)
+ counts = COUNTS.search(output)
+ expected_code = 1 if negative else 0
+ marker = "Error: Invariant q_inv is violated." if negative else "[ok] No violation found"
+ if (status != expected_code or marker not in output or not counts
+ or int(counts[2]) == 0 or (not negative and int(counts[3]) != 0)
+ or (name in SAFE_DISTINCT and int(counts[2]) != SAFE_DISTINCT[name])
+ or (negative and ("error: found a counterexample" not in output
+ or "behavior up to this point" not in output))):
+ raise SystemExit(f"QUINT-CHECK-FAILED: {name} exit={status}\n{output[-6000:]}")
+ print(f"QUINT-CHECK-OK: {name} distinct={counts[2]} exit={status}", flush=True)
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("lane", nargs="?", default="all",
+ choices=("all", "work", "retirement", "ingress", "lifecycle"))
+ selected = parser.parse_args().lane
+ if not QUINT:
+ parser.error("Quint executable is required")
+ version = subprocess.check_output((QUINT, "--version"), text=True, timeout=5).strip()
+ if version != "0.33.0":
+ parser.error(f"expected Quint 0.33.0, found {version!r}")
+ for case in CASES:
+ if selected in ("all", case[0]):
+ check_case(case)
+ if selected in ("all", "lifecycle"):
+ result = subprocess.run(("python3", str(ROOT / "check_progress.py")),
+ cwd=ROOT, timeout=120, check=False)
+ if result.returncode:
+ raise SystemExit(result.returncode)
+ print("QUINT-CHECK-OK: selected model contracts complete", flush=True)
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/proof/quint/check_lifecycle_replay.py b/proof/quint/check_lifecycle_replay.py
new file mode 100644
index 0000000..94f89a4
--- /dev/null
+++ b/proof/quint/check_lifecycle_replay.py
@@ -0,0 +1,322 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+"""Exhaust the Quint lifecycle graph and replay every reachable state in Scheme."""
+
+from collections import deque
+from concurrent.futures import ThreadPoolExecutor, as_completed
+import hashlib
+import json
+import os
+from pathlib import Path
+import re
+import subprocess
+import tempfile
+
+from process_runner import run
+
+ROOT = Path(__file__).resolve().parent
+REPO = ROOT.parent.parent
+ACTIONS = ("InstallAdapter", "ReportSuccess", "Plan", "Verify", "Admit", "Decide",
+ "Authorize", "StartEffect", "DeliverEffect", "ChangeSource", "Tick", "Revoke",
+ "RejectDelivery", "FailDelivery", "UnknownDelivery", "Terminal")
+FIELDS = ("revision", "planned", "verified", "admitted", "decided", "granted",
+ "grantEpoch", "epoch", "clock", "sealUntil", "grantUntil", "adapterInstalled",
+ "reportedSuccess", "effectStarted", "startSafe", "reservationRevision",
+ "reservationEpoch", "reservationUntil", "deliveryStatus", "deliveryCalls", "deliverySafe")
+INVARIANTS = ("TypeOK", "AdmissionIsCurrent", "DecisionRequiresAdmission",
+ "GrantRequiresCurrentDecision", "NoUnsafeEffectStart", "NoUnsafeDelivery",
+ "DeliveryRequiresStart", "AtMostOneDelivery")
+FAULTS = (("unsafeStep", "NoUnsafeEffectStart", "UnsafeStart"),
+ ("lateAdmitStep", "AdmissionIsCurrent", "UnsafeLateAdmit"),
+ ("earlyGrantStep", "GrantRequiresCurrentDecision", "UnsafeEarlyGrant"),
+ ("afterRevokeStep", "NoUnsafeEffectStart", "UnsafeAfterRevoke"),
+ ("unsafeDeliveryStep", "NoUnsafeDelivery", "UnsafeDelivery"),
+ ("beforeStartStep", "DeliveryRequiresStart", "UnsafeBeforeStart"),
+ ("replayStep", "AtMostOneDelivery", "UnsafeReplay"))
+SOURCE_CUT = ("proof/quint/AssuranceLifecycle.qnt", "proof/quint/EffectAdmission.qnt",
+ "proof/quint/package-lock.json", "proof/quint/check_lifecycle_replay.py",
+ "proof/quint/test_lifecycle_replay.py",
+ "proof/quint/process_runner.py",
+ "modules/assurance/host.ss", "modules/assurance/effect-host.ss",
+ "modules/assurance/interface.ss", "t/formal/lifecycle-fixture.ss",
+ "t/formal/lifecycle-replay-test.ss", "t/assurance/unit/lifecycle-boundary-test.ss")
+
+
+def source_hashes():
+ return {path: hashlib.sha256((REPO / path).read_bytes()).hexdigest() for path in SOURCE_CUT}
+
+
+def export_graph(quint, work):
+ status, output = run([quint, "compile", str(ROOT / "AssuranceLifecycle.qnt"),
+ "--target", "tlaplus", "--step", "step"], ROOT, "lifecycle-compile")
+ start = output.find("-------------------------- MODULE AssuranceLifecycle")
+ if status or start < 0 or not output.rstrip().endswith("===="):
+ raise RuntimeError(f"Quint compilation failed: {output[-2000:]}")
+ # Only a checker intermediate: all transition bodies come from Quint.
+ # Expanding the compiled step into its named leaf operators lets TLC label
+ # edges without adding a history variable / changing the state quotient.
+ model = (ROOT / "AssuranceLifecycle.qnt").read_text()
+ unions = dict(re.findall(r"action\s+(\w+)\s*=\s*any\s*\{([^}]+)\}", model))
+ def leaf_actions(name):
+ if name not in unions:
+ return {name}
+ return set().union(*(leaf_actions(part.strip()) for part in unions[name].split(",")))
+ if leaf_actions("step") != set(ACTIONS):
+ raise RuntimeError("Quint action surface changed")
+ source = re.sub(r"=+\s*$", "", output[start:])
+ source += "\nReplayNext == " + " \\/ ".join(ACTIONS) + "\n====\n"
+ (work / "AssuranceLifecycle.tla").write_text(source)
+ (work / "safe.cfg").write_text("INIT init\nNEXT ReplayNext\nINVARIANTS " + " ".join(INVARIANTS) + "\n")
+ jar = Path(os.environ.get("QUINT_HOME", str(Path.home() / ".quint"))) / "apalache-dist-0.62.1/apalache/lib/apalache.jar"
+ if not jar.is_file():
+ raise RuntimeError("pinned Quint TLC backend jar is required")
+ status, output = run(["java", "-Xmx512m", "-cp", str(jar), "tlc2.TLC", "-workers", "1",
+ "-metadir", str(work / "meta"), "-config", str(work / "safe.cfg"),
+ "-dump", "dot,actionlabels", str(work / "graph"),
+ str(work / "AssuranceLifecycle.tla")], work, "lifecycle-graph")
+ counts = re.search(r"(\d+) states generated, (\d+) distinct states found, (\d+) states left on queue", output)
+ if status or "Model checking completed. No error has been found." not in output or not counts or int(counts[3]):
+ raise RuntimeError(f"incomplete lifecycle graph: exit={status}\n{output[-3000:]}")
+ return int(counts[2]), work / "graph.dot"
+
+
+def read_graph(path, expected):
+ nodes, edges, initial = {}, [], []
+ for line in path.read_text().splitlines():
+ node = re.match(r'\s*"?(-?\d+)"?\s+\[label="([^"]*)"', line)
+ if node:
+ values = {key: (value == "TRUE" if value in ("TRUE", "FALSE") else int(value))
+ for key, value in re.findall(r"(\w+)\s*\|->\s*(TRUE|FALSE|-?\d+)", node[2])}
+ if set(values) != set(FIELDS):
+ raise ValueError(f"model state schema changed: {set(values) ^ set(FIELDS)}")
+ nodes[node[1]] = values
+ if "style = filled" in line or "style=filled" in line:
+ initial.append(node[1])
+ edge = re.match(r'\s*"?(-?\d+)"?\s*->\s*"?(-?\d+)"?.*label="([^"]+)"', line)
+ if edge:
+ label = edge[3].split("\\n")[0]
+ if label not in ACTIONS:
+ raise ValueError(f"unknown TLC action label {label!r}")
+ edges.append((edge[1], edge[2], label))
+ if len(nodes) != expected or len(initial) != 1 or not edges:
+ raise ValueError(f"incomplete graph: nodes={len(nodes)}/{expected} initial={initial} edges={len(edges)}")
+ if any(origin not in nodes or target not in nodes for origin, target, _ in edges):
+ raise ValueError("edge references a missing state")
+ return nodes, edges, initial[0]
+
+
+def covering_traces(nodes, edges, initial):
+ adjacency = {}
+ for origin, target, action in edges:
+ adjacency.setdefault(origin, []).append((target, action))
+ paths = {initial: [("init", nodes[initial])]}
+ pending = deque([initial])
+ while pending:
+ origin = pending.popleft()
+ for target, action in adjacency.get(origin, []):
+ if target not in paths:
+ paths[target] = paths[origin] + [(action, nodes[target])]
+ pending.append(target)
+ if set(paths) != set(nodes):
+ raise ValueError("TLC dump contains unreachable or missing nodes")
+ # Ignoring self loops, this bounded lifecycle is a DAG. Its minimum vertex
+ # path cover is a bipartite maximum matching. Each path gets a real safe
+ # prefix from init, then continues through original TLC edges. No Host is
+ # cloned or reset mid-path, and no model state is synthesized in Scheme.
+ distinct = {origin: list(dict.fromkeys(target for target, _ in targets if target != origin))
+ for origin, targets in adjacency.items()}
+ indegree = dict.fromkeys(nodes, 0)
+ for targets in distinct.values():
+ for target in targets:
+ indegree[target] += 1
+ queue = deque(node for node in nodes if not indegree[node])
+ ordered = []
+ while queue:
+ origin = queue.popleft()
+ ordered.append(origin)
+ for target in distinct.get(origin, []):
+ indegree[target] -= 1
+ if not indegree[target]:
+ queue.append(target)
+ if len(ordered) != len(nodes):
+ raise ValueError("non-stuttering lifecycle graph is not a DAG")
+ left, right = {}, {}
+ def augment(origin, seen):
+ for target in distinct.get(origin, []):
+ if target in seen:
+ continue
+ seen.add(target)
+ if target not in right or augment(right[target], seen):
+ left[origin], right[target] = target, origin
+ return True
+ return False
+ for origin in nodes:
+ augment(origin, set())
+ labels = {(origin, target): action for origin, target, action in edges}
+ traces = []
+ for origin in nodes:
+ if origin in right:
+ continue
+ trace = list(paths[origin])
+ while origin in left:
+ target = left[origin]
+ trace.append((labels[origin, target], nodes[target]))
+ origin = target
+ traces.append(trace)
+ covered = {action for trace in traces for action, _ in trace}
+ stutters = {action for origin, target, action in edges if origin == target}
+ for action in ACTIONS:
+ if action not in covered and action not in stutters:
+ origin, target, _ = next(edge for edge in edges if edge[2] == action)
+ traces.append(paths[origin] + [(action, nodes[target])])
+ # Preserve renewal and terminal stutter witnesses as actual API calls.
+ for action in ACTIONS:
+ if action not in stutters:
+ continue
+ origin, target, _ = min((edge for edge in edges if edge[0] == edge[1] and edge[2] == action),
+ key=lambda edge: len(paths[edge[0]]))
+ traces.append(paths[origin] + [(action, nodes[target])])
+ if {json.dumps(state, sort_keys=True) for trace in traces for _, state in trace} != {
+ json.dumps(state, sort_keys=True) for state in nodes.values()}:
+ raise ValueError("covering paths do not cover the complete state space")
+ return traces
+
+
+def batches(traces, step_budget=160):
+ batch, steps = [], 0
+ for trace in traces:
+ if len(trace) > step_budget:
+ raise ValueError("one trace exceeds the native step budget")
+ if batch and steps + len(trace) > step_budget:
+ yield batch
+ batch, steps = [], 0
+ batch.append(trace)
+ steps += len(trace)
+ if batch:
+ yield batch
+
+
+def sexpr_trace(trace):
+ return "(" + " ".join(
+ f"({action} (" + " ".join(f"({key} {'#t' if value is True else '#f' if value is False else value})"
+ for key, value in state.items()) + "))"
+ for action, state in trace) + ")"
+
+
+def negative_traces(quint, work, safe):
+ current = lambda q: (q["granted"] == q["revision"] == q["admitted"] == q["decided"]
+ and q["grantEpoch"] == q["epoch"] and q["clock"] < q["grantUntil"])
+ selectors = {
+ "UnsafeStart": lambda q: q["reportedSuccess"] and not q["effectStarted"] and not current(q),
+ "UnsafeLateAdmit": lambda q: q["revision"] == 2 and q["reportedSuccess"] and q["admitted"] == 0,
+ "UnsafeEarlyGrant": lambda q: q["revision"] == 2 and q["reportedSuccess"] and q["admitted"] == 0 and q["granted"] == 0 and q["clock"] < 3,
+ "UnsafeAfterRevoke": lambda q: q["epoch"] > q["grantEpoch"] and q["grantUntil"] > q["clock"] and q["granted"] == 0 and not q["effectStarted"],
+ "UnsafeDelivery": lambda q: q["effectStarted"] and q["deliveryStatus"] == 0 and not current(q),
+ "UnsafeBeforeStart": lambda q: q["reportedSuccess"] and not q["effectStarted"],
+ "UnsafeReplay": lambda q: q["deliveryStatus"] == 1,
+ }
+ traces = []
+ for step, invariant, fault in FAULTS:
+ prefixes = [trace[:index + 1] for trace in safe for index, (_, state) in enumerate(trace)
+ if selectors[fault](state)]
+ if not prefixes:
+ raise RuntimeError(f"no reachable fault input for {fault}")
+ prefix = min(prefixes, key=len)
+ state = prefix[-1][1]
+ record = "{" + ", ".join(f"{key}: {str(value).lower() if isinstance(value, bool) else value}"
+ for key, value in state.items()) + "}"
+ # Select an actually reachable input, then execute the original Quint
+ # fault operator. No guessed output state or random-hit requirement.
+ source = (ROOT / "AssuranceLifecycle.qnt").read_text()
+ generated = work / f"{fault}.qnt"
+ generated.write_text(source.rstrip()[:-1] + f"\n action FaultInit = q' = {record}\n}}\n")
+ # Import resolution remains pinned to the same source cut.
+ (work / "EffectAdmission.qnt").write_text((ROOT / "EffectAdmission.qnt").read_text())
+ status, output = run([quint, "run", str(generated), "--main", "AssuranceLifecycle",
+ "--backend", "typescript", "--seed", "34", "--max-samples", "1",
+ "--n-traces", "1", "--max-steps", "1", "--mbt", "--init", "FaultInit", "--step", fault,
+ "--invariant", invariant, "--verbosity", "1",
+ "--out-itf", str(work / f"{fault}_{{seq}}.json")], REPO, fault)
+ if status != 1 or "Invariant violated" not in output:
+ raise RuntimeError(f"missing typed counterexample for {fault}: {output[-2000:]}")
+ candidates = [json.loads(path.read_text())["states"] for path in work.glob(f"{fault}_*.json")]
+ candidates = [trace for trace in candidates if trace[-1]["mbt::actionTaken"] == fault]
+ if not candidates:
+ raise RuntimeError(f"no failing ITF trace for {fault}")
+ trace = list(prefix)
+ for row in candidates[0][1:]:
+ action, state = row["mbt::actionTaken"], row["q"]
+ if action not in set(ACTIONS) | {"init", fault} or set(state) != set(FIELDS):
+ raise ValueError("negative model action/state schema changed")
+ converted = {}
+ for key, value in state.items():
+ if isinstance(value, bool):
+ converted[key] = value
+ elif isinstance(value, dict) and set(value) == {"#bigint"}:
+ converted[key] = int(value["#bigint"])
+ else:
+ raise ValueError("unexpected ITF scalar")
+ trace.append((action, converted))
+ traces.append(trace)
+ return traces
+
+
+def replay(work, chunk, traces):
+ fixture = work / f"traces-{chunk}.scm"
+ fixture.write_text("(" + "\n".join(map(sexpr_trace, traces)) + ")\n")
+ try:
+ status, output = run(["env", f"AITIA_LIFECYCLE_REPLAY={fixture}", "just",
+ "test-scheme-atomic", "formal", "lifecycle-replay-test.ss"],
+ REPO, f"native-lifecycle-{chunk}", timeout=65)
+ if status or not re.search(r"^OK$", output, re.MULTILINE):
+ raise RuntimeError(f"Scheme replay failed: chunk={chunk} exit={status}\n{output[-8000:]}")
+ except (RuntimeError, TimeoutError) as error:
+ # Keep the exact failed input after the temporary graph is removed.
+ evidence = REPO / ".cache/lifecycle-failures"
+ evidence.mkdir(parents=True, exist_ok=True)
+ saved = evidence / f"traces-{chunk}.scm"
+ saved.write_bytes(fixture.read_bytes())
+ (evidence / f"traces-{chunk}.log").write_text(str(error))
+ raise RuntimeError(f"{error}\nFAILED-LIFECYCLE-INPUT: {saved}") from error
+ return len(traces)
+
+
+def main():
+ hashes = source_hashes()
+ quint = os.environ.get("AITIA_QUINT_BIN", str(ROOT / "node_modules/.bin/quint"))
+ if subprocess.check_output([quint, "--version"], text=True, timeout=5).strip() != "0.33.0":
+ raise RuntimeError("Quint 0.33.0 is required")
+ with tempfile.TemporaryDirectory(prefix="aitia-lifecycle-") as temporary:
+ work = Path(temporary)
+ count, graph = export_graph(quint, work)
+ if count != 19042:
+ raise RuntimeError(f"lifecycle state quotient changed: {count} != 19042")
+ nodes, edges, initial = read_graph(graph, count)
+ traces = covering_traces(nodes, edges, initial)
+ covered = {edge[2] for edge in edges}
+ if covered != set(ACTIONS):
+ raise RuntimeError(f"incomplete action coverage: {covered ^ set(ACTIONS)}")
+ print(f"LIFECYCLE-GRAPH-OK: states={count} graph-edges={len(edges)} actions={len(covered)} traces={len(traces)}", flush=True)
+ faults = negative_traces(quint, work, traces)
+ replay(work, "faults", faults)
+ completed = 0
+ # Four bounded native processes; each retains the existing 1G/60s gate.
+ with ThreadPoolExecutor(max_workers=4) as pool:
+ jobs = [pool.submit(replay, work, chunk, batch)
+ for chunk, batch in enumerate(batches(traces))]
+ try:
+ for job in as_completed(jobs):
+ completed += job.result()
+ print(f"LIFECYCLE-REPLAY: traces={completed}/{len(traces)}", flush=True)
+ except BaseException:
+ for job in jobs:
+ job.cancel()
+ raise
+ if hashes != source_hashes():
+ raise RuntimeError("declared lifecycle source cut changed during verification")
+ print("LIFECYCLE-SOURCE-CUT: " + json.dumps(hashes, sort_keys=True), flush=True)
+ print(f"LIFECYCLE-SCHEME-OK: states={count}/{count} actions={len(covered)}/16 traces={completed}/{len(traces)} faults={len(faults)}/7", flush=True)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/proof/quint/check_progress.py b/proof/quint/check_progress.py
new file mode 100644
index 0000000..8517394
--- /dev/null
+++ b/proof/quint/check_progress.py
@@ -0,0 +1,77 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Check Quint's fair and unfair lifecycle specs with TLC's native temporal lane.
+
+Quint's ``verify --temporal`` places its default transition spec beside the
+selected property; TLC rejects an implication that embeds weak-fairness actions.
+Compiling the Quint source and selecting its named spec in a TLC config keeps
+the source of truth in Quint while exercising the exact fairness formula.
+"""
+
+from __future__ import annotations
+
+import os
+from pathlib import Path
+import re
+import shutil
+import subprocess
+import tempfile
+
+from process_runner import run
+
+
+ROOT = Path(__file__).resolve().parent
+QUINT = os.environ.get("AITIA_QUINT_BIN") or shutil.which("quint")
+APALACHE = (Path(os.environ["QUINT_HOME"]) if "QUINT_HOME" in os.environ
+ else Path.home() / ".quint") / "apalache-dist-0.62.1/apalache/lib/apalache.jar"
+
+
+def main() -> int:
+ if not QUINT or not APALACHE.is_file():
+ raise SystemExit("Quint 0.33.0 and its Apalache 0.62.1 TLC jar are required")
+ version = subprocess.check_output((QUINT, "--version"), text=True, timeout=5).strip()
+ if version != "0.33.0":
+ raise SystemExit(f"expected Quint 0.33.0, found {version}")
+ print("QUINT-PROGRESS: compiling lifecycle to temporary TLA+", flush=True)
+ compiled_status, compiled_output = run(
+ (QUINT, "compile", str(ROOT / "AssuranceLifecycle.qnt"),
+ "--target", "tlaplus", "--step", "stableStep",
+ "--temporal", "EventuallyDelivery"),
+ ROOT, "quint-compile",
+ )
+ module_start = compiled_output.find("-------------------------- MODULE AssuranceLifecycle")
+ source = compiled_output[module_start:] if module_start >= 0 else ""
+ if compiled_status or module_start < 0 or not source.rstrip().endswith("===="):
+ raise SystemExit(f"Quint compilation failed: {compiled_output[-3000:]}")
+ with tempfile.TemporaryDirectory(prefix="aitia-quint-progress-") as directory:
+ work = Path(directory)
+ (work / "AssuranceLifecycle.tla").write_text(source)
+ for name, spec, expected_code, marker in (
+ ("fair", "stableSpec", 0, "Model checking completed. No error has been found."),
+ ("no-fair", "stableSpecNoFair", 13, "Error: Temporal property EventuallyDelivery was violated."),
+ ):
+ print(f"QUINT-PROGRESS: checking {name}", flush=True)
+ config = work / f"{name}.cfg"
+ config.write_text(f"SPECIFICATION {spec}\nPROPERTY EventuallyDelivery\n")
+ meta = work / f"meta-{name}"
+ meta.mkdir()
+ status, output = run(
+ ("java", "-XX:+UseParallelGC", "-Xmx512m", "-cp", str(APALACHE),
+ "tlc2.TLC", "-workers", "1", "-metadir", str(meta),
+ "-config", str(config), str(work / "AssuranceLifecycle.tla")),
+ work, f"quint-progress-{name}",
+ )
+ counts = re.search(r"(\d+) states generated, (\d+) distinct states found, (\d+) states left on queue", output)
+ if status != expected_code or marker not in output or not counts:
+ raise SystemExit(f"QUINT-PROGRESS-FAILED: {name} exit={status}\n{output[-5000:]}")
+ if int(counts[2]) != 20 or int(counts[3]) != 0:
+ raise SystemExit(f"QUINT-PROGRESS-FAILED: unexpected {name} state space")
+ if expected_code and "counter-example" not in output:
+ raise SystemExit(f"QUINT-PROGRESS-FAILED: no counterexample for {name}")
+ print(f"QUINT-PROGRESS-OK: {name} distinct={counts[2]}", flush=True)
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/proof/quint/check_scheme_replay.py b/proof/quint/check_scheme_replay.py
new file mode 100644
index 0000000..00c5d24
--- /dev/null
+++ b/proof/quint/check_scheme_replay.py
@@ -0,0 +1,128 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Replay pinned Quint MBT traces through the actual serialized Scheme Host.
+
+Sampling is not exhaustive refinement. Require all safe actions and both real
+unsafe-model counterexamples; compare every projected state, not just outcomes.
+"""
+
+from __future__ import annotations
+
+import json
+import os
+from pathlib import Path
+import shutil
+import subprocess
+import tempfile
+
+from process_runner import run
+
+ROOT = Path(__file__).resolve().parent
+REPO = ROOT.parent.parent
+ACTIONS = {"RequestCancellation", "ObserveCompletion", "ObserveQueueDrained",
+ "CompleteInventory", "ReviewCut", "ObserveLateActivity",
+ "ObserveInventoryGap", "CloseIngress", "Request", "Start", "Reject",
+ "Retire", "Terminal"}
+FIELDS = (("active?", "work", "active"), ("queued?", "work", "queued"),
+ ("cancellation-requested?", "work", "cancelRequested"),
+ ("inventory-known?", "known"), ("reviewed?", "reviewed"),
+ ("late-activity-found?", "lateFound"), ("inventory-gap-found?", "gapFound"),
+ ("retired?", "retired"), ("ingress-open?", "ingressOpen"),
+ ("authority-epoch", "epoch"), ("cached-grant-epoch", "grantEpoch"),
+ ("pending?", "pending"), ("attempted?", "attempted"))
+
+
+def scalar(value):
+ if isinstance(value, bool):
+ return "#t" if value else "#f"
+ if isinstance(value, dict) and set(value) == {"#bigint"}:
+ return str(int(value["#bigint"]))
+ raise ValueError(f"unexpected ITF scalar: {value!r}")
+
+
+def state_row(state):
+ q = state["q"]
+ expected_keys = {path[1] for path in FIELDS} | {"rejectedAfterRetirement", "startedAfterRetirement"}
+ if set(q) != expected_keys or set(q["work"]) != {"active", "queued", "cancelRequested"}:
+ raise ValueError("model state schema changed; update the explicit correspondence")
+ fields = []
+ for slot, *path in FIELDS:
+ value = q
+ for key in path:
+ value = value[key]
+ fields.append(f"({slot} {scalar(value)})")
+ # MBT action names are a closed set, never arbitrary executable Scheme.
+ action = state["mbt::actionTaken"]
+ if action not in ACTIONS | {"init", "TrustCachedGrant", "RetireWithoutFence"}:
+ raise ValueError(f"unknown Quint action: {action!r}")
+ return f"({action} ({' '.join(fields)}))"
+
+
+def generate(quint, directory, name, step, invariant, samples):
+ print(f"QUINT-SCHEME: generate {name}", flush=True)
+ negative = step != "step"
+ status, output = run(
+ [quint, "run", str(ROOT / "RetirementIngress.qnt"), "--backend", "typescript",
+ "--seed", "34", "--max-samples", str(samples),
+ "--n-traces", "1" if negative else str(samples),
+ "--max-steps", "18", "--mbt", "--step", step, "--invariant", invariant,
+ "--verbosity", "1", "--out-itf", str(directory / f"{name}_{{seq}}.json")],
+ REPO, name)
+ marker = "Invariant violated" if negative else "[ok] No violation found"
+ if status != int(negative) or marker not in output:
+ raise RuntimeError(f"{name}: unexpected Quint result exit={status}\n{output[-2000:]}")
+ traces = [json.loads(path.read_text())["states"]
+ for path in sorted(directory.glob(f"{name}_*.json"))]
+ if not traces or (not negative and len(traces) != samples):
+ raise RuntimeError(f"{name}: incomplete trace output ({len(traces)})")
+ if negative:
+ # Quint may retain passing samples too. Only actual failing traces
+ # belong to the negative lane; their final unsafe action is refused.
+ fault = "RetireWithoutFence" if step == "unfencedStep" else "TrustCachedGrant"
+ traces = [trace for trace in traces if trace[-1]["mbt::actionTaken"] == fault
+ and (trace[-1]["q"]["retired"] if fault == "RetireWithoutFence"
+ else trace[-1]["q"]["startedAfterRetirement"])]
+ if not traces:
+ raise RuntimeError(f"{name}: missing typed unsafe counterexample")
+ return traces
+
+
+def main():
+ quint = os.environ.get("AITIA_QUINT_BIN") or shutil.which("quint")
+ if not quint:
+ quint = str(ROOT / "node_modules/.bin/quint")
+ version = subprocess.check_output([quint, "--version"], text=True, timeout=5).strip()
+ if version != "0.33.0":
+ raise RuntimeError(f"expected Quint 0.33.0, found {version!r}")
+ with tempfile.TemporaryDirectory(prefix="aitia-quint-replay-") as temporary:
+ directory = Path(temporary)
+ safe = generate(quint, directory, "safe", "step",
+ "TypeOK and RetiredIsFenced and NoPostRetirementStart and NoOutstandingWork and InventoryKnown", 512)
+ covered = {state["mbt::actionTaken"] for trace in safe for state in trace[1:]}
+ if covered != ACTIONS:
+ raise RuntimeError(f"safe action coverage mismatch: {covered ^ ACTIONS}")
+ witnesses = [state["q"] for trace in safe for state in trace]
+ distinct = len({json.dumps(q, sort_keys=True) for q in witnesses})
+ if distinct < 177:
+ raise RuntimeError(f"safe state coverage regressed: {distinct} < 177")
+ if not any(q["rejectedAfterRetirement"] for q in witnesses):
+ raise RuntimeError("missing post-retirement rejection witness")
+ unfenced = generate(quint, directory, "unfenced", "unfencedStep", "RetiredIsFenced", 512)
+ cached = generate(quint, directory, "cached", "cachedGrantStep", "NoPostRetirementStart", 512)
+ lanes = (("safe", safe), ("unfenced", unfenced), ("cached", cached))
+ fixture = directory / "traces.scm"
+ fixture.write_text("(" + "\n".join(
+ f"({name} ({' '.join('(' + ' '.join(map(state_row, trace)) + ')' for trace in traces)}))"
+ for name, traces in lanes) + ")\n")
+ environment = dict(os.environ, AITIA_QUINT_REPLAY=str(fixture))
+ result = subprocess.run(["just", "test-scheme-atomic", "formal", "retirement-replay-test.ss"],
+ cwd=REPO, env=environment, timeout=65, check=False)
+ if result.returncode:
+ raise SystemExit(result.returncode)
+ print(f"QUINT-SCHEME-OK: safe-traces={len(safe)} states={distinct}/248 "
+ f"actions={len(covered)} negative-traces={len(unfenced) + len(cached)}", flush=True)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/proof/quint/package-lock.json b/proof/quint/package-lock.json
new file mode 100644
index 0000000..3abe5d9
--- /dev/null
+++ b/proof/quint/package-lock.json
@@ -0,0 +1,799 @@
+{
+ "name": "lambda-aitia-quint-checks",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "lambda-aitia-quint-checks",
+ "dependencies": {
+ "@informalsystems/quint": "0.33.0"
+ }
+ },
+ "node_modules/@grpc/grpc-js": {
+ "version": "1.14.5",
+ "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.5.tgz",
+ "integrity": "sha512-7VZM+SVdEcUUqSQeNI3zM8Qs/BhQKZndPo2h5VkYkAM8Iz0wJIa8mKV5ekQGqG8UUsnkQ0NMxIxwkIHYvj0qOw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@grpc/proto-loader": "^0.8.0",
+ "@js-sdsl/ordered-map": "^4.4.2"
+ },
+ "engines": {
+ "node": ">=12.10.0"
+ }
+ },
+ "node_modules/@grpc/grpc-js/node_modules/@grpc/proto-loader": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.1.tgz",
+ "integrity": "sha512-wtF6h+DY6M3YaDBPAmvuuA6jV8Sif9MjtOI5euKFWRgCDl5PeDpPsHR9u2l6St5ceY8AZgoNDww5+HvEsXFsGg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.5.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@grpc/proto-loader": {
+ "version": "0.7.15",
+ "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz",
+ "integrity": "sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "lodash.camelcase": "^4.3.0",
+ "long": "^5.0.0",
+ "protobufjs": "^7.2.5",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@informalsystems/quint": {
+ "version": "0.33.0",
+ "resolved": "https://registry.npmjs.org/@informalsystems/quint/-/quint-0.33.0.tgz",
+ "integrity": "sha512-1hr+l+3wyKimjNXNl9lovpwmH5C9Ck898FL4yGbuEmFPiz7YRqvFvsB9hlHsaYukXqdUY5nuFKn/qiCon0O88g==",
+ "license": "Apache 2.0",
+ "dependencies": {
+ "@grpc/grpc-js": "^1.11.1",
+ "@grpc/proto-loader": "^0.7.7",
+ "@octokit/request": "^8.1.1",
+ "@sweet-monads/either": "~3.2.0",
+ "@sweet-monads/maybe": "~3.2.0",
+ "@types/line-column": "^1.0.0",
+ "@types/lodash.clonedeep": "4.5.0",
+ "@types/seedrandom": "^3.0.4",
+ "adm-zip": "^0.5.16",
+ "antlr4ts": "^0.5.0-alpha.4",
+ "chalk": "^4.1.2",
+ "cli-progress": "^3.12.0",
+ "cross-spawn": "^7.0.6",
+ "eol": "^0.9.1",
+ "immutable": "^4.3.0",
+ "json-bigint": "^1.0.0",
+ "line-column": "^1.0.2",
+ "lodash": "^4.17.21",
+ "lodash.clonedeep": "4.5.0",
+ "seedrandom": "^3.0.5",
+ "tar": "^7.5.13",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "quint": "dist/src/cli.js"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@isaacs/fs-minipass": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz",
+ "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^7.0.4"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@js-sdsl/ordered-map": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz",
+ "integrity": "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/js-sdsl"
+ }
+ },
+ "node_modules/@octokit/endpoint": {
+ "version": "9.0.6",
+ "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
+ "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/types": "^13.1.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/openapi-types": {
+ "version": "24.2.0",
+ "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
+ "integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
+ "license": "MIT"
+ },
+ "node_modules/@octokit/request": {
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
+ "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/endpoint": "^9.0.6",
+ "@octokit/request-error": "^5.1.1",
+ "@octokit/types": "^13.1.0",
+ "universal-user-agent": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/request-error": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
+ "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/types": "^13.1.0",
+ "deprecation": "^2.0.0",
+ "once": "^1.4.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/@octokit/types": {
+ "version": "13.10.0",
+ "resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
+ "integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
+ "license": "MIT",
+ "dependencies": {
+ "@octokit/openapi-types": "^24.2.0"
+ }
+ },
+ "node_modules/@protobufjs/aspromise": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz",
+ "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/codegen": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.5.tgz",
+ "integrity": "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/eventemitter": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.1.tgz",
+ "integrity": "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/fetch": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.1.tgz",
+ "integrity": "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.1"
+ }
+ },
+ "node_modules/@protobufjs/float": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz",
+ "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/path": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz",
+ "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/pool": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz",
+ "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@protobufjs/utf8": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.2.tgz",
+ "integrity": "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@sweet-monads/either": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@sweet-monads/either/-/either-3.2.0.tgz",
+ "integrity": "sha512-n+nR0b60GRTKb+D76qhTf4NEBXU9zfpigYYEtKtSYbV+5+i5gxr9jFd64pYkY2O7hVsb/G7nspbAeFni/i1ltA==",
+ "license": "MIT",
+ "dependencies": {
+ "@sweet-monads/interfaces": "^3.2.0"
+ }
+ },
+ "node_modules/@sweet-monads/interfaces": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@sweet-monads/interfaces/-/interfaces-3.3.0.tgz",
+ "integrity": "sha512-66akGvjPD4lizQy+w4JSltJilc2w/QPdw8lPAniLJGHwyjmrw9xMJLx76Q/GDnbCU59Werses4aZJLWOlJrL5A==",
+ "license": "MIT"
+ },
+ "node_modules/@sweet-monads/maybe": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/@sweet-monads/maybe/-/maybe-3.2.0.tgz",
+ "integrity": "sha512-/t+K0D/kBfkYOkZaePEsrK868at0M9UIEVgehcM0xscrCSZhKWGteE41vl2XJQqh8WyiFo/mZ5y7eAPSYzS+pg==",
+ "license": "MIT",
+ "dependencies": {
+ "@sweet-monads/interfaces": "^3.2.0"
+ }
+ },
+ "node_modules/@types/line-column": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@types/line-column/-/line-column-1.0.2.tgz",
+ "integrity": "sha512-099oFQmp/Tlf20xW5XI5R4F69N6lF/zQ09XDzc3R5BOLFlqIotgKoNIyj0HD4fQLWcGDreDJv8k/BkLJscrDrw==",
+ "license": "MIT"
+ },
+ "node_modules/@types/lodash": {
+ "version": "4.17.25",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.25.tgz",
+ "integrity": "sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ==",
+ "license": "MIT"
+ },
+ "node_modules/@types/lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/@types/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-IHijjFVPJTvzvrNPz+6nQy5lZQb7uh807RfTIEaQBrZXrIGjZy0L2dEb3hju34J0eqbXLCY6Hub/g81Jl4pGCA==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/lodash": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "26.6.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.4.tgz",
+ "integrity": "sha512-ldVPDCzj7fsaGZrLB0NuHuTvJcsNasysBAqMolr/cgxrLd1xbqxIr3XJiPnHHJUCxj5sNF1vnRj9aWnrVh5Jcg==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~8.9.0"
+ }
+ },
+ "node_modules/@types/seedrandom": {
+ "version": "3.0.8",
+ "resolved": "https://registry.npmjs.org/@types/seedrandom/-/seedrandom-3.0.8.tgz",
+ "integrity": "sha512-TY1eezMU2zH2ozQoAFAQFOPpvP15g+ZgSfTZt31AUUH/Rxtnz3H+A/Sv1Snw2/amp//omibc+AEkTaA8KUeOLQ==",
+ "license": "MIT"
+ },
+ "node_modules/adm-zip": {
+ "version": "0.5.18",
+ "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.18.tgz",
+ "integrity": "sha512-ufJnssQGbxzLNS1Ho9bCtX4rQKCCvoVuDLHoJyc3F9dOGDB4BkWs2Ci0kv53lqocAEQ/Cbi+I2XCsNYGqVYqng==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/antlr4ts": {
+ "version": "0.5.0-alpha.4",
+ "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz",
+ "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==",
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/bignumber.js": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
+ "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz",
+ "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/cli-progress": {
+ "version": "3.12.0",
+ "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz",
+ "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==",
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^4.2.3"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/deprecation": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
+ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==",
+ "license": "ISC"
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "license": "MIT"
+ },
+ "node_modules/eol": {
+ "version": "0.9.1",
+ "resolved": "https://registry.npmjs.org/eol/-/eol-0.9.1.tgz",
+ "integrity": "sha512-Ds/TEoZjwggRoz/Q2O7SE3i4Jm66mqTDfmdHdq/7DKVk3bro9Q8h6WdXKdPqFLMoqxrDK5SVRzHVPOS6uuGtrg==",
+ "license": "MIT"
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "4.3.9",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.9.tgz",
+ "integrity": "sha512-ObHy4YN7ycwZOUCLI1/6svfyAFu7vL8RhAvVu/bh/RZW9EPlOyDaQ9jDQWCtdqzaXUjgXZCW1migtHE7YI7UGQ==",
+ "license": "MIT"
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/isobject": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
+ "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
+ "license": "MIT",
+ "dependencies": {
+ "isarray": "1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/json-bigint": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
+ "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bignumber.js": "^9.0.0"
+ }
+ },
+ "node_modules/line-column": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/line-column/-/line-column-1.0.2.tgz",
+ "integrity": "sha512-Ktrjk5noGYlHsVnYWh62FLVs4hTb8A3e+vucNZMgPeAOITdshMSgv4cCZQeRDjm7+goqmo6+liZwTXo+U3sVww==",
+ "license": "MIT",
+ "dependencies": {
+ "isarray": "^1.0.0",
+ "isobject": "^2.0.0"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.clonedeep": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+ "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
+ "license": "MIT"
+ },
+ "node_modules/long": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/minipass": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz",
+ "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
+ "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^7.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/protobufjs": {
+ "version": "7.6.6",
+ "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.6.6.tgz",
+ "integrity": "sha512-dYDWdjSl5RNb7SgPxGQcRU+GtvP7s2fpkrY0r432PcOIaZ0/rBcxEZnQN67iJhFuQiVw754JDoPruPCNdGsbjg==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@protobufjs/aspromise": "^1.1.2",
+ "@protobufjs/base64": "^1.1.2",
+ "@protobufjs/codegen": "^2.0.5",
+ "@protobufjs/eventemitter": "^1.1.1",
+ "@protobufjs/fetch": "^1.1.1",
+ "@protobufjs/float": "^1.0.2",
+ "@protobufjs/path": "^1.1.2",
+ "@protobufjs/pool": "^1.1.0",
+ "@protobufjs/utf8": "^1.1.1",
+ "@types/node": ">=13.7.0",
+ "long": "^5.3.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/seedrandom": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
+ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==",
+ "license": "MIT"
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar": {
+ "version": "7.5.22",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.22.tgz",
+ "integrity": "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/fs-minipass": "^4.0.0",
+ "chownr": "^3.0.0",
+ "minipass": "^7.1.2",
+ "minizlib": "^3.1.0",
+ "yallist": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "8.9.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-8.9.0.tgz",
+ "integrity": "sha512-KTDyRTYX8sWmKXAikPHHSyc63CRPETMctyjKFupcC6OBLXT3xsN0e9aF7m+mIXutFWpUXuedtowG7iLOzp0kQg==",
+ "license": "MIT"
+ },
+ "node_modules/universal-user-agent": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
+ "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==",
+ "license": "ISC"
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
+ "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.3",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz",
+ "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ }
+ }
+}
diff --git a/proof/quint/package.json b/proof/quint/package.json
new file mode 100644
index 0000000..262330b
--- /dev/null
+++ b/proof/quint/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "lambda-aitia-quint-checks",
+ "version": "0.0.0",
+ "private": true,
+ "license": "Apache-2.0 AND LGPL-2.1-or-later",
+ "dependencies": {
+ "@informalsystems/quint": "0.33.0"
+ }
+}
diff --git a/proof/quint/process_runner.py b/proof/quint/process_runner.py
new file mode 100644
index 0000000..f9fda54
--- /dev/null
+++ b/proof/quint/process_runner.py
@@ -0,0 +1,68 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+"""Run a model checker with real output and a bounded silence watchdog."""
+
+from __future__ import annotations
+
+import os
+import selectors
+import signal
+import subprocess
+import time
+from pathlib import Path
+from typing import Sequence
+
+
+PROGRESS = (
+ "Compiling to TLA+", "Starting checker server", "SanyParser",
+ "Running TLC", "Computing initial states", "states generated",
+ "Model checking completed", "No violation found", "Invariant q_inv is violated",
+ "found a counterexample", "Checking temporal properties", "Temporal property",
+)
+
+
+def run(command: Sequence[str], cwd: Path, label: str, *, timeout: float = 60,
+ silence: float = 12) -> tuple[int, str]:
+ """Return status and exact output; never count a silent checker as progress."""
+ process = subprocess.Popen(command, cwd=cwd, stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT, start_new_session=True)
+ assert process.stdout is not None
+ selector = selectors.DefaultSelector()
+ selector.register(process.stdout, selectors.EVENT_READ)
+ chunks: list[bytes] = []
+ pending = b""
+ began = last_output = time.monotonic()
+ try:
+ while selector.get_map():
+ now = time.monotonic()
+ if now - began > timeout or now - last_output > silence:
+ reason = "total timeout" if now - began > timeout else "silent checker"
+ os.killpg(process.pid, signal.SIGTERM)
+ try:
+ process.wait(timeout=3)
+ except subprocess.TimeoutExpired:
+ os.killpg(process.pid, signal.SIGKILL)
+ process.wait()
+ partial = b"".join(chunks).decode(errors="replace")
+ raise TimeoutError(f"{label}: {reason} after {now - last_output:.1f}s without output\n{partial[-4000:]}")
+ events = selector.select(timeout=min(1.0, silence))
+ for key, _ in events:
+ data = os.read(key.fd, 65536)
+ if not data:
+ selector.unregister(key.fileobj)
+ continue
+ last_output = time.monotonic()
+ chunks.append(data)
+ pending += data
+ while b"\n" in pending:
+ line, pending = pending.split(b"\n", 1)
+ decoded = line.decode(errors="replace")
+ if any(marker in decoded for marker in PROGRESS):
+ print(f"{label}: {decoded.strip()}", flush=True)
+ if pending and any(marker in pending.decode(errors="replace") for marker in PROGRESS):
+ print(f"{label}: {pending.decode(errors='replace').strip()}", flush=True)
+ return process.wait(timeout=3), b"".join(chunks).decode(errors="replace")
+ finally:
+ selector.close()
+ process.stdout.close()
diff --git a/proof/quint/test_lifecycle_replay.py b/proof/quint/test_lifecycle_replay.py
new file mode 100644
index 0000000..49e2ccd
--- /dev/null
+++ b/proof/quint/test_lifecycle_replay.py
@@ -0,0 +1,79 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+"""Fail-closed controls for the finite lifecycle graph admission gate."""
+from pathlib import Path
+import tempfile
+import unittest
+from unittest.mock import patch
+
+import check_lifecycle_replay as checker
+
+
+class LifecycleReplayTests(unittest.TestCase):
+ def graph(self, suffix='', omitted=None):
+ values = {field: False if field.endswith('Safe') or field in
+ ('adapterInstalled', 'reportedSuccess', 'effectStarted') else 0
+ for field in checker.FIELDS if field != omitted}
+ label = ', '.join(f'{key} |-> {str(value).upper() if isinstance(value, bool) else value}'
+ for key, value in values.items())
+ return f'"1" [label="q = [{label}]", style = filled];\n"1" -> "1" [label="Terminal"];\n' + suffix
+
+ def read(self, source, expected=1):
+ with tempfile.TemporaryDirectory() as directory:
+ path = Path(directory) / 'graph.dot'
+ path.write_text(source)
+ return checker.read_graph(path, expected)
+
+ def test_complete_schema(self):
+ nodes, edges, initial = self.read(self.graph())
+ self.assertEqual(set(nodes[initial]), set(checker.FIELDS))
+ self.assertEqual(edges, [('1', '1', 'Terminal')])
+
+ def test_missing_field_is_not_partial_correspondence(self):
+ with self.assertRaisesRegex(ValueError, 'schema'):
+ self.read(self.graph(omitted='deliveryCalls'))
+
+ def test_missing_node_fails(self):
+ with self.assertRaisesRegex(ValueError, 'missing state'):
+ self.read(self.graph('"1" -> "2" [label="Verify"];'))
+
+ def test_unknown_action_is_not_scheme_code(self):
+ with self.assertRaisesRegex(ValueError, 'unknown TLC action'):
+ self.read(self.graph('"1" -> "1" [label="Unexpected"];'))
+
+ def test_incomplete_tlc_count_fails(self):
+ with self.assertRaisesRegex(ValueError, 'incomplete graph'):
+ self.read(self.graph(), expected=2)
+
+ def test_unreachable_state_fails(self):
+ with patch.object(checker, 'ACTIONS', ('Terminal',)):
+ with self.assertRaisesRegex(ValueError, 'unreachable'):
+ checker.covering_traces({'1': {'clock': 0}, '2': {'clock': 1}},
+ [('1', '1', 'Terminal')], '1')
+
+ def test_covering_paths_cover_all_states_and_self_loop_action(self):
+ with patch.object(checker, 'ACTIONS', ('Verify', 'Terminal')):
+ traces = checker.covering_traces({'1': {'clock': 0}, '2': {'clock': 1}},
+ [('1', '2', 'Verify'), ('2', '2', 'Terminal')], '1')
+ self.assertEqual({state['clock'] for trace in traces for _, state in trace}, {0, 1})
+ self.assertEqual({action for trace in traces for action, _ in trace}, {'init', 'Verify', 'Terminal'})
+
+ def test_non_stuttering_cycle_fails_closed(self):
+ with self.assertRaisesRegex(ValueError, 'not a DAG'):
+ checker.covering_traces({'1': {'clock': 0}, '2': {'clock': 1}},
+ [('1', '2', 'Verify'), ('2', '1', 'Revoke')], '1')
+
+ def test_native_batches_preserve_every_trace_and_bound_actual_steps(self):
+ traces = [[('init', {})] * size for size in (80, 80, 21, 140, 20)]
+ packed = list(checker.batches(traces))
+ self.assertEqual([trace for batch in packed for trace in batch], traces)
+ self.assertTrue(all(sum(map(len, batch)) <= 160 for batch in packed))
+ self.assertEqual([sum(map(len, batch)) for batch in packed], [160, 21, 160])
+
+ def test_single_oversized_trace_is_not_split_or_given_a_larger_timeout(self):
+ with self.assertRaisesRegex(ValueError, 'one trace exceeds'):
+ list(checker.batches([[('init', {})] * 161]))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/proof/quint/tlc-config.json b/proof/quint/tlc-config.json
new file mode 100644
index 0000000..e55923a
--- /dev/null
+++ b/proof/quint/tlc-config.json
@@ -0,0 +1 @@
+{"workers":"1","maxHeap":"-Xmx512m"}
diff --git a/run-test.ss b/run-test.ss
index 59dca0a..571804a 100644
--- a/run-test.ss
+++ b/run-test.ss
@@ -3,7 +3,7 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import (only-in :poo-flow/lambda-aitia/testing-observer
+(import (only-in :agentic-ai-lab/lambda-aitia/testing-observer
run-observed-test))
(let (arguments (cddr (command-line)))
diff --git a/schemas/vocabulary-manifest.json b/schemas/vocabulary-manifest.json
index 0a244ad..b0bc9dd 100644
--- a/schemas/vocabulary-manifest.json
+++ b/schemas/vocabulary-manifest.json
@@ -1,6 +1,6 @@
{
"manifestSchema": "lambda-aitia.vocabulary-manifest",
- "revision": 2,
+ "revision": 5,
"semanticOwner": "lambda-aitia",
"nodeKinds": [
"artifact",
@@ -33,7 +33,7 @@
"observation": ["subject", "source", "clock-role", "logical-position"],
"event": ["subject", "event-kind", "observation", "payload-digest", "modality", "commitment-state", "causal-parents"],
"action": ["subject", "action-kind", "requested-by", "scope"],
- "obligation": ["subject", "claim", "snapshot", "evidence-kind", "capability", "scope"],
+ "obligation": ["subject", "claim", "snapshot", "snapshot-revision", "snapshot-context-digest", "evidence-kind", "capability", "scope"],
"evidence": ["producer", "tool", "tool-version", "input-artifacts", "obligation", "subject", "scope", "valid-from", "valid-until", "admission-state"],
"counterexample": ["subject", "challenges", "evidence", "details-digest"],
"finding": ["subject", "challenges", "evidence", "finding-kind"],
@@ -56,7 +56,7 @@
},
"relationPlanes": {
"provenance": ["derived-from", "generated-by", "cites", "used"],
- "structural": ["depends-on", "implements", "tests", "refines"],
+ "structural": ["depends-on", "composes", "implements", "tests", "refines"],
"causal": ["precedes", "causal-parent", "enables", "prevents"],
"assurance": ["supports", "discharges", "defeats", "invalidates"],
"authority": ["authorizes", "denies", "requires-review"]
@@ -66,6 +66,11 @@
"lambda-aitia.assurance-snapshot",
"lambda-aitia.invalidation-receipt",
"lambda-aitia.planning-result",
+ "lambda-aitia.replacement-requirements",
+ "lambda-aitia.replacement-declaration",
+ "lambda-aitia.verifier-choices",
+ "lambda-aitia.evidence-admission",
+ "lambda-aitia.composition-requirements",
"lambda-aitia.native-descriptor",
"lambda-aitia.native-error"
]
diff --git a/scripts/tests/test_build_native_library.py b/scripts/tests/test_build_native_library.py
index f3b0fe0..7a067d0 100644
--- a/scripts/tests/test_build_native_library.py
+++ b/scripts/tests/test_build_native_library.py
@@ -28,6 +28,25 @@ def build_module():
class NativeLinkPolicyTest(unittest.TestCase):
+ def test_orgize_header_search_path_names_the_include_directory(self) -> None:
+ module = build_module()
+ with tempfile.TemporaryDirectory() as directory:
+ header_root = (
+ Path(directory)
+ / "pkg/github.com/tao3k/orgize/bindings/c/include"
+ )
+ header_root.mkdir(parents=True)
+ (header_root / "orgize.h").touch()
+ with patch.dict(
+ os.environ,
+ {"GERBIL_PATH": directory, "C_INCLUDE_PATH": "/caller/include"},
+ ):
+ module.configure_orgize_header()
+ self.assertEqual(
+ os.environ["C_INCLUDE_PATH"],
+ f"{header_root.resolve()}:/caller/include",
+ )
+
def test_gambit_compiler_uses_the_gerbil_release_not_path(self) -> None:
module = build_module()
with tempfile.TemporaryDirectory() as directory:
diff --git a/scripts/tests/test_quint_replay.py b/scripts/tests/test_quint_replay.py
new file mode 100644
index 0000000..bf13b03
--- /dev/null
+++ b/scripts/tests/test_quint_replay.py
@@ -0,0 +1,74 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+"""The correspondence runner must fail closed on schema and checker failures."""
+
+import importlib.util
+from pathlib import Path
+import sys
+import tempfile
+import unittest
+from unittest.mock import patch
+
+ROOT = Path(__file__).resolve().parents[2] / "proof/quint"
+sys.path.insert(0, str(ROOT))
+SPEC = importlib.util.spec_from_file_location("quint_replay", ROOT / "check_scheme_replay.py")
+replay = importlib.util.module_from_spec(SPEC)
+SPEC.loader.exec_module(replay)
+
+
+def initial():
+ return {"mbt::actionTaken": "init", "q": {
+ "work": {"active": True, "queued": True, "cancelRequested": False},
+ "known": False, "reviewed": False, "retired": False, "lateFound": False,
+ "gapFound": False, "ingressOpen": True, "epoch": {"#bigint": "0"},
+ "grantEpoch": {"#bigint": "0"}, "pending": False, "attempted": False,
+ "rejectedAfterRetirement": False, "startedAfterRetirement": False}}
+
+
+class QuintReplayTest(unittest.TestCase):
+ def test_all_projected_slots_and_itf_integer_are_data(self):
+ row = replay.state_row(initial())
+ self.assertIn("(authority-epoch 0)", row)
+ self.assertIn("(cancellation-requested? #f)", row)
+ self.assertEqual(row.count("?") + row.count("-epoch"), len(replay.FIELDS))
+
+ def test_added_model_field_cannot_be_silently_ignored(self):
+ state = initial()
+ state["q"]["newAuthority"] = True
+ with self.assertRaisesRegex(ValueError, "schema changed"):
+ replay.state_row(state)
+
+ def test_missing_work_field_cannot_be_silently_ignored(self):
+ state = initial()
+ del state["q"]["work"]["queued"]
+ with self.assertRaisesRegex(ValueError, "schema changed"):
+ replay.state_row(state)
+
+ def test_action_text_cannot_be_executed(self):
+ state = initial()
+ state["mbt::actionTaken"] = "init) (error injected) ("
+ with self.assertRaisesRegex(ValueError, "unknown Quint action"):
+ replay.state_row(state)
+
+ def test_non_scalar_itf_value_is_rejected(self):
+ with self.assertRaises(ValueError):
+ replay.scalar({"#set": []})
+
+ def test_tool_failure_is_not_a_negative_control(self):
+ with tempfile.TemporaryDirectory() as directory, patch.object(replay, "run", return_value=(2, "Invariant violated")):
+ with self.assertRaisesRegex(RuntimeError, "unexpected Quint result"):
+ replay.generate("quint", Path(directory), "fault", "unfencedStep", "RetiredIsFenced", 1)
+
+ def test_success_without_completed_output_is_rejected(self):
+ with tempfile.TemporaryDirectory() as directory, patch.object(replay, "run", return_value=(0, "[ok] No violation found")):
+ with self.assertRaisesRegex(RuntimeError, "incomplete trace output"):
+ replay.generate("quint", Path(directory), "safe", "step", "TypeOK", 1)
+
+ def test_success_exit_without_success_marker_is_rejected(self):
+ with tempfile.TemporaryDirectory() as directory, patch.object(replay, "run", return_value=(0, "tool error")):
+ with self.assertRaisesRegex(RuntimeError, "unexpected Quint result"):
+ replay.generate("quint", Path(directory), "safe", "step", "TypeOK", 1)
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/t/ADR/build-root.ss b/t/ADR/build-root.ss
index 71038a7..b81fd60 100644
--- a/t/ADR/build-root.ss
+++ b/t/ADR/build-root.ss
@@ -3,6 +3,6 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/ADR/interface)
+(import :agentic-ai-lab/lambda-aitia/modules/ADR/interface)
(export ADR-test-fixtures-loaded?)
(def ADR-test-fixtures-loaded? #t)
diff --git a/t/ADR/unit/ADR-module-test.ss b/t/ADR/unit/ADR-module-test.ss
index 272da63..8b7a142 100644
--- a/t/ADR/unit/ADR-module-test.ss
+++ b/t/ADR/unit/ADR-module-test.ss
@@ -6,10 +6,10 @@
(import :std/test
(only-in :std/error Error?)
(only-in :clan/poo/object .ref)
- :poo-flow/src/module-system/declaration/interface
- (only-in :poo-flow/lambda-aitia/modules/assurance/interface
+ :yuanxu/module-system/selection/objects
+ (only-in :agentic-ai-lab/lambda-aitia/modules/assurance/interface
assurance-decision?)
- :poo-flow/lambda-aitia/modules/ADR/interface)
+ :agentic-ai-lab/lambda-aitia/modules/ADR/interface)
(export ADR-module-test)
@@ -34,7 +34,7 @@
'("Machine-readable lifecycle" "Explicit rationale")
(list chosen rejected) consequences
'("Unit tests validate transition and projection rules.")
- '("tao3k maintainers") '("POO Flow maintainers") '("Aitia consumers")
+ '("tao3k maintainers") '("Agentic AI Lab maintainers") '("Aitia consumers")
(list (ADR-link 'refines-rfc "RFC-0001"))))
(def ADR-module-test
@@ -46,7 +46,7 @@
(check-equal? (.ref ADRProfile 'module-family) 'ADR))
(test-case "only the public ADR selection resolves"
(check-equal?
- (ADR-config (poo-flow-user-module-selection 'custom 'ADR '()))
+ (ADR-config (agentic-ai-lab-user-module-selection 'custom 'ADR '()))
ADR-module))
(test-case "standard record retains drivers, options and consequences"
diff --git a/t/assurance/build-root.ss b/t/assurance/build-root.ss
index 8d97762..4c71399 100644
--- a/t/assurance/build-root.ss
+++ b/t/assurance/build-root.ss
@@ -3,6 +3,6 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/assurance/interface)
+(import :agentic-ai-lab/lambda-aitia/modules/assurance/interface)
(export assurance-test-fixtures-loaded?)
(def assurance-test-fixtures-loaded? #t)
diff --git a/t/assurance/unit/assurance-kernel-test.ss b/t/assurance/unit/assurance-kernel-test.ss
index 38f2ea4..fa48d21 100644
--- a/t/assurance/unit/assurance-kernel-test.ss
+++ b/t/assurance/unit/assurance-kernel-test.ss
@@ -5,8 +5,11 @@
(import :std/test
(only-in :std/error Error?)
+ (only-in :std/list/list find)
(only-in :clan/poo/object .o .ref)
- :poo-flow/lambda-aitia/modules/assurance/interface)
+ (only-in :agentic-ai-lab/core/contribution/verification
+ agentic-ai-lab-verification-adapter agentic-ai-lab-verify)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/interface)
(export assurance-kernel-test)
@@ -64,17 +67,102 @@
(assurance-relation "relation/reverse-dependency" 'structural 'implements
"artifact/source" "claim/release" 'declared))
-(def (software-snapshot nodes relations (unresolved '()))
- (assurance-snapshot
- "snapshot/software" "r1" "graph/software"
- '(("artifact/source" . "r1")) '(("claim/release" . "r1"))
- "event-cut/1" "policy/release" "r1" nodes relations
- evidence-identities: '("evidence/test") unresolved: unresolved))
+(def (verification-obligation id capability)
+ (assurance-obligation
+ id "r1" 'unknown digest-a
+ subject: "software/release" claim: "claim/release"
+ snapshot: "snapshot/software" evidence-kind: 'native-test
+ capability: capability scope: "repository"))
+(def (verification-support id)
+ (assurance-relation
+ (string-append "relation/support/" id) 'assurance 'supports
+ id "claim/release" 'declared))
+(def (verification-dependency source target)
+ (assurance-relation
+ (string-append "relation/depends/" source "/" target)
+ 'structural 'depends-on source target 'declared))
+(def (verification-snapshot obligations relations)
+ (software-snapshot
+ (append (list artifact claim evidence) obligations)
+ (append (list dependency) relations)))
+
+(def (software-snapshot nodes relations (unresolved '()) (revision "r1"))
+ (def (construct values)
+ (assurance-snapshot
+ "snapshot/software" revision "graph/software"
+ '(("artifact/source" . "r1")) '(("claim/release" . "r1"))
+ "event-cut/1" "policy/release" "r1" values relations
+ evidence-identities: '("evidence/test") unresolved: unresolved))
+ (let* ((candidate (construct nodes))
+ (bound-nodes
+ (map (lambda (node)
+ (if (and (assurance-obligation? node)
+ (string=? (.ref node 'snapshot)
+ (.ref candidate 'identity))
+ (not (.ref node 'snapshot-revision))
+ (not (.ref node 'snapshot-context-digest)))
+ (assurance-bind-obligation-to-snapshot node candidate)
+ node))
+ nodes)))
+ (construct bound-nodes)))
(def full-software-snapshot
(software-snapshot
(list artifact claim obligation evidence decision effect)
(list dependency discharge obligation-support
decision-dependency authorization)))
+(def current-obligation
+ (find (lambda (node)
+ (and (assurance-obligation? node)
+ (equal? (.ref node 'identity) "obligation/verify")))
+ (.ref full-software-snapshot 'nodes)))
+(def support-outcome
+ (assurance-verifier-outcome
+ "outcome/kernel" 'succeeded
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ obligation: "obligation/verify" subject: "software/release"
+ scope: "repository"
+ snapshot-revision: (.ref full-software-snapshot 'revision)
+ snapshot-context-digest: (.ref full-software-snapshot 'context-digest)
+ inputs: (list (assurance-verifier-input artifact))
+ output-digest: digest-b))
+(def support-adapter
+ (agentic-ai-lab-verification-adapter
+ "test/kernel-support" (lambda (subject-value now-value until-value) #t)
+ assurance-verification-subject-snapshot))
+(def support-receipt
+ (agentic-ai-lab-verify
+ support-adapter
+ (assurance-verification-subject
+ full-software-snapshot current-obligation evidence support-outcome)
+ 10 20))
+(def (kernel-support? relation-value evidence-value)
+ (assurance-support-sealed-under-adapter?
+ relation-value evidence-value current-obligation full-software-snapshot
+ support-outcome support-adapter support-receipt 11))
+
+(def replacement-claim
+ (assurance-claim
+ "claim/release" "r2" 'unknown digest-b
+ subject: "software/release" predicate: "release-ready-v2"
+ assumptions: '("assumption/toolchain")
+ support-requirements: '("obligation/verify-next")
+ scope: "repository" valid-from: "2026-09-17"))
+(def replacement-candidate
+ (assurance-obligation
+ "obligation/verify-next" "r2" 'unknown digest-a
+ subject: "software/release" claim: "claim/release"
+ snapshot: "snapshot/software" evidence-kind: 'native-test
+ capability: 'gerbil-test scope: "repository"))
+(def replacement-support
+ (assurance-relation
+ "relation/replacement-support" 'assurance 'supports
+ "obligation/verify-next" "claim/release" 'declared))
+(def (replacement-draft nodes relations)
+ (assurance-snapshot
+ "snapshot/software" "r2" "graph/software"
+ '(("artifact/source" . "r1")) '(("claim/release" . "r2"))
+ "event-cut/1" "policy/release" "r1"
+ nodes relations))
(def assurance-kernel-test
(test-suite "Aitia POO-native assurance kernel"
@@ -102,6 +190,12 @@
(test-case "relation kinds cannot cross their owned plane"
(check-equal? (assurance-relation? dependency) #t)
+ (check-equal?
+ (assurance-relation?
+ (assurance-relation
+ "relation/composes" 'structural 'composes
+ "claim/composite" "claim/component-a" 'declared))
+ #t)
(check-exception
(assurance-relation "bad" 'causal 'depends-on
"claim/release" "artifact/source" 'declared)
@@ -235,35 +329,35 @@
(test-case "alternate evidence and temporal order grant no support"
(check-equal?
- (assurance-support-admissible? discharge evidence obligation) #t)
+ (kernel-support? discharge evidence) #t)
(check-equal?
- (assurance-support-admissible?
- discharge (.o (:: @ evidence) state: 'hypothesized) obligation)
+ (kernel-support?
+ discharge (.o (:: @ evidence) state: 'hypothesized))
#f)
(check-equal?
- (assurance-support-admissible?
+ (kernel-support?
(.o (:: @ discharge) modality: 'counterfactual)
- evidence obligation)
+ evidence)
#f)
(check-equal?
- (assurance-support-admissible?
+ (kernel-support?
(assurance-relation "relation/precedes" 'causal 'precedes
"evidence/test" "obligation/verify" 'observed)
- evidence obligation)
+ evidence)
#f))
(test-case "candidate or mismatched evidence cannot discharge an obligation"
(check-equal?
- (assurance-support-admissible?
- discharge (.o (:: @ evidence) admission-state: 'candidate) obligation)
+ (kernel-support?
+ discharge (.o (:: @ evidence) admission-state: 'candidate))
#f)
(check-equal?
- (assurance-support-admissible?
- discharge (.o (:: @ evidence) obligation: "obligation/other") obligation)
+ (kernel-support?
+ discharge (.o (:: @ evidence) obligation: "obligation/other"))
#f)
(check-equal?
- (assurance-support-admissible?
- discharge (.o (:: @ evidence) revision: "r2") obligation)
+ (kernel-support?
+ discharge (.o (:: @ evidence) revision: "r2"))
#f))
(test-case "change invalidation is deterministic and never grants authority"
@@ -359,6 +453,811 @@
(cons "artifact/source"
(assurance-invalidation-receipt-ref claim-change 'impacted)))))
+ (test-case "verification selection is pure and permutation-stable"
+ (let* ((policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(lean gerbil-test gerbil-test)))
+ (permuted-policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test lean)))
+ (permuted
+ (software-snapshot
+ (list effect decision evidence obligation claim artifact)
+ (list authorization decision-dependency obligation-support
+ discharge dependency)))
+ (left
+ (assurance-plan-verification
+ "plan/release" full-software-snapshot
+ '("artifact/source") policy))
+ (right
+ (assurance-plan-verification
+ "plan/release" permuted
+ '("artifact/source") permuted-policy)))
+ (check-equal? (assurance-verification-policy? policy) #t)
+ (check-equal? (.ref policy 'capabilities) '(gerbil-test lean))
+ (check-equal? (assurance-verification-plan? left) #t)
+ (check-equal? (.ref left 'schema) "lambda-aitia.planning-result")
+ (check-equal?
+ (.ref obligation 'snapshot-context-digest) #f)
+ (check-equal?
+ (.ref (car (filter assurance-obligation?
+ (.ref full-software-snapshot 'nodes)))
+ 'snapshot-context-digest)
+ (.ref full-software-snapshot 'context-digest))
+ (check-equal? (.ref left 'selected-obligations)
+ '("obligation/verify"))
+ (check-equal? (.ref left 'blocked-obligations) '())
+ (check-equal?
+ (assurance-verification-request? (car (.ref left 'requests))) #t)
+ (check-equal? (.ref (car (.ref left 'requests)) 'capability)
+ 'gerbil-test)
+ (check-equal? (.ref (car (.ref left 'requests)) 'selected?) #t)
+ (check-equal? (.ref left 'digest) (.ref right 'digest))
+ (check-equal? (.ref left 'verifier-executed?) #f)
+ (check-equal? (.ref left 'release-authorized?) #f)
+ (check-equal? (.ref left 'runtime-executed?) #f)
+ (check-equal? (.ref left 'blocked-effects) '("effect/deploy"))
+ (check-equal? (car (.ref left 'witnesses))
+ '("artifact/source" ("artifact/source") ()))
+ (check-equal?
+ (assurance-verification-request?
+ (.o (:: @ (car (.ref left 'requests)))
+ blocker: 'capability-unavailable))
+ #f)
+ (check-equal?
+ (assurance-verification-plan?
+ (.o (:: @ left) release-authorized?: #t))
+ #f)))
+
+ (test-case "replacement requirements never silently rebind an old obligation"
+ (let* ((target
+ (software-snapshot
+ (list artifact claim evidence) (list dependency) '() "r2"))
+ (permuted-source
+ (software-snapshot
+ (list effect decision evidence obligation claim artifact)
+ (list authorization decision-dependency obligation-support
+ discharge dependency)))
+ (left
+ (assurance-derive-replacement-requirements
+ "replacement/source" full-software-snapshot target
+ '("artifact/source")))
+ (right
+ (assurance-derive-replacement-requirements
+ "replacement/source" permuted-source target
+ '("artifact/source")))
+ (requirement (car (.ref left 'requirements)))
+ (unchanged
+ (assurance-derive-replacement-requirements
+ "replacement/unchanged" full-software-snapshot
+ full-software-snapshot '("artifact/source")))
+ (unknown-change
+ (assurance-derive-replacement-requirements
+ "replacement/unknown-change" full-software-snapshot
+ target '("artifact/source" "artifact/unknown")))
+ (unknown-only
+ (assurance-derive-replacement-requirements
+ "replacement/unknown-only" full-software-snapshot
+ target '("artifact/unknown")))
+ (stale-source
+ (software-snapshot
+ (list artifact claim evidence decision effect
+ (assurance-obligation
+ "obligation/verify" "r1" 'unknown digest-a
+ subject: "software/release" claim: "claim/release"
+ snapshot: "snapshot/software" evidence-kind: 'native-test
+ capability: 'gerbil-test scope: "repository"
+ snapshot-revision: "r0"
+ snapshot-context-digest: digest-a))
+ (list dependency discharge obligation-support
+ decision-dependency authorization)))
+ (stale
+ (assurance-derive-replacement-requirements
+ "replacement/stale-source" stale-source target
+ '("artifact/source"))))
+ (check-equal? (assurance-replacement-derivation? left) #t)
+ (check-equal? (.ref left 'digest) (.ref right 'digest))
+ (check-equal? (length (.ref left 'requirements)) 1)
+ (check-equal? (assurance-replacement-requirement? requirement) #t)
+ (check-equal? (.ref requirement 'source-obligation)
+ "obligation/verify")
+ (check-equal? (.ref requirement 'evidence-kind) 'native-test)
+ (check-equal? (.ref requirement 'blocker) #f)
+ (check-equal? (car (.ref left 'witnesses))
+ '("artifact/source" ("artifact/source") ()))
+ (check-equal? (.ref (car (.ref unchanged 'requirements)) 'blocker)
+ 'target-unchanged)
+ (check-equal?
+ (.ref (car (.ref unknown-change 'requirements)) 'blocker)
+ 'change-unresolved)
+ (check-equal? (.ref unknown-only 'requirements) '())
+ (check-equal? (.ref unknown-only 'unresolved)
+ '("artifact/unknown"))
+ (check-equal? (.ref (car (.ref stale 'requirements)) 'blocker)
+ 'stale-source)
+ (check-equal? (.ref left 'verifier-executed?) #f)
+ (check-equal? (.ref left 'release-authorized?) #f)
+ (check-equal?
+ (filter assurance-obligation? (.ref target 'nodes)) '())))
+
+ (test-case "revised claims and unknown targets block automatic replacement"
+ (let* ((revised-claim
+ (assurance-claim
+ "claim/release" "r2" 'unknown digest-a
+ subject: "software/release" predicate: "release-ready-v2"
+ assumptions: '("assumption/toolchain")
+ support-requirements: '("obligation/verify")
+ scope: "repository" valid-from: "2026-09-17"))
+ (changed-claim-target
+ (assurance-snapshot
+ "snapshot/software" "r2" "graph/software"
+ '(("artifact/source" . "r1")) '(("claim/release" . "r2"))
+ "event-cut/1" "policy/release" "r1"
+ (list artifact revised-claim)
+ (list dependency)))
+ (unknown-target
+ (software-snapshot
+ (list artifact claim evidence) (list dependency)
+ '("artifact/unresolved") "r2"))
+ (foreign-target
+ (assurance-snapshot
+ "snapshot/other" "r2" "graph/software"
+ '(("artifact/source" . "r1")) '(("claim/release" . "r1"))
+ "event-cut/1" "policy/release" "r1"
+ (list artifact claim) (list dependency)))
+ (changed-claim
+ (assurance-derive-replacement-requirements
+ "replacement/changed-claim" full-software-snapshot
+ changed-claim-target '("artifact/source")))
+ (unknown
+ (assurance-derive-replacement-requirements
+ "replacement/unknown" full-software-snapshot
+ unknown-target '("artifact/source")))
+ (foreign
+ (assurance-derive-replacement-requirements
+ "replacement/foreign" full-software-snapshot
+ foreign-target '("artifact/source"))))
+ (check-equal?
+ (.ref (car (.ref changed-claim 'requirements)) 'blocker)
+ 'claim-changed)
+ (check-equal?
+ (.ref (car (.ref unknown 'requirements)) 'blocker)
+ 'target-unresolved)
+ (check-equal?
+ (.ref (car (.ref foreign 'requirements)) 'blocker)
+ 'target-identity-changed)))
+
+ (test-case "an explicit fresh replacement binds without promoting old evidence"
+ (let* ((draft
+ (replacement-draft
+ (list artifact replacement-claim replacement-candidate)
+ (list dependency replacement-support)))
+ (permuted-draft
+ (replacement-draft
+ (list replacement-candidate artifact replacement-claim)
+ (list replacement-support dependency)))
+ (derivation
+ (assurance-derive-replacement-requirements
+ "replacement/explicit" full-software-snapshot draft
+ '("artifact/source")))
+ (permuted-derivation
+ (assurance-derive-replacement-requirements
+ "replacement/explicit" full-software-snapshot permuted-draft
+ '("artifact/source"))))
+ (check-equal? (.ref (car (.ref derivation 'requirements)) 'blocker)
+ 'claim-changed)
+ (let-values (((final receipt)
+ (assurance-declare-replacement-obligation
+ "replacement/declaration" full-software-snapshot
+ draft derivation "obligation/verify"
+ "obligation/verify-next"))
+ ((permuted-final permuted-receipt)
+ (assurance-declare-replacement-obligation
+ "replacement/declaration" full-software-snapshot
+ permuted-draft permuted-derivation
+ "obligation/verify" "obligation/verify-next")))
+ (let ((bound
+ (find (lambda (node)
+ (equal? (.ref node 'identity)
+ "obligation/verify-next"))
+ (.ref final 'nodes))))
+ (check-equal? (assurance-replacement-declaration-receipt? receipt)
+ #t)
+ (check-equal? (.ref receipt 'blocker) #f)
+ (check-equal? (.ref bound 'snapshot-revision) "r2")
+ (check-equal? (.ref bound 'snapshot-context-digest)
+ (.ref final 'context-digest))
+ (check-equal? (.ref replacement-candidate 'snapshot-revision) #f)
+ (check-equal? (.ref receipt 'final-snapshot-digest)
+ (.ref final 'digest))
+ (check-equal? (.ref receipt 'verifier-executed?) #f)
+ (check-equal? (.ref receipt 'release-authorized?) #f)
+ (check-equal? (.ref final 'digest) (.ref permuted-final 'digest))
+ (check-equal? (.ref receipt 'digest)
+ (.ref permuted-receipt 'digest))
+ (check-equal?
+ (assurance-replacement-declaration-receipt?
+ (.o (:: @ receipt) release-authorized?: #t))
+ #f)))))
+
+ (test-case "replacement declaration rejects missing and hypothetical links"
+ (let* ((draft
+ (replacement-draft
+ (list artifact replacement-claim replacement-candidate)
+ (list dependency replacement-support)))
+ (derivation
+ (assurance-derive-replacement-requirements
+ "replacement/negative" full-software-snapshot draft
+ '("artifact/source")))
+ (missing-link
+ (replacement-draft
+ (list artifact replacement-claim replacement-candidate)
+ (list dependency)))
+ (hypothetical-link
+ (replacement-draft
+ (list artifact replacement-claim replacement-candidate)
+ (list dependency
+ (.o (:: @ replacement-support)
+ modality: 'hypothesized))))
+ (foreign-claim
+ (replacement-draft
+ (list artifact replacement-claim
+ (.o (:: @ replacement-candidate)
+ claim: "claim/foreign"))
+ (list dependency replacement-support)))
+ (forged-draft (.o (:: @ draft) digest: digest-a)))
+ (let-values (((missing-final missing-receipt)
+ (assurance-declare-replacement-obligation
+ "replacement/missing" full-software-snapshot
+ missing-link
+ (assurance-derive-replacement-requirements
+ "replacement/missing-derivation"
+ full-software-snapshot missing-link
+ '("artifact/source"))
+ "obligation/verify" "obligation/verify-next"))
+ ((hypothetical-final hypothetical-receipt)
+ (assurance-declare-replacement-obligation
+ "replacement/hypothetical" full-software-snapshot
+ hypothetical-link
+ (assurance-derive-replacement-requirements
+ "replacement/hypothetical-derivation"
+ full-software-snapshot hypothetical-link
+ '("artifact/source"))
+ "obligation/verify" "obligation/verify-next"))
+ ((stale-final stale-receipt)
+ (assurance-declare-replacement-obligation
+ "replacement/stale" full-software-snapshot
+ hypothetical-link derivation
+ "obligation/verify" "obligation/verify-next"))
+ ((foreign-final foreign-receipt)
+ (assurance-declare-replacement-obligation
+ "replacement/foreign-claim" full-software-snapshot
+ foreign-claim
+ (assurance-derive-replacement-requirements
+ "replacement/foreign-claim-derivation"
+ full-software-snapshot foreign-claim
+ '("artifact/source"))
+ "obligation/verify" "obligation/verify-next"))
+ ((forged-final forged-receipt)
+ (assurance-declare-replacement-obligation
+ "replacement/forged" full-software-snapshot
+ forged-draft
+ (assurance-derive-replacement-requirements
+ "replacement/forged-derivation"
+ full-software-snapshot forged-draft
+ '("artifact/source"))
+ "obligation/verify" "obligation/verify-next")))
+ (check-equal? missing-final #f)
+ (check-equal? (.ref missing-receipt 'blocker) 'support-link-missing)
+ (check-equal? hypothetical-final #f)
+ (check-equal? (.ref hypothetical-receipt 'blocker)
+ 'support-link-hypothetical)
+ (check-equal? stale-final #f)
+ (check-equal? (.ref stale-receipt 'blocker)
+ 'derivation-mismatch)
+ (check-equal? foreign-final #f)
+ (check-equal? (.ref foreign-receipt 'blocker)
+ 'candidate-claim-mismatch)
+ (check-equal? forged-final #f)
+ (check-equal? (.ref forged-receipt 'blocker)
+ 'derivation-mismatch))))
+
+ (test-case "verification obligations have a closed evidence-kind vocabulary"
+ (check-equal?
+ +assurance-evidence-kinds+
+ '(proof model-check replay unit-test integration-test native-test
+ static-analysis authorization-differential human-review))
+ (for-each
+ (lambda (kind)
+ (check-equal?
+ (assurance-obligation?
+ (assurance-obligation
+ "obligation/kind" "r1" 'unknown digest-a
+ subject: "software/release" claim: "claim/release"
+ snapshot: "snapshot/software" evidence-kind: kind
+ capability: 'verifier scope: "repository"))
+ #t))
+ +assurance-evidence-kinds+)
+ (check-exception
+ (assurance-obligation
+ "obligation/invalid-kind" "r1" 'unknown digest-a
+ subject: "software/release" claim: "claim/release"
+ snapshot: "snapshot/software" evidence-kind: 'arbitrary-pass
+ capability: 'verifier scope: "repository")
+ Error?))
+
+ (test-case "verifier choices explain matching and rejected declarations"
+ (let* ((policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test)))
+ (plan
+ (assurance-plan-verification
+ "plan/verifier-choice" full-software-snapshot
+ '("artifact/source") policy))
+ (kind-mismatch
+ (assurance-verifier-candidate
+ "candidate/a" "r1" 0 '(proof) 'gerbil-test))
+ (capability-mismatch
+ (assurance-verifier-candidate
+ "candidate/b" "r1" 1 '(native-test) 'lean))
+ (chosen
+ (assurance-verifier-candidate
+ "candidate/z" "r1" 2 '(native-test unit-test) 'gerbil-test))
+ (alternative
+ (assurance-verifier-candidate
+ "candidate/c" "r1" 3 '(native-test) 'gerbil-test))
+ (catalog
+ (list alternative kind-mismatch chosen capability-mismatch))
+ (left
+ (assurance-explain-verifier-choices
+ "choices/release" plan catalog))
+ (right
+ (assurance-explain-verifier-choices
+ "choices/release" plan (reverse catalog)))
+ (revised
+ (assurance-explain-verifier-choices
+ "choices/release" plan
+ (list alternative kind-mismatch capability-mismatch
+ (assurance-verifier-candidate
+ "candidate/z" "r2" 2 '(native-test unit-test)
+ 'gerbil-test))))
+ (missing
+ (assurance-explain-verifier-choices
+ "choices/missing" plan (list kind-mismatch)))
+ (blocked-plan
+ (assurance-plan-verification
+ "plan/no-verifier" full-software-snapshot
+ '("artifact/source")
+ (assurance-verification-policy
+ "policy/release" "r1" '())))
+ (blocked
+ (assurance-explain-verifier-choices
+ "choices/blocked" blocked-plan (list chosen))))
+ (check-equal? (assurance-verifier-choice-receipt? left) #t)
+ (check-equal? (map (lambda (candidate) (.ref candidate 'identity))
+ (.ref left 'candidates))
+ '("candidate/a" "candidate/b" "candidate/z"
+ "candidate/c"))
+ (check-equal? (.ref left 'digest) (.ref right 'digest))
+ (check-equal? (equal? (.ref left 'digest) (.ref revised 'digest))
+ #f)
+ (check-equal? (map (lambda (choice) (.ref choice 'reason))
+ (.ref left 'choices))
+ '(evidence-kind-unsupported capability-mismatch
+ chosen lower-priority))
+ (check-equal? (map (lambda (choice) (.ref choice 'selected?))
+ (.ref left 'choices))
+ '(#f #f #t #f))
+ (check-equal? (.ref left 'unassigned-obligations) '())
+ (check-equal? (.ref missing 'unassigned-obligations)
+ '("obligation/verify"))
+ (check-equal? (.ref (car (.ref blocked 'choices)) 'reason)
+ 'request-blocked)
+ (check-equal? (.ref blocked 'unassigned-obligations) '())
+ (check-equal? (.ref left 'verifier-executed?) #f)
+ (check-equal? (.ref left 'release-authorized?) #f)
+ (check-exception
+ (assurance-explain-verifier-choices
+ "choices/duplicate" plan (list chosen chosen))
+ Error?)
+ (check-exception
+ (assurance-verifier-candidate
+ "candidate/unknown" "r1" 0 '(arbitrary-pass) 'gerbil-test)
+ Error?)))
+
+ (test-case "component support never supplies a composition obligation"
+ (let* ((component-a
+ (assurance-claim
+ "claim/component-a" "r1" 'supported digest-a
+ subject: "software/component-a" predicate: "ready"
+ scope: "repository" valid-from: "2026-09-17"))
+ (component-b
+ (assurance-claim
+ "claim/component-b" "r1" 'supported digest-a
+ subject: "software/component-b" predicate: "ready"
+ scope: "repository" valid-from: "2026-09-17"))
+ (composite
+ (assurance-claim
+ "claim/composite" "r1" 'unknown digest-b
+ subject: "software/composite" predicate: "composition-safe"
+ support-requirements: '("obligation/composition")
+ scope: "repository" valid-from: "2026-09-17"))
+ (candidate-obligation
+ (assurance-obligation
+ "obligation/composition" "r1" 'unknown digest-a
+ subject: "software/composite" claim: "claim/composite"
+ snapshot: "snapshot/composition"
+ evidence-kind: 'integration-test
+ capability: 'composition-test scope: "repository"))
+ (components
+ (list (assurance-relation
+ "relation/composes/a" 'structural 'composes
+ "claim/composite" "claim/component-a" 'declared)
+ (assurance-relation
+ "relation/composes/b" 'structural 'composes
+ "claim/composite" "claim/component-b" 'declared)))
+ (direct-support
+ (assurance-relation
+ "relation/support/composition" 'assurance 'supports
+ "obligation/composition" "claim/composite" 'declared)))
+ (def (construct nodes relations)
+ (assurance-snapshot
+ "snapshot/composition" "r1" "graph/composition"
+ '() '(("claim/component-a" . "r1")
+ ("claim/component-b" . "r1")
+ ("claim/composite" . "r1"))
+ "event-cut/1" "policy/composition" "r1"
+ nodes relations))
+ (let* ((missing-snapshot
+ (construct (list component-a component-b composite)
+ components))
+ (missing
+ (assurance-derive-composition-requirements
+ "composition/missing" missing-snapshot))
+ (permuted
+ (assurance-derive-composition-requirements
+ "composition/missing"
+ (construct (list composite component-b component-a)
+ (reverse components))))
+ (candidate
+ (construct
+ (list component-a component-b composite candidate-obligation)
+ (cons direct-support components)))
+ (stale-obligation
+ (assurance-obligation
+ "obligation/composition" "r1" 'unknown digest-a
+ subject: "software/composite" claim: "claim/composite"
+ snapshot: "snapshot/composition"
+ evidence-kind: 'integration-test
+ capability: 'composition-test scope: "repository"
+ snapshot-revision: "r0"
+ snapshot-context-digest: digest-a))
+ (stale
+ (assurance-derive-composition-requirements
+ "composition/stale"
+ (construct
+ (list component-a component-b composite stale-obligation)
+ (cons direct-support components))))
+ (bound-obligation
+ (assurance-bind-obligation-to-snapshot
+ candidate-obligation candidate))
+ (bound-snapshot
+ (construct
+ (list component-a component-b composite bound-obligation)
+ (cons direct-support components)))
+ (declared
+ (assurance-derive-composition-requirements
+ "composition/declared" bound-snapshot))
+ (changed
+ (assurance-invalidate
+ "composition/changed" bound-snapshot
+ '("claim/component-a"))))
+ (check-equal? (assurance-composition-derivation? missing) #t)
+ (check-equal? (.ref missing 'digest) (.ref permuted 'digest))
+ (check-equal?
+ (.ref (car (.ref missing 'requirements)) 'component-claims)
+ '("claim/component-a" "claim/component-b"))
+ (check-equal?
+ (.ref (car (.ref missing 'requirements)) 'blocker)
+ 'missing-direct-obligation)
+ (check-equal?
+ (.ref (car (.ref stale 'requirements)) 'direct-obligations)
+ '("obligation/composition"))
+ (check-equal?
+ (.ref (car (.ref stale 'requirements)) 'current-obligations) '())
+ (check-equal?
+ (.ref (car (.ref stale 'requirements)) 'blocker)
+ 'stale-direct-obligation)
+ (check-equal?
+ (.ref (car (.ref declared 'requirements)) 'direct-obligations)
+ '("obligation/composition"))
+ (check-equal?
+ (.ref (car (.ref declared 'requirements)) 'current-obligations)
+ '("obligation/composition"))
+ (check-equal?
+ (.ref (car (.ref declared 'requirements)) 'blocker) #f)
+ (check-equal? (.ref declared 'verifier-executed?) #f)
+ (check-equal? (.ref declared 'release-authorized?) #f)
+ (check-equal?
+ (assurance-invalidation-receipt-ref changed 'required-obligations)
+ '("obligation/composition")))))
+
+ (test-case "POO Graph orders affected prerequisites before dependents"
+ (let* ((a (verification-obligation "obligation/a" 'gerbil-test))
+ (b (verification-obligation "obligation/b" 'gerbil-test))
+ (c (verification-obligation "obligation/c" 'gerbil-test))
+ (relations
+ (list (verification-support "obligation/a")
+ (verification-support "obligation/b")
+ (verification-support "obligation/c")
+ (verification-dependency "obligation/a" "obligation/b")
+ (verification-dependency "obligation/b" "obligation/c")))
+ (policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test)))
+ (left
+ (assurance-plan-verification
+ "plan/ordered"
+ (verification-snapshot (list a b c) relations)
+ '("artifact/source") policy))
+ (right
+ (assurance-plan-verification
+ "plan/ordered"
+ (verification-snapshot (list c a b) (reverse relations))
+ '("artifact/source") policy)))
+ (check-equal? (.ref left 'selected-obligations)
+ '("obligation/c" "obligation/b" "obligation/a"))
+ (check-equal? (.ref left 'blocked-obligations) '())
+ (check-equal? (.ref left 'cycle-path) '())
+ (check-equal? (.ref left 'cyclic-components) '())
+ (check-equal? (.ref (car (.ref left 'requests)) 'dependencies) '())
+ (check-equal? (.ref (cadr (.ref left 'requests)) 'dependencies)
+ '("obligation/c"))
+ (check-equal? (.ref left 'digest) (.ref right 'digest))
+ (check-equal? (.ref left 'verifier-executed?) #f)))
+
+ (test-case "an unplanned prerequisite blocks its dependent"
+ (let* ((a (verification-obligation "obligation/a" 'gerbil-test))
+ (b (verification-obligation "obligation/b" 'gerbil-test))
+ (snapshot
+ (verification-snapshot
+ (list a b)
+ (list (verification-support "obligation/a")
+ (verification-dependency "obligation/a" "obligation/b"))))
+ (policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test)))
+ (plan
+ (assurance-plan-verification
+ "plan/unplanned" snapshot '("artifact/source") policy)))
+ (check-equal? (.ref plan 'selected-obligations) '())
+ (check-equal? (.ref plan 'blocked-obligations) '("obligation/a"))
+ (check-equal? (.ref (car (.ref plan 'requests)) 'dependencies)
+ '("obligation/b"))
+ (check-equal? (.ref (car (.ref plan 'requests)) 'blocker)
+ 'dependency-unplanned)))
+
+ (test-case "a blocked prerequisite propagates along POO Graph reachability"
+ (let* ((a (verification-obligation "obligation/a" 'gerbil-test))
+ (b (verification-obligation "obligation/b" 'lean))
+ (snapshot
+ (verification-snapshot
+ (list a b)
+ (list (verification-support "obligation/a")
+ (verification-support "obligation/b")
+ (verification-dependency "obligation/a" "obligation/b"))))
+ (policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test)))
+ (plan
+ (assurance-plan-verification
+ "plan/blocked-prerequisite" snapshot
+ '("artifact/source") policy)))
+ (check-equal? (.ref plan 'selected-obligations) '())
+ (check-equal? (.ref plan 'blocked-obligations)
+ '("obligation/b" "obligation/a"))
+ (check-equal? (.ref (car (.ref plan 'requests)) 'blocker)
+ 'capability-unavailable)
+ (check-equal? (.ref (cadr (.ref plan 'requests)) 'blocker)
+ 'dependency-blocked)))
+
+ (test-case "a dependency cycle blocks its SCC but preserves an independent branch"
+ (let* ((a (verification-obligation "obligation/a" 'gerbil-test))
+ (b (verification-obligation "obligation/b" 'gerbil-test))
+ (c (verification-obligation "obligation/c" 'gerbil-test))
+ (d (verification-obligation "obligation/d" 'gerbil-test))
+ (snapshot
+ (verification-snapshot
+ (list a b c d)
+ (list (verification-support "obligation/a")
+ (verification-support "obligation/b")
+ (verification-support "obligation/c")
+ (verification-support "obligation/d")
+ (verification-dependency "obligation/a" "obligation/b")
+ (verification-dependency "obligation/b" "obligation/a")
+ (verification-dependency "obligation/d" "obligation/a"))))
+ (policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test)))
+ (plan
+ (assurance-plan-verification
+ "plan/cycle" snapshot '("artifact/source") policy)))
+ (check-equal? (.ref plan 'selected-obligations) '("obligation/c"))
+ (check-equal? (.ref plan 'blocked-obligations)
+ '("obligation/a" "obligation/b" "obligation/d"))
+ (check-equal? (.ref plan 'cycle-path)
+ '("obligation/a" "obligation/b" "obligation/a"))
+ (check-equal? (.ref plan 'cyclic-components)
+ '(("obligation/a" "obligation/b")))
+ (check-equal? (map (lambda (request) (.ref request 'blocker))
+ (.ref plan 'requests))
+ '(#f dependency-cycle dependency-cycle
+ dependency-blocked))))
+
+ (test-case "every independent dependency cycle is explained"
+ (let* ((ids '("obligation/a" "obligation/b" "obligation/c"
+ "obligation/d" "obligation/e" "obligation/f"
+ "obligation/g"))
+ (nodes (map (lambda (id)
+ (verification-obligation id 'gerbil-test))
+ ids))
+ (relations
+ (append
+ (map verification-support ids)
+ (list (verification-dependency "obligation/a" "obligation/b")
+ (verification-dependency "obligation/b" "obligation/a")
+ (verification-dependency "obligation/d" "obligation/a")
+ (verification-dependency "obligation/e" "obligation/f")
+ (verification-dependency "obligation/f" "obligation/e")
+ (verification-dependency "obligation/g" "obligation/e"))))
+ (policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test)))
+ (left
+ (assurance-plan-verification
+ "plan/two-cycles"
+ (verification-snapshot nodes relations)
+ '("artifact/source") policy))
+ (right
+ (assurance-plan-verification
+ "plan/two-cycles"
+ (verification-snapshot (reverse nodes) (reverse relations))
+ '("artifact/source") policy)))
+ (check-equal? (.ref left 'selected-obligations) '("obligation/c"))
+ (check-equal? (.ref left 'blocked-obligations)
+ '("obligation/a" "obligation/b" "obligation/d"
+ "obligation/e" "obligation/f" "obligation/g"))
+ (check-equal? (.ref left 'cyclic-components)
+ '(("obligation/a" "obligation/b")
+ ("obligation/e" "obligation/f")))
+ (check-equal? (.ref left 'digest) (.ref right 'digest))
+ (check-equal? (.ref left 'cyclic-components)
+ (.ref right 'cyclic-components))))
+
+ (test-case "missing capability remains an explained blocked obligation"
+ (let* ((policy
+ (assurance-verification-policy "policy/release" "r1" '()))
+ (plan
+ (assurance-plan-verification
+ "plan/no-capability" full-software-snapshot
+ '("artifact/source") policy)))
+ (check-equal? (.ref plan 'selected-obligations) '())
+ (check-equal? (.ref plan 'blocked-obligations)
+ '("obligation/verify"))
+ (check-equal? (.ref (car (.ref plan 'requests)) 'blocker)
+ 'capability-unavailable)
+ (check-equal? (.ref plan 'release-authorized?) #f)))
+
+ (test-case "unresolved inputs and old obligation snapshots fail closed"
+ (let* ((policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test)))
+ (unresolved-snapshot
+ (software-snapshot
+ (list artifact claim obligation evidence decision effect)
+ (list dependency discharge obligation-support
+ decision-dependency authorization)
+ '("artifact/missing")))
+ (unresolved-plan
+ (assurance-plan-verification
+ "plan/unresolved" unresolved-snapshot
+ '("artifact/source") policy))
+ (old-obligation
+ (.o (:: @ obligation) snapshot: "snapshot/old"))
+ (old-snapshot
+ (software-snapshot
+ (list artifact claim old-obligation evidence decision effect)
+ (list dependency discharge obligation-support
+ decision-dependency authorization)))
+ (old-plan
+ (assurance-plan-verification
+ "plan/old" old-snapshot '("artifact/source") policy)))
+ (check-equal? (.ref unresolved-plan 'selected-obligations) '())
+ (check-equal? (.ref unresolved-plan 'unresolved)
+ '("artifact/missing"))
+ (check-equal?
+ (.ref (car (.ref unresolved-plan 'requests)) 'blocker)
+ 'unresolved-frontier)
+ (check-equal? (.ref old-plan 'selected-obligations) '())
+ (check-equal? (.ref (car (.ref old-plan 'requests)) 'blocker)
+ 'stale-obligation)))
+
+ (test-case "same-identity snapshot revisions and contents cannot reuse old obligations"
+ (let* ((policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test)))
+ (nodes (.ref full-software-snapshot 'nodes))
+ (relations (.ref full-software-snapshot 'relations))
+ (new-revision
+ (software-snapshot nodes relations '() "r2"))
+ (changed-content
+ (software-snapshot
+ (map (lambda (node)
+ (if (equal? (.ref node 'identity) "claim/release")
+ (.o (:: @ node) predicate: "release-ready-v2")
+ node))
+ nodes)
+ relations))
+ (revision-plan
+ (assurance-plan-verification
+ "plan/new-revision" new-revision
+ '("artifact/source") policy))
+ (content-plan
+ (assurance-plan-verification
+ "plan/changed-content" changed-content
+ '("artifact/source") policy)))
+ (check-equal? (.ref new-revision 'identity)
+ (.ref full-software-snapshot 'identity))
+ (check-equal? (.ref changed-content 'revision)
+ (.ref full-software-snapshot 'revision))
+ (check-equal? (.ref revision-plan 'selected-obligations) '())
+ (check-equal? (.ref content-plan 'selected-obligations) '())
+ (check-equal? (.ref (car (.ref revision-plan 'requests)) 'blocker)
+ 'stale-obligation)
+ (check-equal? (.ref (car (.ref content-plan 'requests)) 'blocker)
+ 'stale-obligation)
+ (check-equal? (.ref revision-plan 'verifier-executed?) #f)
+ (check-equal? (.ref content-plan 'release-authorized?) #f)
+ (check-exception
+ (assurance-bind-obligation-to-snapshot
+ (car (filter assurance-obligation? nodes)) new-revision)
+ Error?)))
+
+ (test-case "conflicted snapshot remains distinct from unknown frontier"
+ (let* ((snapshot
+ (assurance-snapshot
+ "snapshot/software" "r1" "graph/software"
+ '(("artifact/source" . "r2"))
+ '(("claim/release" . "r1"))
+ "event-cut/1" "policy/release" "r1"
+ (list artifact claim obligation evidence decision effect)
+ (list dependency discharge obligation-support
+ decision-dependency authorization)
+ evidence-identities: '("evidence/test")))
+ (policy
+ (assurance-verification-policy
+ "policy/release" "r1" '(gerbil-test)))
+ (plan
+ (assurance-plan-verification
+ "plan/conflict" snapshot '("artifact/source") policy)))
+ (check-equal? (.ref plan 'conflicts) '("artifact/source"))
+ (check-equal? (.ref plan 'unresolved) '())
+ (check-equal? (.ref plan 'selected-obligations) '())
+ (check-equal? (.ref (car (.ref plan 'requests)) 'blocker)
+ 'conflicted-snapshot)))
+
+ (test-case "verification policy cannot silently change snapshot authority"
+ (check-exception
+ (assurance-verification-policy "policy/release" "r1" '("gerbil-test"))
+ Error?)
+ (check-exception
+ (assurance-plan-verification
+ "plan/wrong-policy" full-software-snapshot
+ '("artifact/source")
+ (assurance-verification-policy
+ "policy/other" "r1" '(gerbil-test)))
+ Error?))
+
(test-case "structural cycles have deterministic SCCs and witnesses"
(let* ((snapshot
(software-snapshot
diff --git a/t/assurance/unit/decision-preflight-test.ss b/t/assurance/unit/decision-preflight-test.ss
new file mode 100644
index 0000000..9c99f0e
--- /dev/null
+++ b/t/assurance/unit/decision-preflight-test.ss
@@ -0,0 +1,228 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+(import :std/test :std/error
+ (only-in :clan/poo/object .o .ref)
+ (only-in :agentic-ai-lab/modules/authorization/providers/cedar/interface
+ agentic-ai-lab-cedar-runtime-handoff
+ agentic-ai-lab-cedar-authorization-request?
+ agentic-ai-lab-cedar-authorization-request->runtime)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/interface)
+
+(export decision-preflight-test)
+
+(def digest-a (string-append "sha256:" (make-string 64 #\a)))
+(def digest-b (string-append "sha256:" (make-string 64 #\b)))
+(def artifact
+ (assurance-artifact "artifact/source" "r1" 'supported digest-a
+ owner: "maintainer" media-kind: 'scheme-source))
+(def claim
+ (assurance-claim "claim/release" "r1" 'unknown digest-b
+ subject: "software/release" predicate: "ready"
+ support-requirements: '("obligation/test")
+ scope: "repository" valid-from: "2026-09-23"))
+(def obligation
+ (assurance-obligation
+ "obligation/test" "r1" 'unknown digest-a
+ subject: "software/release" claim: "claim/release"
+ snapshot: "snapshot/software" evidence-kind: 'native-test
+ capability: 'gerbil-test scope: "repository"))
+(def evidence
+ (assurance-evidence
+ "evidence/test" "r1" 'supported digest-b
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ input-artifacts: '("artifact/source") obligation: "obligation/test"
+ subject: "software/release" scope: "repository"
+ valid-from: "2026-09-23" admission-state: 'candidate))
+(def decision
+ (assurance-decision
+ "decision/release" "r1" 'unknown digest-a
+ subject: "software/release" snapshot: "snapshot/software"
+ policy: "policy/release" authority: "maintainer" outcome: 'unknown))
+(def evidence-link
+ (assurance-relation "relation/discharge" 'assurance 'discharges
+ "evidence/test" "obligation/test" 'observed))
+(def requirement-link
+ (assurance-relation "relation/requirement" 'assurance 'supports
+ "obligation/test" "claim/release" 'declared))
+(def decision-link
+ (assurance-relation "relation/decision-dependency" 'structural 'depends-on
+ "decision/release" "claim/release" 'declared))
+(def relations (list evidence-link requirement-link decision-link))
+
+(def (construct obligation-value relation-values fact-cut-value)
+ (assurance-snapshot
+ "snapshot/software" "r1" "graph/software"
+ '(("artifact/source" . "r1")) '(("claim/release" . "r1"))
+ fact-cut-value "policy/release" "r1"
+ (list artifact claim obligation-value evidence decision) relation-values))
+(def (bound-cut relation-values)
+ (let (draft (construct obligation relation-values "event-cut/1"))
+ (construct (assurance-bind-obligation-to-snapshot obligation draft)
+ relation-values "event-cut/1")))
+(def (bound-obligation snapshot-value)
+ (let loop ((nodes (.ref snapshot-value 'nodes)))
+ (and (pair? nodes)
+ (if (equal? (.ref (car nodes) 'identity) "obligation/test")
+ (car nodes)
+ (loop (cdr nodes))))))
+(def (reported-outcome snapshot-value)
+ (assurance-verifier-outcome
+ "outcome/test" 'succeeded
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ obligation: "obligation/test" subject: "software/release"
+ scope: "repository" snapshot-revision: "r1"
+ snapshot-context-digest: (.ref snapshot-value 'context-digest)
+ inputs: (list (assurance-verifier-input artifact))
+ output-digest: digest-b))
+(def (make-host source)
+ (assurance-verification-host
+ "host/decision-preflight"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () 11) 9 source))
+(def handoff
+ (agentic-ai-lab-cedar-runtime-handoff
+ 1 #u8(1 2 3) digest-a digest-a digest-b digest-b))
+
+(def decision-preflight-test
+ (test-suite "Host Decision preflight is not authorization"
+ (test-case "exact undecided Decision and support issue one Host preflight"
+ (let* ((snapshot-value (bound-cut relations))
+ (host (make-host (lambda () snapshot-value)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation snapshot-value) evidence
+ (reported-outcome snapshot-value)))
+ (preflight
+ (assurance-host-preflight-decision
+ host decision claim (list admission)))
+ (other-host (make-host (lambda () snapshot-value))))
+ (check-equal? (assurance-decision-preflight? preflight) #t)
+ (check-equal? (.ref preflight 'release-authorized?) #f)
+ (check-equal?
+ (assurance-decision-preflight?
+ (.o (:: @ preflight) release-authorized?: #t)) #f)
+ (check-equal?
+ (assurance-host-decision-preflight-current? host preflight) #t)
+ (check-equal?
+ (assurance-host-decision-preflight-current?
+ host (.o (:: @ preflight))) #f)
+ (check-equal?
+ (assurance-host-decision-preflight-current?
+ other-host preflight) #f)
+ (check-equal?
+ (assurance-host-preflight-decision
+ host (.o (:: @ decision) outcome: 'allow)
+ claim (list admission)) #f)
+ (check-equal?
+ (assurance-host-preflight-decision host decision claim '()) #f)
+ (assurance-host-revoke-admission! host admission)
+ (check-equal?
+ (assurance-host-decision-preflight-current? host preflight) #f)))
+
+ (test-case "missing Decision dependency cannot preflight"
+ (let* ((snapshot-value
+ (bound-cut (list evidence-link requirement-link)))
+ (host (make-host (lambda () snapshot-value)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation snapshot-value) evidence
+ (reported-outcome snapshot-value))))
+ (check-equal?
+ (assurance-host-preflight-decision
+ host decision claim (list admission)) #f)))
+
+ (test-case "only a current Host preflight projects an inert Cedar request"
+ (let* ((snapshot-value (bound-cut relations))
+ (host (make-host (lambda () snapshot-value)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation snapshot-value) evidence
+ (reported-outcome snapshot-value)))
+ (preflight
+ (assurance-host-preflight-decision
+ host decision claim (list admission)))
+ (request
+ (assurance-host-cedar-request
+ host preflight "Release" digest-a handoff))
+ (other-host (make-host (lambda () snapshot-value)))
+ (runtime-value
+ (agentic-ai-lab-cedar-authorization-request->runtime request))
+ (context-value (hash-get runtime-value "context")))
+ (check-equal? (agentic-ai-lab-cedar-authorization-request? request) #t)
+ (check-equal? (assurance-host-cedar-request-current? host request) #t)
+ (check-equal?
+ (assurance-host-cedar-request-current?
+ host (.o (:: @ request))) #f)
+ (check-equal?
+ (assurance-host-cedar-request-current?
+ host (.o (:: @ request) action: "Deploy")) #f)
+ (check-equal?
+ (assurance-host-cedar-request-current? other-host request) #f)
+ (check-equal? (hash-get runtime-value "principal") "maintainer")
+ (check-equal? (hash-get runtime-value "resource") "software/release")
+ (check-equal? (hash-get context-value "aitia_preflight")
+ (.ref preflight 'identity))
+ (check-equal? (hash-get context-value "aitia_policy") "policy/release")
+ (check-equal? (hash-get context-value "aitia_preflight_only") #t)
+ (check-equal? (hash-get context-value "agentic_ai_lab_preflight_only") #t)
+ (check-equal?
+ (assurance-host-cedar-request
+ host (.o (:: @ preflight)) "Release" digest-a handoff) #f)
+ (check-exception
+ (assurance-host-cedar-request
+ host preflight "Release" digest-a (.o)) Error?)
+ (assurance-host-revoke-decision-preflight! host preflight)
+ (check-equal?
+ (assurance-host-cedar-request-current? host request) #f)
+ (check-equal?
+ (assurance-host-cedar-request
+ host preflight "Release" digest-a handoff) #f)))
+
+ (test-case "source change and rollback cannot revive a preflight"
+ (let* ((current (bound-cut relations))
+ (host (make-host (lambda () current)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation current) evidence
+ (reported-outcome current)))
+ (preflight
+ (assurance-host-preflight-decision
+ host decision claim (list admission)))
+ (request
+ (assurance-host-cedar-request
+ host preflight "Release" digest-a handoff))
+ (old-cut current))
+ (check-equal?
+ (assurance-host-decision-preflight-current? host preflight) #t)
+ (check-equal?
+ (assurance-host-cedar-request-current? host request) #t)
+ (set! current
+ (construct (bound-obligation old-cut) relations "event-cut/2"))
+ (check-equal?
+ (assurance-host-decision-preflight-current? host preflight) #f)
+ (check-equal?
+ (assurance-host-cedar-request-current? host request) #f)
+ (set! current old-cut)
+ (check-equal?
+ (assurance-host-decision-preflight-current? host preflight) #f)
+ (check-equal?
+ (assurance-host-cedar-request-current? host request) #f)))
+
+ (test-case "explicit preflight revocation is separate from evidence"
+ (let* ((snapshot-value (bound-cut relations))
+ (host (make-host (lambda () snapshot-value)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation snapshot-value) evidence
+ (reported-outcome snapshot-value)))
+ (preflight
+ (assurance-host-preflight-decision
+ host decision claim (list admission))))
+ (assurance-host-revoke-decision-preflight! host preflight)
+ (check-equal?
+ (assurance-host-decision-preflight-current? host preflight) #f)
+ (check-equal?
+ (assurance-host-admission-current? host admission) #t)))))
diff --git a/t/assurance/unit/evidence-admission-test.ss b/t/assurance/unit/evidence-admission-test.ss
new file mode 100644
index 0000000..abac1dd
--- /dev/null
+++ b/t/assurance/unit/evidence-admission-test.ss
@@ -0,0 +1,593 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+(import :std/test
+ (only-in :std/error Error?)
+ (only-in :clan/poo/object .o .ref)
+ (only-in :agentic-ai-lab/core/contribution/verification
+ agentic-ai-lab-verification-adapter agentic-ai-lab-verify
+ agentic-ai-lab-revoke-verification!)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/interface)
+
+(export evidence-admission-test)
+
+(def digest-a (string-append "sha256:" (make-string 64 #\a)))
+(def digest-b (string-append "sha256:" (make-string 64 #\b)))
+(def artifact
+ (assurance-artifact "artifact/source" "r1" 'supported digest-a
+ owner: "maintainer" media-kind: 'scheme-source))
+(def claim
+ (assurance-claim "claim/release" "r1" 'unknown digest-b
+ subject: "software/release" predicate: "release-ready"
+ scope: "repository" valid-from: "2026-09-23"))
+(def obligation
+ (assurance-obligation
+ "obligation/test" "r1" 'unknown digest-a
+ subject: "software/release" claim: "claim/release"
+ snapshot: "snapshot/software" evidence-kind: 'native-test
+ capability: 'gerbil-test scope: "repository"))
+(def (make-snapshot artifact-value obligation-value (revision "r1"))
+ (assurance-snapshot
+ "snapshot/software" revision "graph/software"
+ (list (cons "artifact/source" (.ref artifact-value 'revision)))
+ '(("claim/release" . "r1"))
+ "event-cut/1" "policy/release" "r1"
+ (list artifact-value claim obligation-value) '()))
+(def draft (make-snapshot artifact obligation))
+(def bound-obligation (assurance-bind-obligation-to-snapshot obligation draft))
+(def snapshot (make-snapshot artifact bound-obligation))
+(def outcome
+ (assurance-verifier-outcome
+ "outcome/test" 'succeeded
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ obligation: "obligation/test" subject: "software/release"
+ scope: "repository" snapshot-revision: "r1"
+ snapshot-context-digest: (.ref snapshot 'context-digest)
+ inputs: (list (assurance-verifier-input artifact))
+ output-digest: digest-b))
+(def trusted-evidence
+ (assurance-evidence
+ "evidence/test" "r1" 'supported digest-b
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ input-artifacts: '("artifact/source") obligation: "obligation/test"
+ subject: "software/release" scope: "repository"
+ valid-from: "2026-09-23" admission-state: 'admitted))
+(def trusted-discharge
+ (assurance-relation "relation/discharge" 'assurance 'discharges
+ "evidence/test" "obligation/test" 'observed))
+(def (make-trusted-snapshot obligation-value)
+ (assurance-snapshot
+ "snapshot/software" "r1" "graph/software"
+ '(("artifact/source" . "r1")) '(("claim/release" . "r1"))
+ "event-cut/1" "policy/release" "r1"
+ (list artifact claim obligation-value trusted-evidence)
+ (list trusted-discharge)
+ evidence-identities: '("evidence/test")))
+(def trusted-draft (make-trusted-snapshot obligation))
+(def trusted-obligation
+ (assurance-bind-obligation-to-snapshot obligation trusted-draft))
+(def trusted-snapshot (make-trusted-snapshot trusted-obligation))
+(def trusted-outcome
+ (.o (:: @ outcome)
+ snapshot-context-digest: (.ref trusted-snapshot 'context-digest)))
+(def candidate-evidence
+ (.o (:: @ trusted-evidence) admission-state: 'candidate))
+(def (make-candidate-snapshot source-value obligation-value revision-value)
+ (assurance-snapshot
+ "snapshot/software" revision-value "graph/software"
+ (list (cons "artifact/source" (.ref source-value 'revision)))
+ '(("claim/release" . "r1"))
+ "event-cut/1" "policy/release" "r1"
+ (list source-value claim obligation-value candidate-evidence)
+ (list trusted-discharge)))
+(def candidate-draft
+ (make-candidate-snapshot artifact obligation "r1"))
+(def candidate-obligation
+ (assurance-bind-obligation-to-snapshot obligation candidate-draft))
+(def candidate-snapshot
+ (make-candidate-snapshot artifact candidate-obligation "r1"))
+(def candidate-outcome
+ (.o (:: @ outcome)
+ snapshot-context-digest: (.ref candidate-snapshot 'context-digest)))
+(def trusted-adapter
+ (agentic-ai-lab-verification-adapter
+ "host/native-test"
+ (lambda (subject-value now until)
+ (and (eq? (.ref (.ref subject-value 'outcome) 'status) 'succeeded)
+ (equal? (.ref (.ref subject-value 'evidence) 'content-digest)
+ digest-b)))
+ assurance-verification-subject-snapshot))
+(def trusted-subject
+ (assurance-verification-subject
+ trusted-snapshot trusted-obligation trusted-evidence trusted-outcome))
+(def trusted-receipt
+ (agentic-ai-lab-verify trusted-adapter trusted-subject 10 20))
+(def untrusted-adapter
+ (agentic-ai-lab-verification-adapter
+ "other/native-test"
+ (lambda (subject-value now until) #t)
+ assurance-verification-subject-snapshot))
+(def (verified-support relation-value evidence-value obligation-value
+ snapshot-value outcome-value receipt-value now-value)
+ (assurance-support-sealed-under-adapter?
+ relation-value evidence-value obligation-value snapshot-value outcome-value
+ trusted-adapter receipt-value now-value))
+(def (blocker snapshot-value obligation-value outcome-value)
+ (.ref (assurance-evaluate-evidence-admission
+ snapshot-value obligation-value outcome-value)
+ 'blocker))
+
+(def evidence-admission-test
+ (test-suite "evidence admission eligibility"
+ (test-case "bound success is eligible but does not admit or authorize"
+ (let (receipt
+ (assurance-evaluate-evidence-admission
+ snapshot bound-obligation outcome))
+ (check-equal? (assurance-evidence-admission-receipt? receipt) #t)
+ (check-equal? (.ref receipt 'eligible?) #t)
+ (check-equal? (.ref receipt 'verifier-executed?) #f)
+ (check-equal? (.ref receipt 'release-authorized?) #f)
+ (check-equal? (.ref receipt 'snapshot-digest) (.ref snapshot 'digest))
+ (check-equal?
+ (.ref receipt 'digest)
+ (.ref (assurance-evaluate-evidence-admission
+ snapshot bound-obligation outcome)
+ 'digest))
+ (check-equal?
+ (equal? (.ref receipt 'digest)
+ (.ref (assurance-evaluate-evidence-admission
+ snapshot bound-obligation
+ (.o (:: @ outcome) output-digest: digest-a))
+ 'digest))
+ #f)))
+
+ (test-case "non-success statuses are typed, not green"
+ (for-each
+ (lambda (reported-status)
+ (check-equal?
+ (blocker snapshot bound-obligation
+ (.o (:: @ outcome) status: reported-status))
+ 'outcome-not-successful))
+ '(failed timed-out unavailable indeterminate)))
+
+ (test-case "green exit without output and bound inputs is rejected"
+ (check-equal?
+ (blocker snapshot bound-obligation
+ (.o (:: @ outcome) output-digest: #f))
+ 'missing-output)
+ (check-equal?
+ (blocker snapshot bound-obligation
+ (.o (:: @ outcome) inputs: '()))
+ 'missing-inputs)
+ (check-equal?
+ (blocker snapshot bound-obligation
+ (.o (:: @ outcome)
+ inputs: (list (assurance-verifier-input artifact)
+ (assurance-verifier-input artifact))))
+ 'duplicate-inputs))
+
+ (test-case "changed source revision and digest invalidate old result"
+ (let* ((new-artifact
+ (.o (:: @ artifact) revision: "r2" content-digest: digest-b))
+ (new-draft (make-snapshot new-artifact obligation "r2"))
+ (new-obligation
+ (assurance-bind-obligation-to-snapshot obligation new-draft))
+ (new-snapshot (make-snapshot new-artifact new-obligation "r2")))
+ (check-equal?
+ (blocker new-snapshot bound-obligation outcome)
+ 'stale-obligation)
+ (check-equal?
+ (blocker new-snapshot new-obligation
+ (.o (:: @ outcome)
+ snapshot-revision: "r2"
+ snapshot-context-digest:
+ (.ref new-snapshot 'context-digest)))
+ 'input-binding-mismatch)))
+
+ (test-case "same revision with changed artifact digest is not reusable"
+ (let* ((new-artifact (.o (:: @ artifact) content-digest: digest-b))
+ (new-draft (make-snapshot new-artifact obligation))
+ (new-obligation
+ (assurance-bind-obligation-to-snapshot obligation new-draft))
+ (new-snapshot (make-snapshot new-artifact new-obligation)))
+ (check-equal?
+ (blocker new-snapshot new-obligation outcome)
+ 'outcome-binding-mismatch)
+ (check-equal?
+ (blocker new-snapshot new-obligation
+ (.o (:: @ outcome)
+ snapshot-context-digest:
+ (.ref new-snapshot 'context-digest)))
+ 'input-binding-mismatch)))
+
+ (test-case "same revision with forged obligation semantics is stale"
+ (check-equal?
+ (blocker snapshot
+ (.o (:: @ bound-obligation) subject: "software/other")
+ outcome)
+ 'stale-obligation))
+
+ (test-case "conflicting snapshot never accepts a reported success"
+ (let (conflicted
+ (assurance-snapshot
+ "snapshot/software" "r1" "graph/software"
+ '(("artifact/source" . "r1")) '(("claim/release" . "r1"))
+ "event-cut/1" "policy/release" "r1"
+ (list artifact
+ (.o (:: @ artifact) content-digest: digest-b)
+ claim bound-obligation)
+ '()))
+ (check-equal?
+ (blocker conflicted bound-obligation outcome)
+ 'snapshot-conflicted)))
+
+ (test-case "outcome cannot retarget subject, scope or snapshot"
+ (check-equal?
+ (blocker snapshot bound-obligation
+ (.o (:: @ outcome) subject: "software/other"))
+ 'outcome-binding-mismatch)
+ (check-equal?
+ (blocker snapshot bound-obligation
+ (.o (:: @ outcome) snapshot-revision: "r0"))
+ 'outcome-binding-mismatch))
+
+ (test-case "human review names authority and exact scope"
+ (let* ((human-obligation
+ (.o (:: @ obligation) evidence-kind: 'human-review))
+ (human-draft (make-snapshot artifact human-obligation))
+ (human-bound
+ (assurance-bind-obligation-to-snapshot human-obligation human-draft))
+ (human-snapshot (make-snapshot artifact human-bound))
+ (human-outcome
+ (.o (:: @ outcome)
+ snapshot-context-digest:
+ (.ref human-snapshot 'context-digest))))
+ (check-equal?
+ (blocker human-snapshot human-bound human-outcome)
+ 'human-authority-missing)
+ (check-equal?
+ (blocker human-snapshot human-bound
+ (.o (:: @ human-outcome)
+ accountable-authority: "maintainer"
+ review-scope: "repository"))
+ #f)))
+
+ (test-case "support requires a sealed execution receipt"
+ (check-equal?
+ (verified-support
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome #f 11)
+ #f)
+ (check-equal?
+ (verified-support
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome trusted-receipt 11)
+ #t))
+
+ (test-case "copied seal and presentation mutation cannot forge support"
+ (check-equal?
+ (assurance-support-sealed-under-adapter?
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome
+ (.o identity: "host/native-test"
+ admits?: (lambda (receipt-value subject-value now-value) #t))
+ trusted-receipt 11)
+ #f)
+ (check-equal?
+ (assurance-support-sealed-under-adapter?
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome
+ (.o (:: @ trusted-adapter)) trusted-receipt 11)
+ #f)
+ (check-equal?
+ (verified-support
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome
+ (.o (:: @ trusted-receipt)) 11)
+ #f)
+ (check-equal?
+ (verified-support
+ trusted-discharge trusted-evidence trusted-obligation
+ (.o (:: @ trusted-snapshot) state: 'supported)
+ trusted-outcome trusted-receipt 11)
+ #f)
+ (check-equal?
+ (verified-support
+ trusted-discharge
+ (.o (:: @ trusted-evidence) tool-version: "v20")
+ trusted-obligation trusted-snapshot trusted-outcome
+ trusted-receipt 11)
+ #f)
+ (check-equal?
+ (verified-support
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot
+ (.o (:: @ trusted-outcome) tool-version: "v20")
+ trusted-receipt 11)
+ #f)
+ (check-equal?
+ (assurance-support-sealed-under-adapter?
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome untrusted-adapter
+ trusted-receipt 11)
+ #f))
+
+ (test-case "configured Host owns adapter, clock and revocation"
+ (let* ((now 11)
+ (host
+ (assurance-verification-host
+ "host/assurance-test"
+ (lambda (subject-value issued-at expires-at)
+ (and (eq? (.ref (.ref subject-value 'outcome) 'status)
+ 'succeeded)
+ (equal? (.ref (.ref subject-value 'evidence)
+ 'content-digest)
+ digest-b)))
+ (lambda () now) 9 (lambda () trusted-snapshot)))
+ (receipt
+ (assurance-host-verify
+ host trusted-snapshot trusted-obligation trusted-evidence
+ trusted-outcome)))
+ (check-equal? (if receipt #t #f) #t)
+ (check-equal?
+ (assurance-host-verify
+ host trusted-snapshot trusted-obligation
+ (.o (:: @ trusted-evidence) tool-version: "v20")
+ trusted-outcome)
+ #f)
+ (check-equal?
+ (assurance-host-sealed-support?
+ host trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome receipt)
+ #t)
+ (check-exception
+ (assurance-host-sealed-support?
+ (.o (:: @ host)) trusted-discharge trusted-evidence
+ trusted-obligation trusted-snapshot trusted-outcome receipt)
+ Error?)
+ (check-exception
+ (assurance-host-sealed-support?
+ (.o identity: "host/assurance-test")
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome receipt)
+ Error?)
+ (check-equal?
+ (assurance-host-verify
+ host trusted-snapshot trusted-obligation trusted-evidence
+ (.o (:: @ trusted-outcome) status: 'failed))
+ #f)
+ (set! now 20)
+ (check-equal?
+ (assurance-host-sealed-support?
+ host trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome receipt)
+ #f)
+ (set! now 11)
+ (check-exception
+ (assurance-host-sealed-support?
+ host trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome receipt)
+ Error?))
+ (let* ((host
+ (assurance-verification-host
+ "host/revocation-test"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () 11) 9 (lambda () trusted-snapshot)))
+ (receipt
+ (assurance-host-verify
+ host trusted-snapshot trusted-obligation trusted-evidence
+ trusted-outcome)))
+ (check-equal?
+ (assurance-host-sealed-support?
+ host trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome receipt)
+ #t)
+ (assurance-host-revoke! host receipt)
+ (check-equal?
+ (assurance-host-sealed-support?
+ host trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome receipt)
+ #f)))
+
+ (test-case "configured verifier refusal never issues a seal"
+ (let (host
+ (assurance-verification-host
+ "host/refusal-test"
+ (lambda (subject-value issued-at expires-at) #f)
+ (lambda () 11) 9 (lambda () trusted-snapshot)))
+ (check-equal?
+ (assurance-host-verify
+ host trusted-snapshot trusted-obligation trusted-evidence
+ trusted-outcome)
+ #f)))
+
+ (test-case "old Host seal stays invalid after a source cut returns"
+ (let* ((current trusted-snapshot)
+ (host
+ (assurance-verification-host
+ "host/seal-cut-test"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () 11) 9 (lambda () current)))
+ (receipt
+ (assurance-host-verify
+ host trusted-snapshot trusted-obligation trusted-evidence
+ trusted-outcome)))
+ (check-equal?
+ (assurance-host-sealed-support?
+ host trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome receipt)
+ #t)
+ (set! current (.o (:: @ trusted-snapshot) fact-cut: "event-cut/2"))
+ (check-exception
+ (assurance-host-sealed-support?
+ host trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome receipt)
+ Error?)
+ (set! current trusted-snapshot)
+ (check-equal?
+ (assurance-host-sealed-support?
+ host trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome receipt)
+ #f)))
+
+ (test-case "Host admission binds candidate evidence to an immutable cut"
+ (let* ((current candidate-snapshot)
+ (host
+ (assurance-verification-host
+ "host/admission-test"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () 11) 9 (lambda () current)))
+ (admission
+ (assurance-host-admit
+ host candidate-obligation candidate-evidence candidate-outcome)))
+ (check-equal? (if admission #t #f) #t)
+ (check-equal? (.ref candidate-evidence 'admission-state) 'candidate)
+ (check-equal? (assurance-host-admission-current? host admission) #t)
+ (check-equal?
+ (assurance-host-admission-current? host (.o (:: @ admission))) #f)
+ (check-equal?
+ (assurance-host-admission-current?
+ host (.o identity: (.ref admission 'identity))) #f)
+ (check-equal?
+ (assurance-host-admit
+ host candidate-obligation
+ (.o (:: @ candidate-evidence) tool-version: "v20")
+ candidate-outcome)
+ #f)
+ (let* ((new-source
+ (.o (:: @ artifact) revision: "r2" content-digest: digest-b))
+ (new-snapshot
+ (make-candidate-snapshot new-source obligation "r2")))
+ (set! current new-snapshot)
+ (check-equal?
+ (assurance-host-admission-current? host admission) #f)
+ (set! current candidate-snapshot)
+ (check-equal?
+ (assurance-host-admission-current? host admission) #f))))
+
+ (test-case "only the exact current assurance edge consumes a Host admission"
+ (let* ((now 11)
+ (current candidate-snapshot)
+ (host
+ (assurance-verification-host
+ "host/admitted-support-test"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () now) 9 (lambda () current)))
+ (other-host
+ (assurance-verification-host
+ "host/admitted-support-other"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () now) 9 (lambda () current)))
+ (admission
+ (assurance-host-admit
+ host candidate-obligation candidate-evidence candidate-outcome)))
+ (check-equal?
+ (assurance-host-admitted-support?
+ host trusted-discharge admission) #t)
+ (check-equal?
+ (assurance-host-admitted-support?
+ other-host trusted-discharge admission) #f)
+ (check-equal?
+ (assurance-host-admitted-support?
+ host trusted-discharge (.o (:: @ admission))) #f)
+ (check-equal?
+ (assurance-host-admitted-support?
+ host (.o (:: @ trusted-discharge) modality: 'hypothesized)
+ admission) #f)
+ (check-equal?
+ (assurance-host-admitted-support?
+ host (.o (:: @ trusted-discharge) target: "obligation/other")
+ admission) #f)
+ (set! now 20)
+ (check-equal?
+ (assurance-host-admitted-support?
+ host trusted-discharge admission) #f)))
+
+ (test-case "semantic snapshot mutation with unchanged display digest revokes"
+ (let* ((current candidate-snapshot)
+ (host
+ (assurance-verification-host
+ "host/semantic-cut-test"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () 11) 9 (lambda () current)))
+ (admission
+ (assurance-host-admit
+ host candidate-obligation candidate-evidence candidate-outcome)))
+ (check-equal? (assurance-host-admission-current? host admission) #t)
+ (set! current
+ (.o (:: @ candidate-snapshot) fact-cut: "event-cut/2"))
+ (check-equal? (.ref current 'digest)
+ (.ref candidate-snapshot 'digest))
+ (check-exception
+ (assurance-host-admission-current? host admission) Error?)
+ (set! current candidate-snapshot)
+ (check-equal? (assurance-host-admission-current? host admission) #f)))
+
+ (test-case "invalid Host snapshot source cannot revive an old admission"
+ (let* ((current candidate-snapshot)
+ (host
+ (assurance-verification-host
+ "host/invalid-source-test"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () 11) 9 (lambda () current)))
+ (admission
+ (assurance-host-admit
+ host candidate-obligation candidate-evidence candidate-outcome)))
+ (check-equal? (assurance-host-admission-current? host admission) #t)
+ (set! current #f)
+ (check-exception
+ (assurance-host-admission-current? host admission) Error?)
+ (set! current candidate-snapshot)
+ (check-equal? (assurance-host-admission-current? host admission) #f)))
+
+ (test-case "Host admission expires, revokes and refuses failed verification"
+ (let* ((now 11)
+ (host
+ (assurance-verification-host
+ "host/admission-expiry"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () now) 9 (lambda () candidate-snapshot)))
+ (admission
+ (assurance-host-admit
+ host candidate-obligation candidate-evidence candidate-outcome)))
+ (check-equal? (assurance-host-admission-current? host admission) #t)
+ (set! now 20)
+ (check-equal? (assurance-host-admission-current? host admission) #f)
+ (set! now 11)
+ (check-exception
+ (assurance-host-admission-current? host admission) Error?))
+ (let* ((host
+ (assurance-verification-host
+ "host/admission-revocation"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () 11) 9 (lambda () candidate-snapshot)))
+ (admission
+ (assurance-host-admit
+ host candidate-obligation candidate-evidence candidate-outcome)))
+ (check-equal? (assurance-host-admission-current? host admission) #t)
+ (assurance-host-revoke-admission! host admission)
+ (check-equal? (assurance-host-admission-current? host admission) #f))
+ (let (host
+ (assurance-verification-host
+ "host/admission-refusal"
+ (lambda (subject-value issued-at expires-at) #f)
+ (lambda () 11) 9 (lambda () candidate-snapshot)))
+ (check-equal?
+ (assurance-host-admit
+ host candidate-obligation candidate-evidence candidate-outcome)
+ #f)))
+
+ (test-case "expiry and revocation remove verified support"
+ (check-equal?
+ (verified-support
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome trusted-receipt 20)
+ #f)
+ (agentic-ai-lab-revoke-verification! trusted-adapter trusted-receipt)
+ (check-equal?
+ (verified-support
+ trusted-discharge trusted-evidence trusted-obligation
+ trusted-snapshot trusted-outcome trusted-receipt 11)
+ #f))))
diff --git a/t/assurance/unit/lifecycle-boundary-test.ss b/t/assurance/unit/lifecycle-boundary-test.ss
new file mode 100644
index 0000000..3e876d5
--- /dev/null
+++ b/t/assurance/unit/lifecycle-boundary-test.ss
@@ -0,0 +1,212 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+(import :std/test :std/error (only-in :clan/poo/object .o .ref)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/interface
+ :agentic-ai-lab/lambda-aitia/t/formal/lifecycle-fixture)
+(export lifecycle-boundary-test)
+(def (drive fixture actions)
+ (for-each (lambda (action) (check (lifecycle-action! fixture action) => #t)) actions)
+ fixture)
+(def (ready)
+ (drive (make-lifecycle-fixture) '(InstallAdapter Plan Verify Admit Decide Authorize)))
+(def lifecycle-boundary-test
+ (test-suite "Lifecycle authorization, reservation and delivery boundaries"
+ (test-case "Admit consumes the prior seal without executing or renewing verification"
+ (let (f (drive (make-lifecycle-fixture) '(InstallAdapter Plan Verify)))
+ (check (lifecycle-get f 'verifier-calls) => 1)
+ (check (lifecycle-action! f 'Admit) => #t)
+ (check (lifecycle-get f 'verifier-calls) => 1)
+ (check (.ref (lifecycle-get f 'admission) 'expires-at) => 1))
+ (let (f (drive (make-lifecycle-fixture) '(InstallAdapter Plan Verify Tick)))
+ (check (lifecycle-action! f 'Admit) => #f)
+ (check (lifecycle-get f 'verifier-calls) => 1)))
+ (test-case "untrusted report cannot admit authorize reserve or deliver"
+ (let (f (drive (make-lifecycle-fixture) '(ReportSuccess)))
+ (check (lifecycle-action! f 'UnsafeLateAdmit) => #f)
+ (check (lifecycle-action! f 'UnsafeEarlyGrant) => #f)
+ (check (lifecycle-action! f 'UnsafeStart) => #f)
+ (check (.ref (lifecycle-action! f 'UnsafeBeforeStart) 'outcome) => 'rejected)
+ (check (lifecycle-get f 'authorization-calls) => 0)
+ (check (lifecycle-get f 'delivery-calls) => 0)))
+ (test-case "copied seals and foreign Host seals cannot admit"
+ (let* ((f (drive (make-lifecycle-fixture) '(InstallAdapter Plan Verify)))
+ (other (drive (make-lifecycle-fixture) '(InstallAdapter Plan Verify)))
+ (seal (lifecycle-get f 'seal)))
+ (lifecycle-set! f 'seal (.o (:: @ seal)))
+ (check (lifecycle-action! f 'Admit) => #f)
+ (lifecycle-set! f 'seal (lifecycle-get other 'seal))
+ (check (lifecycle-action! f 'Admit) => #f)))
+ (test-case "deny and indeterminate never receive a grant"
+ (for-each
+ (lambda (mode)
+ (let (f (drive (make-lifecycle-fixture) '(InstallAdapter Plan Verify Admit Decide)))
+ (lifecycle-set! f 'policy-mode mode)
+ (check (lifecycle-action! f 'Authorize) => #f)
+ (check (lifecycle-get f 'authorization-calls) => 1)
+ (check (lifecycle-action! f 'StartEffect) => #f)
+ (check (lifecycle-get f 'delivery-calls) => 0))) '(forbid indeterminate)))
+ (test-case "reserve is not delivery; current reservation hands off exactly once"
+ (let (f (ready))
+ (check (lifecycle-action! f 'StartEffect) => #t)
+ (check (lifecycle-get f 'service-effects) => 0)
+ (check (lifecycle-action! f 'StartEffect) => #f)
+ (check (.ref (lifecycle-action! f 'DeliverEffect) 'delivered?) => #t)
+ (check (.ref (lifecycle-action! f 'UnsafeReplay) 'outcome) => 'rejected)
+ (check (lifecycle-get f 'delivery-calls) => 1)
+ (check (lifecycle-get f 'service-effects) => 1)))
+ (test-case "renewed verification does not renew an old grant or reservation"
+ (let (f (ready))
+ (check (lifecycle-action! f 'Verify) => #t)
+ (check (lifecycle-action! f 'StartEffect) => #t)
+ (check (.ref (lifecycle-action! f 'DeliverEffect) 'delivered?) => #t))
+ (let (f (drive (ready) '(StartEffect Tick Verify Admit Decide Authorize)))
+ (check (.ref (lifecycle-get f 'grant) 'expires-at) => 2)
+ (check (.ref (lifecycle-action! f 'DeliverEffect) 'outcome) => 'rejected)
+ (check (lifecycle-get f 'delivery-calls) => 0)))
+ (test-case "expiry revoke and source change between reserve and delivery fail closed"
+ (for-each
+ (lambda (change)
+ (let (f (drive (ready) '(StartEffect)))
+ (check (lifecycle-action! f change) => #t)
+ (check (.ref (lifecycle-action! f 'UnsafeDelivery) 'outcome) => 'rejected)
+ (check (lifecycle-get f 'delivery-calls) => 0)
+ (check (lifecycle-get f 'service-effects) => 0))) '(Tick Revoke ChangeSource)))
+ (test-case "source change during authorization cannot publish a grant"
+ (let (f (drive (make-lifecycle-fixture) '(InstallAdapter Plan Verify Admit Decide)))
+ (lifecycle-set! f 'authorization-hook
+ (lambda () (lifecycle-set! f 'cut (lifecycle-cut 2))))
+ (check (lifecycle-action! f 'Authorize) => #f)
+ (check (lifecycle-get f 'delivery-calls) => 0)))
+ (test-case "permit cannot publish after policy callback expiry or request mutation"
+ (for-each
+ (lambda (change)
+ (let* ((f (ready)) (request (lifecycle-get f 'request)))
+ (lifecycle-set! f 'authorization-hook
+ (lambda ()
+ (case change
+ ((expiry) (lifecycle-set! f 'clock 1))
+ ((request) (string-set! (.ref request 'action) 0 #\X)))))
+ (check (assurance-effect-host-authorize! (lifecycle-get f 'effect-host)
+ (lifecycle-get f 'verification-host) request) => #f)
+ (check (lifecycle-get f 'authorization-calls) => 2)
+ (check (lifecycle-action! f 'StartEffect) => #f)
+ (check (lifecycle-get f 'delivery-calls) => 0))) '(expiry request)))
+ (test-case "copied grant extended expiry and copied reservation are refused"
+ (let* ((f (ready)) (host (lifecycle-get f 'effect-host))
+ (grant (lifecycle-get f 'grant)))
+ (check (assurance-effect-host-reserve! host (.o (:: @ grant))) => #f)
+ (check (assurance-effect-host-reserve! host (.o (:: @ grant) expires-at: 99)) => #f)
+ (let (reservation (assurance-effect-host-reserve! host grant))
+ (check (.ref (assurance-effect-host-deliver! host (.o (:: @ reservation))) 'outcome) => 'rejected)
+ (check (.ref (assurance-effect-host-deliver! host reservation) 'delivered?) => #t))))
+ (test-case "foreign Host grant and reservation never reach a runtime callback"
+ (let* ((f (ready)) (other (ready)) (host (lifecycle-get other 'effect-host))
+ (grant (lifecycle-get f 'grant)))
+ (check (assurance-effect-host-reserve! host grant) => #f)
+ (check (lifecycle-action! f 'StartEffect) => #t)
+ (check (.ref (assurance-effect-host-deliver! host (lifecycle-get f 'reservation)) 'outcome) => 'rejected)
+ (check (lifecycle-get other 'delivery-calls) => 0)
+ (check (.ref (lifecycle-action! f 'DeliverEffect) 'delivered?) => #t)))
+ (test-case "issued token binding mutation fails closed, including after reservation"
+ (for-each
+ (lambda (reserve-first?)
+ (let* ((f (ready)) (grant (lifecycle-get f 'grant))
+ (binding (.ref (.ref grant 'token) 'binding))
+ (digest (.ref binding 'bundle-digest)))
+ (when reserve-first? (check (lifecycle-action! f 'StartEffect) => #t))
+ (string-set! digest 0 (if (char=? (string-ref digest 0) #\a) #\b #\a))
+ (if reserve-first?
+ (check (.ref (lifecycle-action! f 'DeliverEffect) 'outcome) => 'rejected)
+ (check (lifecycle-action! f 'StartEffect) => #f))
+ (check (lifecycle-get f 'delivery-calls) => 0))) '(#f #t)))
+ (test-case "copied and intent-substituted requests cannot invoke authorization"
+ (let* ((f (ready)) (host (lifecycle-get f 'effect-host))
+ (vh (lifecycle-get f 'verification-host)) (request (lifecycle-get f 'request)))
+ (check (assurance-effect-host-authorize! host vh (.o (:: @ request))) => #f)
+ (check (assurance-effect-host-authorize! host vh (.o (:: @ request) intent: "other")) => #f)
+ (check (lifecycle-get f 'authorization-calls) => 1)))
+ (test-case "observed source ABA cannot revive an old grant"
+ (let* ((f (ready)) (cut (lifecycle-get f 'cut)))
+ (lifecycle-set! f 'cut (lifecycle-cut 2))
+ (check (lifecycle-action! f 'StartEffect) => #f)
+ (lifecycle-set! f 'cut cut)
+ (check (lifecycle-action! f 'StartEffect) => #f)
+ (check (lifecycle-get f 'delivery-calls) => 0)))
+ (test-case "in-place request string and handoff payload changes revoke the frozen request"
+ (for-each
+ (lambda (field)
+ (let* ((f (ready)) (request (lifecycle-get f 'request))
+ (text (if (eq? field 'payload-hex)
+ (.ref (.ref request 'handoff) field) (.ref request field))))
+ (string-set! text 0 (if (char=? (string-ref text 0) #\a) #\b #\a))
+ (check (assurance-host-cedar-request-current? (lifecycle-get f 'verification-host) request) => #f)
+ (check (assurance-effect-host-authorize! (lifecycle-get f 'effect-host)
+ (lifecycle-get f 'verification-host) request) => #f)
+ (check (lifecycle-action! f 'StartEffect) => #f)
+ (check (lifecycle-get f 'authorization-calls) => 1)
+ (check (lifecycle-get f 'delivery-calls) => 0))) '(intent action payload-hex)))
+ (test-case "authorization exception releases the fence without publishing authority"
+ (let (f (drive (make-lifecycle-fixture) '(InstallAdapter Plan Verify Admit Decide)))
+ (lifecycle-set! f 'authorization-hook (lambda () (error "policy runtime failure")))
+ (check-exception (lifecycle-action! f 'Authorize) Error?)
+ (check (lifecycle-get f 'grant) => #f)
+ (lifecycle-set! f 'authorization-hook #f)
+ (check (lifecycle-action! f 'Authorize) => #t)
+ (check (lifecycle-get f 'delivery-calls) => 0)))
+ (test-case "unknown acknowledgement is not delivered and cannot be retried"
+ (let (f (drive (ready) '(StartEffect)))
+ (check (.ref (lifecycle-action! f 'UnknownDelivery) 'delivered?) => #f)
+ (check (lifecycle-get f 'service-effects) => 1)
+ (check (.ref (lifecycle-action! f 'UnsafeReplay) 'outcome) => 'rejected)
+ (check (lifecycle-get f 'service-effects) => 1)))
+ (test-case "failed delivery is attributable failure, not success or retry authority"
+ (let (f (drive (ready) '(StartEffect)))
+ (check (.ref (lifecycle-action! f 'FailDelivery) 'outcome) => 'failed)
+ (check (lifecycle-get f 'service-effects) => 0)
+ (check (.ref (lifecycle-action! f 'UnsafeReplay) 'outcome) => 'rejected)
+ (check (lifecycle-get f 'delivery-calls) => 1)))
+ (test-case "malformed acknowledgement consumes the attempt without success or retry"
+ (let (f (drive (ready) '(StartEffect)))
+ ;; Use the API directly: the model fixture deliberately chooses only
+ ;; its three typed runtime outcomes.
+ (lifecycle-set! f 'delivery-mode 'not-an-acknowledgement)
+ (check-exception (assurance-effect-host-deliver! (lifecycle-get f 'effect-host)
+ (lifecycle-get f 'reservation)) Error?)
+ (check (.ref (lifecycle-action! f 'UnsafeReplay) 'outcome) => 'rejected)
+ (check (lifecycle-get f 'delivery-calls) => 1)))
+ (test-case "deadline crossed during grant validation cannot reserve or deliver"
+ (for-each
+ (lambda (reserve-first?)
+ (let ((f (ready)) (reads 0))
+ (when reserve-first? (check (lifecycle-action! f 'StartEffect) => #t))
+ ;; The effect clock advances from 0 to the strict deadline during
+ ;; this API call. The verification Host remains current at 0.
+ (lifecycle-set! f 'effect-clock-hook
+ (lambda ()
+ (let (now (min reads 1))
+ (set! reads (+ reads 1))
+ now)))
+ (if reserve-first?
+ (check (.ref (lifecycle-action! f 'DeliverEffect) 'outcome) => 'rejected)
+ (check (lifecycle-action! f 'StartEffect) => #f))
+ (check reads => 2)
+ (check (lifecycle-get f 'delivery-calls) => 0)
+ (check (lifecycle-get f 'service-effects) => 0))) '(#f #t)))
+ (test-case "clock rollback cannot restore an expired grant"
+ (let* ((f (ready)) (host (lifecycle-get f 'effect-host)))
+ (lifecycle-set! f 'clock 1)
+ (check (assurance-effect-host-grant-current? host (lifecycle-get f 'grant)) => #f)
+ (lifecycle-set! f 'clock 0)
+ (check-exception (lifecycle-action! f 'StartEffect) Error?)
+ (check (lifecycle-get f 'delivery-calls) => 0)))
+ (test-case "throwing and reentrant delivery stays consumed and releases the transient fence"
+ (let (f (drive (ready) '(StartEffect)))
+ (lifecycle-set! f 'delivery-hook
+ (lambda ()
+ (check-exception (assurance-effect-host-revoke! (lifecycle-get f 'effect-host)) Error?)
+ (error "runtime failure")))
+ (check-exception (lifecycle-action! f 'DeliverEffect) Error?)
+ (check (.ref (lifecycle-action! f 'UnsafeReplay) 'outcome) => 'rejected)
+ (assurance-effect-host-revoke! (lifecycle-get f 'effect-host))
+ (check (lifecycle-get f 'delivery-calls) => 1)))))
diff --git a/t/assurance/unit/required-support-test.ss b/t/assurance/unit/required-support-test.ss
new file mode 100644
index 0000000..8acd6c9
--- /dev/null
+++ b/t/assurance/unit/required-support-test.ss
@@ -0,0 +1,183 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+(import :std/test
+ (only-in :std/list/list find)
+ (only-in :clan/poo/object .o .ref)
+ (only-in :agentic-ai-lab/core/poo-clos/interface
+ poo-clos-model-prototype)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/interface)
+
+(export required-support-test)
+
+(def digest-a (string-append "sha256:" (make-string 64 #\a)))
+(def digest-b (string-append "sha256:" (make-string 64 #\b)))
+(def artifact
+ (assurance-artifact "artifact/source" "r1" 'supported digest-a
+ owner: "maintainer" media-kind: 'scheme-source))
+(def claim
+ (assurance-claim "claim/release" "r1" 'unknown digest-b
+ subject: "software/release" predicate: "ready"
+ support-requirements: '("obligation/test")
+ scope: "repository" valid-from: "2026-09-23"))
+(def obligation
+ (assurance-obligation
+ "obligation/test" "r1" 'unknown digest-a
+ subject: "software/release" claim: "claim/release"
+ snapshot: "snapshot/software" evidence-kind: 'native-test
+ capability: 'gerbil-test scope: "repository"))
+(def evidence
+ (assurance-evidence
+ "evidence/test" "r1" 'supported digest-b
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ input-artifacts: '("artifact/source") obligation: "obligation/test"
+ subject: "software/release" scope: "repository"
+ valid-from: "2026-09-23" admission-state: 'candidate))
+(def evidence-link
+ (assurance-relation "relation/discharge" 'assurance 'discharges
+ "evidence/test" "obligation/test" 'observed))
+(def requirement-link
+ (assurance-relation "relation/requirement" 'assurance 'supports
+ "obligation/test" "claim/release" 'declared))
+(def relations (list evidence-link requirement-link))
+
+(def (construct claim-value obligation-value relation-values)
+ (assurance-snapshot
+ "snapshot/software" "r1" "graph/software"
+ '(("artifact/source" . "r1")) '(("claim/release" . "r1"))
+ "event-cut/1" "policy/release" "r1"
+ (list artifact claim-value obligation-value evidence) relation-values))
+(def (bound-cut claim-value relation-values)
+ (let (draft (construct claim-value obligation relation-values))
+ (construct claim-value
+ (assurance-bind-obligation-to-snapshot obligation draft)
+ relation-values)))
+(def (bound-obligation snapshot)
+ (find (lambda (node)
+ (equal? (.ref node 'identity) "obligation/test"))
+ (.ref snapshot 'nodes)))
+(def (reported-outcome snapshot)
+ (assurance-verifier-outcome
+ "outcome/test" 'succeeded
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ obligation: "obligation/test" subject: "software/release"
+ scope: "repository" snapshot-revision: "r1"
+ snapshot-context-digest: (.ref snapshot 'context-digest)
+ inputs: (list (assurance-verifier-input artifact))
+ output-digest: digest-b))
+(def (make-host source)
+ (assurance-verification-host
+ "host/required-support"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () 11) 9 source))
+(def (first-blocker receipt)
+ (.ref (car (.ref receipt 'requirements)) 'blocker))
+
+(def required-support-test
+ (test-suite "Host required support is an inert Decision input"
+ (test-case "row model is well formed"
+ (let (row (.o (:: @ (poo-clos-model-prototype AssessmentRequiredSupport))
+ obligation: "obligation/test" supported?: #t blocker: #f))
+ (check-equal? (assessment-required-support? row) #t)))
+ (test-case "exact admission and both relations close declared support only"
+ (let* ((snapshot (bound-cut claim relations))
+ (host (make-host (lambda () snapshot)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation snapshot) evidence
+ (reported-outcome snapshot)))
+ (complete
+ (assurance-host-required-support host claim (list admission)))
+ (missing (assurance-host-required-support host claim '()))
+ (copied
+ (assurance-host-required-support
+ host claim (list (.o (:: @ admission))))))
+ (check-equal? (assurance-required-support? complete) #t)
+ (check-equal? (.ref complete 'complete?) #t)
+ (check-equal? (.ref complete 'release-authorized?) #f)
+ (check-equal?
+ (assurance-required-support?
+ (.o (:: @ complete) release-authorized?: #t)) #f)
+ (check-equal? (first-blocker missing) 'admission-missing)
+ (check-equal? (first-blocker copied) 'admission-missing)))
+
+ (test-case "undeclared and disconnected requirements stay blocked"
+ (let* ((snapshot (bound-cut claim relations))
+ (host (make-host (lambda () snapshot)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation snapshot) evidence
+ (reported-outcome snapshot)))
+ (two-required
+ (.o (:: @ claim)
+ support-requirements:
+ '("obligation/test" "obligation/independent")))
+ (two-cut (bound-cut two-required relations))
+ (two-host (make-host (lambda () two-cut)))
+ (assessment
+ (assurance-host-required-support
+ two-host two-required (list admission)))
+ (no-link-cut (bound-cut claim (list evidence-link)))
+ (no-link-host (make-host (lambda () no-link-cut)))
+ (no-link-admission
+ (assurance-host-admit
+ no-link-host (bound-obligation no-link-cut) evidence
+ (reported-outcome no-link-cut)))
+ (disconnected
+ (assurance-host-required-support
+ no-link-host claim (list no-link-admission))))
+ (check-equal? (.ref assessment 'complete?) #f)
+ (check-equal?
+ (.ref (cadr (.ref assessment 'requirements)) 'blocker)
+ 'obligation-missing)
+ (check-equal? (first-blocker disconnected) 'support-link-missing)))
+
+ (test-case "assumption closure is not inferred from verifier admission"
+ (let* ((assumed
+ (.o (:: @ claim) assumptions: '("assumption/toolchain")))
+ (snapshot (bound-cut assumed relations))
+ (host (make-host (lambda () snapshot)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation snapshot) evidence
+ (reported-outcome snapshot)))
+ (assessment
+ (assurance-host-required-support host assumed (list admission))))
+ (check-equal? (.ref assessment 'complete?) #f)
+ (check-equal?
+ (if (memq 'assumptions-unresolved (.ref assessment 'blockers)) #t #f)
+ #t)))
+
+ (test-case "expiry and revocation reopen required support"
+ (let* ((now 11)
+ (snapshot (bound-cut claim relations))
+ (host
+ (assurance-verification-host
+ "host/required-support-expiry"
+ (lambda (subject-value issued-at expires-at) #t)
+ (lambda () now) 9 (lambda () snapshot)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation snapshot) evidence
+ (reported-outcome snapshot))))
+ (check-equal?
+ (.ref (assurance-host-required-support host claim (list admission))
+ 'complete?) #t)
+ (set! now 20)
+ (check-equal?
+ (first-blocker
+ (assurance-host-required-support host claim (list admission)))
+ 'admission-invalid))
+ (let* ((snapshot (bound-cut claim relations))
+ (host (make-host (lambda () snapshot)))
+ (admission
+ (assurance-host-admit
+ host (bound-obligation snapshot) evidence
+ (reported-outcome snapshot))))
+ (assurance-host-revoke-admission! host admission)
+ (check-equal?
+ (first-blocker
+ (assurance-host-required-support host claim (list admission)))
+ 'admission-missing)))))
diff --git a/t/bindings/build-root.ss b/t/bindings/build-root.ss
index 1755860..11e07fc 100644
--- a/t/bindings/build-root.ss
+++ b/t/bindings/build-root.ss
@@ -2,6 +2,6 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/bindings/c/aitia-native)
+(import :agentic-ai-lab/lambda-aitia/bindings/c/aitia-native)
(export lambda-aitia-binding-test-fixtures-loaded?)
(def lambda-aitia-binding-test-fixtures-loaded? #t)
diff --git a/t/bindings/unit/aitia-native-test.ss b/t/bindings/unit/aitia-native-test.ss
index f209e52..c5405e0 100644
--- a/t/bindings/unit/aitia-native-test.ss
+++ b/t/bindings/unit/aitia-native-test.ss
@@ -4,7 +4,7 @@
(import :std/test
(only-in :std/encoding/json JSONReadOptions string->json)
- (only-in :poo-flow/lambda-aitia/bindings/c/aitia-contract
+ (only-in :agentic-ai-lab/lambda-aitia/bindings/c/aitia-contract
aitia-abi-revision
aitia-descriptor-payload
aitia-sdlc-flow-plan-payload
@@ -20,7 +20,7 @@
(string->json payload +aitia-native-test-json-read-options+))
(def +accepted-change+
- "{\"event\":\"pull-request\",\"repository\":\"tao3k/poo-flow\",\"revision\":\"0123456789abcdef\",\"source-ref\":\"feature/aitia\",\"target-ref\":\"develop\",\"pull-request\":42,\"checks\":[{\"name\":\"commit-policy\",\"conclusion\":\"success\"},{\"name\":\"build\",\"conclusion\":\"success\"},{\"name\":\"unit-test\",\"conclusion\":\"success\"},{\"name\":\"nasa-7150-2d\",\"conclusion\":\"success\"}]}")
+ "{\"event\":\"pull-request\",\"repository\":\"tao3k/agentic-ai-lab\",\"revision\":\"0123456789abcdef\",\"source-ref\":\"feature/aitia\",\"target-ref\":\"develop\",\"pull-request\":42,\"checks\":[{\"name\":\"commit-policy\",\"conclusion\":\"success\"},{\"name\":\"build\",\"conclusion\":\"success\"},{\"name\":\"unit-test\",\"conclusion\":\"success\"},{\"name\":\"nasa/sdlc/npr-7150.2\",\"conclusion\":\"success\",\"standardEdition\":\"D\",\"sourceLockDigest\":\"sha256:cfb963b8cd81fd8e22e9b47251c1dc7927b85fcdf9ec9366057cd38cb94f338c\"}]}")
(def aitia-native-test
(test-suite "Aitia Scheme-native C ABI"
@@ -47,7 +47,7 @@
"release/42/decide" "release/42/authorize"
"release/42/effect"))
(check (hash-get plan "semanticOwner") => "lambda-aitia")
- (check (hash-get plan "runtimeOwner") => "poo-flow")
+ (check (hash-get plan "runtimeOwner") => "agentic-ai-lab")
(check (hash-get plan "releaseAuthorized") => #f)
(check (hash-get plan "runtimeExecuted") => #f)))
(test-case "Scheme remains the GitOps decision owner"
diff --git a/t/fixtures/composition-value/aitia.ss b/t/fixtures/composition-value/aitia.ss
deleted file mode 100644
index c110098..0000000
--- a/t/fixtures/composition-value/aitia.ss
+++ /dev/null
@@ -1,8 +0,0 @@
-;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
-;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-
-(use-composition aitia
- (project
- repository: "tao3k/lambda-aitia"
- languages: '(scheme python lean tla+))
- (delivery provider: 'github))
diff --git a/t/formal/lifecycle-fixture.ss b/t/formal/lifecycle-fixture.ss
new file mode 100644
index 0000000..615979f
--- /dev/null
+++ b/t/formal/lifecycle-fixture.ss
@@ -0,0 +1,189 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; This fixture drives real plan / verification / admission / preflight /
+;;; token / reservation APIs. It never imports model expected states.
+;;; Configured local runtime callbacks are controls, not a native Cedar proof.
+(import :std/test (only-in :clan/poo/object .o .ref)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/interface
+ (only-in :agentic-ai-lab/modules/authorization/providers/cedar/interface
+ agentic-ai-lab-cedar-decision agentic-ai-lab-cedar-runtime-handoff))
+(export make-lifecycle-fixture lifecycle-action! lifecycle-state
+ lifecycle-get lifecycle-set! lifecycle-cut)
+
+(def digest-a (string-append "sha256:" (make-string 64 #\a)))
+(def digest-b (string-append "sha256:" (make-string 64 #\b)))
+(def (lifecycle-cut revision)
+ (let* ((rev (number->string revision))
+ (artifact (assurance-artifact "source" rev 'supported
+ (if (= revision 1) digest-a digest-b) owner: "fixture" media-kind: 'scheme-source))
+ (claim (assurance-claim "claim" rev 'unknown digest-b subject: "release" predicate: "ready"
+ support-requirements: '("test") scope: "repo" valid-from: "2026-10-11"))
+ (obligation (assurance-obligation "test" rev 'unknown digest-a subject: "release"
+ claim: "claim" snapshot: "cut" evidence-kind: 'native-test
+ capability: 'gerbil-test scope: "repo"))
+ (evidence (assurance-evidence "evidence" rev 'supported digest-b producer: "fixture"
+ tool: "local-verifier" tool-version: "1" input-artifacts: '("source")
+ obligation: "test" subject: "release" scope: "repo"
+ valid-from: "2026-10-11" admission-state: 'candidate))
+ (decision (assurance-decision "decision" rev 'unknown digest-a subject: "release"
+ snapshot: "cut" policy: "policy" authority: "owner" outcome: 'unknown))
+ (relations (list
+ (assurance-relation "input" 'structural 'depends-on "claim" "source" 'declared)
+ (assurance-relation "support" 'assurance 'supports "test" "claim" 'declared)
+ (assurance-relation "discharge" 'assurance 'discharges "evidence" "test" 'observed)
+ (assurance-relation "decision-input" 'structural 'depends-on "decision" "claim" 'declared))))
+ (def (snapshot bound)
+ (assurance-snapshot "cut" rev "graph" (list (cons "source" rev))
+ (list (cons "claim" rev)) (string-append "events/" rev) "policy" "1"
+ (list artifact claim bound evidence decision) relations))
+ (let* ((bound (assurance-bind-obligation-to-snapshot obligation (snapshot obligation)))
+ (cut (snapshot bound))
+ (outcome (assurance-verifier-outcome "outcome" 'succeeded producer: "fixture"
+ tool: "local-verifier" tool-version: "1" obligation: "test"
+ subject: "release" scope: "repo" snapshot-revision: rev
+ snapshot-context-digest: (.ref cut 'context-digest)
+ inputs: (list (assurance-verifier-input artifact)) output-digest: digest-b)))
+ (let ((revision-value revision) (evidence-value evidence) (outcome-value outcome)
+ (claim-value claim) (decision-value decision))
+ (.o revision: revision-value snapshot: cut obligation: bound evidence: evidence-value
+ outcome: outcome-value claim: claim-value decision: decision-value)))))
+(def cuts (vector (lifecycle-cut 1) (lifecycle-cut 2)))
+(def (lifecycle-get fixture key) (hash-ref fixture key))
+(def (lifecycle-set! fixture key value) (hash-put! fixture key value))
+(def (increment! fixture key) (lifecycle-set! fixture key (+ 1 (lifecycle-get fixture key))))
+(def (make-lifecycle-fixture)
+ (let (fixture (make-hash-table-eq))
+ (for-each (lambda (key) (lifecycle-set! fixture key #f))
+ '(installed reported plan seal admission admission-seal preflight request grant reservation
+ started authorization-hook delivery-hook effect-clock-hook))
+ (for-each (lambda (key) (lifecycle-set! fixture key 0))
+ '(clock verifier-calls authorization-calls delivery-calls service-effects
+ grant-epoch grant-until reservation-revision reservation-epoch reservation-until delivery-status))
+ (lifecycle-set! fixture 'delivery-mode 'delivered)
+ (lifecycle-set! fixture 'policy-mode 'permit)
+ (lifecycle-set! fixture 'cut (vector-ref cuts 0))
+ (lifecycle-set! fixture 'verification-host
+ (assurance-verification-host "lifecycle/verification"
+ (lambda (subject now until)
+ (increment! fixture 'verifier-calls)
+ (lifecycle-get fixture 'installed))
+ (lambda () (lifecycle-get fixture 'clock)) 1
+ (lambda () (.ref (lifecycle-get fixture 'cut) 'snapshot))))
+ (lifecycle-set! fixture 'effect-host
+ (assurance-effect-host
+ (lambda (request)
+ (increment! fixture 'authorization-calls)
+ (when (lifecycle-get fixture 'authorization-hook)
+ ((lifecycle-get fixture 'authorization-hook)))
+ (agentic-ai-lab-cedar-decision "local-runtime-decision" (lifecycle-get fixture 'policy-mode)
+ "policy" digest-a digest-b '()))
+ (lambda (request token)
+ (increment! fixture 'delivery-calls)
+ (when (lifecycle-get fixture 'delivery-hook)
+ ((lifecycle-get fixture 'delivery-hook)))
+ (unless (eq? (lifecycle-get fixture 'delivery-mode) 'failed)
+ (increment! fixture 'service-effects))
+ (lifecycle-get fixture 'delivery-mode))
+ (lambda ()
+ (if (lifecycle-get fixture 'effect-clock-hook)
+ ((lifecycle-get fixture 'effect-clock-hook))
+ (lifecycle-get fixture 'clock))) 1))
+ fixture))
+
+(def (lifecycle-action! fixture name)
+ (let* ((cut (lifecycle-get fixture 'cut)) (vh (lifecycle-get fixture 'verification-host))
+ (rh (lifecycle-get fixture 'effect-host))
+ (snapshot (.ref cut 'snapshot)) (obligation (.ref cut 'obligation))
+ (evidence (.ref cut 'evidence)) (outcome (.ref cut 'outcome)))
+ (case name
+ ((init Terminal) #t)
+ ((InstallAdapter) (lifecycle-set! fixture 'installed #t) #t)
+ ((ReportSuccess) (lifecycle-set! fixture 'reported #t) #t)
+ ((Plan)
+ (let (plan (assurance-plan-verification "plan" snapshot '("source")
+ (assurance-verification-policy "policy" "1" '(gerbil-test))))
+ (unless (equal? (.ref plan 'selected-obligations) '("test"))
+ (error "fixture obligation was not selected"))
+ (lifecycle-set! fixture 'plan plan) #t))
+ ((Verify)
+ (and (lifecycle-get fixture 'plan)
+ (let (seal (assurance-host-verify vh snapshot obligation evidence outcome))
+ (lifecycle-set! fixture 'seal seal) (if seal #t #f))))
+ ((Admit UnsafeLateAdmit)
+ (let (admission (assurance-host-admit-verified vh obligation evidence outcome
+ (lifecycle-get fixture 'seal)))
+ (when admission
+ (lifecycle-set! fixture 'admission admission)
+ (lifecycle-set! fixture 'admission-seal (lifecycle-get fixture 'seal)))
+ (if admission #t #f)))
+ ((Decide)
+ (let (preflight (assurance-host-preflight-decision vh (.ref cut 'decision)
+ (.ref cut 'claim) (if (lifecycle-get fixture 'admission)
+ (list (lifecycle-get fixture 'admission)) '())))
+ (when preflight (lifecycle-set! fixture 'preflight preflight))
+ (if preflight #t #f)))
+ ((Authorize UnsafeEarlyGrant)
+ (let* ((request (assurance-host-cedar-request vh (lifecycle-get fixture 'preflight)
+ (string-copy "Release") (string-copy digest-a) (agentic-ai-lab-cedar-runtime-handoff
+ 1 #u8(1) digest-a digest-a digest-b digest-b)))
+ (grant (and request (assurance-effect-host-authorize! rh vh request))))
+ (when grant
+ (lifecycle-set! fixture 'request request)
+ (lifecycle-set! fixture 'grant grant)
+ (lifecycle-set! fixture 'grant-epoch (.ref grant 'epoch))
+ (lifecycle-set! fixture 'grant-until (.ref grant 'expires-at)))
+ (if grant #t #f)))
+ ((StartEffect UnsafeStart UnsafeAfterRevoke)
+ (let (reservation (assurance-effect-host-reserve! rh (lifecycle-get fixture 'grant)))
+ (when reservation
+ (lifecycle-set! fixture 'reservation reservation)
+ (lifecycle-set! fixture 'started #t)
+ (lifecycle-set! fixture 'reservation-revision (.ref cut 'revision))
+ (lifecycle-set! fixture 'reservation-epoch (lifecycle-get fixture 'grant-epoch))
+ (lifecycle-set! fixture 'reservation-until (lifecycle-get fixture 'grant-until)))
+ (if reservation #t #f)))
+ ((DeliverEffect RejectDelivery FailDelivery UnknownDelivery UnsafeDelivery UnsafeBeforeStart UnsafeReplay)
+ (lifecycle-set! fixture 'delivery-mode
+ (case name ((FailDelivery) 'failed) ((UnknownDelivery) 'indeterminate) (else 'delivered)))
+ (let* ((receipt (assurance-effect-host-deliver! rh (lifecycle-get fixture 'reservation)))
+ (status (case (.ref receipt 'outcome)
+ ((delivered) 1) ((rejected) 2) ((failed) 3) ((indeterminate) 4))))
+ ;; Unsafe probes must not rewrite an already attributable outcome.
+ (unless (memq name '(UnsafeDelivery UnsafeBeforeStart UnsafeReplay))
+ (lifecycle-set! fixture 'delivery-status status))
+ receipt))
+ ((Tick) (increment! fixture 'clock) #t)
+ ((ChangeSource)
+ (lifecycle-set! fixture 'cut (vector-ref cuts 1))
+ (for-each (lambda (key) (lifecycle-set! fixture key #f)) '(plan seal admission preflight request))
+ (lifecycle-set! fixture 'grant-until 0) #t)
+ ((Revoke)
+ (when (lifecycle-get fixture 'admission)
+ (assurance-host-revoke-admission! vh (lifecycle-get fixture 'admission)))
+ (when (and (lifecycle-get fixture 'seal)
+ (not (eq? (lifecycle-get fixture 'seal) (lifecycle-get fixture 'admission-seal))))
+ (assurance-host-revoke! vh (lifecycle-get fixture 'seal)))
+ (for-each (lambda (key) (lifecycle-set! fixture key #f)) '(seal admission preflight request))
+ (assurance-effect-host-revoke! rh) #t)
+ (else (error "unknown lifecycle action" name)))))
+
+(def (lifecycle-state fixture)
+ (let* ((cut (lifecycle-get fixture 'cut)) (rev (.ref cut 'revision))
+ (vh (lifecycle-get fixture 'verification-host)) (rh (lifecycle-get fixture 'effect-host))
+ (seal (lifecycle-get fixture 'seal)) (grant (lifecycle-get fixture 'grant)))
+ (.o revision: rev planned: (if (lifecycle-get fixture 'plan) rev 0)
+ verified: (if seal rev 0) sealUntil: (if seal (.ref seal 'expires-at) 0)
+ admitted: (if (assurance-host-admission-current? vh (lifecycle-get fixture 'admission)) rev 0)
+ decided: (if (assurance-host-decision-preflight-current? vh (lifecycle-get fixture 'preflight)) rev 0)
+ granted: (if (assurance-effect-host-grant-current? rh grant) rev 0)
+ grantEpoch: (lifecycle-get fixture 'grant-epoch) grantUntil: (lifecycle-get fixture 'grant-until)
+ epoch: (assurance-effect-host-epoch rh) clock: (lifecycle-get fixture 'clock)
+ adapterInstalled: (lifecycle-get fixture 'installed) reportedSuccess: (lifecycle-get fixture 'reported)
+ effectStarted: (lifecycle-get fixture 'started) startSafe: #t
+ reservationRevision: (lifecycle-get fixture 'reservation-revision)
+ reservationEpoch: (lifecycle-get fixture 'reservation-epoch)
+ reservationUntil: (lifecycle-get fixture 'reservation-until)
+ deliveryStatus: (lifecycle-get fixture 'delivery-status)
+ deliveryCalls: (lifecycle-get fixture 'delivery-calls) deliverySafe: #t)))
diff --git a/t/formal/lifecycle-replay-test.ss b/t/formal/lifecycle-replay-test.ss
new file mode 100644
index 0000000..840545b
--- /dev/null
+++ b/t/formal/lifecycle-replay-test.ss
@@ -0,0 +1,43 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+(import :std/test (only-in :clan/poo/object .ref)
+ ./lifecycle-fixture)
+(export lifecycle-replay-test)
+(def lifecycle-replay-test
+ (test-suite "Full bounded Quint lifecycle / real Scheme API graph replay"
+ (test-case "every supplied edge has the same projected Scheme state"
+ (let (file (getenv "AITIA_LIFECYCLE_REPLAY" #f))
+ (unless file (error "run through just check-lifecycle-scheme"))
+ (let (traces (call-with-input-file file read))
+ (check (pair? traces) => #t)
+ (for-each
+ (lambda (trace)
+ (let (fixture (make-lifecycle-fixture))
+ (for-each
+ (lambda (row)
+ (let ((action (car row)) (expected (cadr row)))
+ (if (memq action '(UnsafeStart UnsafeLateAdmit UnsafeEarlyGrant UnsafeAfterRevoke
+ UnsafeDelivery UnsafeBeforeStart UnsafeReplay))
+ (let* ((before (lifecycle-state fixture))
+ (calls (lifecycle-get fixture 'delivery-calls))
+ (result (lifecycle-action! fixture action)))
+ (if (memq action '(UnsafeDelivery UnsafeBeforeStart UnsafeReplay))
+ (check (.ref result 'outcome) => 'rejected)
+ (check result => #f))
+ (check (lifecycle-get fixture 'delivery-calls) => calls)
+ (let (after (lifecycle-state fixture))
+ (for-each (lambda (field)
+ (check (.ref after (car field)) => (.ref before (car field)))) expected)))
+ (begin
+ (let (result (lifecycle-action! fixture action))
+ (check (if result #t #f) => #t))
+ (let (actual (lifecycle-state fixture))
+ (for-each (lambda (field)
+ (check (.ref actual (car field)) => (cadr field))) expected))))
+ (when (eq? action 'StartEffect)
+ (check (lifecycle-get fixture 'delivery-calls) => 0)
+ (check (lifecycle-get fixture 'service-effects) => 0))))
+ trace)
+ (displayln "LIFECYCLE-TRACE-COMPLETE steps=" (length trace))
+ (force-output))) traces))))))
diff --git a/t/formal/retirement-binding-test.ss b/t/formal/retirement-binding-test.ss
new file mode 100644
index 0000000..2f2a4a9
--- /dev/null
+++ b/t/formal/retirement-binding-test.ss
@@ -0,0 +1,91 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+(import :std/test
+ (only-in :std/misc/ports read-all-as-string)
+ (only-in :clan/poo/object .ref)
+ (only-in :yuanxu/feature-system/source-lock-feature source-lock-payload-digest)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/interface
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface
+ :agentic-ai-lab/lambda-aitia/user-interface/scenarios/job-retirement-contract)
+(export retirement-binding-test)
+
+;;; IO belongs to the qualification fixture, not the public design value.
+;;; Hash every member before making one group artifact: changing any model,
+;;; config, imported helper or proof source invalidates the declared source cut.
+(def (source-group-digest paths)
+ (assurance-canonical-digest
+ (map (lambda (path)
+ (list path (source-lock-payload-digest
+ (call-with-input-file path read-all-as-string)))) paths)))
+(def (source id digest)
+ (assurance-artifact id "r1" 'supported digest
+ owner: "lambda-aitia" media-kind: 'formal-source
+ provenance: '("repository-source-bytes")))
+(def quint-source (source "retirement/quint" (source-group-digest job-retirement-quint-sources)))
+(def lean-source (source "retirement/lean" (source-group-digest job-retirement-lean-sources)))
+(def scheme-source (source "retirement/scheme" (source-group-digest job-retirement-scheme-sources)))
+(def (snapshot quint lean scheme)
+ (assurance-snapshot
+ "retirement/formal-cut" "cut-1" "retirement/formal-sources"
+ '(("retirement/quint" . "r1") ("retirement/lean" . "r1")
+ ("retirement/scheme" . "r1")) '()
+ "retirement/design-r1" "formal-review" "r1" (list quint lean scheme) '()))
+(def source-cut (snapshot quint-source lean-source scheme-source))
+(def links
+ (map (lambda (artifact)
+ (sdlc-design-implementation-link
+ job-retirement-contract job-retirement-safety artifact source-cut))
+ (list quint-source lean-source scheme-source)))
+
+(def retirement-binding-test
+ (test-suite "Retirement POO contract to formal source binding"
+ (test-case "three source cuts bind one declaration without granting conformance"
+ (let (review (sdlc-design-implementation-review
+ job-retirement-contract source-cut links))
+ (check (.ref review 'mapping-current?) => #t)
+ (for-each
+ (lambda (link)
+ (check (.ref link 'contract) => "job-executor/retirement")
+ (check (.ref link 'contract-revision) => "r1")
+ (check (.ref link 'contract-digest)
+ => (sdlc-design-contract-digest job-retirement-contract))) links)
+ (check (.ref review 'implementation-conforms?) => #f)
+ (check (.ref review 'evidence-admitted?) => #f)
+ (check (.ref review 'release-authorized?) => #f)))
+ (test-case "same-revision Quint source mutation invalidates the joined mapping"
+ (let* ((changed (source "retirement/quint" (source-lock-payload-digest "changed model")))
+ (review (sdlc-design-implementation-review
+ job-retirement-contract (snapshot changed lean-source scheme-source) links)))
+ (check (.ref review 'mapping-current?) => #f)
+ (check (length (.ref review 'blocked-links)) => 3)
+ (check (.ref (car (.ref review 'blocked-links)) 'blocker) => 'snapshot-changed)))
+ (test-case "same-revision Lean source mutation also invalidates the mapping"
+ (let* ((changed (source "retirement/lean" (source-lock-payload-digest "changed law")))
+ (review (sdlc-design-implementation-review
+ job-retirement-contract (snapshot quint-source changed scheme-source) links)))
+ (check (.ref review 'mapping-current?) => #f)
+ (check (length (.ref review 'blocked-links)) => 3)
+ (check (.ref (car (.ref review 'blocked-links)) 'blocker) => 'snapshot-changed)))
+ (test-case "same-revision Scheme implementation mutation invalidates the mapping"
+ (let* ((changed (source "retirement/scheme" (source-lock-payload-digest "changed Host")))
+ (review (sdlc-design-implementation-review
+ job-retirement-contract (snapshot quint-source lean-source changed) links)))
+ (check (.ref review 'mapping-current?) => #f)
+ (check (length (.ref review 'blocked-links)) => 3)
+ (check (.ref (car (.ref review 'blocked-links)) 'blocker) => 'snapshot-changed)))
+ (test-case "a changed design premise cannot reuse either formal link"
+ (let* ((changed
+ (sdlc-design-contract
+ "job-executor/retirement" "r1" "RFC/0004/retirement-ingress"
+ (.ref job-retirement-contract 'responsibilities)
+ (.ref job-retirement-contract 'owned-state) '()
+ (cons (sdlc-design-assumption "distributed-fence" "a1"
+ "Closing and epoch advancement may be separate operations.")
+ (.ref job-retirement-contract 'assumptions))
+ (list job-retirement-safety) '()))
+ (review (sdlc-design-implementation-review changed source-cut links)))
+ (check (.ref review 'mapping-current?) => #f)
+ (check (length (.ref review 'blocked-links)) => 3)
+ (for-each (lambda (link) (check (.ref link 'blocker) => 'contract-changed))
+ (.ref review 'blocked-links))))))
diff --git a/t/formal/retirement-execution-test.ss b/t/formal/retirement-execution-test.ss
new file mode 100644
index 0000000..d523c41
--- /dev/null
+++ b/t/formal/retirement-execution-test.ss
@@ -0,0 +1,157 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Execute the bounded retirement-ingress controls against the local Scheme
+;;; Host. The callback counter is an actual handoff result, not model metadata.
+(import :std/test
+ (only-in :clan/poo/object .ref)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/retirement-host)
+(export retirement-execution-test)
+
+(def (accepted? result) (.ref result 'accepted?))
+(def (reason result) (.ref result 'reason))
+(def (ready-for-review host)
+ (aitia-retirement-host-observe-completion! host)
+ (aitia-retirement-host-observe-queue-drained! host)
+ (aitia-retirement-host-complete-inventory! host)
+ host)
+
+(def retirement-execution-test
+ (test-suite "Retirement ingress actual Scheme Host execution"
+ (test-case "cancellation is not completion or queue drain"
+ (let (host (aitia-retirement-host))
+ (check (accepted? (aitia-retirement-host-request-cancellation! host)) => #t)
+ (aitia-retirement-host-complete-inventory! host)
+ (aitia-retirement-host-close-ingress! host)
+ (check (reason (aitia-retirement-host-retire! host)) => 'active-work)
+ (check (.ref (aitia-retirement-host-snapshot host) 'retired?) => #f)))
+ (test-case "unfenced review cannot retire"
+ (let (host (ready-for-review (aitia-retirement-host)))
+ (check (accepted? (aitia-retirement-host-review-cut! host)) => #t)
+ (check (reason (aitia-retirement-host-retire! host)) => 'ingress-open)
+ (check (.ref (aitia-retirement-host-snapshot host) 'authority-epoch) => 0)
+ (check (accepted? (aitia-retirement-host-close-ingress! host)) => #t)
+ (check (.ref (aitia-retirement-host-snapshot host) 'authority-epoch) => 1)
+ (check (accepted? (aitia-retirement-host-retire! host)) => #t)))
+ (test-case "cancellation does not discharge queued work after completion"
+ (let (host (aitia-retirement-host))
+ (aitia-retirement-host-request-cancellation! host)
+ (aitia-retirement-host-observe-completion! host)
+ (aitia-retirement-host-complete-inventory! host)
+ (aitia-retirement-host-close-ingress! host)
+ (check (reason (aitia-retirement-host-review-cut! host)) => 'queued-work)
+ (check (reason (aitia-retirement-host-retire! host)) => 'queued-work)
+ (check (.ref (aitia-retirement-host-snapshot host) 'queued?) => #t)))
+ (test-case "quiescence inventory and fence cannot substitute for review"
+ (let (host (ready-for-review (aitia-retirement-host)))
+ (aitia-retirement-host-close-ingress! host)
+ (check (reason (aitia-retirement-host-retire! host)) => 'review-missing)
+ (check (accepted? (aitia-retirement-host-review-cut! host)) => #t)
+ (check (accepted? (aitia-retirement-host-retire! host)) => #t)))
+ (test-case "closure is idempotent and fences an already pending request"
+ (let* ((host (aitia-retirement-host)) (calls 0)
+ (handoff (aitia-retirement-effect-handoff
+ (lambda () (set! calls (+ calls 1))))))
+ (aitia-retirement-host-request-start! host)
+ (aitia-retirement-host-close-ingress! host)
+ (check (reason (aitia-retirement-host-close-ingress! host)) => 'already-closed)
+ (check (.ref (aitia-retirement-host-snapshot host) 'authority-epoch) => 1)
+ (check (reason (aitia-retirement-host-attempt-start! host handoff)) => 'stale-grant)
+ (check calls => 0)
+ (check (.ref (aitia-retirement-host-snapshot host) 'attempted?) => #t)))
+ (test-case "failed handoff releases the transient fence without retry or completion"
+ (let* ((host (ready-for-review (aitia-retirement-host))) (calls 0)
+ (handoff (aitia-retirement-effect-handoff
+ (lambda () (set! calls (+ calls 1)) (error "handoff failed")))))
+ (aitia-retirement-host-review-cut! host)
+ (aitia-retirement-host-request-start! host)
+ (check (with-catch (lambda (_failure) 'failed)
+ (lambda () (aitia-retirement-host-attempt-start! host handoff)
+ 'unexpected-success)) => 'failed)
+ (check calls => 1)
+ (check (.ref (aitia-retirement-host-snapshot host) 'handoff-in-progress?) => #f)
+ (check (.ref (aitia-retirement-host-snapshot host) 'active?) => #t)
+ (check (accepted? (aitia-retirement-host-request-start! host)) => #f)
+ (check (reason (aitia-retirement-host-retire! host)) => 'active-work)
+ (check (accepted? (aitia-retirement-host-observe-completion! host)) => #t)
+ (aitia-retirement-host-close-ingress! host)
+ (check (accepted? (aitia-retirement-host-retire! host)) => #t)))
+ (test-case "late work invalidates the old finalization attempt"
+ (let (host (ready-for-review (aitia-retirement-host)))
+ (aitia-retirement-host-review-cut! host)
+ (aitia-retirement-host-observe-late-activity! host)
+ (aitia-retirement-host-close-ingress! host)
+ (check (reason (aitia-retirement-host-retire! host)) => 'active-work)
+ (check (.ref (aitia-retirement-host-snapshot host) 'retired?) => #f)))
+ (test-case "unknown inventory prevents retirement after review"
+ (let (host (ready-for-review (aitia-retirement-host)))
+ (aitia-retirement-host-review-cut! host)
+ (aitia-retirement-host-observe-inventory-gap! host)
+ (aitia-retirement-host-close-ingress! host)
+ (check (reason (aitia-retirement-host-retire! host)) => 'inventory-unknown)
+ (check (.ref (aitia-retirement-host-snapshot host) 'retired?) => #f)))
+ (test-case "accepted current grant invokes one real Scheme handoff"
+ (let* ((host (aitia-retirement-host))
+ (calls 0)
+ (reentered #f)
+ (handoff (aitia-retirement-effect-handoff
+ (lambda ()
+ (set! calls (+ calls 1))
+ (set! reentered
+ (accepted? (aitia-retirement-host-request-start! host)))))))
+ (check (accepted? (aitia-retirement-host-request-start! host)) => #t)
+ (let (result (aitia-retirement-host-attempt-start! host handoff))
+ (check (accepted? result) => #t)
+ (check (.ref result 'handoff-executed?) => #t))
+ (check calls => 1)
+ (check reentered => #f)
+ (check (accepted? (aitia-retirement-host-request-start! host)) => #f)
+ (check (reason (aitia-retirement-host-retire! host)) => 'active-work)))
+ (test-case "foreign thread cannot use the serialized Host"
+ (let* ((host (aitia-retirement-host))
+ (result
+ (thread-join!
+ (thread-start!
+ (make-thread
+ (lambda ()
+ (with-catch (lambda (_failure) 'refused)
+ (lambda ()
+ (aitia-retirement-host-close-ingress! host)
+ 'accepted))))))))
+ (check result => 'refused)
+ (check (.ref (aitia-retirement-host-snapshot host) 'ingress-open?) => #t)))
+ (test-case "a reentrant handoff cannot retire before it returns"
+ (let* ((host (ready-for-review (aitia-retirement-host)))
+ (premature 'not-attempted)
+ (handoff
+ (aitia-retirement-effect-handoff
+ (lambda ()
+ (set! premature
+ (with-catch (lambda (_failure) 'refused)
+ (lambda ()
+ (aitia-retirement-host-observe-completion! host)
+ (aitia-retirement-host-close-ingress! host)
+ (accepted? (aitia-retirement-host-retire! host)))))))))
+ (aitia-retirement-host-review-cut! host)
+ (aitia-retirement-host-request-start! host)
+ (check (accepted? (aitia-retirement-host-attempt-start! host handoff)) => #t)
+ (check premature => 'refused)
+ (check (.ref (aitia-retirement-host-snapshot host) 'active?) => #t)
+ (check (.ref (aitia-retirement-host-snapshot host) 'retired?) => #f)))
+ (test-case "post-retirement cached grant cannot execute the handoff"
+ (let* ((host (ready-for-review (aitia-retirement-host)))
+ (calls 0)
+ (handoff (aitia-retirement-effect-handoff
+ (lambda () (set! calls (+ calls 1))))))
+ (aitia-retirement-host-review-cut! host)
+ (aitia-retirement-host-close-ingress! host)
+ (check (accepted? (aitia-retirement-host-retire! host)) => #t)
+ (check (accepted? (aitia-retirement-host-request-start! host)) => #t)
+ (let (result (aitia-retirement-host-attempt-start! host handoff))
+ (check (accepted? result) => #f)
+ (check (reason result) => 'stale-grant)
+ (check (.ref result 'handoff-executed?) => #f))
+ (check calls => 0)
+ (check (.ref (aitia-retirement-host-snapshot host) 'active?) => #f)
+ (check (.ref (aitia-retirement-host-snapshot host) 'retired?) => #t)))))
diff --git a/t/formal/retirement-replay-test.ss b/t/formal/retirement-replay-test.ss
new file mode 100644
index 0000000..a0ab855
--- /dev/null
+++ b/t/formal/retirement-replay-test.ss
@@ -0,0 +1,85 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; ITF is projected to data, never evaluated. The native test lifecycle owns
+;;; execution; the Quint runner only supplies model states and action names.
+(import :std/test
+ (only-in :clan/poo/object .ref)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/retirement-host)
+(export retirement-replay-test)
+
+(def (invoke-action name host handoff)
+ (case name
+ ((init Terminal) #f)
+ ((RequestCancellation) (aitia-retirement-host-request-cancellation! host))
+ ((ObserveCompletion) (aitia-retirement-host-observe-completion! host))
+ ((ObserveQueueDrained) (aitia-retirement-host-observe-queue-drained! host))
+ ((CompleteInventory) (aitia-retirement-host-complete-inventory! host))
+ ((ReviewCut) (aitia-retirement-host-review-cut! host))
+ ((ObserveLateActivity) (aitia-retirement-host-observe-late-activity! host))
+ ((ObserveInventoryGap) (aitia-retirement-host-observe-inventory-gap! host))
+ ((CloseIngress) (aitia-retirement-host-close-ingress! host))
+ ((Request) (aitia-retirement-host-request-start! host))
+ ((Start Reject TrustCachedGrant) (aitia-retirement-host-attempt-start! host handoff))
+ ((Retire RetireWithoutFence) (aitia-retirement-host-retire! host))
+ (else (error "unknown replay action" name))))
+
+(def (check-state host expected)
+ (let (snapshot (aitia-retirement-host-snapshot host))
+ (for-each (lambda (field)
+ (check (.ref snapshot (car field)) => (cadr field))) expected)
+ (check (.ref snapshot 'handoff-in-progress?) => #f)))
+
+(def (replay lane trace)
+ (let* ((host (aitia-retirement-host))
+ (calls 0)
+ (expected-calls 0)
+ (handoff (aitia-retirement-effect-handoff
+ (lambda () (set! calls (+ calls 1))))))
+ (let loop ((states trace))
+ (unless (null? states)
+ (let* ((row (car states)) (name (car row))
+ (before (aitia-retirement-host-snapshot host))
+ (result (invoke-action name host handoff))
+ (fault? (and (not (eq? lane 'safe)) (null? (cdr states)))))
+ (cond
+ (fault?
+ (check (memq name '(RetireWithoutFence TrustCachedGrant)) ? pair?)
+ (check (.ref result 'accepted?) => #f)
+ (check (.ref result 'handoff-executed?) => #f)
+ (check (.ref result 'reason)
+ => (if (eq? name 'RetireWithoutFence) 'ingress-open 'stale-grant))
+ ;; The intentionally unsafe model's final state must NOT match
+ ;; Scheme. Compare the unchanged cut, except consumed start flags.
+ (for-each
+ (lambda (slot)
+ (check (.ref (aitia-retirement-host-snapshot host) slot)
+ => (.ref before slot)))
+ '(active? queued? retired? ingress-open? authority-epoch))
+ (when (eq? name 'TrustCachedGrant)
+ (check (.ref (aitia-retirement-host-snapshot host) 'pending?) => #f)
+ (check (.ref (aitia-retirement-host-snapshot host) 'attempted?) => #t)))
+ (else
+ (when result
+ (check (.ref result 'accepted?) => (not (eq? name 'Reject)))
+ (check (.ref result 'handoff-executed?)
+ => (if (memq name '(Start TrustCachedGrant)) #t #f)))
+ (when (memq name '(Start TrustCachedGrant))
+ (set! expected-calls (+ expected-calls 1)))
+ (check-state host (cadr row))))
+ (check calls => expected-calls)
+ (loop (cdr states)))))))
+
+(def retirement-replay-test
+ (test-suite "Quint MBT / real Scheme Host correspondence"
+ (test-case "safe state traces and typed unsafe-model refusals"
+ (let (fixture (getenv "AITIA_QUINT_REPLAY" #f))
+ (unless fixture (error "run via just check-quint-scheme; model traces are required"))
+ (let (lanes (call-with-input-file fixture read))
+ (check (map car lanes) => '(safe unfenced cached))
+ (for-each
+ (lambda (lane)
+ (check (pair? (cadr lane)) => #t)
+ (for-each (lambda (trace) (replay (car lane) trace)) (cadr lane)))
+ lanes))))))
diff --git a/t/gitops/build-root.ss b/t/gitops/build-root.ss
index 9229324..b0810f3 100644
--- a/t/gitops/build-root.ss
+++ b/t/gitops/build-root.ss
@@ -2,6 +2,6 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/gitops/interface)
+(import :agentic-ai-lab/lambda-aitia/modules/gitops/interface)
(export gitops-test-fixtures-loaded?)
(def gitops-test-fixtures-loaded? #t)
diff --git a/t/gitops/unit/gitops-protocol-test.ss b/t/gitops/unit/gitops-protocol-test.ss
index 83de2e1..7f82026 100644
--- a/t/gitops/unit/gitops-protocol-test.ss
+++ b/t/gitops/unit/gitops-protocol-test.ss
@@ -5,8 +5,8 @@
(import :std/test
(only-in :clan/poo/object .cc .ref)
(only-in :clan/poo/mop element?)
- :poo-flow/src/module-system/poo-clos/interface
- :poo-flow/lambda-aitia/modules/gitops/interface)
+ :agentic-ai-lab/core/poo-clos/interface
+ :agentic-ai-lab/lambda-aitia/modules/gitops/interface)
(export gitops-protocol-test)
(.defclass TestGitOpsEvaluator (GitOpsEvaluator) ())
diff --git a/t/integration/github-workflow-test.ss b/t/integration/github-workflow-test.ss
index 4c2da9e..087a498 100644
--- a/t/integration/github-workflow-test.ss
+++ b/t/integration/github-workflow-test.ss
@@ -3,31 +3,55 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import :std/test
+ (only-in :std/list/list find)
(only-in :clan/poo/object .ref)
- :poo-flow/src/module-system/profile-composition/interface
- :poo-flow/lambda-aitia/user-interface/config
- :poo-flow/lambda-aitia/user-interface/scenarios/github-gitops)
+ :agentic-ai-lab/lambda-aitia/user-interface/config
+ :agentic-ai-lab/lambda-aitia/user-interface/profiles/nasa/sdlc
+ :agentic-ai-lab/lambda-aitia/user-interface/scenarios/github-gitops)
(export github-workflow-test)
-(def repository "tao3k/poo-flow")
+(def repository "tao3k/agentic-ai-lab")
(def revision "0123456789abcdef")
+(def nasa-standard (car (.ref nasa-sdlc-npr7150_2 'standards)))
+(def (nasa-check (edition (.ref nasa-standard 'edition))
+ (digest (.ref nasa-standard 'source-lock-digest)))
+ (github-check 'nasa/sdlc/npr-7150.2 repository revision 'success
+ standard-edition: edition source-lock-digest: digest))
(def (successful-checks names (at-revision revision))
- (map (lambda (name) (github-check name repository at-revision 'success)) names))
-(def dev-checks '(commit-policy build unit-test nasa-7150-2d))
+ (map (lambda (name)
+ (if (eq? name 'nasa/sdlc/npr-7150.2)
+ (github-check name repository at-revision 'success
+ standard-edition: (.ref nasa-standard 'edition)
+ source-lock-digest:
+ (.ref nasa-standard 'source-lock-digest))
+ (github-check name repository at-revision 'success)))
+ names))
+(def dev-checks '(commit-policy build unit-test nasa/sdlc/npr-7150.2))
(def (run-github-gitops change checks)
(github-run-gitops github-gitops-sdlc change checks))
(def github-workflow-test
(test-suite "GitHub GitOps SDLC lifecycle"
(test-case "Dev Staging Production are GitOps Profiles; NASA is one Standard"
- (check-equal? (poo-flow-scenario-case-name github-gitops-sdlc)
+ (check-equal? (.ref github-gitops-sdlc 'name)
'github-gitops-sdlc)
(check-equal? (map (lambda (profile) (.ref profile 'name))
- (poo-flow-scenario-case-profiles github-gitops-sdlc))
- '(actions dev staging production nasa-7150-2d))
+ (.ref github-gitops-sdlc 'profiles))
+ '(actions dev staging production nasa/sdlc/npr-7150.2))
(check-equal? (map (lambda (standard) (.ref standard 'identity))
- (.ref nasa-7150-2d 'standards))
- '("nasa/npr-7150.2d")))
+ (.ref nasa-sdlc-npr7150_2 'standards))
+ '("nasa/sdlc/npr-7150.2"))
+ (check-equal? (map (lambda (standard) (.ref standard 'edition))
+ (.ref nasa-sdlc-npr7150_2 'standards))
+ '("D"))
+ (let* ((proof
+ (find (lambda (value)
+ (eq? (.ref value 'profile-identity) 'npr-7150.2))
+ (.ref github-gitops-sdlc 'selection-proofs)))
+ (module-id (.ref proof 'module-definition)))
+ (check-equal? (.ref module-id 'namespace) 'nasa)
+ (check-equal? (.ref module-id 'name) 'sdlc)
+ (check-equal? (.ref proof 'profile-identity) 'npr-7150.2)))
(test-case "PR into develop advances Dev only with current checks and Standard assessment"
(let* ((change (github-change 'pull-request repository revision
"feature/gitops" "develop" 42))
@@ -36,7 +60,7 @@
(check-equal? (.ref decision 'environment) 'dev)
(check-equal? (.ref decision 'accepted) #t)
(check-equal? (.ref decision 'next-profile) 'staging)
- (check-equal? (.ref decision 'standards) '(nasa-7150-2d))))
+ (check-equal? (.ref decision 'standards) '(nasa/sdlc/npr-7150.2))))
(test-case "missing NASA assessment fails closed"
(let (decision
(run-github-gitops
@@ -44,7 +68,34 @@
"feature/gitops" "develop" 42)
(successful-checks '(commit-policy build unit-test))))
(check-equal? (.ref decision 'accepted) #f)
- (check-equal? (.ref decision 'missing-checks) '(nasa-7150-2d))))
+ (check-equal? (.ref decision 'missing-checks) '(nasa/sdlc/npr-7150.2))))
+ (test-case "same-name green check without an edition-bound source lock fails closed"
+ (let (decision
+ (run-github-gitops
+ (github-change 'pull-request repository revision
+ "feature/gitops" "develop" 42)
+ (append (successful-checks '(commit-policy build unit-test))
+ (list (github-check 'nasa/sdlc/npr-7150.2
+ repository revision 'success)))))
+ (check-equal? (.ref decision 'accepted) #f)
+ (check-equal? (.ref decision 'stale-checks) '(nasa/sdlc/npr-7150.2))
+ (check-equal? (.ref decision 'reasons)
+ '(standard-assessment-mismatch))))
+ (test-case "wrong NASA edition or source lock cannot authorize promotion"
+ (for-each
+ (lambda (check)
+ (let (decision
+ (run-github-gitops
+ (github-change 'pull-request repository revision
+ "feature/gitops" "develop" 42)
+ (append (successful-checks '(commit-policy build unit-test))
+ (list check))))
+ (check-equal? (.ref decision 'accepted) #f)
+ (check-equal? (.ref decision 'reasons)
+ '(standard-assessment-mismatch))))
+ (list (nasa-check "C") (nasa-check
+ (.ref nasa-standard 'edition)
+ "sha256:wrong-lock"))))
(test-case "checks for another Git revision cannot authorize promotion"
(let (decision
(run-github-gitops
@@ -58,13 +109,13 @@
(run-github-gitops
(github-change 'push repository revision "develop" "develop" #f)
(successful-checks
- '(integration-test security-review nasa-7150-2d))))
+ '(integration-test security-review nasa/sdlc/npr-7150.2))))
(production-decision
(run-github-gitops
(github-change 'workflow-dispatch repository revision
"develop" "production" #f)
(successful-checks
- '(release-authority signed-provenance nasa-7150-2d)))))
+ '(release-authority signed-provenance nasa/sdlc/npr-7150.2)))))
(check-equal? (.ref staging-decision 'profile) 'staging)
(check-equal? (.ref staging-decision 'next-profile) 'production)
(check-equal? (.ref production-decision 'profile) 'production)
diff --git a/t/modules/build-root.ss b/t/modules/build-root.ss
index e7f1b78..cc8a359 100644
--- a/t/modules/build-root.ss
+++ b/t/modules/build-root.ss
@@ -2,7 +2,7 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/gitops/interface
- :poo-flow/lambda-aitia/modules/sdlc/interface)
+(import :agentic-ai-lab/lambda-aitia/modules/gitops/interface
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface)
(export lambda-aitia-module-test-fixtures-loaded?)
(def lambda-aitia-module-test-fixtures-loaded? #t)
diff --git a/t/modules/unit/composition-identity-test.ss b/t/modules/unit/composition-identity-test.ss
index 01d81ef..98a9fc8 100644
--- a/t/modules/unit/composition-identity-test.ss
+++ b/t/modules/unit/composition-identity-test.ss
@@ -5,78 +5,52 @@
(import (only-in :std/test check-equal? test-case test-suite)
(only-in :clan/poo/object .ref)
- (only-in :poo-flow/src/module-system/profile-composition/interface
- poo-flow-composition-catalog-ref
- poo-flow-composition-identity-official?
- poo-flow-composition-identity-qualified-name
- poo-flow-load-composition-value
- poo-flow-scenario-case?)
- (only-in :poo-flow/src/module-system/declaration/interface
- poo-flow-user-module-selection-flags
- poo-flow-user-module-selection-key)
- (only-in :poo-flow/src/modules/proof/interface
- poo-flow-proof-module?)
- (only-in :poo-flow/src/user-interface/profile-core
- poo-flow-user-profile-modules)
- :poo-flow/lambda-aitia/modules/formal-methods/interface
- :poo-flow/lambda-aitia/user-interface/compositions/aitia)
+ (only-in :agentic-ai-lab/modules/workflow/scenario/case
+ agentic-ai-lab-scenario-case?)
+ (only-in :yuanxu/module-system/selection/objects
+ agentic-ai-lab-user-module-selection-flags
+ agentic-ai-lab-user-module-selection-key)
+ (only-in :yuanxu/profile-composition/user-profile
+ agentic-ai-lab-user-profile-modules)
+ (only-in :agentic-ai-lab/modules/proof/interface
+ agentic-ai-lab-proof-module?)
+ :agentic-ai-lab/lambda-aitia/modules/formal-methods/interface
+ :agentic-ai-lab/lambda-aitia/user-interface/compositions/aitia)
(export lambda-aitia-composition-identity-test)
(def lambda-aitia-composition-identity-test
(test-suite
- "official Aitia Composition identity"
- (test-case "publishes Aitia through the reserved unqualified selector"
- (check-equal?
- (poo-flow-composition-identity-qualified-name
- aitia-composition-identity)
- 'aitia)
- (check-equal?
- (poo-flow-composition-identity-official?
- aitia-composition-identity)
- #t))
- (test-case "registers the official Aitia value without namespace fallback"
- (check-equal?
- (eq? (poo-flow-composition-catalog-ref
- aitia-composition-catalog 'aitia)
- aitia-composition)
- #t)
- (check-equal?
- (.ref aitia-composition-catalog 'module-names)
- '(gitops sdlc ADR assurance formal-methods)))
- (test-case "default Profile selects the complete software engineering closure"
+ "official Aitia native Profile composition"
+ (test-case "Aitia owns one qualified semantic Module"
+ (check-equal? (.ref (.ref AitiaModule 'identity) 'namespace)
+ 'software-engineering)
+ (check-equal? (.ref (.ref AitiaModule 'identity) 'name) 'aitia))
+ (test-case "root is one closed Agentic AI Lab Case"
+ (check-equal? (agentic-ai-lab-scenario-case? aitia) #t)
+ (check-equal? (.ref aitia 'name) 'aitia)
+ (check-equal? (length (.ref aitia 'profiles)) 1)
+ (check-equal? (length (.ref aitia 'profile-bindings)) 1)
+ (check-equal? (length (.ref aitia 'selection-proofs)) 1)
+ (check-equal? (.ref (.ref aitia 'admission) 'accepted?) #t)
+ (check-equal? (.ref aitia 'runtime-executed?) #f))
+ (test-case "default Project selects the complete software engineering closure"
(let (modules
- (poo-flow-user-profile-modules
- (.ref aitia-composition 'default-profile)))
+ (agentic-ai-lab-user-profile-modules (car (.ref aitia 'profiles))))
(check-equal?
- (map poo-flow-user-module-selection-key modules)
+ (map agentic-ai-lab-user-module-selection-key modules)
'((software-engineering . gitops)
(software-engineering . sdlc)
+ (nasa . sdlc)
(software-engineering . ADR)
(software-engineering . assurance)
(software-engineering . formal-methods)))
(check-equal?
- (poo-flow-user-module-selection-flags (list-ref modules 4))
- '(+tla+ +lean +cedar))))
- (test-case "formal-method declarations reuse the POO Flow Proof module"
- (check-equal? (poo-flow-proof-module? aitia-formal-methods-module) #t)
- (check-equal? (.ref aitia-tla-plus-provider 'runtime-executed?) #f)
+ (agentic-ai-lab-user-module-selection-flags (list-ref modules 5))
+ '(+quint +lean +cedar))))
+ (test-case "formal-method declarations reuse the Agentic AI Lab Proof module"
+ (check-equal? (agentic-ai-lab-proof-module? aitia-formal-methods-module) #t)
+ (check-equal? (.ref aitia-quint-provider 'runtime-executed?) #f)
(check-equal? (.ref aitia-lean-provider 'obligation-only?) #t)
(check-equal? (.ref aitia-cedar-provider 'role)
- 'authorization-policy-validation))
- (test-case "loads the downstream file as one closed Case"
- (let (case-value
- (poo-flow-load-composition-value
- "t/fixtures/composition-value/aitia.ss"
- aitia-composition-catalog))
- (check-equal? (poo-flow-scenario-case? case-value) #t)
- (check-equal? (.ref case-value 'name) 'aitia)
- (check-equal? (length (.ref case-value 'profiles)) 1)
- (check-equal? (length (.ref case-value 'stages)) 1)
- (check-equal?
- (.ref (.ref (car (.ref case-value 'profiles)) 'project) 'repository)
- "tao3k/lambda-aitia")
- (check-equal?
- (.ref (.ref (car (.ref case-value 'profiles)) 'delivery) 'provider)
- 'github)
- (check-equal? (.ref (.ref case-value 'admission) 'accepted?) #t)))))
+ 'authorization-policy-validation))))
diff --git a/t/modules/unit/source-collection-test.ss b/t/modules/unit/source-collection-test.ss
index 87094b8..bdb72fc 100644
--- a/t/modules/unit/source-collection-test.ss
+++ b/t/modules/unit/source-collection-test.ss
@@ -3,29 +3,27 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import (only-in :std/test check-equal? test-case test-suite)
- (only-in :poo-flow/src/module-system/loader/source
- poo-flow-module-source-ref-metadata
- poo-flow-module-source-ref-value)
- (only-in :poo-flow/src/module-system/loader/module-source-interface
- make-poo-flow-contribution-module-source
- poo-flow-load-modules))
+ (only-in :agentic-ai-lab/core/module-system/source/objects
+ agentic-ai-lab-module-source-ref-metadata
+ agentic-ai-lab-module-source-ref-value)
+ (only-in :yuanxu/module-system/source/collection make-agentic-ai-lab-contribution-module-source agentic-ai-lab-module-source-collection-interfaces))
(export lambda-aitia-source-collection-test)
(def (metadata-ref source-ref key)
- (let (entry (assq key (poo-flow-module-source-ref-metadata source-ref)))
+ (let (entry (assq key (agentic-ai-lab-module-source-ref-metadata source-ref)))
(and entry (cdr entry))))
(def lambda-aitia-module-source
- (make-poo-flow-contribution-module-source
+ (make-agentic-ai-lab-contribution-module-source
'lambda-aitia "."))
(def lambda-aitia-source-collection-test
(test-suite "Aitia module ownership and registered load path"
(test-case "Aitia discovers its complete software engineering module set"
- (let (sources (poo-flow-load-modules lambda-aitia-module-source))
+ (let (sources (agentic-ai-lab-module-source-collection-interfaces lambda-aitia-module-source))
(check-equal?
- (map poo-flow-module-source-ref-value sources)
+ (map agentic-ai-lab-module-source-ref-value sources)
'("modules/ADR/interface.ss"
"modules/assurance/interface.ss"
"modules/formal-methods/interface.ss"
@@ -37,9 +35,9 @@
(custom . gitops) (custom . sdlc)))))
(test-case "the package-local GitOps module retains Aitia ownership"
- (let* ((sources (poo-flow-load-modules lambda-aitia-module-source))
+ (let* ((sources (agentic-ai-lab-module-source-collection-interfaces lambda-aitia-module-source))
(source (list-ref sources 3)))
(check-equal? (metadata-ref source 'source-collection) 'lambda-aitia)
(check-equal?
- (poo-flow-module-source-ref-value source)
+ (agentic-ai-lab-module-source-ref-value source)
"modules/gitops/interface.ss")))))
diff --git a/t/modules/unit/testing-memory-profile-test.ss b/t/modules/unit/testing-memory-profile-test.ss
index 90ee49f..ffed5a0 100644
--- a/t/modules/unit/testing-memory-profile-test.ss
+++ b/t/modules/unit/testing-memory-profile-test.ss
@@ -8,7 +8,7 @@
(only-in :asp-gerbil-scheme/testing-api
testing-interface-max-heap-mib-for
testing-interface-runtime-options-for)
- (only-in :poo-flow/lambda-aitia/testing-interface
+ (only-in :agentic-ai-lab/lambda-aitia/testing-interface
+lambda-aitia-testing-interface+))
(export testing-memory-profile-test)
diff --git a/t/qualification/nasa-complete-source-review.org b/t/qualification/nasa-complete-source-review.org
index 3d95404..d3294c1 100644
--- a/t/qualification/nasa-complete-source-review.org
+++ b/t/qualification/nasa-complete-source-review.org
@@ -97,4 +97,4 @@ natural-language requirement or referenced NASA standard has been satisfied.
Evidence content, signer authority/delegation, project classification, declared
scope completeness, and signature authenticity require independent verification.
The module never certifies NASA compliance or authorizes a release. The whole
-POO Flow release/install suite was not evaluated by these independent lanes.
+Agentic AI Lab release/install suite was not evaluated by these independent lanes.
diff --git a/t/qualification/nasa-verified-lifecycle.org b/t/qualification/nasa-verified-lifecycle.org
index 5c12f30..52d17d2 100644
--- a/t/qualification/nasa-verified-lifecycle.org
+++ b/t/qualification/nasa-verified-lifecycle.org
@@ -24,7 +24,7 @@ their selected requirements. Mixed project/institutional policies fail.
flowchart LR
A["POO project and evidence snapshots"] --> B["NASA verification request"]
B --> C["Host configured verification operation"]
- C --> D["POO Flow session receipt issuance"]
+ C --> D["Agentic AI Lab session receipt issuance"]
D --> E["NASA current snapshot and expiry checks"]
A --> E
E --> F["Cumulative stage decision"]
@@ -50,7 +50,7 @@ contains no default approval callback.
* Native qualification
-The Lambda Aitia vertical now also closes over POO Flow's domain-neutral
+The Lambda Aitia vertical now also closes over Agentic AI Lab's domain-neutral
Standards protocol. The focused Provider test proves that exact resolution
selects one edition and six source references without source I/O, explicit
materialization admits 198,644 source bytes only after content identity checks,
@@ -72,7 +72,7 @@ commands. Final totals and warm measurements follow below. The complete 100- and
named synthetic verifiers and all source-paragraph records; missing evidence
and revoked receipts independently block those baselines.
-Current reproduction from the containing POO Flow checkout:
+Current reproduction from the containing Agentic AI Lab checkout:
#+begin_src sh
just check-contribute lambda-aitia sdlc
@@ -117,7 +117,7 @@ silently recomputed from the newer child-only run.
| Lane | Native checks | Result |
|---+---+---|
-| POO Flow contribution contract/build/testing/model/verification | 50 | passed |
+| Agentic AI Lab contribution contract/build/testing/model/verification | 50 | passed |
| Independent contribution unit | 448 | passed |
| Independent contribution user-interface | 78 | passed |
| Independent contribution source | 12 | passed |
diff --git a/t/qualification/sdlc-condition-and-trace.org b/t/qualification/sdlc-condition-and-trace.org
index a56bf25..8d7c09c 100644
--- a/t/qualification/sdlc-condition-and-trace.org
+++ b/t/qualification/sdlc-condition-and-trace.org
@@ -7,10 +7,10 @@
* Verified scope
Native module build and independent directory-based user-case build passed in
-isolated child output against the POO Flow libraries. The seven child suites
+isolated child output against the Agentic AI Lab libraries. The seven child suites
passed 384 checks: governance 18, SDLC 17, config 7, source scenarios 39,
NASA catalog 268, trace/applicability 25, release scenario 10.
-POO Flow core contribution/build suites independently passed 14 checks.
+Agentic AI Lab core contribution/build suites independently passed 14 checks.
The separate parent source integration lane passed four checks through the
actual user-interface/init.ss and SDLC contribution projection.
diff --git a/t/sdlc/build-root.ss b/t/sdlc/build-root.ss
index 2cfbdec..50d045a 100644
--- a/t/sdlc/build-root.ss
+++ b/t/sdlc/build-root.ss
@@ -4,7 +4,7 @@
;;; -*- Gerbil -*-
;;; Atomic fixture root for t/sdlc/...
-(import :poo-flow/lambda-aitia/modules/sdlc/standards/interface)
+(import :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/interface)
(include "support/inventories.ss")
(export sdlc-test-fixtures-loaded?)
(def sdlc-test-fixtures-loaded? #t)
diff --git a/t/sdlc/source-admission-test.ss b/t/sdlc/source-admission-test.ss
index c41f7b9..a861aa3 100644
--- a/t/sdlc/source-admission-test.ss
+++ b/t/sdlc/source-admission-test.ss
@@ -16,10 +16,10 @@
(only-in :asp-gerbil-scheme/testing-source-admission-api
testing-interface-prepared-source-admission-suite)
(only-in :std/test check)
- (only-in :poo-flow/src/module-system/observability/source-admission
- poo-flow-source-admission-observability-profile-prototype
- poo-flow-observe-source-admission!
- poo-flow-source-admission)
+ (only-in :agentic-ai-lab/dev/modules/testing/source-admission
+ agentic-ai-lab-source-admission-observability-profile-prototype
+ agentic-ai-lab-observe-source-admission!
+ agentic-ai-lab-source-admission)
"./build-root")
(export sdlc-source-admission-test)
@@ -35,7 +35,7 @@
(def +prepared-graph-budget-us+ 100000)
(def +sdlc-source-admission-observability+
- (.o (:: @ poo-flow-source-admission-observability-profile-prototype)
+ (.o (:: @ agentic-ai-lab-source-admission-observability-profile-prototype)
(identity 'lambda-aitia/sdlc-source-admission)
(owner 'lambda-aitia)
(module 'sdlc)
@@ -49,9 +49,9 @@
.admit-prepared-source-graph:
(lambda (_test entries)
(let* ((root +lambda-contributor-root+)
- (receipt (poo-flow-observe-source-admission!
+ (receipt (agentic-ai-lab-observe-source-admission!
+sdlc-source-admission-observability+
- (poo-flow-source-admission root entries))))
+ (agentic-ai-lab-source-admission root entries))))
(check (.ref receipt 'admitted?) => #t)
;; The ASP source-admission slot is specifically a prepared-graph
;; contract. A cold import-closure replay can satisfy the broader
diff --git a/t/sdlc/support/inventories.ss b/t/sdlc/support/inventories.ss
index f18d781..b0e81fb 100644
--- a/t/sdlc/support/inventories.ss
+++ b/t/sdlc/support/inventories.ss
@@ -4,10 +4,10 @@
;;; Synthetic complete inventories shared by module-owned tests only.
(import (only-in :clan/poo/object .ref)
- :poo-flow/lambda-aitia/modules/sdlc/objects
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-review
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-structured
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/objects
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-review
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-structured
:std/list/list)
(def (test-inventories project class-value digest-value)
(let* ((rules (nasa-trace-rules class-value))
diff --git a/t/sdlc/unit/design-contract-test.ss b/t/sdlc/unit/design-contract-test.ss
new file mode 100644
index 0000000..f665852
--- /dev/null
+++ b/t/sdlc/unit/design-contract-test.ss
@@ -0,0 +1,179 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+(import :std/test :std/error
+ (only-in :clan/poo/object .ref)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface)
+
+(export design-contract-test)
+
+(def idempotency
+ (sdlc-design-assumption
+ "external-idempotency" "a1"
+ "The provider deduplicates tenant/job/operation keys"))
+(def unique-effect
+ (sdlc-design-guarantee
+ "unique-effect" "g1"
+ "At most one externally committed effect per operation key"))
+(def cancellation
+ (sdlc-design-guarantee
+ "cancel-before-commit" "g1"
+ "Cancellation before the commit point prevents a new commit"))
+(def retry-v1
+ (sdlc-design-variation "retry-policy" "v1" '("unique-effect")))
+(def retry-v2
+ (sdlc-design-variation "retry-policy" "v2" '("unique-effect")))
+
+(def (contract revision assumptions guarantees variations
+ effects: (effects '("external-operation"))
+ owned-state: (owned '("job-ledger"))
+ decision: (decision "ADR/job-executor"))
+ (sdlc-design-contract
+ "job-executor" revision decision '("execute-job") owned effects
+ assumptions guarantees variations))
+
+(def baseline
+ (contract "r1" (list idempotency) (list unique-effect cancellation)
+ (list retry-v1)))
+
+(def design-contract-test
+ (test-suite "SDLC design contract replacement"
+ (test-case "retry variation reopens only its declared guarantee"
+ (let* ((next (contract "r2" (list idempotency)
+ (list unique-effect cancellation) (list retry-v2)))
+ (review (sdlc-design-replacement-review baseline next))
+ (project (sdlc-project "job-service" "r2" "software" #t))
+ (retry-node (sdlc-trace-node "retry-policy" 'design project))
+ (guarantee-node (sdlc-trace-node "unique-effect" 'design project))
+ (verification-node
+ (sdlc-trace-node "verify-unique-effect" 'verification project))
+ (edges
+ (list (sdlc-trace-edge "retry-to-guarantee" "design-depends-on"
+ "retry-policy" "unique-effect" project)
+ (sdlc-trace-edge "guarantee-to-check" "design-depends-on"
+ "unique-effect" "verify-unique-effect" project)))
+ (impact
+ (sdlc-change-impact project
+ (list retry-node guarantee-node verification-node)
+ edges (.ref review 'changed-identities)
+ '("design-depends-on"))))
+ (check-equal? (.ref review 'declared-substitutable?) #f)
+ (check-equal? (.ref review 'blockers) '(variation-changed))
+ (check-equal? (.ref review 'changed-identities) '("retry-policy"))
+ (check-equal? (.ref review 'recheck-guarantees) '("unique-effect"))
+ (check-equal? (.ref impact 'recheck-verifications)
+ '("verify-unique-effect"))
+ (check-equal? (.ref review 'evidence-admitted?) #f)
+ (check-equal? (.ref review 'release-authorized?) #f)))
+ (test-case "new provider assumption cannot masquerade as compatible"
+ (let* ((extra (sdlc-design-assumption
+ "provider-available" "a1" "Provider is always available"))
+ (next (contract "r2" (list idempotency extra)
+ (list unique-effect cancellation) (list retry-v1)))
+ (review (sdlc-design-replacement-review baseline next)))
+ (check-equal? (.ref review 'blockers)
+ '(stronger-or-changed-assumption))
+ (check-equal? (.ref review 'recheck-guarantees)
+ '("cancel-before-commit" "unique-effect"))))
+ (test-case "a weakened guarantee or added effect is an explicit blocker"
+ (let* ((weakened-effect
+ (sdlc-design-guarantee
+ "unique-effect" "g2"
+ "At most two externally committed effects per operation key"))
+ (weakened (contract "r2" (list idempotency)
+ (list weakened-effect cancellation)
+ (list retry-v1)))
+ (more-effects
+ (contract "r2" (list idempotency)
+ (list unique-effect cancellation) (list retry-v1)
+ effects: '("external-operation" "audit-write"))))
+ (check-equal?
+ (.ref (sdlc-design-replacement-review baseline weakened) 'blockers)
+ '(weaker-or-changed-guarantee))
+ (check-equal?
+ (.ref (sdlc-design-replacement-review baseline more-effects) 'blockers)
+ '(new-effect))))
+ (test-case "lost ACK exposes the difference between a key and a logical operation"
+ (let* ((logical-effect
+ (sdlc-design-guarantee
+ "unique-effect" "g2"
+ "At most one external commit per logical job operation across retries and restarts"))
+ (revised (contract "r2" (list idempotency)
+ (list logical-effect cancellation)
+ (list retry-v2)))
+ (review (sdlc-design-replacement-review baseline revised))
+ (with-adr (contract "r2" (list idempotency)
+ (list logical-effect cancellation)
+ (list retry-v2)
+ decision: "lambda-aitia-adr-0008"))
+ (decision-review
+ (sdlc-design-replacement-review baseline with-adr)))
+ (check-equal? (.ref review 'declared-substitutable?) #f)
+ (check-equal? (.ref review 'recheck-guarantees) '("unique-effect"))
+ (check-equal? (.ref decision-review 'recheck-guarantees)
+ '("cancel-before-commit" "unique-effect"))
+ (check-equal? (.ref review 'evidence-admitted?) #f)
+ (check-equal? (.ref review 'release-authorized?) #f)))
+ (test-case "declaration-level compatibility never admits new evidence"
+ (let* ((next (contract "r2" '() (list unique-effect cancellation)
+ (list retry-v1)))
+ (review (sdlc-design-replacement-review baseline next)))
+ (check-equal? (.ref review 'declared-substitutable?) #t)
+ (check-equal? (.ref review 'recheck-guarantees)
+ '("cancel-before-commit" "unique-effect"))
+ (check-equal? (.ref (sdlc-design-replacement-review
+ baseline
+ (contract "r2" (list idempotency)
+ (list unique-effect cancellation)
+ (list retry-v1)))
+ 'changed-identities)
+ '("job-executor"))
+ (check-equal? (.ref review 'release-authorized?) #f)))
+ (test-case "changing the selected ADR reopens every guarantee"
+ (let (review
+ (sdlc-design-replacement-review
+ baseline
+ (contract "r2" (list idempotency)
+ (list unique-effect cancellation) (list retry-v1)
+ decision: "ADR/job-executor-v2")))
+ (check-equal? (.ref review 'blockers) '(decision-changed))
+ (check-equal? (.ref review 'changed-identities) '("job-executor"))
+ (check-equal? (.ref review 'recheck-guarantees)
+ '("cancel-before-commit" "unique-effect"))))
+ (test-case "local deduplication is a distinct design, not a proof-preserving override"
+ (let* ((alternative
+ (sdlc-design-contract
+ "job-executor" "r2" "ADR/local-deduplication"
+ '("execute-job" "reconcile-unknown-effect")
+ '("job-ledger" "dedup-ledger")
+ '("external-operation") '()
+ (list unique-effect cancellation) (list retry-v1)))
+ (review (sdlc-design-replacement-review baseline alternative)))
+ (check-equal? (.ref review 'declared-substitutable?) #f)
+ (check-equal? (.ref review 'blockers)
+ '(responsibility-changed state-ownership-changed
+ decision-changed))
+ (check-equal? (.ref review 'recheck-guarantees)
+ '("cancel-before-commit" "unique-effect"))))
+ (test-case "same revision mutation and orphan dependency fail closed"
+ (check-exception
+ (sdlc-design-replacement-review
+ baseline
+ (contract "r1" (list idempotency) (list cancellation)
+ (list retry-v1)))
+ Error?)
+ (check-exception
+ (contract "r2" (list idempotency) (list cancellation)
+ (list retry-v1))
+ Error?)
+ (check-exception
+ (contract "r2" (list idempotency idempotency)
+ (list unique-effect cancellation) (list retry-v1))
+ Error?)
+ (check-exception
+ (contract "r2" (list idempotency) '() '())
+ Error?)
+ (check-exception
+ (sdlc-design-variation "retry-policy" "v3" '())
+ Error?))))
diff --git a/t/sdlc/unit/design-implementation-test.ss b/t/sdlc/unit/design-implementation-test.ss
new file mode 100644
index 0000000..0e9525b
--- /dev/null
+++ b/t/sdlc/unit/design-implementation-test.ss
@@ -0,0 +1,105 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+(import :std/test :std/error
+ (only-in :clan/poo/object .ref)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/interface
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface)
+
+(export design-implementation-test)
+
+(def digest-a (string-append "sha256:" (make-string 64 #\a)))
+(def digest-b (string-append "sha256:" (make-string 64 #\b)))
+(def guarantee
+ (sdlc-design-guarantee "unique-effect" "g1" "At most one external commit"))
+(def cancellation
+ (sdlc-design-guarantee "cancel-before-commit" "g1" "No new commit after cancellation"))
+(def (contract revision guarantees)
+ (sdlc-design-contract "job-executor" revision "ADR/job-executor"
+ '("execute-job") '("job-ledger")
+ '("external-operation") '() guarantees '()))
+(def baseline (contract "r1" (list guarantee)))
+(def source
+ (assurance-artifact "artifact/job-executor" "s1" 'supported digest-a
+ owner: "lambda-aitia" media-kind: 'scheme-source
+ provenance: '("repository")))
+(def (snapshot source-value
+ source-revisions: (revisions (list (cons "artifact/job-executor" "s1")))
+ unresolved: (unresolved '()))
+ (assurance-snapshot "snapshot/job-executor" "cut-1" "graph/job-executor"
+ revisions '() "fact-cut-1" "policy/design" "p1"
+ (list source-value) '() unresolved: unresolved))
+(def current-snapshot (snapshot source))
+(def current-link
+ (sdlc-design-implementation-link baseline guarantee source current-snapshot))
+
+(def design-implementation-test
+ (test-suite "SDLC design to source mapping"
+ (test-case "exact assurance snapshot binding is current but not conformance"
+ (let (review
+ (sdlc-design-implementation-review baseline current-snapshot
+ (list current-link)))
+ (check-equal? (.ref review 'mapping-current?) #t)
+ (check-equal? (.ref review 'mapped-guarantees) '("unique-effect"))
+ (check-equal? (.ref review 'unmapped-guarantees) '())
+ (check-equal? (.ref review 'implementation-conforms?) #f)
+ (check-equal? (.ref review 'evidence-admitted?) #f)
+ (check-equal? (.ref review 'release-authorized?) #f)))
+ (test-case "new contract revision or unmapped guarantee reopens coverage"
+ (let* ((next (contract "r2" (list guarantee cancellation)))
+ (review (sdlc-design-implementation-review
+ next current-snapshot (list current-link))))
+ (check-equal? (.ref review 'mapping-current?) #f)
+ (check-equal? (.ref review 'unmapped-guarantees)
+ '("cancel-before-commit" "unique-effect"))
+ (check-equal? (.ref (car (.ref review 'blocked-links)) 'blocker)
+ 'contract-changed)))
+ (test-case "same-revision contract mutation cannot reuse an old link"
+ (let* ((changed-guarantee
+ (sdlc-design-guarantee "unique-effect" "g1" "At most two commits"))
+ (changed-contract (contract "r1" (list changed-guarantee)))
+ (review (sdlc-design-implementation-review
+ changed-contract current-snapshot (list current-link))))
+ (check-equal? (.ref review 'mapping-current?) #f)
+ (check-equal? (.ref (car (.ref review 'blocked-links)) 'blocker)
+ 'contract-changed)))
+ (test-case "source change invalidates exact snapshot binding"
+ (let* ((new-source
+ (assurance-artifact "artifact/job-executor" "s1" 'supported digest-b
+ owner: "lambda-aitia" media-kind: 'scheme-source
+ provenance: '("repository")))
+ (changed (snapshot new-source))
+ (review (sdlc-design-implementation-review
+ baseline changed (list current-link))))
+ (check-equal? (.ref review 'mapping-current?) #f)
+ (check-equal? (.ref review 'unmapped-guarantees) '("unique-effect"))
+ (check-equal? (.ref (car (.ref review 'blocked-links)) 'blocker)
+ 'snapshot-changed)))
+ (test-case "unbound source and unresolved snapshot cannot qualify"
+ (let* ((unbound (snapshot source source-revisions: '()))
+ (link (sdlc-design-implementation-link
+ baseline guarantee source unbound))
+ (review (sdlc-design-implementation-review baseline unbound
+ (list link)))
+ (frontier (snapshot source unresolved: '("artifact/missing")))
+ (frontier-link
+ (sdlc-design-implementation-link baseline guarantee source frontier))
+ (frontier-review
+ (sdlc-design-implementation-review baseline frontier
+ (list frontier-link))))
+ (check-equal? (.ref (car (.ref review 'blocked-links)) 'blocker)
+ 'source-unbound)
+ (check-equal? (.ref frontier-review 'mapping-current?) #f)
+ (check-equal? (.ref frontier-review 'snapshot-frontier?) #t)))
+ (test-case "a different source presentation cannot match a canonical cut"
+ (let* ((different
+ (assurance-artifact "artifact/job-executor" "s1" 'supported digest-b
+ owner: "lambda-aitia" media-kind: 'scheme-source
+ provenance: '("repository")))
+ (link (sdlc-design-implementation-link
+ baseline guarantee different current-snapshot))
+ (review (sdlc-design-implementation-review baseline current-snapshot
+ (list link))))
+ (check-equal? (.ref (car (.ref review 'blocked-links)) 'blocker)
+ 'source-changed)))))
diff --git a/t/sdlc/unit/design-verification-test.ss b/t/sdlc/unit/design-verification-test.ss
new file mode 100644
index 0000000..4212c0b
--- /dev/null
+++ b/t/sdlc/unit/design-verification-test.ss
@@ -0,0 +1,323 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+(import :std/test
+ (only-in :std/list/list find)
+ (only-in :clan/poo/object .o .ref)
+ (only-in :yuanxu/feature-system/source-lock-feature
+ source-lock-payload-digest)
+ :agentic-ai-lab/lambda-aitia/modules/assurance/interface
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface)
+
+(export design-verification-test)
+
+(def source-bytes "(def (execute-job) 'committed)\n")
+(def digest-a (source-lock-payload-digest source-bytes))
+(def digest-b (string-append "sha256:" (make-string 64 #\b)))
+(def guarantee
+ (sdlc-design-guarantee "unique-effect" "g1" "At most one external commit"))
+(def contract
+ (sdlc-design-contract "job-executor" "r1" "ADR/job-executor"
+ '("execute-job") '("job-ledger")
+ '("external-operation") '() (list guarantee) '()))
+(def source
+ (assurance-artifact "artifact/source" "s1" 'supported digest-a
+ owner: "lambda-aitia" media-kind: 'scheme-source
+ provenance: '("repository")))
+(def other-source
+ (assurance-artifact "artifact/other" "s1" 'supported digest-b
+ owner: "lambda-aitia" media-kind: 'scheme-source
+ provenance: '("repository")))
+(def claim
+ (assurance-claim "claim/unique-effect" "r1" 'unknown digest-a
+ subject: "job-executor"
+ predicate: "At most one external commit"
+ support-requirements: '("obligation/test")
+ scope: "repository" valid-from: "2026-09-24"))
+(def obligation
+ (assurance-obligation "obligation/test" "r1" 'unknown digest-a
+ subject: "job-executor" claim: "claim/unique-effect"
+ snapshot: "snapshot/job-executor"
+ evidence-kind: 'native-test capability: 'gerbil-test
+ scope: "repository"))
+(def evidence
+ (assurance-evidence "evidence/test" "r1" 'supported digest-b
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ input-artifacts: '("artifact/source")
+ obligation: "obligation/test" subject: "job-executor"
+ scope: "repository" valid-from: "2026-09-24"
+ admission-state: 'candidate))
+(def other-evidence
+ (assurance-evidence "evidence/test" "r1" 'supported digest-b
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ input-artifacts: '("artifact/other")
+ obligation: "obligation/test" subject: "job-executor"
+ scope: "repository" valid-from: "2026-09-24"
+ admission-state: 'candidate))
+(def evidence-link
+ (assurance-relation "relation/evidence" 'assurance 'discharges
+ "evidence/test" "obligation/test" 'observed))
+(def requirement-link
+ (assurance-relation "relation/requirement" 'assurance 'supports
+ "obligation/test" "claim/unique-effect" 'declared))
+(def source-link
+ (assurance-relation "relation/source" 'structural 'depends-on
+ "claim/unique-effect" "artifact/source" 'declared))
+
+(def (construct obligation-value evidence-value relation-values)
+ (assurance-snapshot
+ "snapshot/job-executor" "cut-1" "graph/job-executor"
+ '(("artifact/source" . "s1") ("artifact/other" . "s1"))
+ '(("claim/unique-effect" . "r1"))
+ "fact-cut-1" "policy/design" "p1"
+ (list source other-source claim obligation-value evidence-value) relation-values))
+(def (bound-cut relation-values evidence-value)
+ (let (draft (construct obligation evidence-value relation-values))
+ (construct (assurance-bind-obligation-to-snapshot obligation draft)
+ evidence-value relation-values)))
+(def (bound-obligation snapshot-value)
+ (find (lambda (node)
+ (equal? (.ref node 'identity) "obligation/test"))
+ (.ref snapshot-value 'nodes)))
+(def (outcome snapshot-value input-source)
+ (assurance-verifier-outcome
+ "outcome/test" 'succeeded
+ producer: "gxtest" tool: "gerbil-test" tool-version: "v19"
+ obligation: "obligation/test" subject: "job-executor" scope: "repository"
+ snapshot-revision: (.ref snapshot-value 'revision)
+ snapshot-context-digest: (.ref snapshot-value 'context-digest)
+ inputs: (list (assurance-verifier-input input-source))
+ output-digest: digest-b))
+(def (host source-procedure source-reader: (reader #f))
+ (assurance-verification-host
+ "host/design-verification"
+ (if reader
+ (lambda (subject-value issued-at expires-at inputs)
+ (and (= (length inputs) 1)
+ (equal? (.ref (car inputs) 'identity) "artifact/source")
+ (equal? (.ref (car inputs) 'payload) source-bytes)
+ (equal? (.ref (.ref subject-value 'outcome) 'output-digest)
+ digest-b)
+ (< issued-at expires-at)))
+ (lambda (subject-value issued-at expires-at)
+ (and (equal? (.ref (.ref subject-value 'outcome) 'output-digest)
+ digest-b)
+ (< issued-at expires-at))))
+ (lambda () 11) 9 source-procedure source-reader: reader))
+(def (review snapshot-value host-value input-source evidence-value)
+ (let* ((bound (bound-obligation snapshot-value))
+ (reported (outcome snapshot-value input-source))
+ (subject (assurance-verification-subject
+ snapshot-value bound evidence-value reported))
+ (admission (assurance-host-admit
+ host-value bound evidence-value reported))
+ (mapping
+ (sdlc-design-implementation-link contract guarantee source
+ snapshot-value)))
+ (values
+ (sdlc-design-guarantee-support-review
+ host-value contract guarantee (list mapping) claim subject
+ evidence-link admission (if admission (list admission) '()))
+ admission subject mapping)))
+
+(def design-verification-test
+ (test-suite "SDLC design guarantee Host support"
+ (test-case "source-bound Host admission closes support but not conformance"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ evidence))
+ (configured (host (lambda () cut))))
+ (let-values (((receipt admission subject mapping)
+ (review cut configured source evidence)))
+ (check-equal? (.ref receipt 'source-bound-support-current?) #t)
+ (check-equal? (.ref receipt 'source-bytes-checked-support-current?) #f)
+ (check-equal? (.ref receipt 'verifier-independence-established?) #f)
+ (check-equal? (.ref receipt 'implementation-conforms?) #f)
+ (check-equal? (.ref receipt 'release-authorized?) #f)
+ (check-equal? (.ref receipt 'runtime-executed?) #f))))
+ (test-case "Host-owned source bytes must match the mapped digest"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ evidence))
+ (configured
+ (host (lambda () cut)
+ source-reader: (lambda (identity)
+ (and (equal? identity "artifact/source")
+ source-bytes)))))
+ (let-values (((receipt admission subject mapping)
+ (review cut configured source evidence)))
+ (check-equal? (.ref receipt 'source-bytes-checked-support-current?) #t)
+ (check-equal? (.ref receipt 'verifier-independence-established?) #f)
+ (check-equal? (.ref receipt 'implementation-conforms?) #f))))
+ (test-case "changed Host bytes fail closed"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ evidence))
+ (payload "different")
+ (configured
+ (host (lambda () cut)
+ source-reader: (lambda (identity) payload))))
+ (let-values (((receipt admission subject mapping)
+ (review cut configured source evidence)))
+ (check-equal? admission #f)
+ (check-equal? (.ref receipt 'source-bound-support-current?) #f)
+ (check-equal? (.ref receipt 'source-bytes-checked-support-current?) #f)
+ (set! payload source-bytes)
+ (check-equal?
+ (.ref (sdlc-design-guarantee-support-review
+ configured contract guarantee (list mapping) claim subject
+ evidence-link admission '())
+ 'source-bytes-checked-support-current?)
+ #f)
+ (let-values (((fresh-receipt fresh-admission _subject _mapping)
+ (review cut configured source evidence)))
+ (check-equal? (if fresh-admission #t #f) #t)
+ (check-equal?
+ (.ref fresh-receipt 'source-bytes-checked-support-current?)
+ #t)))))
+ (test-case "issued source-bound admission cannot revive after byte drift"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ evidence))
+ (payload source-bytes)
+ (configured
+ (host (lambda () cut)
+ source-reader: (lambda (identity) payload))))
+ (let-values (((receipt admission subject mapping)
+ (review cut configured source evidence)))
+ (check-equal? (if admission #t #f) #t)
+ (check-equal? (.ref receipt 'source-bytes-checked-support-current?) #t)
+ (set! payload "different")
+ (check-equal?
+ (assurance-host-admission-current? configured admission) #f)
+ (set! payload source-bytes)
+ (check-equal?
+ (assurance-host-admission-current? configured admission) #f)
+ (let-values (((fresh-receipt fresh-admission _subject _mapping)
+ (review cut configured source evidence)))
+ (check-equal? (if fresh-admission #t #f) #t)
+ (check-equal?
+ (.ref fresh-receipt 'source-bytes-checked-support-current?)
+ #t)))))
+ (test-case "source bytes moving during verifier execution prevent issuance"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ evidence))
+ (payload source-bytes)
+ (configured
+ (assurance-verification-host
+ "host/source-race"
+ (lambda (subject issued-at expires-at inputs)
+ (check-equal? (.ref (car inputs) 'payload) source-bytes)
+ (set! payload "different")
+ #t)
+ (lambda () 11) 9 (lambda () cut)
+ source-reader: (lambda (identity) payload)))
+ (reported (outcome cut source)))
+ (check-equal?
+ (assurance-host-admit
+ configured (bound-obligation cut) evidence reported)
+ #f)))
+ (test-case "verifier cannot mutate handed source bytes and keep a seal"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ evidence))
+ (configured
+ (assurance-verification-host
+ "host/handed-input-mutation"
+ (lambda (subject issued-at expires-at inputs)
+ (let (input (car inputs))
+ (set-car! inputs
+ (.o identity: (.ref input 'identity)
+ revision: (.ref input 'revision)
+ digest: (source-lock-payload-digest "different")
+ payload: "different")))
+ #t)
+ (lambda () 11) 9 (lambda () cut)
+ source-reader: (lambda (identity) source-bytes)))
+ (reported (outcome cut source)))
+ (check-equal?
+ (assurance-host-admit
+ configured (bound-obligation cut) evidence reported)
+ #f)))
+ (test-case "a cut moving during Host source read fails closed"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ evidence))
+ (next (bound-cut (list evidence-link requirement-link)
+ evidence))
+ (current-cut cut)
+ (configured
+ (host (lambda () current-cut)
+ source-reader:
+ (lambda (identity)
+ (set! current-cut next)
+ source-bytes))))
+ (let-values (((receipt admission subject mapping)
+ (review cut configured source evidence)))
+ (check-equal? admission #f)
+ (check-equal? (.ref receipt 'source-bytes-checked-support-current?) #f))))
+ (test-case "design assumptions cannot disappear from the Assurance Claim"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ evidence))
+ (configured (host (lambda () cut)))
+ (assumed
+ (sdlc-design-contract
+ "job-executor" "r2" "ADR/job-executor"
+ '("execute-job") '("job-ledger") '("external-operation")
+ (list (sdlc-design-assumption
+ "provider-idempotency" "a1" "Provider deduplicates keys"))
+ (list guarantee) '()))
+ (reported (outcome cut source))
+ (bound (bound-obligation cut))
+ (subject (assurance-verification-subject
+ cut bound evidence reported))
+ (admission (assurance-host-admit configured bound evidence reported))
+ (mapping (sdlc-design-implementation-link
+ assumed guarantee source cut))
+ (receipt
+ (sdlc-design-guarantee-support-review
+ configured assumed guarantee (list mapping) claim subject
+ evidence-link admission (list admission))))
+ (check-equal? (.ref receipt 'mapping-current?) #t)
+ (check-equal? (.ref receipt 'claim-current?) #f)
+ (check-equal? (.ref receipt 'source-bound-support-current?) #f)))
+ (test-case "missing claim-to-source dependency blocks design support"
+ (let* ((cut (bound-cut (list evidence-link requirement-link) evidence))
+ (configured (host (lambda () cut))))
+ (let-values (((receipt admission subject mapping)
+ (review cut configured source evidence)))
+ (check-equal? (.ref receipt 'host-admission-current?) #t)
+ (check-equal? (.ref receipt 'source-input-bound?) #f)
+ (check-equal? (.ref receipt 'source-bound-support-current?) #f))))
+ (test-case "admission over another current source does not cover design source"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ other-evidence))
+ (configured (host (lambda () cut))))
+ (let-values (((receipt admission subject mapping)
+ (review cut configured other-source other-evidence)))
+ (check-equal? (.ref receipt 'host-admission-current?) #t)
+ (check-equal? (.ref receipt 'source-input-bound?) #f)
+ (check-equal? (.ref receipt 'source-bound-support-current?) #f))))
+ (test-case "revoked or copied admission cannot close support"
+ (let* ((cut (bound-cut (list evidence-link requirement-link source-link)
+ evidence))
+ (configured (host (lambda () cut))))
+ (let-values (((receipt admission subject mapping)
+ (review cut configured source evidence)))
+ (let ((copied (.o (:: @ admission)))
+ (before (.ref receipt 'source-bound-support-current?)))
+ (check-equal? before #t)
+ (check-equal?
+ (.ref (sdlc-design-guarantee-support-review
+ configured contract guarantee (list mapping) claim subject
+ evidence-link admission '())
+ 'source-bound-support-current?)
+ #f)
+ (check-equal?
+ (.ref (sdlc-design-guarantee-support-review
+ configured contract guarantee (list mapping) claim subject
+ evidence-link copied (list copied))
+ 'source-bound-support-current?)
+ #f)
+ (assurance-host-revoke-admission! configured admission)
+ (check-equal?
+ (.ref (sdlc-design-guarantee-support-review
+ configured contract guarantee (list mapping) claim subject
+ evidence-link admission (list admission))
+ 'source-bound-support-current?)
+ #f)))))))
diff --git a/t/sdlc/unit/job-retirement-impact-test.ss b/t/sdlc/unit/job-retirement-impact-test.ss
new file mode 100644
index 0000000..eecf4b6
--- /dev/null
+++ b/t/sdlc/unit/job-retirement-impact-test.ss
@@ -0,0 +1,91 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+(import :std/test
+ (only-in :clan/poo/object .ref)
+ (only-in :yuanxu/graph/types agentic-ai-lab-graph-id)
+ (only-in :agentic-ai-lab/modules/temporal-causality/interface
+ agentic-ai-lab-structural-impact-analyze
+ agentic-ai-lab-causal-cut agentic-ai-lab-temporal-causal-classify)
+ :agentic-ai-lab/lambda-aitia/user-interface/scenarios/job-executor-retirement)
+
+(export job-retirement-impact-test)
+
+(def (impact graph (complete? #t))
+ (agentic-ai-lab-structural-impact-analyze
+ graph '(automatic-retry) job-retirement-relations 'dependents complete?))
+
+(def (classify graph)
+ (agentic-ai-lab-temporal-causal-classify
+ graph (agentic-ai-lab-causal-cut graph 4) "retry-enabled" 7))
+
+(def job-retirement-impact-test
+ (test-suite "Job-executor retirement Impact qualification"
+ (test-case "old dependents survive analysis of a proposed removal"
+ (let* ((receipt (impact job-retirement-before))
+ (affected (.ref receipt 'affected-node-ids))
+ (witness
+ (car (filter (lambda (value)
+ (eq? (.ref value 'target-node-id) 'verify-queued-retry))
+ (.ref receipt 'relation-trajectories)))))
+ (check (length affected) => 5)
+ (for-each (lambda (id) (check (if (memq id affected) #t #f) => #t))
+ '(automatic-retry historical-result active-job queued-job
+ verify-queued-retry))
+ (check (memq 'unrelated-export affected) => #f)
+ (check (.ref witness 'node-path)
+ => '(automatic-retry queued-job verify-queued-retry))
+ (check (.ref witness 'relation-path) => '(USES_CAPABILITY VERIFIES))
+ (check (.ref receipt 'release-authorized?) => #f)
+ (check (.ref receipt 'runtime-executed?) => #f)))
+ (test-case "candidate graph cannot turn missing retired identity into no impact"
+ (let (before (impact job-retirement-before))
+ (check-exception (impact job-retirement-candidate) true)
+ (check (agentic-ai-lab-graph-id job-retirement-before)
+ => 'job-executor/before-retirement)
+ (check (.ref (impact job-retirement-before) 'affected-node-ids)
+ => (.ref before 'affected-node-ids))))
+ (test-case "unknown external inventory prevents scoped completeness"
+ (let (receipt (impact job-retirement-before #f))
+ (check (.ref receipt 'status) => 'partial-impact)
+ (check (.ref receipt 'release-authorized?) => #f)))
+ (test-case "past occurrence and current activity remain separate facts"
+ (let* ((cut (agentic-ai-lab-causal-cut job-retirement-event-graph 4))
+ (receipt (classify job-retirement-event-graph)))
+ (check (.ref receipt 'past-event-ids)
+ => '("retry-enabled" "historical-result" "job-started"))
+ (check (.ref receipt 'current-event-ids)
+ => '("job-still-active" "retirement-review"))
+ (check (.ref receipt 'future-event-ids) => '("queued-retry"))
+ (check (.ref receipt 'counterfactual-event-ids) => '("retire-retry"))
+ (check (.ref receipt 'outside-horizon-event-ids) => '("later-retry"))
+ (check (.ref receipt 'hypothesized-event-ids) => '())
+ (check (member "retire-retry"
+ (map (lambda (event) (.ref event 'identity))
+ (.ref cut 'events))) => #f)
+ (check (.ref receipt 'assurance-closed?) => #f)
+ (check (.ref receipt 'runtime-executed?) => #f)))
+ (test-case "later review does not rewrite the earlier historical cut"
+ (let* ((old (agentic-ai-lab-causal-cut job-retirement-event-graph 2))
+ (current (agentic-ai-lab-causal-cut job-retirement-event-graph 4))
+ (old-events (.ref old 'events))
+ (historical (cadr old-events)))
+ (check (map (lambda (event) (.ref event 'identity)) old-events)
+ => '("retry-enabled" "historical-result" "job-started"))
+ (check (.ref historical 'payload-identity) => "historical-result/payload")
+ (check (.ref historical 'modality) => 'observed)
+ (check (.ref historical 'committed?) => #t)
+ (check (if (memq historical (.ref current 'events)) #t #f) => #t)
+ (check (map (lambda (event) (.ref event 'identity)) (.ref old 'events))
+ => '("retry-enabled" "historical-result" "job-started"))))
+ (test-case "a missing causal parent remains an unknown frontier"
+ (let (receipt (classify job-retirement-incomplete-event-graph))
+ (check (.ref receipt 'status) => 'partial-temporal-classification)
+ (check (.ref receipt 'unknown-frontier) => '("unknown-consumer-origin"))
+ (check (.ref receipt 'release-authorized?) => #f)))
+ (test-case "a proposal cannot be promoted to the observed change trigger"
+ (check-exception
+ (agentic-ai-lab-temporal-causal-classify
+ job-retirement-event-graph (agentic-ai-lab-causal-cut job-retirement-event-graph 4)
+ "retire-retry" 7)
+ true))))
diff --git a/t/sdlc/unit/nasa-catalog-test.ss b/t/sdlc/unit/nasa-catalog-test.ss
index f66763a..369f111 100644
--- a/t/sdlc/unit/nasa-catalog-test.ss
+++ b/t/sdlc/unit/nasa-catalog-test.ss
@@ -3,8 +3,8 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import :std/test :std/error
- :poo-flow/src/module-system/contribution/interface
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
+ (only-in :clan/poo/object .ref .slot?)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
:std/list/list)
(export nasa-catalog-test)
(def nasa-catalog-test
@@ -15,7 +15,7 @@
(check-equal? (length (delete-duplicates/hash (map (lambda (r) (.ref r 'identity)) rows))) 130)
(check-equal? (length (filter (lambda (r) (.slot? r 'class-matrix)) rows)) 100)
(for-each (lambda (r)
- (check-equal? (.ref r 'standard) "nasa/npr-7150.2d")
+ (check-equal? (.ref r 'standard) "nasa/sdlc/npr-7150.2")
(check-equal? (.ref r 'assessment) 'not-evaluated)) rows)))
(test-case "matrix blanks never become unconditional exemptions"
(check-equal? (nasa-matrix-invocation "SWE-013" 'e) 'invoked)
diff --git a/t/sdlc/unit/nasa-certification-test.ss b/t/sdlc/unit/nasa-certification-test.ss
index 01d8469..6fe29cb 100644
--- a/t/sdlc/unit/nasa-certification-test.ss
+++ b/t/sdlc/unit/nasa-certification-test.ss
@@ -4,10 +4,10 @@
(import :std/test :std/error
(only-in :clan/poo/object .o .ref)
- :poo-flow/src/module-system/contribution/verification
- :poo-flow/lambda-aitia/modules/sdlc/objects
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-policy
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-certification)
+ :agentic-ai-lab/core/contribution/verification
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/objects
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-policy
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-certification)
(export nasa-certification-test)
@@ -76,7 +76,7 @@
(let* ((a (adapter))
(request (nasa-certification-verification-request
dossier compliant-decision))
- (receipt (poo-flow-verify a request 10 20))
+ (receipt (agentic-ai-lab-verify a request 10 20))
(review (nasa-certification-review
dossier compliant-decision a (list receipt) 11)))
(check-equal? (.ref review 'status)
@@ -102,7 +102,7 @@
"decision-rejected" dossier 'responsible-nasa-official
"authorized-reviewer" "records/rmm-rejection-7" 'noncompliant))
(request (nasa-certification-verification-request dossier decision))
- (receipt (poo-flow-verify a request 10 20))
+ (receipt (agentic-ai-lab-verify a request 10 20))
(review (nasa-certification-review dossier decision a (list receipt) 11)))
(check-equal? (.ref review 'status)
'noncompliant-by-verified-authority)
diff --git a/t/sdlc/unit/nasa-lifecycle-test.ss b/t/sdlc/unit/nasa-lifecycle-test.ss
index 7d95eb5..2cb9faa 100644
--- a/t/sdlc/unit/nasa-lifecycle-test.ss
+++ b/t/sdlc/unit/nasa-lifecycle-test.ss
@@ -4,12 +4,12 @@
(import :std/test :std/error
(only-in :clan/poo/object .o .ref)
- :poo-flow/src/module-system/contribution/verification
- :poo-flow/lambda-aitia/modules/sdlc/objects
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-coverage
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-review
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-lifecycle
+ :agentic-ai-lab/core/contribution/verification
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/objects
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-coverage
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-review
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-lifecycle
:std/list/list)
(include "../support/inventories.ss")
(def project (sdlc-project "test-flight" "r1" "software" #t))
@@ -30,8 +30,8 @@
((tailoring-decision) (equal? (.ref (.ref (.ref value 'facts) 'packet) 'identity) "waiver-test"))
(else #f))))
(def (adapter) (nasa-verification-adapter "test-only" test-verifier))
-(def (context-receipt a) (poo-flow-verify a (nasa-context-request project 'a context) 10 20))
-(def (evidence-receipt a) (poo-flow-verify a (nasa-evidence-request record) 10 20))
+(def (context-receipt a) (agentic-ai-lab-verify a (nasa-context-request project 'a context) 10 20))
+(def (evidence-receipt a) (agentic-ai-lab-verify a (nasa-evidence-request record) 10 20))
(def (gate a receipts records (now 11)) (nasa-stage-gate policy project 'a context records a receipts now))
(export nasa-lifecycle-test)
(def nasa-lifecycle-test
@@ -64,7 +64,7 @@
(check-exception (nasa-stage-policy "wrong-owner" '("SWE-013") scope: 'institution) Error?)
(let* ((a (adapter))
(e (nasa-verifiable-evidence (nasa-criterion-evidence "institution" project "SWE-002" "SWE-002/p1" "test-reviewer" 'pass) digest))
- (receipt (poo-flow-verify a (nasa-evidence-request e) 10 20)))
+ (receipt (agentic-ai-lab-verify a (nasa-evidence-request e) 10 20)))
(check-equal? (.ref (nasa-stage-gate (nasa-stage-policy "institution" '("SWE-002") scope: 'institution)
project 'a context (list e) a (list (context-receipt a) receipt) 11) 'admitted?) #t)))
(test-case "claimed pass is insufficient and context is independently verified"
@@ -79,7 +79,7 @@
(check-equal? (.ref (gate a (list c e) (list (.o (:: @ record) source-digest: "stale"))) 'admitted?) #f)
(check-equal? (.ref (nasa-stage-gate policy project 'a (.o (:: @ context) safety-critical?: #t) (list record) a (list c e) 11) 'admitted?) #f)
(check-equal? (.ref (gate a (list c e) (list record (.o (:: @ record) identity: "failure" outcome: 'fail))) 'status) 'requirements-blocked)
- (poo-flow-revoke-verification! a e)
+ (agentic-ai-lab-revoke-verification! a e)
(check-equal? (.ref (gate a (list c e) (list record)) 'admitted?) #f)))
(test-case "all 130 requirements traverse the verifier in their separate baselines"
(let (all-context
@@ -98,14 +98,14 @@
(nasa-verifiable-evidence
(nasa-criterion-evidence (.ref criterion 'identity) project id (.ref criterion 'identity) "test-reviewer" 'pass) digest))
(nasa-requirement-criteria id))) (.ref p 'requirements))))
- (c (poo-flow-verify a (nasa-context-request project 'a all-context) 10 20))
+ (c (agentic-ai-lab-verify a (nasa-context-request project 'a all-context) 10 20))
(inventory-values (if (eq? owner 'project) (test-inventories project 'a digest) '()))
(receipts (append (list c)
- (map (lambda (e) (poo-flow-verify a (nasa-evidence-request e) 10 20)) records)
- (map (lambda (i) (poo-flow-verify a (nasa-inventory-request i 'a) 10 20)) inventory-values))))
+ (map (lambda (e) (agentic-ai-lab-verify a (nasa-evidence-request e) 10 20)) records)
+ (map (lambda (i) (agentic-ai-lab-verify a (nasa-inventory-request i 'a) 10 20)) inventory-values))))
(check-equal? (.ref (nasa-stage-gate p project 'a all-context records a receipts 11 inventories: inventory-values) 'status) 'stage-admitted)
(check-equal? (.ref (nasa-stage-gate p project 'a all-context (cdr records) a receipts 11 inventories: inventory-values) 'admitted?) #f)
- (poo-flow-revoke-verification! a (cadr receipts))
+ (agentic-ai-lab-revoke-verification! a (cadr receipts))
(check-equal? (.ref (nasa-stage-gate p project 'a all-context records a receipts 11 inventories: inventory-values) 'admitted?) #f)))
'(project institution))))
(test-case "a later stage cannot substitute its own evidence for earlier obligations"
@@ -113,7 +113,7 @@
(records (map (lambda (c) (nasa-verifiable-evidence
(nasa-criterion-evidence (.ref c 'identity) project "SWE-015" (.ref c 'identity) "test-reviewer" 'pass) digest))
(nasa-requirement-criteria "SWE-015")))
- (receipts (cons (context-receipt a) (map (lambda (e) (poo-flow-verify a (nasa-evidence-request e) 10 20)) records)))
+ (receipts (cons (context-receipt a) (map (lambda (e) (agentic-ai-lab-verify a (nasa-evidence-request e) 10 20)) records)))
(forged (.o (:: @ (nasa-lifecycle-start project)) stage: "planning")))
(check-equal? (.ref (nasa-stage-gate later project 'a context records a receipts 11) 'admitted?) #t)
(check-equal? (.ref (nasa-transition forged (list policy later) "later" project 'a context records a receipts 11) 'advanced?) #f)))
@@ -136,7 +136,7 @@
(packet (nasa-tailoring-packet "waiver-test" project "SWE-141" "test" "risk" "mitigation" "risk/R" "matrix/M"))
(attestation (nasa-authority-attestation "signature" packet 'hq-osma "test-signer" "record/R" 'approved))
(submission (nasa-tailoring-verification-request project 'a context packet (list attestation)))
- (c (context-receipt a)) (approval (poo-flow-verify a submission 10 20)))
+ (c (context-receipt a)) (approval (agentic-ai-lab-verify a submission 10 20)))
(check-equal? (.ref (nasa-stage-gate p project 'a context '() a (list c) 11 tailorings: (list submission)) 'admitted?) #f)
(check-equal? (.ref (nasa-stage-gate p project 'a context '() a (list c approval) 11 tailorings: (list submission)) 'admitted?) #t)
(check-equal? (.ref (nasa-stage-gate p project 'a context
@@ -144,5 +144,5 @@
a (list c approval) 11 tailorings: (list submission)) 'admitted?) #f)
(check-exception (nasa-tailoring-verification-request project 'a context packet '()) Error?)
(check-exception (nasa-tailoring-verification-request project 'a context packet (list (.o (:: @ attestation) decision: 'rejected))) Error?)
- (poo-flow-revoke-verification! a approval)
+ (agentic-ai-lab-revoke-verification! a approval)
(check-equal? (.ref (nasa-stage-gate p project 'a context '() a (list c approval) 11 tailorings: (list submission)) 'admitted?) #f)))))
diff --git a/t/sdlc/unit/nasa-review-test.ss b/t/sdlc/unit/nasa-review-test.ss
index a28c7de..cce8a98 100644
--- a/t/sdlc/unit/nasa-review-test.ss
+++ b/t/sdlc/unit/nasa-review-test.ss
@@ -3,11 +3,11 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import :std/test :std/error
- :poo-flow/src/module-system/contribution/interface
- :poo-flow/lambda-aitia/modules/sdlc/interface
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-review
+ (only-in :clan/poo/object .o .ref)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d-catalog
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-review
:std/list/list)
(def project (sdlc-project "flight" "r1" "software" #t))
(def known-context
diff --git a/t/sdlc/unit/nasa-standard-provider-test.ss b/t/sdlc/unit/nasa-standard-provider-test.ss
index 1298283..7f8fca8 100644
--- a/t/sdlc/unit/nasa-standard-provider-test.ss
+++ b/t/sdlc/unit/nasa-standard-provider-test.ss
@@ -9,18 +9,18 @@
(only-in :std/misc/ports read-all-as-string)
(only-in :std/test check-equal? check-exception test-case test-suite)
(only-in :gerbil/core string-suffix?)
- (only-in :poo-flow/src/feature-system/interface
+ (only-in :yuanxu/feature-system/interface
sources-lock-freeze
write-sources-lock-module)
- (only-in :poo-flow/src/modules/standards/interface
- poo-flow-standard-digest
- poo-flow-standard-materialization-receipt-valid?
- poo-flow-standard-resolution-receipt-bundle
- poo-flow-standard-resolution-receipt-valid?
- poo-flow-standard-validate
- poo-flow-standard-validation-closure?)
- :poo-flow/lambda-aitia/modules/sdlc/standards/sources
- :poo-flow/lambda-aitia/modules/sdlc/standards/interface)
+ (only-in :agentic-ai-lab/modules/standards/interface
+ agentic-ai-lab-standard-digest
+ agentic-ai-lab-standard-materialization-receipt-valid?
+ agentic-ai-lab-standard-resolution-receipt-bundle
+ agentic-ai-lab-standard-resolution-receipt-valid?
+ agentic-ai-lab-standard-validate
+ agentic-ai-lab-standard-validation-closure?)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/sources
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/interface)
(export nasa-standard-provider-test)
@@ -41,6 +41,11 @@
(def nasa-standard-provider-test
(test-suite
"NASA NPR 7150.2D Standards Core Provider"
+ (test-case
+ "Standards family shares the public NASA SDLC identity"
+ (check-equal? (.ref Nasa7150_2DStandardFamily 'identity)
+ "nasa/sdlc/npr-7150.2")
+ (check-equal? (.ref Nasa7150_2DStandardFamily 'semantic-kind) 'sdlc))
(test-case
"declares all immutable NASA source facts through Sources Lock Feature"
(check-equal? (.ref Nasa7150_2DSourcesLock 'feature-id) 'sources-lock)
@@ -50,7 +55,7 @@
"source.lock.ss is the deterministic product of declarations and bytes"
(let* ((generated-lock
(sources-lock-freeze
- "lambda-aitia/nasa-npr-7150.2d/sources"
+ "lambda-aitia/nasa/sdlc/npr-7150.2/D/sources"
"2022-03-08"
Nasa7150_2DSources
read-lambda-aitia-source
@@ -85,12 +90,12 @@
(begin
(provider-phase 'resolve-start)
(nasa-7150-2d-resolve
- module (poo-flow-standard-digest 'nasa-test-terminology))))
+ module (agentic-ai-lab-standard-digest 'nasa-test-terminology))))
(bundle
(begin
(provider-phase 'resolve-complete)
- (poo-flow-standard-resolution-receipt-bundle receipt))))
- (check-equal? (poo-flow-standard-resolution-receipt-valid? receipt) #t)
+ (agentic-ai-lab-standard-resolution-receipt-bundle receipt))))
+ (check-equal? (agentic-ai-lab-standard-resolution-receipt-valid? receipt) #t)
(check-equal? (.ref bundle 'edition-count) 1)
(check-equal? (.ref bundle 'artifact-count) 6)
(check-equal? (.ref bundle 'byte-count) 197510)
@@ -103,7 +108,7 @@
(receipts (nasa-7150-2d-materialize-sources module)))
(check-equal? (length receipts) 6)
(check-equal?
- (andmap poo-flow-standard-materialization-receipt-valid? receipts)
+ (andmap agentic-ai-lab-standard-materialization-receipt-valid? receipts)
#t)
(check-equal?
(apply +
@@ -138,11 +143,11 @@
(closure
(nasa-7150-2d-validation-closure
module 'sdlc-project
- (poo-flow-standard-digest 'nasa-project-snapshot)))
+ (agentic-ai-lab-standard-digest 'nasa-project-snapshot)))
(provider (.ref (.ref module 'providers) 'nasa)))
- (check-equal? (poo-flow-standard-validation-closure? closure) #t)
+ (check-equal? (agentic-ai-lab-standard-validation-closure? closure) #t)
(check-equal? (length (.ref closure 'constraints)) 130)
(check-equal? (.ref closure 'runtime-executed?) #f)
(check-exception
- (poo-flow-standard-validate provider closure (.o))
+ (agentic-ai-lab-standard-validate provider closure (.o))
Error?)))))
diff --git a/t/sdlc/unit/nasa-structured-test.ss b/t/sdlc/unit/nasa-structured-test.ss
index 4fe282f..f3f4c78 100644
--- a/t/sdlc/unit/nasa-structured-test.ss
+++ b/t/sdlc/unit/nasa-structured-test.ss
@@ -3,12 +3,14 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import :std/test :std/error
- :poo-flow/src/module-system/contribution/interface
- :poo-flow/src/module-system/contribution/verification
- :poo-flow/lambda-aitia/modules/sdlc/interface
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-review
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-structured
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-lifecycle
+ (only-in :clan/poo/object .o .ref)
+ (only-in :agentic-ai-lab/core/contribution/verification
+ agentic-ai-lab-verify agentic-ai-lab-revoke-verification!)
+ :agentic-ai-lab/core/contribution/verification
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-review
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-structured
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-lifecycle
:std/list/list)
(export nasa-structured-test)
(include "../support/inventories.ss")
@@ -38,7 +40,7 @@
(nasa-requirement-criteria id)))
ids)))
(def (receipts adapter records inventory-values)
- (map (lambda (r) (poo-flow-verify adapter r 0 10))
+ (map (lambda (r) (agentic-ai-lab-verify adapter r 0 10))
(append (list (nasa-context-request project 'a context))
(map nasa-evidence-request records)
(map (lambda (i) (nasa-inventory-request i 'a)) inventory-values))))
@@ -76,7 +78,7 @@
(check-equal? (.ref (gate (list (safety-with 100 14) trace) proofs) 'admitted?) #f)
(check-equal? (.ref (gate (cons safety inventories) proofs) 'admitted?) #f)
(check-equal? (.ref (nasa-stage-gate policy project 'a context records a proofs 10 inventories: inventories) 'admitted?) #f)
- (poo-flow-revoke-verification! a (car (reverse proofs)))
+ (agentic-ai-lab-revoke-verification! a (car (reverse proofs)))
(check-equal? (.ref (gate inventories proofs) 'admitted?) #f)))
(test-case "cumulative transitions preserve inventory requirements"
(let* ((p (nasa-stage-policy "safety" '("SWE-219")))
diff --git a/t/sdlc/unit/sdlc-config-test.ss b/t/sdlc/unit/sdlc-config-test.ss
index 138b716..ad636d4 100644
--- a/t/sdlc/unit/sdlc-config-test.ss
+++ b/t/sdlc/unit/sdlc-config-test.ss
@@ -3,28 +3,30 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import :std/test :std/error
- :poo-flow/src/module-system/load
- :poo-flow/src/module-system/declaration/interface
- :poo-flow/src/module-system/contribution/interface
- :poo-flow/lambda-aitia/modules/sdlc/config)
+ (only-in :yuanxu/module-system/selection/syntax
+ agentic-ai-lab-modules!)
+ :yuanxu/module-system/selection/objects
+ (only-in :clan/poo/object .ref)
+ (only-in :agentic-ai-lab/core/contribution/objects admit-contributions)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/config)
(def (selected . flags)
- (sdlc-config (poo-flow-user-module-selection 'custom 'sdlc flags)))
+ (sdlc-config (agentic-ai-lab-user-module-selection 'custom 'sdlc flags)))
(export sdlc-config-test)
(def sdlc-config-test
(test-suite "SDLC init selection projection"
- (test-case "existing custom module syntax selects the standard"
- (let* ((bundles (poo-flow-modules!
- :custom (sdlc @ "../lambda-aitia/modules/sdlc" +nasa-7150-2d)))
+ (test-case "custom SDLC module is standard-free"
+ (let* ((bundles (agentic-ai-lab-modules!
+ :custom (sdlc @ "../lambda-aitia/modules/sdlc")))
(selection (caar bundles))
(contribution (sdlc-config selection))
(standards (.ref (.ref contribution 'profile) 'standards)))
- (check-equal? (poo-flow-user-module-selection-entrypoint selection)
+ (check-equal? (agentic-ai-lab-user-module-selection-entrypoint selection)
"../lambda-aitia/modules/sdlc/interface.ss")
- (check-equal? (map (lambda (s) (.ref s 'identity)) standards) '("nasa/npr-7150.2d"))
+ (check-equal? standards '())
(check-equal? (.ref (admit-contributions (list contribution) '()) 'accepted?) #t)))
(test-case "no feature means no NASA selection"
(check-equal? (.ref (.ref (selected) 'profile) 'standards) '()))
(test-case "unsupported features and unrelated modules are rejected"
- (check-exception (selected '+nasa-7150-2c) Error?)
- (check-exception (selected '+nasa-7150-2d '+nasa-7150-2d) Error?)
- (check-exception (sdlc-config (poo-flow-user-module-selection 'custom 'other '())) Error?))))
+ (check-exception (selected '+nasa) Error?)
+ (check-exception (selected '+npr-7150.2) Error?)
+ (check-exception (sdlc-config (agentic-ai-lab-user-module-selection 'custom 'other '())) Error?))))
diff --git a/t/sdlc/unit/sdlc-flow-test.ss b/t/sdlc/unit/sdlc-flow-test.ss
index 6c5d631..d97d949 100644
--- a/t/sdlc/unit/sdlc-flow-test.ss
+++ b/t/sdlc/unit/sdlc-flow-test.ss
@@ -4,15 +4,15 @@
(import :std/test
(only-in :clan/poo/object .ref)
- (only-in :poo-flow/src/graph/types
- poo-flow-graph? poo-flow-graph-edges poo-flow-graph-nodes)
- :poo-flow/lambda-aitia/modules/sdlc/interface)
+ (only-in :yuanxu/graph/types
+ agentic-ai-lab-graph? agentic-ai-lab-graph-edges agentic-ai-lab-graph-nodes)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface)
(export sdlc-flow-test)
(def sdlc-flow-test
(test-suite "Aitia production SDLC flow projection"
- (test-case "Aitia semantics project one complete lifecycle onto POO Flow DAG"
+ (test-case "Aitia semantics project one complete lifecycle onto Agentic AI Lab DAG"
(let (plan (sdlc-flow-plan "release/42"))
(check-equal?
(.ref plan 'topological-order)
diff --git a/t/sdlc/unit/sdlc-model-test.ss b/t/sdlc/unit/sdlc-model-test.ss
index 9869221..3b78685 100644
--- a/t/sdlc/unit/sdlc-model-test.ss
+++ b/t/sdlc/unit/sdlc-model-test.ss
@@ -3,8 +3,8 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import :std/test :std/error
- :poo-flow/src/module-system/contribution/interface
- :poo-flow/lambda-aitia/modules/sdlc/interface)
+ (only-in :clan/poo/object .o .ref)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface)
(def project (sdlc-project "flight" "r2" "software" #t))
(def evidence (sdlc-evidence "ev" "flight" "r2" "software" "nasa" "SWE-052" "test" 'pass))
(export sdlc-model-test)
diff --git a/t/sdlc/unit/sdlc-test.ss b/t/sdlc/unit/sdlc-test.ss
index 204f3a5..41b164e 100644
--- a/t/sdlc/unit/sdlc-test.ss
+++ b/t/sdlc/unit/sdlc-test.ss
@@ -3,9 +3,10 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import :std/test :std/error
- :poo-flow/src/module-system/contribution/interface
- :poo-flow/lambda-aitia/modules/sdlc/interface
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d)
+ (only-in :clan/poo/object .o .ref)
+ (only-in :agentic-ai-lab/core/contribution/objects admit-contributions)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d)
(def ProjectSdlcProfile (sdlc-with-standards SdlcProfile (list Nasa7150_2D)))
(def project-sdlc-module (sdlc-contribution ProjectSdlcProfile))
(export sdlc-test)
@@ -24,7 +25,7 @@
(test-case "clause references preserve edition and source location"
(let ((clause (nasa-requirement-by-id "SWE-013")))
(check-equal? (.ref clause 'identity) "SWE-013")
- (check-equal? (.ref clause 'standard) "nasa/npr-7150.2d")
+ (check-equal? (.ref clause 'standard) "nasa/sdlc/npr-7150.2")
(check-equal? (.ref clause 'section) "3.1.3")
(check-equal? (.ref clause 'topic) 'lifecycle-planning)))
(test-case "other standards compose without changing SDLC or NASA"
diff --git a/t/sdlc/unit/sdlc-trace-test.ss b/t/sdlc/unit/sdlc-trace-test.ss
index 788b09c..0db2151 100644
--- a/t/sdlc/unit/sdlc-trace-test.ss
+++ b/t/sdlc/unit/sdlc-trace-test.ss
@@ -3,9 +3,9 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
(import :std/test :std/error
- :poo-flow/src/module-system/contribution/interface
- :poo-flow/lambda-aitia/modules/sdlc/interface
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-7150-2d)
+ (only-in :clan/poo/object .o .ref)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/interface
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-7150-2d)
(def project (sdlc-project "flight" "r2" "software" #t))
(def rule (sdlc-trace-rule "SWE-052/verification" 'requirement 'verification))
(def req (sdlc-trace-node "req" 'requirement project))
@@ -36,7 +36,7 @@
(check-equal? (.ref result 'unresolved-edges) '("link")))
(check-exception (review (list req req test) (list edge)) Error?)
(check-exception (review (list req test) (list edge edge)) Error?))
- (test-case "change impact delegates trajectories to POO Flow Graph"
+ (test-case "change impact delegates trajectories to Agentic AI Lab Graph"
(let (result
(sdlc-change-impact
project (list req test) (list edge)
diff --git a/testing-interface.ss b/testing-interface.ss
index 5a71dd0..b1ccbe7 100644
--- a/testing-interface.ss
+++ b/testing-interface.ss
@@ -13,9 +13,9 @@
testing-interface-map-profile
testing-test-selector)
:std/list/list
- (only-in :poo-flow/src/module-system/observability/testing-extension
- make-poo-flow-testing-observability-profile
- poo-flow-testing-observability-extension))
+ (only-in :agentic-ai-lab/dev/modules/testing/testing-extension
+ make-agentic-ai-lab-testing-observability-profile
+ agentic-ai-lab-testing-observability-extension))
(export +lambda-aitia-testing-interface+)
@@ -46,7 +46,7 @@
+lambda-aitia-large-memory-selectors+))
(def +lambda-aitia-testing-interface+
- (poo-flow-testing-observability-extension
+ (agentic-ai-lab-testing-observability-extension
(testing-interface-map-profile
(testing-interface-map-profile
+lambda-aitia-bounded-testing-interface+
@@ -54,5 +54,5 @@
+testing-process-isolation-profile+)
+lambda-aitia-source-admission-selector+
+testing-serial-resource-profile+)
- (make-poo-flow-testing-observability-profile
+ (make-agentic-ai-lab-testing-observability-profile
'lambda-aitia/testing 5)))
diff --git a/tools/build-native-library.py b/tools/build-native-library.py
index 54a89c9..1795e9f 100644
--- a/tools/build-native-library.py
+++ b/tools/build-native-library.py
@@ -120,6 +120,27 @@ def configure_gambit_compiler(home: Path) -> str:
return str(compiler)
+def configure_orgize_header() -> None:
+ """Make Orgize's installed public header visible to Gambit's C phase."""
+
+ gerbil_path = os.environ.get("GERBIL_PATH")
+ if not gerbil_path:
+ raise RuntimeError("GERBIL_PATH must identify the installed Gerbil packages")
+ header_root = (
+ Path(gerbil_path).resolve()
+ / "pkg/github.com/tao3k/orgize/bindings/c/include"
+ )
+ if not (header_root / "orgize.h").is_file():
+ raise RuntimeError(
+ "Orgize's public C header is absent; run gxpkg deps --install "
+ f"for the pinned Agentic AI Lab dependencies: {header_root}"
+ )
+ previous = os.environ.get("C_INCLUDE_PATH")
+ os.environ["C_INCLUDE_PATH"] = os.pathsep.join(
+ part for part in (str(header_root), previous) if part
+ )
+
+
def module_closure(project: Path) -> tuple[list[tuple[str, Path]], Path]:
expression = r'''(let* ((ctx (import-module "bindings/c/aitia-native.ss"))
(deps (gxc#find-runtime-module-deps ctx)))
@@ -166,6 +187,7 @@ def generated_define(link_source: Path, name: str) -> str:
def main() -> int:
configure_darwin_toolchain()
+ configure_orgize_header()
parser = argparse.ArgumentParser()
parser.add_argument("--output", required=True, type=Path)
arguments = parser.parse_args()
@@ -236,7 +258,7 @@ def main() -> int:
"-cc-options",
(
f"-D___VERSION={generated_define(link_source, '___VERSION')} "
- "-DPOO_FLOW_AITIA_LINKER="
+ "-DAGENTIC_AI_LAB_AITIA_LINKER="
f"{generated_define(link_source, '___LINKER_ID')}"
),
"-obj",
@@ -249,7 +271,7 @@ def main() -> int:
module_objects = [replace_suffix(path, ".o") for path in user_scm]
libgerbil_objects = [replace_suffix(path, ".o") for path in libgerbil_scm]
- # Imported POO Flow modules may have a static Scheme/C projection without
+ # Imported Agentic AI Lab modules may have a static Scheme/C projection without
# having been public native entry points in the parent build. The Aitia
# production library owns its complete link closure, so materialize only
# those missing objects from the C sources generated by the link pass.
diff --git a/tools/import-nasa-catalog.py b/tools/import-nasa-catalog.py
index bdc39aa..e7ab884 100644
--- a/tools/import-nasa-catalog.py
+++ b/tools/import-nasa-catalog.py
@@ -44,7 +44,7 @@
assert len(bodies)==130 and len(matrix)==100
assert {k for k,v in bodies.items() if v['page']!='Chapter2'}==set(matrix)
lines=[';;; Generated from official NODIS HTML; do not hand edit.',
- '(import :poo-flow/src/module-system/contribution/interface)',
+ '(import :agentic-ai-lab/src/module-system/contribution/interface)',
'(export nasa-requirement-catalog nasa-catalog-source-digests)',
'(def nasa-catalog-source-digests', ' (.o']
for name in ['chapter2','chapter3','chapter4','chapter5','chapter6','appendix-c']:
@@ -55,7 +55,7 @@
(page (list-ref row 2)) (excerpt (list-ref row 3))
(parts (list-ref row 4)) (notes (list-ref row 5))
(matrix (list-ref row 6))
- (value (.o identity: id standard: "nasa/npr-7150.2d"
+ (value (.o identity: id standard: "nasa/sdlc/npr-7150.2"
section: section-value source-url: (string-append
"https://nodis3.gsfc.nasa.gov/displayDir.cfm?Internal_ID=N_PR_7150_002D_&page_name=" page)
source-excerpt: excerpt source-parts: parts source-notes: notes
diff --git a/tools/nasa-implementation-report.ss b/tools/nasa-implementation-report.ss
index ffd4e4d..4f4a3f1 100644
--- a/tools/nasa-implementation-report.ss
+++ b/tools/nasa-implementation-report.ss
@@ -3,8 +3,8 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
;;; Render the executable ledger; no separately maintained requirement table.
-(import :poo-flow/src/module-system/contribution/interface
- :poo-flow/lambda-aitia/modules/sdlc/standards/nasa-coverage)
+(import (only-in :clan/poo/object .ref)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/nasa-coverage)
(def (main . args)
(display "#+title: NASA implementation coverage ledger\n\n")
(display "Generated by =gxi tools/nasa-implementation-report.ss=.\n")
diff --git a/tools/update-sources-lock.ss b/tools/update-sources-lock.ss
index c5df6e8..f2ede9d 100644
--- a/tools/update-sources-lock.ss
+++ b/tools/update-sources-lock.ss
@@ -6,10 +6,10 @@
(import (only-in :gerbil/core path-expand)
(only-in :std/misc/ports read-all-as-string)
- (only-in :poo-flow/src/feature-system/source-lock-feature
+ (only-in :yuanxu/feature-system/source-lock-feature
sources-lock-freeze
write-sources-lock-module)
- :poo-flow/lambda-aitia/modules/sdlc/standards/sources)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/standards/sources)
(def arguments (cddr (command-line)))
(def root (if (pair? arguments) (car arguments) "."))
@@ -19,7 +19,7 @@
(def lock
(sources-lock-freeze
- "lambda-aitia/nasa-npr-7150.2d/sources"
+ "lambda-aitia/nasa/sdlc/npr-7150.2/D/sources"
"2022-03-08"
Nasa7150_2DSources
read-source
diff --git a/user-interface/compositions/aitia.ss b/user-interface/compositions/aitia.ss
index 7793f8f..3db47c3 100644
--- a/user-interface/compositions/aitia.ss
+++ b/user-interface/compositions/aitia.ss
@@ -3,52 +3,32 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-;;; Boundary: official maintained Aitia Composition and its catalog entry.
-;;; Invariant: Aitia owns domain assembly only; selection, loading, planning and
-;;; identity rules come from POO Flow.
+;;; Official Aitia composition over Agentic AI Lab's current Profile algebra.
+;;; Domain selection stays in the maintained Project Profile; Agentic AI Lab owns
+;;; module selection, composition, Case lowering and runtime admission.
+(import (only-in :clan/poo/object .o)
+ (only-in :agentic-ai-lab/core/module-system/schema/relations
+ agentic-ai-lab-semantic-identity)
+ (only-in :yuanxu/module-system/authoring/roles agentic-ai-lab-semantic-module)
+ (only-in :agentic-ai-lab/core/profile-composition/profile-bundle
+ agentic-ai-lab-profile-export agentic-ai-lab-module-profiles
+ profiles compose)
+ (only-in :agentic-ai-lab/core/profile-composition/selection-syntax use-module)
+ (only-in :agentic-ai-lab/modules/workflow/scenario/composition-syntax user-composition)
+ :agentic-ai-lab/lambda-aitia/user-interface/profiles/software-engineering/project)
-(import (only-in :poo-flow/src/module-system/profile-composition/interface
- poo-flow-composition
- poo-flow-composition-catalog
- poo-flow-official-composition-identity
- poo-flow-scenario-case
- poo-flow-scenario-clause
- poo-flow-scenario-profile-binding
- poo-flow-scenario-stage)
- :poo-flow/lambda-aitia/modules/formal-methods/interface
- :poo-flow/lambda-aitia/user-interface/profiles/software-engineering/project)
+(export AitiaModule aitia)
-(export aitia-composition-identity
- aitia-composition
- aitia-composition-catalog)
+(def AitiaModule
+ (agentic-ai-lab-semantic-module
+ (agentic-ai-lab-semantic-identity 'software-engineering 'aitia)
+ profiles:
+ (agentic-ai-lab-module-profiles
+ (agentic-ai-lab-profile-export
+ 'default
+ (.o (:: @ default-software-engineering-project)
+ stages: (.o software-engineering-project: (.o)))))))
-(def aitia-composition-identity
- (poo-flow-official-composition-identity 'aitia))
-
-(def (aitia-default-case project-profile)
- (poo-flow-scenario-case
- 'aitia
- '()
- (list project-profile)
- (list
- (poo-flow-scenario-stage
- 'software-engineering-project
- (list
- (poo-flow-scenario-clause
- 'profile
- '(default-software-engineering-project)))))
- (list
- (poo-flow-scenario-profile-binding
- 'aitia
- 'default-software-engineering-project))))
-
-(def aitia-composition
- (poo-flow-composition
- aitia-composition-identity
- default-software-engineering-project
- aitia-default-case))
-
-(def aitia-composition-catalog
- (poo-flow-composition-catalog
- (list aitia-composition)
- '(gitops sdlc ADR assurance formal-methods)))
+(user-composition aitia
+ (compose profiles
+ (use-module AitiaModule default)))
diff --git a/user-interface/config.ss b/user-interface/config.ss
index 2fb966c..b938db4 100644
--- a/user-interface/config.ss
+++ b/user-interface/config.ss
@@ -3,21 +3,34 @@
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
;;; -*- Gerbil -*-
-;;; Final User Composition: provider + environment Profiles + SDLC Standard.
-(import :poo-flow/src/user-interface/config-discovery-syntax)
-(export github-gitops-sdlc)
+;;; Maintained GitHub/GitOps/SDLC Case. Selection and Case lowering belong to
+;;; Agentic AI Lab; the concrete policy Profiles remain owned by Aitia.
+(import (only-in :agentic-ai-lab/core/profile-composition/profile-bundle
+ profiles compose
+ agentic-ai-lab-profile-export agentic-ai-lab-module-profiles)
+ (only-in :agentic-ai-lab/core/profile-composition/selection-syntax use-module)
+ (only-in :agentic-ai-lab/modules/workflow/scenario/composition-syntax user-composition)
+ (only-in :agentic-ai-lab/core/module-system/schema/relations
+ agentic-ai-lab-semantic-identity)
+ (only-in :yuanxu/module-system/authoring/roles agentic-ai-lab-semantic-module)
+ :agentic-ai-lab/lambda-aitia/user-interface/profiles/github/actions
+ :agentic-ai-lab/lambda-aitia/user-interface/profiles/gitops/dev
+ :agentic-ai-lab/lambda-aitia/user-interface/profiles/gitops/staging
+ :agentic-ai-lab/lambda-aitia/user-interface/profiles/gitops/production
+ :agentic-ai-lab/lambda-aitia/user-interface/profiles/nasa/sdlc)
+(export AitiaDeliveryModule github-gitops-sdlc)
-(use-composition github-gitops-sdlc
- (modules
- (use-module funflow as github
- (profile actions))
- (use-module gitops as delivery
- (profile dev)
- (profile staging)
- (profile production))
- (use-module sdlc as sdlc
- (profile nasa-7150-2d)))
- (compose
- (profile github actions)
- (profiles delivery dev staging production)
- (profile sdlc nasa-7150-2d)))
+(def AitiaDeliveryModule
+ (agentic-ai-lab-semantic-module
+ (agentic-ai-lab-semantic-identity 'software-engineering 'delivery)
+ profiles:
+ (agentic-ai-lab-module-profiles
+ (agentic-ai-lab-profile-export 'actions actions)
+ (agentic-ai-lab-profile-export 'dev dev)
+ (agentic-ai-lab-profile-export 'staging staging)
+ (agentic-ai-lab-profile-export 'production production))))
+
+(user-composition github-gitops-sdlc
+ (compose profiles
+ (use-module AitiaDeliveryModule actions dev staging production)
+ (use-module NasaSdlcModule npr-7150.2)))
diff --git a/user-interface/contracts/engineering-workspace.org b/user-interface/contracts/engineering-workspace.org
new file mode 100644
index 0000000..3af78a5
--- /dev/null
+++ b/user-interface/contracts/engineering-workspace.org
@@ -0,0 +1,95 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Aitia engineering workspace — Scheme-owned Org contracts
+
+:PROPERTIES:
+:ID: aitia-engineering-workspace-contract
+:STATUS: draft
+:END:
+
+Orgize's Scheme/POO Org Elements and Org Contract modules own these declarations.
+The tagged Scheme blocks lower to admitted POO values, then to Rust AOT plans
+consumed over the Scheme-declared Rowan graph. No legacy CLI evaluator or
+Python implementation defines the semantics. CONTRACT_ID and CONTRACT_SCOPE
+remain native Org properties; :org-contract is the upstream block selector,
+not a replacement metadata channel.
+
+These contracts check reviewable structure only. They do not resolve identity,
+verify the content of evidence, complete a review or grant execution authority.
+Consumer generation/evaluation must be qualified on the Scheme/Rowan path.
+
+* Engineering workspace
+:PROPERTIES:
+:CONTRACT_ID: lambda-aitia.engineering-workspace
+:CONTRACT_SCOPE: document
+:END:
+
+#+begin_src scheme :org-contract
+(assert-org-element "workspace.organization" error
+ (bindings)
+ (org-elements headline (property title "Organization") (child-of scope))
+ (expect at-least 1))
+(assert-org-element "workspace.requirements" error
+ (bindings)
+ (org-elements headline (property title "Requirements") (descendant-of scope))
+ (expect at-least 1))
+(assert-org-element "workspace.assumptions" error
+ (bindings)
+ (org-elements headline (property title "Assumptions") (descendant-of scope))
+ (expect at-least 1))
+(assert-org-element "workspace.alternatives" error
+ (bindings)
+ (org-elements headline (property title "Alternatives") (descendant-of scope))
+ (expect at-least 1))
+(assert-org-element "workspace.review" error
+ (bindings)
+ (org-elements headline (property title "Review") (descendant-of scope))
+ (expect at-least 1))
+(assert-org-element "workspace.receipts" error
+ (bindings)
+ (org-elements headline (property title "Receipts") (descendant-of scope))
+ (expect at-least 1))
+#+end_src
+
+* Design decision review
+:PROPERTIES:
+:CONTRACT_ID: lambda-aitia.design-review
+:CONTRACT_SCOPE: subtree
+:END:
+
+The section bindings are local to the selected decision. A required next gate
+is proving that another decision's content cannot satisfy these assertions.
+
+#+begin_src scheme :org-contract
+(assert-org-element "decision.requirements" error
+ (bindings
+ (bind requirements
+ (org-elements headline (property title "Requirements") (child-of scope))))
+ (org-elements headline (child-of requirements))
+ (expect at-least 1))
+(assert-org-element "decision.assumptions" error
+ (bindings
+ (bind assumptions
+ (org-elements headline (property title "Assumptions") (child-of scope))))
+ (org-elements headline (child-of assumptions))
+ (expect at-least 1))
+(assert-org-element "decision.alternatives" error
+ (bindings
+ (bind alternatives
+ (org-elements headline (property title "Alternatives") (child-of scope))))
+ (org-elements headline (child-of alternatives))
+ (expect at-least 2))
+(assert-org-element "decision.review" error
+ (bindings
+ (bind review
+ (org-elements headline (property title "Review") (child-of scope))))
+ (org-elements headline (child-of review))
+ (expect at-least 1))
+(assert-org-element "decision.receipts" error
+ (bindings
+ (bind receipts
+ (org-elements headline (property title "Receipts") (child-of scope))))
+ (org-elements link (descendant-of receipts))
+ (expect at-least 1))
+#+end_src
diff --git a/user-interface/profiles/github/actions.ss b/user-interface/profiles/github/actions.ss
index 1a4de3a..a8bacdd 100644
--- a/user-interface/profiles/github/actions.ss
+++ b/user-interface/profiles/github/actions.ss
@@ -6,14 +6,14 @@
;;; Reusable GitHub workflow Profiles; no scenario or runtime execution lives here.
(import (only-in :clan/poo/object .def)
- :poo-flow/src/modules/funflow/github-ci-contract)
+ :agentic-ai-lab/modules/funflow/github-ci-contract)
(export actions)
-(.def (actions @ poo-flow-funflow-github-ci-profile)
+(.def (actions @ agentic-ai-lab-funflow-github-ci-profile)
(name 'actions)
(owner 'lambda-aitia)
(features '(pull-request environments deployments schema-validation))
- (extends poo-flow-funflow-github-ci-profile)
+ (extends agentic-ai-lab-funflow-github-ci-profile)
(scope '(workflow))
(capabilities '(pull-request environments deployments))
(guard '(schema-validated))
diff --git a/user-interface/profiles/gitops/dev.ss b/user-interface/profiles/gitops/dev.ss
index bc985c1..8085141 100644
--- a/user-interface/profiles/gitops/dev.ss
+++ b/user-interface/profiles/gitops/dev.ss
@@ -2,7 +2,7 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/gitops/interface)
+(import :agentic-ai-lab/lambda-aitia/modules/gitops/interface)
(export dev)
(define-gitops-profile dev OpenGitOpsProfile
environment: 'dev
diff --git a/user-interface/profiles/gitops/production.ss b/user-interface/profiles/gitops/production.ss
index 4064571..b7d2642 100644
--- a/user-interface/profiles/gitops/production.ss
+++ b/user-interface/profiles/gitops/production.ss
@@ -2,7 +2,7 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/gitops/interface)
+(import :agentic-ai-lab/lambda-aitia/modules/gitops/interface)
(export production)
(define-gitops-profile production OpenGitOpsProfile
environment: 'production
diff --git a/user-interface/profiles/gitops/staging.ss b/user-interface/profiles/gitops/staging.ss
index 2e59435..0cfa1ad 100644
--- a/user-interface/profiles/gitops/staging.ss
+++ b/user-interface/profiles/gitops/staging.ss
@@ -2,7 +2,7 @@
;;;
;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-(import :poo-flow/lambda-aitia/modules/gitops/interface)
+(import :agentic-ai-lab/lambda-aitia/modules/gitops/interface)
(export staging)
(define-gitops-profile staging OpenGitOpsProfile
environment: 'staging
diff --git a/user-interface/profiles/nasa/sdlc.ss b/user-interface/profiles/nasa/sdlc.ss
new file mode 100644
index 0000000..1e65311
--- /dev/null
+++ b/user-interface/profiles/nasa/sdlc.ss
@@ -0,0 +1,30 @@
+;;; -*- Gerbil -*-
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;;
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Organization NASA / domain SDLC / standard family NPR 7150.2.
+;;; Agentic AI Lab owns the typed namespace, Module and Profile selection.
+(import (only-in :clan/poo/object .def)
+ (only-in :agentic-ai-lab/core/module-system/schema/relations
+ agentic-ai-lab-semantic-identity)
+ (only-in :yuanxu/module-system/authoring/roles agentic-ai-lab-semantic-module)
+ (only-in :agentic-ai-lab/core/profile-composition/profile-bundle
+ agentic-ai-lab-profile-export agentic-ai-lab-module-profiles)
+ :agentic-ai-lab/lambda-aitia/modules/sdlc/config)
+(export NasaSdlcModule nasa-sdlc-npr7150_2)
+
+(.def (nasa-sdlc-npr7150_2 @ sdlc-nasa-7150-profile)
+ (name 'nasa/sdlc/npr-7150.2)
+ (role 'standard)
+ (standard "nasa/sdlc/npr-7150.2")
+ (owner 'lambda-aitia)
+ (extends sdlc-nasa-7150-profile)
+ (runtime-executed #f))
+
+(def NasaSdlcModule
+ (agentic-ai-lab-semantic-module
+ (agentic-ai-lab-semantic-identity 'nasa 'sdlc)
+ profiles:
+ (agentic-ai-lab-module-profiles
+ (agentic-ai-lab-profile-export 'npr-7150.2 nasa-sdlc-npr7150_2))))
diff --git a/user-interface/profiles/sdlc/nasa-7150-2d.ss b/user-interface/profiles/sdlc/nasa-7150-2d.ss
deleted file mode 100644
index 2040d2b..0000000
--- a/user-interface/profiles/sdlc/nasa-7150-2d.ss
+++ /dev/null
@@ -1,15 +0,0 @@
-;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
-;;;
-;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
-
-;;; -*- Gerbil -*-
-(import (only-in :clan/poo/object .def)
- :poo-flow/lambda-aitia/modules/sdlc/config)
-(export nasa-7150-2d)
-(.def (nasa-7150-2d @ sdlc-nasa-7150-profile)
- (name 'nasa-7150-2d)
- (role 'standard)
- (standard "nasa/npr-7150.2d")
- (owner 'lambda-aitia)
- (extends sdlc-nasa-7150-profile)
- (runtime-executed #f))
diff --git a/user-interface/profiles/software-engineering/project.ss b/user-interface/profiles/software-engineering/project.ss
index ecd4aef..eb8ecae 100644
--- a/user-interface/profiles/software-engineering/project.ss
+++ b/user-interface/profiles/software-engineering/project.ss
@@ -5,35 +5,37 @@
;;; Boundary: maintained default Software Engineering Project Profile.
;;; Invariant: the Profile selects Aitia knowledge and obligations only; module
-;;; realization and Runtime execution remain separate POO Flow phases.
+;;; realization and Runtime execution remain separate Agentic AI Lab phases.
-(import (only-in :poo-flow/src/module-system/declaration/interface
- poo-flow-settings
- poo-flow-user-module-selection)
- (only-in :poo-flow/src/user-interface/profile-core
- pooFlowUserProfile))
+(import (only-in :yuanxu/module-system/selection/objects
+ agentic-ai-lab-settings
+ agentic-ai-lab-user-module-selection)
+ (only-in :yuanxu/profile-composition/user-profile
+ agenticAiLabUserProfile))
(export default-software-engineering-project)
(def default-software-engineering-project
- (pooFlowUserProfile
+ (agenticAiLabUserProfile
'default-software-engineering-project
(list
(list
- (poo-flow-user-module-selection
+ (agentic-ai-lab-user-module-selection
'software-engineering 'gitops '(+open-gitops))
- (poo-flow-user-module-selection
- 'software-engineering 'sdlc '(+nasa-7150-2d))
- (poo-flow-user-module-selection
+ (agentic-ai-lab-user-module-selection
+ 'software-engineering 'sdlc '())
+ (agentic-ai-lab-user-module-selection
+ 'nasa 'sdlc '(+npr-7150.2))
+ (agentic-ai-lab-user-module-selection
'software-engineering 'ADR '(+rfc-relations))
- (poo-flow-user-module-selection
+ (agentic-ai-lab-user-module-selection
'software-engineering 'assurance '(+causal-evidence))
- (poo-flow-user-module-selection
- 'software-engineering 'formal-methods '(+tla+ +lean +cedar))))
- (poo-flow-settings
+ (agentic-ai-lab-user-module-selection
+ 'software-engineering 'formal-methods '(+quint +lean +cedar))))
+ (agentic-ai-lab-settings
project-kind: 'software-engineering
composition: 'aitia
- formal-method-obligations: '(tla+ lean cedar)
+ formal-method-obligations: '(quint lean cedar)
runtime-executed?: #f)
'(project-kind
composition
diff --git a/user-interface/scenarios/github-gitops.ss b/user-interface/scenarios/github-gitops.ss
index e8c4866..71f6abb 100644
--- a/user-interface/scenarios/github-gitops.ss
+++ b/user-interface/scenarios/github-gitops.ss
@@ -4,11 +4,15 @@
;;; -*- Gerbil -*-
;;; Provider adapter only. The GitOps module performs the pure policy decision.
-(import :poo-flow/lambda-aitia/modules/gitops/interface)
+(import :agentic-ai-lab/lambda-aitia/modules/gitops/interface)
(export github-change github-check github-run-gitops)
(def (github-change event repository revision source-ref target-ref pull-request)
(gitops-change 'github event repository revision source-ref target-ref pull-request))
-(def (github-check name repository revision conclusion)
- (gitops-check name repository revision conclusion))
+(def (github-check name repository revision conclusion
+ standard-edition: (standard-edition #f)
+ source-lock-digest: (source-lock-digest #f))
+ (gitops-check name repository revision conclusion
+ standard-edition: standard-edition
+ source-lock-digest: source-lock-digest))
(def (github-run-gitops composition change checks)
(gitops-evaluate composition change checks))
diff --git a/user-interface/scenarios/job-executor-retirement.ss b/user-interface/scenarios/job-executor-retirement.ss
new file mode 100644
index 0000000..a288093
--- /dev/null
+++ b/user-interface/scenarios/job-executor-retirement.ss
@@ -0,0 +1,81 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Synthetic qualification facts, not observations from a production service.
+;;; Algorithms and receipt authority stay with Agentic AI Lab's public owners.
+(import (only-in :yuanxu/graph/types
+ agentic-ai-lab-graph agentic-ai-lab-graph-node agentic-ai-lab-graph-edge)
+ (only-in :agentic-ai-lab/modules/temporal-causality/interface
+ agentic-ai-lab-temporal-observation agentic-ai-lab-causal-event
+ agentic-ai-lab-causal-event-graph))
+
+(export job-retirement-before job-retirement-candidate
+ job-retirement-relations job-retirement-events
+ job-retirement-event-graph job-retirement-incomplete-event-graph)
+
+(def job-retirement-relations '(PRODUCED_UNDER USES_CAPABILITY VERIFIES))
+
+(def job-retirement-before
+ (agentic-ai-lab-graph
+ 'job-executor/before-retirement
+ (map agentic-ai-lab-graph-node
+ '(automatic-retry historical-result active-job queued-job
+ verify-queued-retry unrelated-export))
+ (list
+ (agentic-ai-lab-graph-edge 'historical-result 'automatic-retry 'PRODUCED_UNDER)
+ (agentic-ai-lab-graph-edge 'active-job 'automatic-retry 'USES_CAPABILITY)
+ (agentic-ai-lab-graph-edge 'queued-job 'automatic-retry 'USES_CAPABILITY)
+ (agentic-ai-lab-graph-edge 'verify-queued-retry 'queued-job 'VERIFIES))))
+
+;;; Candidate topology only: moving these edges is not a migration receipt.
+;;; Historical interpretation still binds job-retirement-before, not this graph.
+(def job-retirement-candidate
+ (agentic-ai-lab-graph
+ 'job-executor/candidate-after-retirement
+ (map agentic-ai-lab-graph-node
+ '(reviewed-recovery historical-result active-job queued-job
+ verify-queued-retry unrelated-export))
+ (list
+ (agentic-ai-lab-graph-edge 'active-job 'reviewed-recovery 'USES_CAPABILITY)
+ (agentic-ai-lab-graph-edge 'queued-job 'reviewed-recovery 'USES_CAPABILITY)
+ (agentic-ai-lab-graph-edge 'verify-queued-retry 'queued-job 'VERIFIES))))
+
+(def (fixture-event id kind position parents modality committed?)
+ (agentic-ai-lab-causal-event
+ id "job-executor/retirement-fixture" kind
+ (agentic-ai-lab-temporal-observation
+ (string-append id "/time") 'logical-version position
+ "synthetic-retirement-fixture")
+ (string-append id "/payload") parents modality committed?))
+
+(def job-retirement-events
+ (list
+ (fixture-event "retry-enabled" 'capability-enabled 1 '() 'observed #t)
+ (fixture-event "historical-result" 'job-completed 2
+ '("retry-enabled") 'observed #t)
+ (fixture-event "job-started" 'job-started 2
+ '("retry-enabled") 'observed #t)
+ ;; Current activity is explicitly observed; old creation time cannot infer it.
+ (fixture-event "job-still-active" 'job-state-observed 4
+ '("job-started") 'observed #t)
+ (fixture-event "retirement-review" 'review-requested 4
+ '("retry-enabled") 'observed #t)
+ (fixture-event "queued-retry" 'planned-retry 6
+ '("retry-enabled") 'declared #f)
+ (fixture-event "retire-retry" 'proposed-retirement 5
+ '("retirement-review") 'counterfactual #f)
+ (fixture-event "later-retry" 'planned-retry 10
+ '("retry-enabled") 'declared #f)
+ (fixture-event "unrelated-export" 'export-completed 4 '() 'observed #t)))
+
+(def job-retirement-event-graph
+ (agentic-ai-lab-causal-event-graph
+ "job-executor/retirement-fixture" job-retirement-events))
+
+(def job-retirement-incomplete-event-graph
+ (agentic-ai-lab-causal-event-graph
+ "job-executor/retirement-fixture"
+ (append job-retirement-events
+ (list (fixture-event "external-observation" 'consumer-observed 4
+ '("retry-enabled" "unknown-consumer-origin")
+ 'observed #t)))))
diff --git a/user-interface/scenarios/job-retirement-contract.ss b/user-interface/scenarios/job-retirement-contract.ss
new file mode 100644
index 0000000..718acb1
--- /dev/null
+++ b/user-interface/scenarios/job-retirement-contract.ss
@@ -0,0 +1,55 @@
+;;; SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+;;; SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+;;; Maintained POO design declaration for the bounded formal experiment.
+;;; Source bindings are not Host evidence admission or implementation refinement.
+(import (only-in :agentic-ai-lab/lambda-aitia/modules/sdlc/design
+ sdlc-design-contract sdlc-design-assumption sdlc-design-guarantee))
+(export job-retirement-contract job-retirement-safety
+ job-retirement-quint-sources job-retirement-lean-sources
+ job-retirement-scheme-sources)
+
+(def job-retirement-safety
+ (sdlc-design-guarantee
+ "retirement-safety" "g1"
+ "Retirement leaves no active or queued work; a cached grant cannot start a later effect."))
+(def job-retirement-contract
+ (sdlc-design-contract
+ "job-executor/retirement" "r1" "RFC/0004/retirement-ingress"
+ '("review-retirement" "invalidate-cached-authority" "drain-known-work")
+ '("retirement-review-cut") '()
+ (list
+ (sdlc-design-assumption "atomic-epoch-fence" "a1"
+ "Closing issuance and advancing the authority epoch is one atomic step.")
+ (sdlc-design-assumption "known-inventory" "a1"
+ "Inventory at finalization covers all active and queued consumers.")
+ (sdlc-design-assumption "no-new-grant" "a1"
+ "No new grant is issued after closure in the modeled scope.")
+ (sdlc-design-assumption "bounded-client" "a1"
+ "The Quint composition models one cached grant, one request and one attempt."))
+ (list job-retirement-safety) '()))
+
+;;; Dependency closure for the retirement slice, not unrelated assurance gates.
+;;; Lists name repository source assets; they are not a second workflow DSL.
+(def job-retirement-quint-sources
+ '("proof/quint/EffectAdmission.qnt"
+ "proof/quint/WorkCore.qnt"
+ "proof/quint/WorkLifecycle.qnt"
+ "proof/quint/RetirementReview.qnt"
+ "proof/quint/RetirementIngress.qnt"
+ "proof/quint/package.json"
+ "proof/quint/package-lock.json"
+ "proof/quint/tlc-config.json"
+ "proof/quint/check_contract.py"
+ "proof/quint/check_scheme_replay.py"
+ "proof/quint/process_runner.py"))
+(def job-retirement-lean-sources
+ '("proof/lean/LambdaAitiaProof/Modules/Sdlc/Retirement.lean"
+ "proof/lean/LambdaAitiaProof/Modules/Sdlc/RetirementIngress.lean"))
+(def job-retirement-scheme-sources
+ '("modules/sdlc/retirement-host.ss"
+ "t/formal/retirement-execution-test.ss"
+ "t/formal/retirement-replay-test.ss"
+ "justfile"
+ ".github/workflows/ci.yml"
+ "build.ss"))
diff --git a/user-interface/workspaces/job-executor.org b/user-interface/workspaces/job-executor.org
new file mode 100644
index 0000000..4db2764
--- /dev/null
+++ b/user-interface/workspaces/job-executor.org
@@ -0,0 +1,289 @@
+# SPDX-FileCopyrightText: 2026 tao3k team and Contributors
+# SPDX-License-Identifier: Apache-2.0 AND LGPL-2.1-or-later
+
+#+title: Job executor — engineering design workspace
+#+startup: overview
+#+TODO: TODO REVIEW BLOCKED | DONE CANCELLED
+#+category: aitia-design
+
+:PROPERTIES:
+:ID: aitia-job-executor-workspace
+:REVISION: r2
+:STATUS: draft
+:CONTRACT_ORG: lambda-aitia.engineering-workspace
+:END:
+
+* Design question
+:PROPERTIES:
+:ID: aitia-job-executor-question
+:END:
+
+How can one logical job finish after acknowledgement loss without creating a
+second external effect? This maintained Aitia work surface connects people,
+Agent review roles, design alternatives and bounded evidence in native Org.
+Its starting decision is [[file:../../docs/adrs/0008-stable-operation-key-after-lost-ack.org][ADR 0008]], which remains proposed.
+
+This file targets the Scheme-owned Org Elements query path. Its consumer
+qualification is pending; legacy CLI queries do not close that gate.
+Role references below are proposed
+assignments, not registered principals, running Agents or granted capabilities.
+The Aitia Org-to-Scheme projection and controlled edit/execution loop remain
+pending under [[file:../../docs/rfcs/0005-org-native-engineering-workspace.org][RFC 0005]]. Reading this file executes no source block.
+
+| Dimension | Current state | Authority / source |
+|-----------+---------------+--------------------|
+| Design choice | proposed: stable logical identity | ADR 0008; independent review pending |
+| Local qualification | bounded pass and known-fault replay | linked source-fixture receipt; not provider certification |
+| Guarantee support | full support unresolved | retention, intent, concurrency and external commit boundaries open |
+| Effect authority | not granted by this workspace | existing Cedar / Runtime admission required |
+| Production outcome | not observed here | no production execution receipt |
+
+* Organization
+:PROPERTIES:
+:ID: aitia-job-executor-organization
+:END:
+
+Roles refer to the existing Agentic AI Lab Organization Bundle concepts. An
+application must resolve actual principal/role/Agent identities, visibility
+and delegations before scheduling. Org nesting does not confer authority.
+
+| Proposed role | Responsibility | Suggested context projection | Not granted by this document |
+|---------------+----------------+------------------------------+------------------------------|
+| design-owner | owns requirements, alternatives and ADR proposal | whole design and review findings | self-certification of external guarantees |
+| case-reviewer | reviews historical relevance and counterevidence | source inventory, assumptions and alternatives | mutation of provider or release policy |
+| guarantee-reviewer | checks gaps across component contracts | requirements, assumptions, owner matrix and scoped receipts | conversion of a hypothesis into proof |
+| verification-runner | requests bounded checks through Runtime | selected obligation, bound inputs and tool contract | arbitrary Org code execution or provider credentials |
+| decision-reviewer | reviews the proposed choice and its conditions | alternatives, objections, obligations and evidence references | bypassing Cedar / Runtime effect gates |
+
+The same person or Agent may fill more than one role only when the application
+permits it; a required independent review must retain actual principal
+separation. No Agent is spawned by a heading or an =OWNER_ROLE= property.
+
+* Design decision — stable logical identity
+:PROPERTIES:
+:ID: aitia-job-executor-design-decision
+:STATUS: proposed
+:CONTRACT_ORG: lambda-aitia.design-review
+:END:
+
+This subtree is the review context for ADR 0008. Its contract checks local
+requirements, assumptions, alternatives, review work and receipt references;
+passing does not accept the decision or establish any external guarantee.
+
+** Requirements
+:PROPERTIES:
+:ID: aitia-job-executor-requirements
+:END:
+
+*** Unique logical effect
+:PROPERTIES:
+:ID: aitia-job-executor-unique-effect
+:AITIA_KIND: requirement
+:OWNER_ROLE: design-owner
+:END:
+
+One logical job operation must not commit a duplicate effect within the
+qualified provider contract. Per-key uniqueness is insufficient when a retry
+can change its key. A completed review must state the scope rather than claim
+unconditional exactly-once delivery.
+
+*** Completion after transient response loss
+:PROPERTIES:
+:ID: aitia-job-executor-completion
+:AITIA_KIND: requirement
+:OWNER_ROLE: design-owner
+:END:
+
+The job must be able to complete after transient acknowledgement loss under
+explicit service-availability and retry/reconciliation conditions. Turning
+off retries cannot silently remove this requirement.
+
+** Assumptions
+:PROPERTIES:
+:ID: aitia-job-executor-assumptions
+:END:
+
+*** Provider retains logical-operation identity
+:PROPERTIES:
+:ID: aitia-job-executor-retention
+:AITIA_KIND: assumption
+:OWNER_ROLE: design-owner
+:STATUS: unqualified
+:END:
+
+The provider's deduplication scope and retention cover permitted retries.
+There is no measured retention duration in the current fixture. A shortened
+retention interval, identity collision or late request reopens this assumption.
+
+*** Effect and deduplication survive failure coherently
+:PROPERTIES:
+:ID: aitia-job-executor-atomicity
+:AITIA_KIND: assumption
+:OWNER_ROLE: guarantee-reviewer
+:STATUS: unqualified
+:END:
+
+The actual provider supplies atomic commit or a qualified recovery protocol.
+The local SQLite row stands for both the key and the effect; it does not test
+an independent external side effect. Two Cedar permits are not a uniqueness
+mechanism. A lost ACK leaves the caller uncertain, not entitled to assume no
+commit occurred.
+
+** Alternatives
+:PROPERTIES:
+:ID: aitia-job-executor-alternatives
+:END:
+
+#+name: retry-design-alternatives
+| Option | Unique logical effect | Completion | Additional obligations | Current judgment |
+|--------+-----------------------+------------+------------------------+------------------|
+| Stop after lost ACK | avoids a retry-induced duplicate, but does not establish original outcome | not guaranteed | explicit unknown outcome and recovery owner | conflicts with unattended completion unless recovery is added |
+| Retry with stable identity | conditional on scope, retention and provider semantics | conditional on availability and retry policy | parameter binding, persistence, concurrent attempts and crash checks | proposed by ADR 0008; one bounded fixture passes |
+| Query / reconcile before further action | depends on authoritative correlation and reconciliation semantics | depends on query availability and outcome resolution | bind original identity; absence must not be mistaken for failure when history is incomplete | candidate; no local implementation or receipt |
+
+These are comparisons under the same requirements, not a numeric ranking.
+The first and third options are not claimed to have been executed. Reconciliation
+may complement stable identity; the alternatives are not inherently exclusive.
+
+*** Stop after lost ACK
+:PROPERTIES:
+:ID: aitia-job-executor-option-stop
+:END:
+
+The comparison above identifies the missing completion/recovery guarantee.
+
+*** Retry with stable identity
+:PROPERTIES:
+:ID: aitia-job-executor-option-stable-identity
+:END:
+
+ADR 0008 proposes this option under the assumptions in this decision subtree.
+
+*** Query and reconcile
+:PROPERTIES:
+:ID: aitia-job-executor-option-reconcile
+:END:
+
+The comparison above retains this unimplemented candidate and its unknowns.
+
+** Historical material
+:PROPERTIES:
+:ID: aitia-job-executor-history
+:END:
+
+[[file:../../docs/plans/engineering-case-source-inventory.org][The source inventory]] retains attribution and applicability boundaries for
+the AWS idempotency article, the etcd watch report and the GitHub incident
+analysis. The first informs identity/retention questions. The other two remain
+candidate questions about missing history and cross-component assumptions;
+they are not evidence of an Aitia defect.
+
+** Review
+:PROPERTIES:
+:ID: aitia-job-executor-review
+:END:
+
+*** TODO Review retention and retry horizon :assumption:review:
+:PROPERTIES:
+:ID: aitia-job-executor-review-retention
+:OWNER_ROLE: case-reviewer
+:SUBJECT_ID: aitia-job-executor-retention
+:END:
+
+- [ ] Name the actual provider contract and identity scope.
+- [ ] Compare retry horizon with retention, including late requests.
+- [ ] Record contrary evidence and the required action outside the guarantee.
+
+Expected Agent contribution: an attributed applicability finding attached to
+this node, with proposed changes and explicit unknowns. It cannot accept the ADR.
+
+*** TODO Review guarantee composition :guarantee:review:
+:PROPERTIES:
+:ID: aitia-job-executor-review-composition
+:OWNER_ROLE: guarantee-reviewer
+:SUBJECT_ID: aitia-job-executor-atomicity
+:END:
+
+- [ ] Bind authorized intent to dispatched parameters.
+- [ ] Qualify mismatched-parameter rejection and concurrent attempts.
+- [ ] Qualify crash boundaries with the actual effect provider.
+
+Use the [[file:../../docs/adrs/0008-stable-operation-key-after-lost-ack.org][existing owner matrix]]: Host supplies trusted context, Cedar evaluates
+authorization, Runtime enforces at use, and provider mechanisms establish
+effect uniqueness. Do not add a second policy evaluator.
+
+*** BLOCKED Connect the source-bound Org review projection :integration:
+:PROPERTIES:
+:ID: aitia-job-executor-review-projection
+:OWNER_ROLE: design-owner
+:SUBJECT_ID: aitia-job-executor-workspace
+:END:
+
+The Scheme sources are located on Orgize's =codex/scheme-rowan-org-cutover=
+branch. Qualify an installable package boundary before wiring this projection:
+the current gerbil-parser Scheme dependency points back to Agentic AI Lab, and Orgize
+does not yet have a Gerbil package entrypoint. See RFC 0005's package audit.
+Reuse parser-owned identities/ranges and POO objects. Do not implement an Org
+parser in Python or infer supported bindings from the existence of the CLI.
+
+*** TODO Review the proposed ADR :decision:review:
+:PROPERTIES:
+:ID: aitia-job-executor-review-decision
+:OWNER_ROLE: decision-reviewer
+:SUBJECT_ID: lambda-aitia-adr-0008
+:END:
+
+- [ ] Review the same requirements across alternatives and retained objections.
+- [ ] Confirm the missing qualifications and responsible owners.
+- [ ] Record a decision revision; editing this TODO does not accept the ADR.
+
+** Receipts
+:PROPERTIES:
+:ID: aitia-job-executor-receipts
+:END:
+
+The [[file:../../bindings/python/qualification/job_executor/README.org][source-fixture replay receipt]] records the 2026-09-24 run at code commit
+=f3438241780e863db6c0b518d86628b540f96cd1=: fixed mode passed, while buggy mode
+failed specifically with two commits. This is a linked historical receipt, not
+a new run produced by opening this document or a trusted Host-issued admission.
+
+| Observation | Scope | Does not establish |
+|-------------+-------+--------------------|
+| Fixed strategy passed | single job, fixed payload, sequential restart and local provider | retention, multi-tenant or independent external-effect guarantees |
+| Buggy strategy failed with two commits | deliberate known-fault regression | novel bug discovery or causal proof for a production service |
+| Org contract check | workspace sections and decision-local review structure | identity resolution, role authority, evidence freshness or execution |
+
+The separate [[file:../../docs/receipts/2026-09-24-retirement-impact.org][retirement Impact receipt]] qualifies a synthetic automatic-retry
+removal analysis through Agentic AI Lab. It is not a new run of the persistent Python
+worker or evidence that queued tasks were migrated or cancelled.
+
+* Revision journal
+:PROPERTIES:
+:ID: aitia-job-executor-journal
+:END:
+:LOGBOOK:
+- Note taken on [2026-09-24 Thu] \\
+ Created the native authoring/query work surface. No role assignment or
+ production authorization was issued. Existing receipts remain linked.
+:END:
+
+Keep later judgments as new revisions with source and reason. An Agent edit
+proposal must bind the document digest, node ID, original range and expected
+old content; a concurrent edit requires review/replanning, not a blind offset
+replacement. A moved heading retains identity but gains no delegated rights.
+
+* Workflow
+
+#+begin_export mermaid
+flowchart TD
+ O["Org design node
authored"] --> Q["Orgize projection
located and queryable"]
+ Q --> R["Role-scoped review
proposed"]
+ R --> P["Node edit
pending owner acceptance"]
+ P --> C["Revised design
obligations reopened"]
+ C --> G["Cedar / Runtime handoff
qualification pending"]
+ G --> E["Actual execution receipt
required before claiming results"]
+ E --> O
+#+end_export
+
+This document is an authored work surface, not a qualification receipt.
+Scheme admission, AOT generation and actual consumer evaluation remain required.
+The diagram describes the intended interaction, not completed execution.